Merge gromacs-4-6 into master
authorRoland Schulz <roland@utk.edu>
Sun, 11 Dec 2011 20:17:43 +0000 (15:17 -0500)
committerRoland Schulz <roland@utk.edu>
Sun, 11 Dec 2011 20:18:51 +0000 (15:18 -0500)
Conflicts:
CMakeLists.txt
README
bootstrap
share/template/.gitignore
src/gmxlib/.gitignore
src/gmxlib/CMakeLists.txt
src/kernel/.gitignore
src/ngmx/.gitignore
src/tools/.gitignore
src/tools/CMakeLists.txt
src/tools/gmx_dos.c
src/tools/gmx_energy.c
src/gromacs/CMakeLists.txt

Change-Id: I18a484ef470a8af9fc0eb80d086eb80f45de2d2c

3108 files changed:
.gitignore
CMakeLists.txt
Doxyfile-lib.cmakein [new file with mode: 0644]
Doxyfile-user.cmakein [new file with mode: 0644]
Doxyfile.cmakein [new file with mode: 0644]
admin/.cvsignore [deleted file]
bootstrap [deleted file]
cmake/ThreadMPI.cmake
include/.cvsignore [deleted file]
include/CMakeLists.txt [deleted file]
include/centerofmass.h [deleted file]
include/gmx_statistics.h [deleted file]
include/gmx_wallcycle.h [deleted file]
include/gmxfio.h [deleted file]
include/indexutil.h [deleted file]
include/mainpage.h [deleted file]
include/mdrun.h [deleted file]
include/mpelogging.h [deleted file]
include/names.h [deleted file]
include/nbsearch.h [deleted file]
include/physics.h [deleted file]
include/poscalc.h [deleted file]
include/position.h [deleted file]
include/selection.h [deleted file]
include/selmethod.h [deleted file]
include/selparam.h [deleted file]
include/selvalue.h [deleted file]
include/string2.h [deleted file]
include/thread_mpi/CMakeLists.txt [deleted file]
include/thread_mpi/atomic/CMakeLists.txt [deleted file]
include/thread_mpi/atomic/gcc_x86.h [deleted file]
include/trajana.h [deleted file]
include/types/.cvsignore [deleted file]
include/types/enums.h [deleted file]
include/types/inputrec.h [deleted file]
include/vec.h [deleted file]
man/.cvsignore [deleted file]
man/man1/.cvsignore [deleted file]
scripts/.cvsignore [deleted file]
scripts/.gitignore [new file with mode: 0644]
scripts/GMXRC.bash.cmakein
scripts/GMXRC.cmakein
scripts/GMXRC.zsh.cmakein
share/.cvsignore [deleted file]
share/CMakeLists.txt
share/html/.cvsignore [deleted file]
share/html/images/.cvsignore [deleted file]
share/html/online/.cvsignore [deleted file]
share/template/.cvsignore [deleted file]
share/template/.gitignore
share/template/CMakeLists.txt [new file with mode: 0644]
share/template/template.cpp [new file with mode: 0644]
share/template/template_doc.cpp [new file with mode: 0644]
share/top/.cvsignore [deleted file]
share/top/gurgle.dat
share/tutor/.cvsignore [deleted file]
share/tutor/gmxdemo/.cvsignore [deleted file]
share/tutor/methanol/.cvsignore [deleted file]
share/tutor/mixed/.cvsignore [deleted file]
share/tutor/nmr1/.cvsignore [deleted file]
share/tutor/nmr2/.cvsignore [deleted file]
share/tutor/speptide/.cvsignore [deleted file]
share/tutor/water/.cvsignore [deleted file]
src/.cvsignore [deleted file]
src/CMakeLists.txt
src/contrib/.cvsignore [deleted file]
src/external/boost/README [new file with mode: 0644]
src/external/boost/boost/assert.hpp [new file with mode: 0644]
src/external/boost/boost/checked_delete.hpp [new file with mode: 0644]
src/external/boost/boost/config.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi/borland_prefix.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi/borland_suffix.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi/msvc_prefix.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi/msvc_suffix.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi_prefix.hpp [new file with mode: 0644]
src/external/boost/boost/config/abi_suffix.hpp [new file with mode: 0644]
src/external/boost/boost/config/auto_link.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/borland.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/clang.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/codegear.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/comeau.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/common_edg.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/compaq_cxx.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/digitalmars.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/gcc.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/gcc_xml.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/greenhills.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/hp_acc.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/intel.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/kai.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/metrowerks.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/mpw.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/nvcc.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/pathscale.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/pgi.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/sgi_mipspro.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/sunpro_cc.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/vacpp.hpp [new file with mode: 0644]
src/external/boost/boost/config/compiler/visualc.hpp [new file with mode: 0644]
src/external/boost/boost/config/no_tr1/cmath.hpp [new file with mode: 0644]
src/external/boost/boost/config/no_tr1/complex.hpp [new file with mode: 0644]
src/external/boost/boost/config/no_tr1/functional.hpp [new file with mode: 0644]
src/external/boost/boost/config/no_tr1/memory.hpp [new file with mode: 0644]
src/external/boost/boost/config/no_tr1/utility.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/aix.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/amigaos.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/beos.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/bsd.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/cygwin.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/hpux.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/irix.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/linux.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/macos.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/qnxnto.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/solaris.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/symbian.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/vms.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/vxworks.hpp [new file with mode: 0644]
src/external/boost/boost/config/platform/win32.hpp [new file with mode: 0644]
src/external/boost/boost/config/posix_features.hpp [new file with mode: 0644]
src/external/boost/boost/config/requires_threads.hpp [new file with mode: 0644]
src/external/boost/boost/config/select_compiler_config.hpp [new file with mode: 0644]
src/external/boost/boost/config/select_platform_config.hpp [new file with mode: 0644]
src/external/boost/boost/config/select_stdlib_config.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/dinkumware.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/libcomo.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/libcpp.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/libstdcpp3.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/modena.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/msl.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/roguewave.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/sgi.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/stlport.hpp [new file with mode: 0644]
src/external/boost/boost/config/stdlib/vacpp.hpp [new file with mode: 0644]
src/external/boost/boost/config/suffix.hpp [new file with mode: 0644]
src/external/boost/boost/config/user.hpp [new file with mode: 0644]
src/external/boost/boost/config/warning_disable.hpp [new file with mode: 0644]
src/external/boost/boost/current_function.hpp [new file with mode: 0644]
src/external/boost/boost/detail/interlocked.hpp [new file with mode: 0644]
src/external/boost/boost/detail/lightweight_mutex.hpp [new file with mode: 0644]
src/external/boost/boost/detail/sp_typeinfo.hpp [new file with mode: 0644]
src/external/boost/boost/detail/workaround.hpp [new file with mode: 0644]
src/external/boost/boost/exception/all.hpp [new file with mode: 0644]
src/external/boost/boost/exception/current_exception_cast.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/attribute_noreturn.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/error_info_impl.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/exception_ptr.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/is_output_streamable.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/object_hex_dump.hpp [new file with mode: 0644]
src/external/boost/boost/exception/detail/type_info.hpp [new file with mode: 0644]
src/external/boost/boost/exception/diagnostic_information.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_api_function.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_at_line.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_errno.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_file_handle.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_file_name.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_file_open_mode.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_nested_exception.hpp [new file with mode: 0644]
src/external/boost/boost/exception/errinfo_type_info_name.hpp [new file with mode: 0644]
src/external/boost/boost/exception/error_info.hpp [new file with mode: 0644]
src/external/boost/boost/exception/exception.hpp [new file with mode: 0644]
src/external/boost/boost/exception/get_error_info.hpp [new file with mode: 0644]
src/external/boost/boost/exception/info.hpp [new file with mode: 0644]
src/external/boost/boost/exception/to_string.hpp [new file with mode: 0644]
src/external/boost/boost/exception/to_string_stub.hpp [new file with mode: 0644]
src/external/boost/boost/exception_ptr.hpp [new file with mode: 0644]
src/external/boost/boost/memory_order.hpp [new file with mode: 0644]
src/external/boost/boost/non_type.hpp [new file with mode: 0644]
src/external/boost/boost/shared_ptr.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/bad_weak_ptr.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count_gcc.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count_pthreads.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count_sync.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/atomic_count_win32.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/lightweight_mutex.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/lwm_nop.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/lwm_pthreads.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/lwm_win32_cs.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/operator_bool.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/shared_count.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/shared_ptr_nmt.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_convertible.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_nt.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_pt.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_sync.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_base_w32.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_counted_impl.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/sp_has_sync.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_gcc_arm.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_nt.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_pool.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_pt.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_sync.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/spinlock_w32.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/detail/yield_k.hpp [new file with mode: 0644]
src/external/boost/boost/smart_ptr/shared_ptr.hpp [new file with mode: 0644]
src/external/boost/boost/throw_exception.hpp [new file with mode: 0644]
src/external/boost/boost/type.hpp [new file with mode: 0644]
src/external/boost/boost/utility/enable_if.hpp [new file with mode: 0644]
src/external/boost/boost/version.hpp [new file with mode: 0644]
src/external/boost/libs/smart_ptr/src/sp_collector.cpp [new file with mode: 0644]
src/external/boost/libs/smart_ptr/src/sp_debug_hooks.cpp [new file with mode: 0644]
src/external/gmock-1.6.0/CMakeLists.txt [new file with mode: 0644]
src/external/gmock-1.6.0/COPYING [new file with mode: 0644]
src/external/gmock-1.6.0/README [new file with mode: 0644]
src/external/gmock-1.6.0/README.Gromacs [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/COPYING [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-death-test.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-message.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-param-test.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-printers.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-spi.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-test-part.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest-typed-test.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest_pred_impl.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/gtest_prod.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-death-test-internal.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-filepath.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-internal.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-linked_ptr.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util-generated.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-port.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-string.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-tuple.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-type-util.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-all.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-death-test.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-filepath.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-internal-inl.h [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-port.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-printers.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-test-part.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest-typed-test.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest.cc [new file with mode: 0644]
src/external/gmock-1.6.0/gtest/src/gtest_main.cc [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-actions.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-cardinalities.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-generated-actions.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-generated-matchers.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-generated-nice-strict.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-matchers.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-more-actions.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock-spec-builders.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/gmock.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/internal/gmock-generated-internal-utils.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h [new file with mode: 0644]
src/external/gmock-1.6.0/include/gmock/internal/gmock-port.h [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock-all.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock-cardinalities.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock-internal-utils.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock-matchers.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock-spec-builders.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock.cc [new file with mode: 0644]
src/external/gmock-1.6.0/src/gmock_main.cc [new file with mode: 0644]
src/gmxlib/.cvsignore [deleted file]
src/gmxlib/.gitignore [deleted file]
src/gmxlib/CMakeLists.txt [deleted file]
src/gmxlib/libgmx.pc.cmakein [deleted file]
src/gmxlib/mvdata.c [deleted file]
src/gmxlib/names.c [deleted file]
src/gmxlib/network.c [deleted file]
src/gmxlib/selection/.cvsignore [deleted file]
src/gmxlib/selection/compiler.c [deleted file]
src/gmxlib/selection/evaluate.c [deleted file]
src/gmxlib/selection/evaluate.h [deleted file]
src/gmxlib/selection/keywords.h [deleted file]
src/gmxlib/selection/mempool.c [deleted file]
src/gmxlib/selection/mempool.h [deleted file]
src/gmxlib/selection/params.c [deleted file]
src/gmxlib/selection/parser.c [deleted file]
src/gmxlib/selection/parser.h [deleted file]
src/gmxlib/selection/parser.y [deleted file]
src/gmxlib/selection/parsetree.c [deleted file]
src/gmxlib/selection/parsetree.h [deleted file]
src/gmxlib/selection/regenerate_parser.sh [deleted file]
src/gmxlib/selection/scanner.c [deleted file]
src/gmxlib/selection/scanner.h [deleted file]
src/gmxlib/selection/scanner.l [deleted file]
src/gmxlib/selection/scanner_flex.h [deleted file]
src/gmxlib/selection/scanner_internal.c [deleted file]
src/gmxlib/selection/scanner_internal.h [deleted file]
src/gmxlib/selection/selcollection.h [deleted file]
src/gmxlib/selection/selection.c [deleted file]
src/gmxlib/selection/selelem.c [deleted file]
src/gmxlib/selection/selelem.h [deleted file]
src/gmxlib/selection/selhelp.c [deleted file]
src/gmxlib/selection/selhelp.h [deleted file]
src/gmxlib/selection/selmethod.c [deleted file]
src/gmxlib/selection/selvalue.c [deleted file]
src/gmxlib/selection/sm_compare.c [deleted file]
src/gmxlib/selection/sm_distance.c [deleted file]
src/gmxlib/selection/sm_insolidangle.c [deleted file]
src/gmxlib/selection/sm_keywords.c [deleted file]
src/gmxlib/selection/sm_merge.c [deleted file]
src/gmxlib/selection/sm_permute.c [deleted file]
src/gmxlib/selection/sm_position.c [deleted file]
src/gmxlib/selection/sm_same.c [deleted file]
src/gmxlib/selection/sm_simple.c [deleted file]
src/gmxlib/selection/symrec.c [deleted file]
src/gmxlib/selection/symrec.h [deleted file]
src/gmxlib/selection/test_selection.c [deleted file]
src/gmxlib/statistics/gmx_statistics.c [deleted file]
src/gmxlib/string2.c [deleted file]
src/gmxlib/tpxio.c [deleted file]
src/gmxlib/trajana/.cvsignore [deleted file]
src/gmxlib/trajana/centerofmass.c [deleted file]
src/gmxlib/trajana/indexutil.c [deleted file]
src/gmxlib/trajana/nbsearch.c [deleted file]
src/gmxlib/trajana/poscalc.c [deleted file]
src/gmxlib/trajana/position.c [deleted file]
src/gmxlib/trajana/trajana.c [deleted file]
src/gmxlib/txtdump.c [deleted file]
src/gmxlib/version.c.cmakein [deleted file]
src/gromacs/CMakeLists.txt [new file with mode: 0644]
src/gromacs/analysisdata.h [new file with mode: 0644]
src/gromacs/analysisdata/CMakeLists.txt [new file with mode: 0644]
src/gromacs/analysisdata/abstractdata-impl.h [new file with mode: 0644]
src/gromacs/analysisdata/abstractdata.cpp [new file with mode: 0644]
src/gromacs/analysisdata/abstractdata.h [new file with mode: 0644]
src/gromacs/analysisdata/analysisdata-impl.h [new file with mode: 0644]
src/gromacs/analysisdata/analysisdata.cpp [new file with mode: 0644]
src/gromacs/analysisdata/analysisdata.h [new file with mode: 0644]
src/gromacs/analysisdata/arraydata.cpp [new file with mode: 0644]
src/gromacs/analysisdata/arraydata.h [new file with mode: 0644]
src/gromacs/analysisdata/datamodule.h [new file with mode: 0644]
src/gromacs/analysisdata/dataproxy.cpp [new file with mode: 0644]
src/gromacs/analysisdata/dataproxy.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/CMakeLists.txt [new file with mode: 0644]
src/gromacs/analysisdata/modules/average.cpp [new file with mode: 0644]
src/gromacs/analysisdata/modules/average.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/displacement-impl.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/displacement.cpp [new file with mode: 0644]
src/gromacs/analysisdata/modules/displacement.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/histogram.cpp [new file with mode: 0644]
src/gromacs/analysisdata/modules/histogram.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/plot-impl.h [new file with mode: 0644]
src/gromacs/analysisdata/modules/plot.cpp [new file with mode: 0644]
src/gromacs/analysisdata/modules/plot.h [new file with mode: 0644]
src/gromacs/analysisdata/tests/.gitignore [new file with mode: 0644]
src/gromacs/analysisdata/tests/CMakeLists.txt [new file with mode: 0644]
src/gromacs/analysisdata/tests/analysisdata.cpp [new file with mode: 0644]
src/gromacs/analysisdata/tests/mock_module.h [new file with mode: 0644]
src/gromacs/basicmath.h [new file with mode: 0644]
src/gromacs/fatalerror.h [new file with mode: 0644]
src/gromacs/fatalerror/CMakeLists.txt [new file with mode: 0644]
src/gromacs/fatalerror/errorcodes.cpp [new file with mode: 0644]
src/gromacs/fatalerror/errorcodes.h [new file with mode: 0644]
src/gromacs/fatalerror/errorformat.cpp [new file with mode: 0644]
src/gromacs/fatalerror/errorformat.h [new file with mode: 0644]
src/gromacs/fatalerror/exceptions.cpp [new file with mode: 0644]
src/gromacs/fatalerror/exceptions.h [new file with mode: 0644]
src/gromacs/fatalerror/gmxassert.cpp [new file with mode: 0644]
src/gromacs/fatalerror/gmxassert.h [new file with mode: 0644]
src/gromacs/fatalerror/messagestringcollector.cpp [new file with mode: 0644]
src/gromacs/fatalerror/messagestringcollector.h [new file with mode: 0644]
src/gromacs/genversion.sh [moved from src/gmxlib/genversion.sh with 100% similarity]
src/gromacs/gmxlib/3dview.c [moved from src/gmxlib/3dview.c with 100% similarity]
src/gromacs/gmxlib/CMakeLists.txt [new file with mode: 0644]
src/gromacs/gmxlib/atomprop.c [moved from src/gmxlib/atomprop.c with 100% similarity]
src/gromacs/gmxlib/bfunc.h [moved from src/gmxlib/bfunc.h with 100% similarity]
src/gromacs/gmxlib/bondfree.c [moved from src/gmxlib/bondfree.c with 100% similarity]
src/gromacs/gmxlib/calcgrid.c [moved from src/gmxlib/calcgrid.c with 100% similarity]
src/gromacs/gmxlib/calch.c [moved from src/gmxlib/calch.c with 100% similarity]
src/gromacs/gmxlib/chargegroup.c [moved from src/gmxlib/chargegroup.c with 100% similarity]
src/gromacs/gmxlib/checkpoint.c [moved from src/gmxlib/checkpoint.c with 100% similarity]
src/gromacs/gmxlib/cinvsqrtdata.c [moved from src/gmxlib/cinvsqrtdata.c with 100% similarity]
src/gromacs/gmxlib/confio.c [moved from src/gmxlib/confio.c with 100% similarity]
src/gromacs/gmxlib/copyrite.c [moved from src/gmxlib/copyrite.c with 100% similarity]
src/gromacs/gmxlib/crecipdata.c [moved from src/gmxlib/crecipdata.c with 100% similarity]
src/gromacs/gmxlib/debugb.h [moved from src/gmxlib/debugb.h with 100% similarity]
src/gromacs/gmxlib/dihres.c [moved from src/gmxlib/dihres.c with 100% similarity]
src/gromacs/gmxlib/disre.c [moved from src/gmxlib/disre.c with 100% similarity]
src/gromacs/gmxlib/dlb.h [moved from src/gmxlib/dlb.h with 100% similarity]
src/gromacs/gmxlib/do_fit.c [moved from src/gmxlib/do_fit.c with 100% similarity]
src/gromacs/gmxlib/enxio.c [moved from src/gmxlib/enxio.c with 100% similarity]
src/gromacs/gmxlib/ewald_util.c [moved from src/gmxlib/ewald_util.c with 100% similarity]
src/gromacs/gmxlib/ffscanf.c [moved from src/gmxlib/ffscanf.c with 100% similarity]
src/gromacs/gmxlib/filenm.c [moved from src/gmxlib/filenm.c with 100% similarity]
src/gromacs/gmxlib/futil.c [moved from src/gmxlib/futil.c with 100% similarity]
src/gromacs/gmxlib/futil_test.c [moved from src/gmxlib/futil_test.c with 100% similarity]
src/gromacs/gmxlib/gbutil.c [moved from src/gmxlib/gbutil.c with 100% similarity]
src/gromacs/gmxlib/gmx_arpack.c [moved from src/gmxlib/gmx_arpack.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/blas_copyright [moved from src/gmxlib/gmx_blas/blas_copyright with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dasum.c [moved from src/gmxlib/gmx_blas/dasum.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/daxpy.c [moved from src/gmxlib/gmx_blas/daxpy.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dcopy.c [moved from src/gmxlib/gmx_blas/dcopy.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/ddot.c [moved from src/gmxlib/gmx_blas/ddot.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dgemm.c [moved from src/gmxlib/gmx_blas/dgemm.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dgemv.c [moved from src/gmxlib/gmx_blas/dgemv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dger.c [moved from src/gmxlib/gmx_blas/dger.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dnrm2.c [moved from src/gmxlib/gmx_blas/dnrm2.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/drot.c [moved from src/gmxlib/gmx_blas/drot.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dscal.c [moved from src/gmxlib/gmx_blas/dscal.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dswap.c [moved from src/gmxlib/gmx_blas/dswap.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dsymv.c [moved from src/gmxlib/gmx_blas/dsymv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dsyr2.c [moved from src/gmxlib/gmx_blas/dsyr2.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dsyr2k.c [moved from src/gmxlib/gmx_blas/dsyr2k.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dtrmm.c [moved from src/gmxlib/gmx_blas/dtrmm.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dtrmv.c [moved from src/gmxlib/gmx_blas/dtrmv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/dtrsm.c [moved from src/gmxlib/gmx_blas/dtrsm.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/idamax.c [moved from src/gmxlib/gmx_blas/idamax.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/isamax.c [moved from src/gmxlib/gmx_blas/isamax.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sasum.c [moved from src/gmxlib/gmx_blas/sasum.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/saxpy.c [moved from src/gmxlib/gmx_blas/saxpy.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/scopy.c [moved from src/gmxlib/gmx_blas/scopy.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sdot.c [moved from src/gmxlib/gmx_blas/sdot.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sgemm.c [moved from src/gmxlib/gmx_blas/sgemm.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sgemv.c [moved from src/gmxlib/gmx_blas/sgemv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sger.c [moved from src/gmxlib/gmx_blas/sger.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/snrm2.c [moved from src/gmxlib/gmx_blas/snrm2.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/srot.c [moved from src/gmxlib/gmx_blas/srot.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sscal.c [moved from src/gmxlib/gmx_blas/sscal.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/sswap.c [moved from src/gmxlib/gmx_blas/sswap.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/ssymv.c [moved from src/gmxlib/gmx_blas/ssymv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/ssyr2.c [moved from src/gmxlib/gmx_blas/ssyr2.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/ssyr2k.c [moved from src/gmxlib/gmx_blas/ssyr2k.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/strmm.c [moved from src/gmxlib/gmx_blas/strmm.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/strmv.c [moved from src/gmxlib/gmx_blas/strmv.c with 100% similarity]
src/gromacs/gmxlib/gmx_blas/strsm.c [moved from src/gmxlib/gmx_blas/strsm.c with 100% similarity]
src/gromacs/gmxlib/gmx_cyclecounter.c [moved from src/gmxlib/gmx_cyclecounter.c with 100% similarity]
src/gromacs/gmxlib/gmx_fatal.c [moved from src/gmxlib/gmx_fatal.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dbdsdc.c [moved from src/gmxlib/gmx_lapack/dbdsdc.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dbdsqr.c [moved from src/gmxlib/gmx_lapack/dbdsqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgebd2.c [moved from src/gmxlib/gmx_lapack/dgebd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgebrd.c [moved from src/gmxlib/gmx_lapack/dgebrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgelq2.c [moved from src/gmxlib/gmx_lapack/dgelq2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgelqf.c [moved from src/gmxlib/gmx_lapack/dgelqf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgeqr2.c [moved from src/gmxlib/gmx_lapack/dgeqr2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgeqrf.c [moved from src/gmxlib/gmx_lapack/dgeqrf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgesdd.c [moved from src/gmxlib/gmx_lapack/dgesdd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgetf2.c [moved from src/gmxlib/gmx_lapack/dgetf2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgetrf.c [moved from src/gmxlib/gmx_lapack/dgetrf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgetri.c [moved from src/gmxlib/gmx_lapack/dgetri.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dgetrs.c [moved from src/gmxlib/gmx_lapack/dgetrs.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlabrd.c [moved from src/gmxlib/gmx_lapack/dlabrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlacpy.c [moved from src/gmxlib/gmx_lapack/dlacpy.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlae2.c [moved from src/gmxlib/gmx_lapack/dlae2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaebz.c [moved from src/gmxlib/gmx_lapack/dlaebz.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaed6.c [moved from src/gmxlib/gmx_lapack/dlaed6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaev2.c [moved from src/gmxlib/gmx_lapack/dlaev2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlagtf.c [moved from src/gmxlib/gmx_lapack/dlagtf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlagts.c [moved from src/gmxlib/gmx_lapack/dlagts.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlamrg.c [moved from src/gmxlib/gmx_lapack/dlamrg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlange.c [moved from src/gmxlib/gmx_lapack/dlange.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlanst.c [moved from src/gmxlib/gmx_lapack/dlanst.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlansy.c [moved from src/gmxlib/gmx_lapack/dlansy.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlapy2.c [moved from src/gmxlib/gmx_lapack/dlapy2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlar1vx.c [moved from src/gmxlib/gmx_lapack/dlar1vx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarf.c [moved from src/gmxlib/gmx_lapack/dlarf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarfb.c [moved from src/gmxlib/gmx_lapack/dlarfb.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarfg.c [moved from src/gmxlib/gmx_lapack/dlarfg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarft.c [moved from src/gmxlib/gmx_lapack/dlarft.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarnv.c [moved from src/gmxlib/gmx_lapack/dlarnv.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarrbx.c [moved from src/gmxlib/gmx_lapack/dlarrbx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarrex.c [moved from src/gmxlib/gmx_lapack/dlarrex.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarrfx.c [moved from src/gmxlib/gmx_lapack/dlarrfx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlarrvx.c [moved from src/gmxlib/gmx_lapack/dlarrvx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlartg.c [moved from src/gmxlib/gmx_lapack/dlartg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaruv.c [moved from src/gmxlib/gmx_lapack/dlaruv.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlas2.c [moved from src/gmxlib/gmx_lapack/dlas2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlascl.c [moved from src/gmxlib/gmx_lapack/dlascl.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd0.c [moved from src/gmxlib/gmx_lapack/dlasd0.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd1.c [moved from src/gmxlib/gmx_lapack/dlasd1.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd2.c [moved from src/gmxlib/gmx_lapack/dlasd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd3.c [moved from src/gmxlib/gmx_lapack/dlasd3.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd4.c [moved from src/gmxlib/gmx_lapack/dlasd4.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd5.c [moved from src/gmxlib/gmx_lapack/dlasd5.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd6.c [moved from src/gmxlib/gmx_lapack/dlasd6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd7.c [moved from src/gmxlib/gmx_lapack/dlasd7.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasd8.c [moved from src/gmxlib/gmx_lapack/dlasd8.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasda.c [moved from src/gmxlib/gmx_lapack/dlasda.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasdq.c [moved from src/gmxlib/gmx_lapack/dlasdq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasdt.c [moved from src/gmxlib/gmx_lapack/dlasdt.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaset.c [moved from src/gmxlib/gmx_lapack/dlaset.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq1.c [moved from src/gmxlib/gmx_lapack/dlasq1.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq2.c [moved from src/gmxlib/gmx_lapack/dlasq2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq3.c [moved from src/gmxlib/gmx_lapack/dlasq3.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq4.c [moved from src/gmxlib/gmx_lapack/dlasq4.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq5.c [moved from src/gmxlib/gmx_lapack/dlasq5.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasq6.c [moved from src/gmxlib/gmx_lapack/dlasq6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasr.c [moved from src/gmxlib/gmx_lapack/dlasr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasrt.c [moved from src/gmxlib/gmx_lapack/dlasrt.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasrt2.c [moved from src/gmxlib/gmx_lapack/dlasrt2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlassq.c [moved from src/gmxlib/gmx_lapack/dlassq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlasv2.c [moved from src/gmxlib/gmx_lapack/dlasv2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlaswp.c [moved from src/gmxlib/gmx_lapack/dlaswp.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dlatrd.c [moved from src/gmxlib/gmx_lapack/dlatrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorg2r.c [moved from src/gmxlib/gmx_lapack/dorg2r.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorgbr.c [moved from src/gmxlib/gmx_lapack/dorgbr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorgl2.c [moved from src/gmxlib/gmx_lapack/dorgl2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorglq.c [moved from src/gmxlib/gmx_lapack/dorglq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorgqr.c [moved from src/gmxlib/gmx_lapack/dorgqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorm2l.c [moved from src/gmxlib/gmx_lapack/dorm2l.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorm2r.c [moved from src/gmxlib/gmx_lapack/dorm2r.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dormbr.c [moved from src/gmxlib/gmx_lapack/dormbr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dorml2.c [moved from src/gmxlib/gmx_lapack/dorml2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dormlq.c [moved from src/gmxlib/gmx_lapack/dormlq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dormql.c [moved from src/gmxlib/gmx_lapack/dormql.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dormqr.c [moved from src/gmxlib/gmx_lapack/dormqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dormtr.c [moved from src/gmxlib/gmx_lapack/dormtr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dstebz.c [moved from src/gmxlib/gmx_lapack/dstebz.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dstegr.c [moved from src/gmxlib/gmx_lapack/dstegr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dstein.c [moved from src/gmxlib/gmx_lapack/dstein.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dsteqr.c [moved from src/gmxlib/gmx_lapack/dsteqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dsterf.c [moved from src/gmxlib/gmx_lapack/dsterf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dstevr.c [moved from src/gmxlib/gmx_lapack/dstevr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dsyevr.c [moved from src/gmxlib/gmx_lapack/dsyevr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dsytd2.c [moved from src/gmxlib/gmx_lapack/dsytd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dsytrd.c [moved from src/gmxlib/gmx_lapack/dsytrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dtrti2.c [moved from src/gmxlib/gmx_lapack/dtrti2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/dtrtri.c [moved from src/gmxlib/gmx_lapack/dtrtri.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ilasrt2.c [moved from src/gmxlib/gmx_lapack/ilasrt2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/lapack_copyright [moved from src/gmxlib/gmx_lapack/lapack_copyright with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/lapack_limits.h [moved from src/gmxlib/gmx_lapack/lapack_limits.h with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sbdsdc.c [moved from src/gmxlib/gmx_lapack/sbdsdc.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sbdsqr.c [moved from src/gmxlib/gmx_lapack/sbdsqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgebd2.c [moved from src/gmxlib/gmx_lapack/sgebd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgebrd.c [moved from src/gmxlib/gmx_lapack/sgebrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgelq2.c [moved from src/gmxlib/gmx_lapack/sgelq2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgelqf.c [moved from src/gmxlib/gmx_lapack/sgelqf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgeqr2.c [moved from src/gmxlib/gmx_lapack/sgeqr2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgeqrf.c [moved from src/gmxlib/gmx_lapack/sgeqrf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgesdd.c [moved from src/gmxlib/gmx_lapack/sgesdd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgetf2.c [moved from src/gmxlib/gmx_lapack/sgetf2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgetrf.c [moved from src/gmxlib/gmx_lapack/sgetrf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgetri.c [moved from src/gmxlib/gmx_lapack/sgetri.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sgetrs.c [moved from src/gmxlib/gmx_lapack/sgetrs.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slabrd.c [moved from src/gmxlib/gmx_lapack/slabrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slacpy.c [moved from src/gmxlib/gmx_lapack/slacpy.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slae2.c [moved from src/gmxlib/gmx_lapack/slae2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaebz.c [moved from src/gmxlib/gmx_lapack/slaebz.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaed6.c [moved from src/gmxlib/gmx_lapack/slaed6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaev2.c [moved from src/gmxlib/gmx_lapack/slaev2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slagtf.c [moved from src/gmxlib/gmx_lapack/slagtf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slagts.c [moved from src/gmxlib/gmx_lapack/slagts.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slamrg.c [moved from src/gmxlib/gmx_lapack/slamrg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slange.c [moved from src/gmxlib/gmx_lapack/slange.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slanst.c [moved from src/gmxlib/gmx_lapack/slanst.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slansy.c [moved from src/gmxlib/gmx_lapack/slansy.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slapy2.c [moved from src/gmxlib/gmx_lapack/slapy2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slar1vx.c [moved from src/gmxlib/gmx_lapack/slar1vx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarf.c [moved from src/gmxlib/gmx_lapack/slarf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarfb.c [moved from src/gmxlib/gmx_lapack/slarfb.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarfg.c [moved from src/gmxlib/gmx_lapack/slarfg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarft.c [moved from src/gmxlib/gmx_lapack/slarft.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarnv.c [moved from src/gmxlib/gmx_lapack/slarnv.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarrbx.c [moved from src/gmxlib/gmx_lapack/slarrbx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarrex.c [moved from src/gmxlib/gmx_lapack/slarrex.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarrfx.c [moved from src/gmxlib/gmx_lapack/slarrfx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slarrvx.c [moved from src/gmxlib/gmx_lapack/slarrvx.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slartg.c [moved from src/gmxlib/gmx_lapack/slartg.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaruv.c [moved from src/gmxlib/gmx_lapack/slaruv.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slas2.c [moved from src/gmxlib/gmx_lapack/slas2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slascl.c [moved from src/gmxlib/gmx_lapack/slascl.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd0.c [moved from src/gmxlib/gmx_lapack/slasd0.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd1.c [moved from src/gmxlib/gmx_lapack/slasd1.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd2.c [moved from src/gmxlib/gmx_lapack/slasd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd3.c [moved from src/gmxlib/gmx_lapack/slasd3.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd4.c [moved from src/gmxlib/gmx_lapack/slasd4.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd5.c [moved from src/gmxlib/gmx_lapack/slasd5.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd6.c [moved from src/gmxlib/gmx_lapack/slasd6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd7.c [moved from src/gmxlib/gmx_lapack/slasd7.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasd8.c [moved from src/gmxlib/gmx_lapack/slasd8.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasda.c [moved from src/gmxlib/gmx_lapack/slasda.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasdq.c [moved from src/gmxlib/gmx_lapack/slasdq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasdt.c [moved from src/gmxlib/gmx_lapack/slasdt.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaset.c [moved from src/gmxlib/gmx_lapack/slaset.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq1.c [moved from src/gmxlib/gmx_lapack/slasq1.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq2.c [moved from src/gmxlib/gmx_lapack/slasq2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq3.c [moved from src/gmxlib/gmx_lapack/slasq3.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq4.c [moved from src/gmxlib/gmx_lapack/slasq4.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq5.c [moved from src/gmxlib/gmx_lapack/slasq5.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasq6.c [moved from src/gmxlib/gmx_lapack/slasq6.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasr.c [moved from src/gmxlib/gmx_lapack/slasr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasrt.c [moved from src/gmxlib/gmx_lapack/slasrt.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasrt2.c [moved from src/gmxlib/gmx_lapack/slasrt2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slassq.c [moved from src/gmxlib/gmx_lapack/slassq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slasv2.c [moved from src/gmxlib/gmx_lapack/slasv2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slaswp.c [moved from src/gmxlib/gmx_lapack/slaswp.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/slatrd.c [moved from src/gmxlib/gmx_lapack/slatrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorg2r.c [moved from src/gmxlib/gmx_lapack/sorg2r.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorgbr.c [moved from src/gmxlib/gmx_lapack/sorgbr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorgl2.c [moved from src/gmxlib/gmx_lapack/sorgl2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorglq.c [moved from src/gmxlib/gmx_lapack/sorglq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorgqr.c [moved from src/gmxlib/gmx_lapack/sorgqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorm2l.c [moved from src/gmxlib/gmx_lapack/sorm2l.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorm2r.c [moved from src/gmxlib/gmx_lapack/sorm2r.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sormbr.c [moved from src/gmxlib/gmx_lapack/sormbr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sorml2.c [moved from src/gmxlib/gmx_lapack/sorml2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sormlq.c [moved from src/gmxlib/gmx_lapack/sormlq.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sormql.c [moved from src/gmxlib/gmx_lapack/sormql.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sormqr.c [moved from src/gmxlib/gmx_lapack/sormqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sormtr.c [moved from src/gmxlib/gmx_lapack/sormtr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sstebz.c [moved from src/gmxlib/gmx_lapack/sstebz.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sstegr.c [moved from src/gmxlib/gmx_lapack/sstegr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sstein.c [moved from src/gmxlib/gmx_lapack/sstein.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ssteqr.c [moved from src/gmxlib/gmx_lapack/ssteqr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ssterf.c [moved from src/gmxlib/gmx_lapack/ssterf.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/sstevr.c [moved from src/gmxlib/gmx_lapack/sstevr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ssyevr.c [moved from src/gmxlib/gmx_lapack/ssyevr.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ssytd2.c [moved from src/gmxlib/gmx_lapack/ssytd2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/ssytrd.c [moved from src/gmxlib/gmx_lapack/ssytrd.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/strti2.c [moved from src/gmxlib/gmx_lapack/strti2.c with 100% similarity]
src/gromacs/gmxlib/gmx_lapack/strtri.c [moved from src/gmxlib/gmx_lapack/strtri.c with 100% similarity]
src/gromacs/gmxlib/gmx_matrix.c [moved from src/gmxlib/gmx_matrix.c with 100% similarity]
src/gromacs/gmxlib/gmx_random.c [moved from src/gmxlib/gmx_random.c with 100% similarity]
src/gromacs/gmxlib/gmx_random_gausstable.h [moved from src/gmxlib/gmx_random_gausstable.h with 100% similarity]
src/gromacs/gmxlib/gmx_sort.c [moved from src/gmxlib/gmx_sort.c with 100% similarity]
src/gromacs/gmxlib/gmx_system_xdr.c [moved from src/gmxlib/gmx_system_xdr.c with 100% similarity]
src/gromacs/gmxlib/gmxcpp.c [moved from src/gmxlib/gmxcpp.c with 100% similarity]
src/gromacs/gmxlib/gmxfio.c [moved from src/gmxlib/gmxfio.c with 100% similarity]
src/gromacs/gmxlib/gmxfio_asc.c [moved from src/gmxlib/gmxfio_asc.c with 100% similarity]
src/gromacs/gmxlib/gmxfio_bin.c [moved from src/gmxlib/gmxfio_bin.c with 100% similarity]
src/gromacs/gmxlib/gmxfio_int.h [moved from src/gmxlib/gmxfio_int.h with 100% similarity]
src/gromacs/gmxlib/gmxfio_rw.c [moved from src/gmxlib/gmxfio_rw.c with 100% similarity]
src/gromacs/gmxlib/gmxfio_xdr.c [moved from src/gmxlib/gmxfio_xdr.c with 100% similarity]
src/gromacs/gmxlib/ifunc.c [moved from src/gmxlib/ifunc.c with 100% similarity]
src/gromacs/gmxlib/index.c [moved from src/gmxlib/index.c with 100% similarity]
src/gromacs/gmxlib/inputrec.c [moved from src/gmxlib/inputrec.c with 100% similarity]
src/gromacs/gmxlib/invblock.c [moved from src/gmxlib/invblock.c with 100% similarity]
src/gromacs/gmxlib/invsqrt_test.c [moved from src/gmxlib/invsqrt_test.c with 100% similarity]
src/gromacs/gmxlib/libxdrf.c [moved from src/gmxlib/libxdrf.c with 100% similarity]
src/gromacs/gmxlib/macros.c [moved from src/gmxlib/macros.c with 100% similarity]
src/gromacs/gmxlib/main.c [moved from src/gmxlib/main.c with 100% similarity]
src/gromacs/gmxlib/maths.c [moved from src/gmxlib/maths.c with 100% similarity]
src/gromacs/gmxlib/matio.c [moved from src/gmxlib/matio.c with 100% similarity]
src/gromacs/gmxlib/md5.c [moved from src/gmxlib/md5.c with 100% similarity]
src/gromacs/gmxlib/minvert.h [moved from src/gmxlib/minvert.h with 100% similarity]
src/gromacs/gmxlib/mshift.c [moved from src/gmxlib/mshift.c with 100% similarity]
src/gromacs/gmxlib/mtop_util.c [moved from src/gmxlib/mtop_util.c with 100% similarity]
src/gromacs/gmxlib/mtxio.c [moved from src/gmxlib/mtxio.c with 100% similarity]
src/gromacs/gmxlib/mvdata.c [new file with mode: 0644]
src/gromacs/gmxlib/names.c [new file with mode: 0644]
src/gromacs/gmxlib/network.c [new file with mode: 0644]
src/gromacs/gmxlib/nonbonded/nb_free_energy.c [moved from src/gmxlib/nonbonded/nb_free_energy.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_free_energy.h [moved from src/gmxlib/nonbonded/nb_free_energy.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_generic.c [moved from src/gmxlib/nonbonded/nb_generic.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_generic.h [moved from src/gmxlib/nonbonded/nb_generic.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_generic_cg.c [moved from src/gmxlib/nonbonded/nb_generic_cg.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_generic_cg.h [moved from src/gmxlib/nonbonded/nb_generic_cg.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/interaction.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/interaction.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel010_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel010_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel010_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel010_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel020_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel020_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel020_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel020_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel030_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel030_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel030_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel030_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel100_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel100_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel100_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel100_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel101_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel101_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel101_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel101_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel102_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel102_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel102_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel102_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel103_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel103_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel103_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel103_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel104_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel104_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel104_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel104_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel110_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel110_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel110_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel110_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel111_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel111_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel111_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel111_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel112_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel112_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel112_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel112_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel113_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel113_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel113_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel113_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel114_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel114_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel114_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel114_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel120_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel120_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel120_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel120_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel121_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel121_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel121_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel121_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel122_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel122_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel122_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel122_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel123_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel123_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel123_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel123_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel124_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel124_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel124_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel124_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel130_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel130_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel130_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel130_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel131_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel131_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel131_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel131_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel132_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel132_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel132_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel132_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel133_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel133_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel133_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel133_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel134_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel134_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel134_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel134_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel200_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel200_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel200_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel200_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel201_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel201_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel201_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel201_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel202_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel202_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel202_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel202_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel203_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel203_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel203_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel203_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel204_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel204_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel204_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel204_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel210_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel210_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel210_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel210_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel211_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel211_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel211_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel211_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel212_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel212_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel212_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel212_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel213_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel213_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel213_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel213_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel214_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel214_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel214_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel214_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel220_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel220_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel220_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel220_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel221_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel221_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel221_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel221_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel222_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel222_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel222_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel222_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel223_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel223_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel223_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel223_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel224_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel224_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel224_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel224_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel230_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel230_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel230_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel230_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel231_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel231_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel231_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel231_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel232_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel232_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel232_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel232_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel233_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel233_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel233_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel233_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel234_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel234_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel234_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel234_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel300_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel300_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel300_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel300_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel301_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel301_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel301_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel301_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel302_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel302_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel302_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel302_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel303_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel303_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel303_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel303_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel304_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel304_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel304_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel304_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel310_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel310_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel310_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel310_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel311_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel311_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel311_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel311_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel312_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel312_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel312_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel312_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel313_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel313_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel313_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel313_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel314_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel314_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel314_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel314_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel320_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel320_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel320_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel320_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel321_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel321_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel321_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel321_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel322_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel322_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel322_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel322_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel323_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel323_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel323_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel323_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel324_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel324_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel324_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel324_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel330_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel330_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel330_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel330_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel331_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel331_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel331_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel331_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel332_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel332_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel332_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel332_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel333_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel333_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel333_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel333_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel334_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel334_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel334_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel334_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel400_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel400_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel400_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel400_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel410_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel410_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel410_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel410_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel420_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel420_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel420_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel420_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel430_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel430_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel430_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel430_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_bluegene.c [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_bluegene.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_gen_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_gen_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w3_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w3_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w3w3_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w3w3_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w4_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w4_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w4w4_bluegene.h [moved from src/gmxlib/nonbonded/nb_kernel_bluegene/nb_kernel_w4w4_bluegene.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel010.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel010.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel010.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel010.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel020.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel020.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel020.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel020.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel030.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel030.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel030.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel030.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel100.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel100.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel100.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel100.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel101.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel101.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel101.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel101.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel102.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel102.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel102.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel102.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel103.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel103.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel103.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel103.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel104.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel104.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel104.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel104.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel110.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel110.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel110.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel110.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel111.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel111.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel111.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel111.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel112.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel112.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel112.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel112.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel113.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel113.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel113.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel113.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel114.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel114.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel114.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel114.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel120.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel120.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel120.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel120.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel121.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel121.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel121.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel121.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel122.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel122.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel122.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel122.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel123.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel123.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel123.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel123.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel124.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel124.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel124.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel124.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel130.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel130.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel130.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel130.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel131.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel131.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel131.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel131.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel132.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel132.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel132.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel132.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel133.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel133.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel133.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel133.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel134.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel134.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel134.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel134.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel200.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel200.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel200.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel200.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel201.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel201.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel201.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel201.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel202.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel202.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel202.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel202.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel203.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel203.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel203.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel203.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel204.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel204.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel204.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel204.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel210.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel210.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel210.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel210.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel211.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel211.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel211.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel211.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel212.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel212.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel212.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel212.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel213.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel213.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel213.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel213.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel214.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel214.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel214.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel214.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel220.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel220.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel220.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel220.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel221.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel221.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel221.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel221.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel222.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel222.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel222.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel222.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel223.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel223.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel223.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel223.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel224.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel224.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel224.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel224.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel230.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel230.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel230.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel230.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel231.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel231.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel231.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel231.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel232.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel232.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel232.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel232.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel233.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel233.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel233.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel233.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel234.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel234.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel234.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel234.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel300.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel300.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel300.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel300.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel301.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel301.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel301.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel301.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel302.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel302.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel302.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel302.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel303.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel303.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel303.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel303.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel304.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel304.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel304.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel304.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel310.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel310.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel310.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel310.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel311.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel311.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel311.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel311.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel312.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel312.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel312.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel312.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel313.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel313.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel313.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel313.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel314.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel314.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel314.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel314.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel320.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel320.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel320.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel320.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel321.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel321.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel321.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel321.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel322.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel322.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel322.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel322.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel323.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel323.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel323.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel323.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel324.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel324.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel324.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel324.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel330.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel330.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel330.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel330.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel331.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel331.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel331.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel331.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel332.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel332.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel332.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel332.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel333.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel333.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel333.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel333.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel334.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel334.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel334.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel334.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel400.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel400.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel400.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel400.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel410.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel410.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel410.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel410.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel420.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel420.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel420.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel420.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel430.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel430.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel430.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel430.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsall.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsall.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsall.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsall.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsallgb.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsallgb.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsallgb.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_allvsallgb.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_c.c [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_c.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_c/nb_kernel_c.h [moved from src/gmxlib/nonbonded/nb_kernel_c/nb_kernel_c.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel010.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel010.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel020.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel020.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel030.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel030.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel100.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel100.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel101.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel101.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel102.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel102.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel103.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel103.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel104.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel104.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel110.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel110.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel111.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel111.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel112.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel112.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel113.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel113.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel114.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel114.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel120.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel120.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel121.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel121.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel122.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel122.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel123.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel123.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel124.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel124.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel130.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel130.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel131.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel131.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel132.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel132.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel133.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel133.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel134.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel134.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel200.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel200.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel201.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel201.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel202.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel202.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel203.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel203.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel204.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel204.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel210.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel210.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel211.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel211.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel212.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel212.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel213.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel213.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel214.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel214.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel220.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel220.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel221.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel221.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel222.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel222.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel223.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel223.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel224.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel224.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel230.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel230.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel231.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel231.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel232.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel232.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel233.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel233.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel234.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel234.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel300.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel300.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel301.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel301.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel302.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel302.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel303.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel303.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel304.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel304.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel310.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel310.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel311.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel311.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel312.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel312.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel313.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel313.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel314.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel314.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel320.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel320.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel321.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel321.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel322.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel322.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel323.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel323.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel324.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel324.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel330.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel330.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel331.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel331.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel332.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel332.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel333.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel333.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel334.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel334.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel400.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel400.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel410.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel410.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel420.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel420.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel430.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/f77dkernel430.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel010_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel010_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel010_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel010_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel020_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel020_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel020_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel020_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel030_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel030_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel030_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel030_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel100_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel100_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel100_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel100_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel101_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel101_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel101_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel101_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel102_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel102_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel102_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel102_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel103_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel103_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel103_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel103_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel104_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel104_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel104_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel104_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel110_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel110_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel110_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel110_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel111_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel111_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel111_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel111_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel112_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel112_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel112_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel112_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel113_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel113_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel113_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel113_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel114_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel114_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel114_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel114_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel120_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel120_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel120_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel120_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel121_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel121_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel121_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel121_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel122_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel122_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel122_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel122_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel123_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel123_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel123_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel123_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel124_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel124_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel124_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel124_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel130_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel130_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel130_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel130_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel131_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel131_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel131_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel131_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel132_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel132_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel132_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel132_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel133_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel133_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel133_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel133_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel134_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel134_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel134_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel134_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel200_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel200_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel200_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel200_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel201_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel201_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel201_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel201_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel202_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel202_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel202_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel202_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel203_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel203_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel203_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel203_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel204_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel204_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel204_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel204_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel210_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel210_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel210_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel210_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel211_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel211_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel211_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel211_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel212_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel212_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel212_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel212_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel213_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel213_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel213_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel213_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel214_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel214_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel214_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel214_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel220_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel220_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel220_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel220_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel221_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel221_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel221_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel221_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel222_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel222_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel222_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel222_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel223_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel223_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel223_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel223_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel224_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel224_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel224_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel224_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel230_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel230_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel230_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel230_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel231_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel231_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel231_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel231_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel232_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel232_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel232_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel232_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel233_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel233_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel233_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel233_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel234_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel234_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel234_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel234_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel300_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel300_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel300_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel300_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel301_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel301_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel301_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel301_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel302_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel302_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel302_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel302_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel303_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel303_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel303_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel303_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel304_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel304_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel304_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel304_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel310_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel310_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel310_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel310_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel311_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel311_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel311_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel311_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel312_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel312_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel312_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel312_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel313_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel313_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel313_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel313_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel314_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel314_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel314_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel314_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel320_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel320_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel320_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel320_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel321_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel321_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel321_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel321_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel322_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel322_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel322_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel322_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel323_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel323_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel323_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel323_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel324_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel324_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel324_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel324_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel330_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel330_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel330_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel330_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel331_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel331_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel331_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel331_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel332_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel332_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel332_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel332_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel333_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel333_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel333_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel333_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel334_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel334_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel334_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel334_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel400_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel400_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel400_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel400_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel410_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel410_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel410_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel410_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel420_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel420_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel420_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel420_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel430_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel430_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel430_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel430_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77_double.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77_double.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77sync.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_double/nb_kernel_f77sync.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel010.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel010.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel020.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel020.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel030.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel030.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel100.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel100.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel101.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel101.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel102.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel102.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel103.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel103.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel104.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel104.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel110.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel110.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel111.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel111.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel112.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel112.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel113.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel113.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel114.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel114.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel120.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel120.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel121.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel121.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel122.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel122.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel123.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel123.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel124.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel124.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel130.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel130.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel131.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel131.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel132.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel132.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel133.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel133.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel134.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel134.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel200.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel200.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel201.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel201.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel202.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel202.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel203.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel203.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel204.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel204.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel210.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel210.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel211.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel211.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel212.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel212.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel213.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel213.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel214.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel214.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel220.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel220.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel221.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel221.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel222.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel222.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel223.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel223.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel224.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel224.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel230.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel230.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel231.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel231.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel232.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel232.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel233.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel233.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel234.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel234.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel300.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel300.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel301.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel301.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel302.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel302.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel303.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel303.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel304.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel304.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel310.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel310.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel311.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel311.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel312.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel312.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel313.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel313.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel314.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel314.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel320.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel320.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel321.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel321.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel322.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel322.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel323.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel323.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel324.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel324.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel330.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel330.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel331.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel331.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel332.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel332.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel333.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel333.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel334.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel334.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel400.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel400.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel410.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel410.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel420.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel420.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel430.f [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/f77skernel430.f with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel010_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel010_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel010_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel010_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel020_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel020_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel020_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel020_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel030_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel030_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel030_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel030_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel100_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel100_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel100_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel100_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel101_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel101_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel101_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel101_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel102_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel102_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel102_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel102_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel103_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel103_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel103_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel103_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel104_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel104_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel104_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel104_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel110_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel110_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel110_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel110_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel111_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel111_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel111_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel111_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel112_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel112_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel112_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel112_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel113_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel113_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel113_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel113_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel114_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel114_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel114_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel114_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel120_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel120_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel120_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel120_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel121_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel121_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel121_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel121_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel122_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel122_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel122_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel122_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel123_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel123_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel123_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel123_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel124_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel124_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel124_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel124_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel130_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel130_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel130_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel130_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel131_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel131_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel131_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel131_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel132_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel132_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel132_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel132_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel133_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel133_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel133_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel133_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel134_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel134_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel134_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel134_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel200_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel200_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel200_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel200_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel201_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel201_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel201_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel201_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel202_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel202_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel202_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel202_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel203_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel203_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel203_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel203_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel204_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel204_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel204_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel204_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel210_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel210_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel210_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel210_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel211_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel211_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel211_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel211_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel212_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel212_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel212_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel212_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel213_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel213_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel213_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel213_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel214_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel214_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel214_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel214_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel220_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel220_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel220_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel220_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel221_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel221_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel221_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel221_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel222_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel222_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel222_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel222_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel223_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel223_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel223_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel223_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel224_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel224_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel224_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel224_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel230_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel230_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel230_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel230_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel231_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel231_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel231_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel231_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel232_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel232_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel232_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel232_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel233_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel233_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel233_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel233_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel234_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel234_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel234_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel234_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel300_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel300_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel300_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel300_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel301_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel301_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel301_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel301_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel302_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel302_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel302_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel302_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel303_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel303_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel303_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel303_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel304_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel304_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel304_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel304_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel310_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel310_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel310_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel310_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel311_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel311_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel311_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel311_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel312_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel312_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel312_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel312_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel313_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel313_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel313_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel313_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel314_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel314_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel314_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel314_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel320_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel320_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel320_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel320_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel321_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel321_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel321_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel321_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel322_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel322_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel322_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel322_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel323_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel323_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel323_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel323_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel324_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel324_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel324_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel324_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel330_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel330_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel330_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel330_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel331_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel331_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel331_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel331_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel332_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel332_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel332_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel332_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel333_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel333_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel333_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel333_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel334_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel334_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel334_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel334_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel400_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel400_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel400_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel400_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel410_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel410_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel410_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel410_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel420_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel420_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel420_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel420_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel430_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel430_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel430_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel430_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77_single.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77_single.h [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77sync.c [moved from src/gmxlib/nonbonded/nb_kernel_f77_single/nb_kernel_f77sync.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/README [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel010_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel030_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel100_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel101_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel102_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel103_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel104_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel110_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel111_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel112_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel113_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel114_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel130_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel131_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel132_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel133_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel134_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel200_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel201_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel202_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel203_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel204_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel210_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel211_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel212_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel213_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel214_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel230_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel231_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel232_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel233_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel234_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel300_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel301_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel302_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel303_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel304_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel310_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel311_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel312_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel313_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel314_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel330_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel331_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel332_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel333_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel334_ia32_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel400_ia32_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel400_ia32_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel400_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel400_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel410_ia32_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel410_ia32_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel410_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel410_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel430_ia32_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel430_ia32_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel430_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel430_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsall_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsall_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsall_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsall_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsallgb_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsallgb_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsallgb_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_allvsallgb_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel_ia32_sse_test_asm_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/README [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel010_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel030_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel100_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel101_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel102_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel103_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel104_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel110_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel111_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel112_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel113_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel114_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel130_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel131_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel132_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel133_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel134_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel200_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel201_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel202_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel203_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel204_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel210_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel211_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel212_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel213_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel214_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel230_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel231_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel232_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel233_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel234_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel300_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel301_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel302_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel303_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel304_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel310_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel311_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel312_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel313_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel314_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel330_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel331_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel332_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel333_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel334_ia32_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel400_ia32_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel400_ia32_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel400_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel400_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel410_ia32_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel410_ia32_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel410_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel410_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel430_ia32_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel430_ia32_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel430_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel430_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsall_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsall_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsall_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsall_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsallgb_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsallgb_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsallgb_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_allvsallgb_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm.h [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel_ia32_sse2_test_asm_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/README [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/ia64_cpuid.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/ia64_cpuid.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/ia64_cpuid.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/ia64_cpuid.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel010nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel030nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel100nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel110nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel130nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel200nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel210nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel230nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel300nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel310nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel330nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel400nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel410nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430nf_ia64_double.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430nf_ia64_double.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430nf_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel430nf_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_double.c [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_double.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_double/nb_kernel_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/README [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/ia64_cpuid.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/ia64_cpuid.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/ia64_cpuid.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/ia64_cpuid.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel010nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel030nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel100nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel110nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel130nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel200nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel210nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel230nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel300nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel310nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel330nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel400nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel410nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430nf_ia64_single.S [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430nf_ia64_single.S with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430nf_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel430nf_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel_ia64_single.c [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel_ia64_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel_ia64_single.h [moved from src/gmxlib/nonbonded/nb_kernel_ia64_single/nb_kernel_ia64_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel010_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel010_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel010_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel010_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel020_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel020_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel020_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel020_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel030_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel030_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel030_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel030_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel100_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel100_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel100_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel100_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel101_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel101_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel101_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel101_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel102_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel102_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel102_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel102_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel103_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel103_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel103_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel103_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel104_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel104_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel104_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel104_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel110_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel110_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel110_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel110_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel111_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel111_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel111_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel111_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel112_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel112_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel112_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel112_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel113_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel113_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel113_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel113_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel114_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel114_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel114_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel114_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel120_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel120_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel120_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel120_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel121_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel121_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel121_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel121_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel122_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel122_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel122_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel122_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel123_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel123_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel123_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel123_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel124_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel124_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel124_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel124_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel130_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel130_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel130_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel130_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel131_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel131_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel131_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel131_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel132_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel132_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel132_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel132_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel133_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel133_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel133_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel133_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel134_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel134_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel134_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel134_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel200_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel200_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel200_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel200_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel201_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel201_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel201_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel201_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel202_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel202_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel202_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel202_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel203_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel203_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel203_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel203_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel204_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel204_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel204_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel204_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel210_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel210_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel210_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel210_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel211_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel211_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel211_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel211_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel212_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel212_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel212_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel212_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel213_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel213_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel213_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel213_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel214_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel214_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel214_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel214_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel220_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel220_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel220_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel220_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel221_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel221_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel221_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel221_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel222_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel222_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel222_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel222_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel223_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel223_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel223_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel223_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel224_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel224_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel224_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel224_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel230_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel230_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel230_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel230_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel231_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel231_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel231_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel231_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel232_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel232_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel232_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel232_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel233_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel233_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel233_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel233_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel234_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel234_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel234_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel234_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel300_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel300_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel300_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel300_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel301_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel301_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel301_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel301_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel302_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel302_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel302_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel302_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel303_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel303_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel303_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel303_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel304_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel304_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel304_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel304_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel310_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel310_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel310_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel310_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel311_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel311_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel311_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel311_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel312_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel312_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel312_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel312_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel313_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel313_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel313_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel313_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel314_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel314_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel314_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel314_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel320_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel320_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel320_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel320_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel321_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel321_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel321_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel321_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel322_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel322_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel322_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel322_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel323_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel323_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel323_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel323_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel324_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel324_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel324_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel324_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel330_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel330_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel330_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel330_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel331_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel331_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel331_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel331_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel332_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel332_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel332_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel332_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel333_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel333_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel333_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel333_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel334_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel334_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel334_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel334_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel400_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel400_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel400_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel400_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel410_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel410_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel410_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel410_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel420_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel420_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel420_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel420_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel430_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel430_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel430_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel430_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_power6.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_power6.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_power6.h [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_power6.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_pwr6sync.c [moved from src/gmxlib/nonbonded/nb_kernel_power6/nb_kernel_pwr6sync.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel010.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel010.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel020.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel020.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel030.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel030.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel100.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel100.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel101.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel101.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel102.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel102.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel103.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel103.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel104.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel104.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel110.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel110.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel111.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel111.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel112.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel112.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel113.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel113.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel114.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel114.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel120.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel120.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel121.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel121.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel122.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel122.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel123.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel123.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel124.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel124.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel130.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel130.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel131.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel131.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel132.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel132.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel133.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel133.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel134.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel134.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel200.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel200.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel201.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel201.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel202.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel202.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel203.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel203.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel204.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel204.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel210.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel210.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel211.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel211.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel212.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel212.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel213.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel213.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel214.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel214.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel220.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel220.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel221.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel221.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel222.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel222.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel223.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel223.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel224.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel224.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel230.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel230.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel231.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel231.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel232.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel232.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel233.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel233.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel234.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel234.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel300.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel300.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel301.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel301.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel302.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel302.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel303.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel303.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel304.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel304.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel310.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel310.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel311.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel311.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel312.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel312.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel313.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel313.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel314.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel314.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel320.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel320.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel321.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel321.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel322.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel322.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel323.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel323.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel324.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel324.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel330.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel330.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel331.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel331.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel332.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel332.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel333.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel333.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel334.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel334.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel400.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel400.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel410.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel410.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel420.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel420.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel430.F [moved from src/gmxlib/nonbonded/nb_kernel_power6/pwr6kernel430.F with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/README [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel010_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel010_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel010_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel010_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel030_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel030_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel030_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel030_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel100_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel100_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel100_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel100_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel101_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel101_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel101_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel101_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel102_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel102_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel102_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel102_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel103_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel103_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel103_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel103_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel104_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel104_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel104_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel104_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel110_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel110_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel110_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel110_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel111_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel111_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel111_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel111_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel112_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel112_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel112_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel112_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel113_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel113_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel113_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel113_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel114_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel114_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel114_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel114_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel130_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel130_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel130_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel130_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel131_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel131_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel131_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel131_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel132_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel132_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel132_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel132_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel133_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel133_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel133_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel133_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel134_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel134_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel134_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel134_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel200_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel200_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel200_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel200_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel201_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel201_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel201_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel201_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel202_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel202_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel202_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel202_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel203_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel203_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel203_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel203_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel204_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel204_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel204_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel204_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel210_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel210_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel210_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel210_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel211_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel211_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel211_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel211_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel212_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel212_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel212_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel212_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel213_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel213_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel213_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel213_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel214_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel214_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel214_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel214_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel230_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel230_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel230_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel230_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel231_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel231_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel231_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel231_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel232_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel232_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel232_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel232_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel233_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel233_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel233_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel233_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel234_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel234_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel234_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel234_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel300_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel300_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel300_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel300_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel301_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel301_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel301_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel301_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel302_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel302_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel302_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel302_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel303_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel303_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel303_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel303_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel304_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel304_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel304_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel304_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel310_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel310_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel310_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel310_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel311_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel311_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel311_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel311_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel312_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel312_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel312_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel312_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel313_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel313_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel313_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel313_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel314_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel314_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel314_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel314_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel330_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel330_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel330_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel330_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel331_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel331_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel331_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel331_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel332_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel332_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel332_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel332_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel333_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel333_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel333_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel333_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel334_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel334_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel334_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel334_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel400_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel400_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel400_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel400_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel410_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel410_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel410_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel410_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel430_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel430_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel430_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel430_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec_test.c [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec_test.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec_test.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/nb_kernel_ppc_altivec_test.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_ppc_altivec/ppc_altivec_util.h [moved from src/gmxlib/nonbonded/nb_kernel_ppc_altivec/ppc_altivec_util.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel400_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel400_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel400_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel400_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel410_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel410_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel410_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel410_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel430_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel430_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel430_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel430_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_double/nb_kernel_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel110_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel110_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel332_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel332_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel332_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel332_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel400_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel400_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel400_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel400_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel410_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel410_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel410_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel410_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel430_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel430_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel430_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel430_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsall_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsall_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsall_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsall_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsallgb_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsallgb_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsallgb_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_allvsallgb_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_sse2_single/sse_common_single.h [moved from src/gmxlib/nonbonded/nb_kernel_sse2_single/sse_common_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/README [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel010_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel030_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel100_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel101_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel102_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel103_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel104_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel110_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel111_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel112_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel113_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel114_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel130_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel131_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel132_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel133_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel134_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel200_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel201_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel202_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel203_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel204_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel210_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel211_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel212_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel213_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel214_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel230_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel231_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel232_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel233_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel234_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel300_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel301_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel302_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel303_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel304_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel310_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel311_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel312_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel313_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel314_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel330_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel331_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel332_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel333_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel334_x86_64_sse_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel400_x86_64_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel400_x86_64_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel400_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel400_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel410_x86_64_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel410_x86_64_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel410_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel410_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel430_x86_64_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel430_x86_64_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel430_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel430_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsall_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsall_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsall_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsall_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsallgb_sse2_single.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsallgb_sse2_single.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsallgb_sse2_single.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_allvsallgb_sse2_single.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel_x86_64_sse_test_asm_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/README [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/README with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel010_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel030_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel100_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel101_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel102_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel103_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel104_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel110_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel111_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel112_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel113_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel114_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel130_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel131_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel132_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel133_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel134_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel200_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel201_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel202_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel203_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel204_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel210_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel211_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel212_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel213_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel214_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel230_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel231_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel232_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel233_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel234_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel300_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel301_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel302_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel303_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel304_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel310_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel311_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel312_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel313_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel314_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel330_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel331_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel332_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel333_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel334_x86_64_sse2_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel400_x86_64_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel400_x86_64_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel400_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel400_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel410_x86_64_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel410_x86_64_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel410_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel410_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel430_x86_64_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel430_x86_64_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel430_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel430_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsall_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsall_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsall_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsall_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsallgb_sse2_double.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsallgb_sse2_double.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsallgb_sse2_double.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_allvsallgb_sse2_double.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2.c [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2.c with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_asm.h [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_asm.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_asm.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_asm.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_intel_syntax.s [moved from src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel_x86_64_sse2_test_intel_syntax.s with 100% similarity]
src/gromacs/gmxlib/nonbonded/nb_kerneltype.h [moved from src/gmxlib/nonbonded/nb_kerneltype.h with 100% similarity]
src/gromacs/gmxlib/nonbonded/nonbonded.c [moved from src/gmxlib/nonbonded/nonbonded.c with 100% similarity]
src/gromacs/gmxlib/nrama.c [moved from src/gmxlib/nrama.c with 100% similarity]
src/gromacs/gmxlib/nrjac.c [moved from src/gmxlib/nrjac.c with 100% similarity]
src/gromacs/gmxlib/nrnb.c [moved from src/gmxlib/nrnb.c with 100% similarity]
src/gromacs/gmxlib/oenv.c [moved from src/gmxlib/oenv.c with 100% similarity]
src/gromacs/gmxlib/orires.c [moved from src/gmxlib/orires.c with 100% similarity]
src/gromacs/gmxlib/pargs.c [moved from src/gmxlib/pargs.c with 100% similarity]
src/gromacs/gmxlib/pbc.c [moved from src/gmxlib/pbc.c with 100% similarity]
src/gromacs/gmxlib/pdbio.c [moved from src/gmxlib/pdbio.c with 100% similarity]
src/gromacs/gmxlib/physics.c [new file with mode: 0644]
src/gromacs/gmxlib/physics_test.c [new file with mode: 0644]
src/gromacs/gmxlib/princ.c [moved from src/gmxlib/princ.c with 100% similarity]
src/gromacs/gmxlib/rando.c [moved from src/gmxlib/rando.c with 100% similarity]
src/gromacs/gmxlib/random.c [moved from src/gmxlib/random.c with 100% similarity]
src/gromacs/gmxlib/rbin.c [moved from src/gmxlib/rbin.c with 100% similarity]
src/gromacs/gmxlib/readinp.c [moved from src/gmxlib/readinp.c with 100% similarity]
src/gromacs/gmxlib/replace.c [moved from src/gmxlib/replace.c with 100% similarity]
src/gromacs/gmxlib/replace.h [moved from src/gmxlib/replace.h with 100% similarity]
src/gromacs/gmxlib/rmpbc.c [moved from src/gmxlib/rmpbc.c with 100% similarity]
src/gromacs/gmxlib/sfactor.c [moved from src/gmxlib/sfactor.c with 100% similarity]
src/gromacs/gmxlib/shift_util.c [moved from src/gmxlib/shift_util.c with 100% similarity]
src/gromacs/gmxlib/sighandler.c [moved from src/gmxlib/sighandler.c with 100% similarity]
src/gromacs/gmxlib/smalloc.c [moved from src/gmxlib/smalloc.c with 100% similarity]
src/gromacs/gmxlib/sortwater.c [moved from src/gmxlib/sortwater.c with 100% similarity]
src/gromacs/gmxlib/sparsematrix.c [moved from src/gmxlib/sparsematrix.c with 100% similarity]
src/gromacs/gmxlib/splitter.c [moved from src/gmxlib/splitter.c with 100% similarity]
src/gromacs/gmxlib/statistics/gmx_statistics.c [new file with mode: 0644]
src/gromacs/gmxlib/statistics/gmx_statistics_test.c [moved from src/gmxlib/statistics/gmx_statistics_test.c with 100% similarity]
src/gromacs/gmxlib/statistics/histogram.c [moved from src/gmxlib/statistics/histogram.c with 100% similarity]
src/gromacs/gmxlib/statutil.c [moved from src/gmxlib/statutil.c with 100% similarity]
src/gromacs/gmxlib/strdb.c [moved from src/gmxlib/strdb.c with 100% similarity]
src/gromacs/gmxlib/string2.c [new file with mode: 0644]
src/gromacs/gmxlib/symtab.c [moved from src/gmxlib/symtab.c with 100% similarity]
src/gromacs/gmxlib/tcontrol.c [moved from src/gmxlib/tcontrol.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/CMakeLists.txt [moved from src/gmxlib/thread_mpi/CMakeLists.txt with 100% similarity]
src/gromacs/gmxlib/thread_mpi/alltoall.c [moved from src/gmxlib/thread_mpi/alltoall.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/barrier.c [moved from src/gmxlib/thread_mpi/barrier.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/bcast.c [moved from src/gmxlib/thread_mpi/bcast.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/collective.c [moved from src/gmxlib/thread_mpi/collective.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/collective.h [moved from src/gmxlib/thread_mpi/collective.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/comm.c [moved from src/gmxlib/thread_mpi/comm.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/errhandler.c [moved from src/gmxlib/thread_mpi/errhandler.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/event.c [moved from src/gmxlib/thread_mpi/event.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/gather.c [moved from src/gmxlib/thread_mpi/gather.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/group.c [moved from src/gmxlib/thread_mpi/group.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/impl.h [moved from src/gmxlib/thread_mpi/impl.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/list.c [moved from src/gmxlib/thread_mpi/list.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/lock.c [moved from src/gmxlib/thread_mpi/lock.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/numa_malloc.c [moved from src/gmxlib/thread_mpi/numa_malloc.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/once.c [moved from src/gmxlib/thread_mpi/once.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/p2p.h [moved from src/gmxlib/thread_mpi/p2p.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/p2p_buffer.c [moved from src/gmxlib/thread_mpi/p2p_buffer.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/p2p_protocol.c [moved from src/gmxlib/thread_mpi/p2p_protocol.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/p2p_send_recv.c [moved from src/gmxlib/thread_mpi/p2p_send_recv.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/p2p_wait.c [moved from src/gmxlib/thread_mpi/p2p_wait.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/profile.c [moved from src/gmxlib/thread_mpi/profile.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/profile.h [moved from src/gmxlib/thread_mpi/profile.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/pthreads.c [moved from src/gmxlib/thread_mpi/pthreads.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/pthreads.h [moved from src/gmxlib/thread_mpi/pthreads.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/reduce.c [moved from src/gmxlib/thread_mpi/reduce.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/reduce_fast.c [moved from src/gmxlib/thread_mpi/reduce_fast.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/scatter.c [moved from src/gmxlib/thread_mpi/scatter.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/settings.h [moved from src/gmxlib/thread_mpi/settings.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/tmpi_init.c [moved from src/gmxlib/thread_mpi/tmpi_init.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/tmpi_ops.h [moved from src/gmxlib/thread_mpi/tmpi_ops.h with 100% similarity]
src/gromacs/gmxlib/thread_mpi/topology.c [moved from src/gmxlib/thread_mpi/topology.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/type.c [moved from src/gmxlib/thread_mpi/type.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/winthreads.c [moved from src/gmxlib/thread_mpi/winthreads.c with 100% similarity]
src/gromacs/gmxlib/thread_mpi/winthreads.h [moved from src/gmxlib/thread_mpi/winthreads.h with 100% similarity]
src/gromacs/gmxlib/topsort.c [moved from src/gmxlib/topsort.c with 100% similarity]
src/gromacs/gmxlib/tpxio.c [new file with mode: 0644]
src/gromacs/gmxlib/trajana/displacement.c [moved from src/gmxlib/trajana/displacement.c with 100% similarity]
src/gromacs/gmxlib/trnio.c [moved from src/gmxlib/trnio.c with 100% similarity]
src/gromacs/gmxlib/trxio.c [moved from src/gmxlib/trxio.c with 100% similarity]
src/gromacs/gmxlib/txtdump.c [new file with mode: 0644]
src/gromacs/gmxlib/typedefs.c [moved from src/gmxlib/typedefs.c with 100% similarity]
src/gromacs/gmxlib/version.h [moved from src/gmxlib/version.h with 100% similarity]
src/gromacs/gmxlib/viewit.c [moved from src/gmxlib/viewit.c with 100% similarity]
src/gromacs/gmxlib/vmddlopen.c [moved from src/gmxlib/vmddlopen.c with 100% similarity]
src/gromacs/gmxlib/vmdio.c [moved from src/gmxlib/vmdio.c with 100% similarity]
src/gromacs/gmxlib/warninp.c [moved from src/gmxlib/warninp.c with 100% similarity]
src/gromacs/gmxlib/wgms.c [moved from src/gmxlib/wgms.c with 100% similarity]
src/gromacs/gmxlib/wman.c [moved from src/gmxlib/wman.c with 100% similarity]
src/gromacs/gmxlib/writeps.c [moved from src/gmxlib/writeps.c with 100% similarity]
src/gromacs/gmxlib/xdrd.c [moved from src/gmxlib/xdrd.c with 100% similarity]
src/gromacs/gmxlib/xtcio.c [moved from src/gmxlib/xtcio.c with 100% similarity]
src/gromacs/gmxlib/xvgr.c [moved from src/gmxlib/xvgr.c with 100% similarity]
src/gromacs/gmxpreprocess/CMakeLists.txt [new file with mode: 0644]
src/gromacs/gmxpreprocess/add_par.c [moved from src/kernel/add_par.c with 100% similarity]
src/gromacs/gmxpreprocess/add_par.h [moved from src/kernel/add_par.h with 100% similarity]
src/gromacs/gmxpreprocess/compute_io.c [moved from src/kernel/compute_io.c with 100% similarity]
src/gromacs/gmxpreprocess/compute_io.h [moved from src/kernel/compute_io.h with 100% similarity]
src/gromacs/gmxpreprocess/fflibutil.c [moved from src/kernel/fflibutil.c with 100% similarity]
src/gromacs/gmxpreprocess/fflibutil.h [moved from src/kernel/fflibutil.h with 100% similarity]
src/gromacs/gmxpreprocess/gen_ad.c [moved from src/kernel/gen_ad.c with 100% similarity]
src/gromacs/gmxpreprocess/gen_vsite.c [moved from src/kernel/gen_vsite.c with 100% similarity]
src/gromacs/gmxpreprocess/gen_vsite.h [moved from src/kernel/gen_vsite.h with 100% similarity]
src/gromacs/gmxpreprocess/genhydro.c [moved from src/kernel/genhydro.c with 100% similarity]
src/gromacs/gmxpreprocess/genhydro.h [moved from src/kernel/genhydro.h with 100% similarity]
src/gromacs/gmxpreprocess/gpp_atomtype.c [moved from src/kernel/gpp_atomtype.c with 100% similarity]
src/gromacs/gmxpreprocess/gpp_bond_atomtype.c [moved from src/kernel/gpp_bond_atomtype.c with 100% similarity]
src/gromacs/gmxpreprocess/gpp_bond_atomtype.h [moved from src/kernel/gpp_bond_atomtype.h with 100% similarity]
src/gromacs/gmxpreprocess/h_db.c [moved from src/kernel/h_db.c with 100% similarity]
src/gromacs/gmxpreprocess/h_db.h [moved from src/kernel/h_db.h with 100% similarity]
src/gromacs/gmxpreprocess/hackblock.c [moved from src/kernel/hackblock.c with 100% similarity]
src/gromacs/gmxpreprocess/pdb2top.c [moved from src/kernel/pdb2top.c with 100% similarity]
src/gromacs/gmxpreprocess/pgutil.c [moved from src/kernel/pgutil.c with 100% similarity]
src/gromacs/gmxpreprocess/pgutil.h [moved from src/kernel/pgutil.h with 100% similarity]
src/gromacs/gmxpreprocess/readir.c [new file with mode: 0644]
src/gromacs/gmxpreprocess/readir.h [new file with mode: 0644]
src/gromacs/gmxpreprocess/readpull.c [moved from src/kernel/readpull.c with 100% similarity]
src/gromacs/gmxpreprocess/readrot.c [new file with mode: 0644]
src/gromacs/gmxpreprocess/resall.c [moved from src/kernel/resall.c with 100% similarity]
src/gromacs/gmxpreprocess/ter_db.c [moved from src/kernel/ter_db.c with 100% similarity]
src/gromacs/gmxpreprocess/ter_db.h [moved from src/kernel/ter_db.h with 100% similarity]
src/gromacs/gmxpreprocess/topdirs.c [moved from src/kernel/topdirs.c with 100% similarity]
src/gromacs/gmxpreprocess/topdirs.h [moved from src/kernel/topdirs.h with 100% similarity]
src/gromacs/gmxpreprocess/topexcl.c [moved from src/kernel/topexcl.c with 100% similarity]
src/gromacs/gmxpreprocess/topexcl.h [moved from src/kernel/topexcl.h with 100% similarity]
src/gromacs/gmxpreprocess/topio.c [moved from src/kernel/topio.c with 100% similarity]
src/gromacs/gmxpreprocess/topio.h [moved from src/kernel/topio.h with 100% similarity]
src/gromacs/gmxpreprocess/toppush.c [moved from src/kernel/toppush.c with 100% similarity]
src/gromacs/gmxpreprocess/toppush.h [moved from src/kernel/toppush.h with 100% similarity]
src/gromacs/gmxpreprocess/topshake.c [moved from src/kernel/topshake.c with 100% similarity]
src/gromacs/gmxpreprocess/topshake.h [moved from src/kernel/topshake.h with 100% similarity]
src/gromacs/gmxpreprocess/toputil.c [moved from src/kernel/toputil.c with 100% similarity]
src/gromacs/gmxpreprocess/vsite_parm.c [moved from src/kernel/vsite_parm.c with 100% similarity]
src/gromacs/gmxpreprocess/vsite_parm.h [moved from src/kernel/vsite_parm.h with 100% similarity]
src/gromacs/gromacs.h [new file with mode: 0644]
src/gromacs/legacyheaders/3dview.h [moved from include/3dview.h with 100% similarity]
src/gromacs/legacyheaders/CMakeLists.txt [new file with mode: 0644]
src/gromacs/legacyheaders/assert.h [moved from include/assert.h with 100% similarity]
src/gromacs/legacyheaders/atomprop.h [moved from include/atomprop.h with 100% similarity]
src/gromacs/legacyheaders/bondf.h [moved from include/bondf.h with 100% similarity]
src/gromacs/legacyheaders/calcgrid.h [moved from include/calcgrid.h with 100% similarity]
src/gromacs/legacyheaders/calch.h [moved from include/calch.h with 100% similarity]
src/gromacs/legacyheaders/calcmu.h [moved from include/calcmu.h with 100% similarity]
src/gromacs/legacyheaders/chargegroup.h [moved from include/chargegroup.h with 100% similarity]
src/gromacs/legacyheaders/checkpoint.h [moved from include/checkpoint.h with 100% similarity]
src/gromacs/legacyheaders/confio.h [moved from include/confio.h with 100% similarity]
src/gromacs/legacyheaders/constr.h [moved from include/constr.h with 100% similarity]
src/gromacs/legacyheaders/copyrite.h [moved from include/copyrite.h with 100% similarity]
src/gromacs/legacyheaders/coulomb.h [moved from include/coulomb.h with 100% similarity]
src/gromacs/legacyheaders/dihre.h [moved from include/dihre.h with 100% similarity]
src/gromacs/legacyheaders/displacement.h [moved from include/displacement.h with 100% similarity]
src/gromacs/legacyheaders/disre.h [moved from include/disre.h with 100% similarity]
src/gromacs/legacyheaders/do_fit.h [moved from include/do_fit.h with 100% similarity]
src/gromacs/legacyheaders/domdec.h [moved from include/domdec.h with 100% similarity]
src/gromacs/legacyheaders/domdec_network.h [moved from include/domdec_network.h with 100% similarity]
src/gromacs/legacyheaders/ebin.h [moved from include/ebin.h with 100% similarity]
src/gromacs/legacyheaders/edsam.h [moved from include/edsam.h with 100% similarity]
src/gromacs/legacyheaders/enxio.h [moved from include/enxio.h with 100% similarity]
src/gromacs/legacyheaders/ffscanf.h [moved from include/ffscanf.h with 100% similarity]
src/gromacs/legacyheaders/filenm.h [moved from include/filenm.h with 100% similarity]
src/gromacs/legacyheaders/force.h [moved from include/force.h with 100% similarity]
src/gromacs/legacyheaders/futil.h [moved from include/futil.h with 100% similarity]
src/gromacs/legacyheaders/gbutil.h [moved from include/gbutil.h with 100% similarity]
src/gromacs/legacyheaders/gen_ad.h [moved from include/gen_ad.h with 100% similarity]
src/gromacs/legacyheaders/genborn.h [moved from include/genborn.h with 100% similarity]
src/gromacs/legacyheaders/gmx_ana.h [moved from include/gmx_ana.h with 100% similarity]
src/gromacs/legacyheaders/gmx_arpack.h [moved from include/gmx_arpack.h with 100% similarity]
src/gromacs/legacyheaders/gmx_blas.h [moved from include/gmx_blas.h with 100% similarity]
src/gromacs/legacyheaders/gmx_cyclecounter.h [moved from include/gmx_cyclecounter.h with 100% similarity]
src/gromacs/legacyheaders/gmx_fatal.h [moved from include/gmx_fatal.h with 100% similarity]
src/gromacs/legacyheaders/gmx_fft.h [moved from include/gmx_fft.h with 100% similarity]
src/gromacs/legacyheaders/gmx_ga2la.h [moved from include/gmx_ga2la.h with 100% similarity]
src/gromacs/legacyheaders/gmx_lapack.h [moved from include/gmx_lapack.h with 100% similarity]
src/gromacs/legacyheaders/gmx_matrix.h [moved from include/gmx_matrix.h with 100% similarity]
src/gromacs/legacyheaders/gmx_parallel_3dfft.h [moved from include/gmx_parallel_3dfft.h with 100% similarity]
src/gromacs/legacyheaders/gmx_random.h [moved from include/gmx_random.h with 100% similarity]
src/gromacs/legacyheaders/gmx_sort.h [moved from include/gmx_sort.h with 100% similarity]
src/gromacs/legacyheaders/gmx_sse2_double.h [moved from include/gmx_sse2_double.h with 100% similarity]
src/gromacs/legacyheaders/gmx_sse2_single.h [moved from include/gmx_sse2_single.h with 100% similarity]
src/gromacs/legacyheaders/gmx_statistics.h [new file with mode: 0644]
src/gromacs/legacyheaders/gmx_system_xdr.h [moved from include/gmx_system_xdr.h with 100% similarity]
src/gromacs/legacyheaders/gmx_wallcycle.h [new file with mode: 0644]
src/gromacs/legacyheaders/gmxcomplex.h [moved from include/gmxcomplex.h with 100% similarity]
src/gromacs/legacyheaders/gmxcpp.h [moved from include/gmxcpp.h with 100% similarity]
src/gromacs/legacyheaders/gmxfio.h [new file with mode: 0644]
src/gromacs/legacyheaders/gpp_atomtype.h [moved from include/gpp_atomtype.h with 100% similarity]
src/gromacs/legacyheaders/gpp_nextnb.h [moved from include/gpp_nextnb.h with 100% similarity]
src/gromacs/legacyheaders/grompp.h [moved from include/grompp.h with 100% similarity]
src/gromacs/legacyheaders/gstat.h [moved from include/gstat.h with 100% similarity]
src/gromacs/legacyheaders/hackblock.h [moved from include/hackblock.h with 100% similarity]
src/gromacs/legacyheaders/histogram.h [moved from include/histogram.h with 100% similarity]
src/gromacs/legacyheaders/index.h [moved from include/index.h with 100% similarity]
src/gromacs/legacyheaders/inputrec.h [moved from include/inputrec.h with 100% similarity]
src/gromacs/legacyheaders/invblock.h [moved from include/invblock.h with 100% similarity]
src/gromacs/legacyheaders/macros.h [moved from include/macros.h with 100% similarity]
src/gromacs/legacyheaders/magic.h [moved from include/magic.h with 100% similarity]
src/gromacs/legacyheaders/main.h [moved from include/main.h with 100% similarity]
src/gromacs/legacyheaders/maths.h [moved from include/maths.h with 100% similarity]
src/gromacs/legacyheaders/matio.h [moved from include/matio.h with 100% similarity]
src/gromacs/legacyheaders/md5.h [moved from include/md5.h with 100% similarity]
src/gromacs/legacyheaders/mdatoms.h [moved from include/mdatoms.h with 100% similarity]
src/gromacs/legacyheaders/mdebin.h [moved from include/mdebin.h with 100% similarity]
src/gromacs/legacyheaders/mdrun.h [new file with mode: 0644]
src/gromacs/legacyheaders/membed.h [new file with mode: 0644]
src/gromacs/legacyheaders/molfile_plugin.h [moved from include/molfile_plugin.h with 100% similarity]
src/gromacs/legacyheaders/mshift.h [moved from include/mshift.h with 100% similarity]
src/gromacs/legacyheaders/mtop_util.h [moved from include/mtop_util.h with 100% similarity]
src/gromacs/legacyheaders/mtxio.h [moved from include/mtxio.h with 100% similarity]
src/gromacs/legacyheaders/mvdata.h [moved from include/mvdata.h with 100% similarity]
src/gromacs/legacyheaders/names.h [new file with mode: 0644]
src/gromacs/legacyheaders/network.h [moved from include/network.h with 100% similarity]
src/gromacs/legacyheaders/nonbonded.h [moved from include/nonbonded.h with 100% similarity]
src/gromacs/legacyheaders/nrama.h [moved from include/nrama.h with 100% similarity]
src/gromacs/legacyheaders/nrjac.h [moved from include/nrjac.h with 100% similarity]
src/gromacs/legacyheaders/nrnb.h [moved from include/nrnb.h with 100% similarity]
src/gromacs/legacyheaders/ns.h [moved from include/ns.h with 100% similarity]
src/gromacs/legacyheaders/nsgrid.h [moved from include/nsgrid.h with 100% similarity]
src/gromacs/legacyheaders/oenv.h [moved from include/oenv.h with 100% similarity]
src/gromacs/legacyheaders/orires.h [moved from include/orires.h with 100% similarity]
src/gromacs/legacyheaders/partdec.h [moved from include/partdec.h with 100% similarity]
src/gromacs/legacyheaders/pbc.h [moved from include/pbc.h with 100% similarity]
src/gromacs/legacyheaders/pdb2top.h [moved from include/pdb2top.h with 100% similarity]
src/gromacs/legacyheaders/pdbio.h [moved from include/pdbio.h with 100% similarity]
src/gromacs/legacyheaders/perf_est.h [moved from include/perf_est.h with 100% similarity]
src/gromacs/legacyheaders/physics.h [new file with mode: 0644]
src/gromacs/legacyheaders/pme.h [moved from include/pme.h with 100% similarity]
src/gromacs/legacyheaders/pppm.h [moved from include/pppm.h with 100% similarity]
src/gromacs/legacyheaders/princ.h [moved from include/princ.h with 100% similarity]
src/gromacs/legacyheaders/pull.h [moved from include/pull.h with 100% similarity]
src/gromacs/legacyheaders/pull_rotation.h [new file with mode: 0644]
src/gromacs/legacyheaders/qmmm.h [moved from include/qmmm.h with 100% similarity]
src/gromacs/legacyheaders/random.h [moved from include/random.h with 100% similarity]
src/gromacs/legacyheaders/rbin.h [moved from include/rbin.h with 100% similarity]
src/gromacs/legacyheaders/rdgroup.h [moved from include/rdgroup.h with 100% similarity]
src/gromacs/legacyheaders/readinp.h [moved from include/readinp.h with 100% similarity]
src/gromacs/legacyheaders/resall.h [moved from include/resall.h with 100% similarity]
src/gromacs/legacyheaders/rmpbc.h [moved from include/rmpbc.h with 100% similarity]
src/gromacs/legacyheaders/sfactor.h [moved from include/sfactor.h with 100% similarity]
src/gromacs/legacyheaders/shellfc.h [moved from include/shellfc.h with 100% similarity]
src/gromacs/legacyheaders/shift.h [moved from include/shift.h with 100% similarity]
src/gromacs/legacyheaders/sighandler.h [moved from include/sighandler.h with 100% similarity]
src/gromacs/legacyheaders/smalloc.h [moved from include/smalloc.h with 100% similarity]
src/gromacs/legacyheaders/sortwater.h [moved from include/sortwater.h with 100% similarity]
src/gromacs/legacyheaders/sparsematrix.h [moved from include/sparsematrix.h with 100% similarity]
src/gromacs/legacyheaders/split.h [moved from include/split.h with 100% similarity]
src/gromacs/legacyheaders/splitter.h [moved from include/splitter.h with 100% similarity]
src/gromacs/legacyheaders/statutil.h [moved from include/statutil.h with 100% similarity]
src/gromacs/legacyheaders/strdb.h [moved from include/strdb.h with 100% similarity]
src/gromacs/legacyheaders/string2.h [new file with mode: 0644]
src/gromacs/legacyheaders/symtab.h [moved from include/symtab.h with 100% similarity]
src/gromacs/legacyheaders/sysstuff.h [moved from include/sysstuff.h with 100% similarity]
src/gromacs/legacyheaders/tgroup.h [moved from include/tgroup.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi.h [moved from include/thread_mpi.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic.h [moved from include/thread_mpi/atomic.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/cycles.h [moved from include/thread_mpi/atomic/cycles.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc.h [moved from include/thread_mpi/atomic/gcc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc_ia64.h [moved from include/thread_mpi/atomic/gcc_ia64.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc_intrinsics.h [moved from include/thread_mpi/atomic/gcc_intrinsics.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc_ppc.h [moved from include/thread_mpi/atomic/gcc_ppc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc_spinlock.h [moved from include/thread_mpi/atomic/gcc_spinlock.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/gcc_x86.h [new file with mode: 0644]
src/gromacs/legacyheaders/thread_mpi/atomic/msvc.h [moved from include/thread_mpi/atomic/msvc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/suncc-sparc.h [moved from include/thread_mpi/atomic/suncc-sparc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/atomic/xlc_ppc.h [moved from include/thread_mpi/atomic/xlc_ppc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/barrier.h [moved from include/thread_mpi/barrier.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/collective.h [moved from include/thread_mpi/collective.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/event.h [moved from include/thread_mpi/event.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/hwinfo.h [moved from include/thread_mpi/hwinfo.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/list.h [moved from include/thread_mpi/list.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/lock.h [moved from include/thread_mpi/lock.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/mpi_bindings.h [moved from include/thread_mpi/mpi_bindings.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/numa_malloc.h [moved from include/thread_mpi/numa_malloc.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/threads.h [moved from include/thread_mpi/threads.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/tmpi.h [moved from include/thread_mpi/tmpi.h with 100% similarity]
src/gromacs/legacyheaders/thread_mpi/wait.h [moved from include/thread_mpi/wait.h with 100% similarity]
src/gromacs/legacyheaders/tmpi.h [moved from include/tmpi.h with 100% similarity]
src/gromacs/legacyheaders/topsort.h [moved from include/topsort.h with 100% similarity]
src/gromacs/legacyheaders/toputil.h [moved from include/toputil.h with 100% similarity]
src/gromacs/legacyheaders/tpxio.h [moved from include/tpxio.h with 100% similarity]
src/gromacs/legacyheaders/trnio.h [moved from include/trnio.h with 100% similarity]
src/gromacs/legacyheaders/txtdump.h [moved from include/txtdump.h with 100% similarity]
src/gromacs/legacyheaders/typedefs.h [moved from include/typedefs.h with 100% similarity]
src/gromacs/legacyheaders/types/atoms.h [moved from include/types/atoms.h with 100% similarity]
src/gromacs/legacyheaders/types/block.h [moved from include/types/block.h with 100% similarity]
src/gromacs/legacyheaders/types/commrec.h [moved from include/types/commrec.h with 100% similarity]
src/gromacs/legacyheaders/types/constr.h [moved from include/types/constr.h with 100% similarity]
src/gromacs/legacyheaders/types/energy.h [moved from include/types/energy.h with 100% similarity]
src/gromacs/legacyheaders/types/enums.h [new file with mode: 0644]
src/gromacs/legacyheaders/types/fcdata.h [moved from include/types/fcdata.h with 100% similarity]
src/gromacs/legacyheaders/types/filenm.h [moved from include/types/filenm.h with 100% similarity]
src/gromacs/legacyheaders/types/forcerec.h [moved from include/types/forcerec.h with 100% similarity]
src/gromacs/legacyheaders/types/genborn.h [moved from include/types/genborn.h with 100% similarity]
src/gromacs/legacyheaders/types/globsig.h [moved from include/types/globsig.h with 100% similarity]
src/gromacs/legacyheaders/types/graph.h [moved from include/types/graph.h with 100% similarity]
src/gromacs/legacyheaders/types/group.h [moved from include/types/group.h with 100% similarity]
src/gromacs/legacyheaders/types/idef.h [moved from include/types/idef.h with 100% similarity]
src/gromacs/legacyheaders/types/ifunc.h [moved from include/types/ifunc.h with 100% similarity]
src/gromacs/legacyheaders/types/inputrec.h [new file with mode: 0644]
src/gromacs/legacyheaders/types/ishift.h [moved from include/types/ishift.h with 100% similarity]
src/gromacs/legacyheaders/types/iteratedconstraints.h [moved from include/types/iteratedconstraints.h with 100% similarity]
src/gromacs/legacyheaders/types/matrix.h [moved from include/types/matrix.h with 100% similarity]
src/gromacs/legacyheaders/types/mdatom.h [moved from include/types/mdatom.h with 100% similarity]
src/gromacs/legacyheaders/types/nblist.h [moved from include/types/nblist.h with 100% similarity]
src/gromacs/legacyheaders/types/nlistheuristics.h [moved from include/types/nlistheuristics.h with 100% similarity]
src/gromacs/legacyheaders/types/nrnb.h [moved from include/types/nrnb.h with 100% similarity]
src/gromacs/legacyheaders/types/ns.h [moved from include/types/ns.h with 100% similarity]
src/gromacs/legacyheaders/types/nsgrid.h [moved from include/types/nsgrid.h with 100% similarity]
src/gromacs/legacyheaders/types/oenv.h [moved from include/types/oenv.h with 100% similarity]
src/gromacs/legacyheaders/types/pbc.h [moved from include/types/pbc.h with 100% similarity]
src/gromacs/legacyheaders/types/qmmmrec.h [moved from include/types/qmmmrec.h with 100% similarity]
src/gromacs/legacyheaders/types/shellfc.h [moved from include/types/shellfc.h with 100% similarity]
src/gromacs/legacyheaders/types/simple.h [moved from include/types/simple.h with 100% similarity]
src/gromacs/legacyheaders/types/state.h [moved from include/types/state.h with 100% similarity]
src/gromacs/legacyheaders/types/symtab.h [moved from include/types/symtab.h with 100% similarity]
src/gromacs/legacyheaders/types/topology.h [moved from include/types/topology.h with 100% similarity]
src/gromacs/legacyheaders/types/trx.h [moved from include/types/trx.h with 100% similarity]
src/gromacs/legacyheaders/update.h [moved from include/update.h with 100% similarity]
src/gromacs/legacyheaders/vcm.h [moved from include/vcm.h with 100% similarity]
src/gromacs/legacyheaders/vec.h [new file with mode: 0644]
src/gromacs/legacyheaders/viewit.h [moved from include/viewit.h with 100% similarity]
src/gromacs/legacyheaders/vmddlopen.h [moved from include/vmddlopen.h with 100% similarity]
src/gromacs/legacyheaders/vmdio.h [moved from include/vmdio.h with 100% similarity]
src/gromacs/legacyheaders/vmdplugin.h [moved from include/vmdplugin.h with 100% similarity]
src/gromacs/legacyheaders/vsite.h [moved from include/vsite.h with 100% similarity]
src/gromacs/legacyheaders/warninp.h [moved from include/warninp.h with 100% similarity]
src/gromacs/legacyheaders/wgms.h [moved from include/wgms.h with 100% similarity]
src/gromacs/legacyheaders/wman.h [moved from include/wman.h with 100% similarity]
src/gromacs/legacyheaders/writeps.h [moved from include/writeps.h with 100% similarity]
src/gromacs/legacyheaders/xdrf.h [moved from include/xdrf.h with 100% similarity]
src/gromacs/legacyheaders/xtcio.h [moved from include/xtcio.h with 100% similarity]
src/gromacs/legacyheaders/xvgr.h [moved from include/xvgr.h with 100% similarity]
src/gromacs/libgromacs.pc.cmakein [new file with mode: 0644]
src/gromacs/mdlib/CMakeLists.txt [new file with mode: 0644]
src/gromacs/mdlib/calcmu.c [moved from src/mdlib/calcmu.c with 100% similarity]
src/gromacs/mdlib/calcvir.c [moved from src/mdlib/calcvir.c with 100% similarity]
src/gromacs/mdlib/clincs.c [moved from src/mdlib/clincs.c with 100% similarity]
src/gromacs/mdlib/constr.c [moved from src/mdlib/constr.c with 100% similarity]
src/gromacs/mdlib/coupling.c [moved from src/mdlib/coupling.c with 100% similarity]
src/gromacs/mdlib/csettle.c [moved from src/mdlib/csettle.c with 100% similarity]
src/gromacs/mdlib/domdec.c [new file with mode: 0644]
src/gromacs/mdlib/domdec_box.c [moved from src/mdlib/domdec_box.c with 100% similarity]
src/gromacs/mdlib/domdec_con.c [moved from src/mdlib/domdec_con.c with 100% similarity]
src/gromacs/mdlib/domdec_network.c [moved from src/mdlib/domdec_network.c with 100% similarity]
src/gromacs/mdlib/domdec_setup.c [moved from src/mdlib/domdec_setup.c with 100% similarity]
src/gromacs/mdlib/domdec_top.c [moved from src/mdlib/domdec_top.c with 100% similarity]
src/gromacs/mdlib/ebin.c [moved from src/mdlib/ebin.c with 100% similarity]
src/gromacs/mdlib/edsam.c [new file with mode: 0644]
src/gromacs/mdlib/ewald.c [moved from src/mdlib/ewald.c with 100% similarity]
src/gromacs/mdlib/fft5d.c [moved from src/mdlib/fft5d.c with 100% similarity]
src/gromacs/mdlib/fft5d.h [moved from src/mdlib/fft5d.h with 100% similarity]
src/gromacs/mdlib/force.c [new file with mode: 0644]
src/gromacs/mdlib/forcerec.c [moved from src/mdlib/forcerec.c with 100% similarity]
src/gromacs/mdlib/genborn.c [moved from src/mdlib/genborn.c with 100% similarity]
src/gromacs/mdlib/genborn_allvsall.c [moved from src/mdlib/genborn_allvsall.c with 100% similarity]
src/gromacs/mdlib/genborn_allvsall.h [moved from src/mdlib/genborn_allvsall.h with 100% similarity]
src/gromacs/mdlib/genborn_allvsall_sse2_double.c [moved from src/mdlib/genborn_allvsall_sse2_double.c with 100% similarity]
src/gromacs/mdlib/genborn_allvsall_sse2_double.h [moved from src/mdlib/genborn_allvsall_sse2_double.h with 100% similarity]
src/gromacs/mdlib/genborn_allvsall_sse2_single.c [moved from src/mdlib/genborn_allvsall_sse2_single.c with 100% similarity]
src/gromacs/mdlib/genborn_allvsall_sse2_single.h [moved from src/mdlib/genborn_allvsall_sse2_single.h with 100% similarity]
src/gromacs/mdlib/genborn_sse2_double.c [moved from src/mdlib/genborn_sse2_double.c with 100% similarity]
src/gromacs/mdlib/genborn_sse2_double.h [moved from src/mdlib/genborn_sse2_double.h with 100% similarity]
src/gromacs/mdlib/genborn_sse2_single.c [moved from src/mdlib/genborn_sse2_single.c with 100% similarity]
src/gromacs/mdlib/genborn_sse2_single.h [moved from src/mdlib/genborn_sse2_single.h with 100% similarity]
src/gromacs/mdlib/ghat.c [moved from src/mdlib/ghat.c with 100% similarity]
src/gromacs/mdlib/gmx_fft.c [moved from src/mdlib/gmx_fft.c with 100% similarity]
src/gromacs/mdlib/gmx_fft_acml.c [moved from src/mdlib/gmx_fft_acml.c with 100% similarity]
src/gromacs/mdlib/gmx_fft_fftpack.c [moved from src/mdlib/gmx_fft_fftpack.c with 100% similarity]
src/gromacs/mdlib/gmx_fft_fftw2.c [moved from src/mdlib/gmx_fft_fftw2.c with 100% similarity]
src/gromacs/mdlib/gmx_fft_fftw3.c [moved from src/mdlib/gmx_fft_fftw3.c with 100% similarity]
src/gromacs/mdlib/gmx_fft_mkl.c [moved from src/mdlib/gmx_fft_mkl.c with 100% similarity]
src/gromacs/mdlib/gmx_parallel_3dfft.c [moved from src/mdlib/gmx_parallel_3dfft.c with 100% similarity]
src/gromacs/mdlib/gmx_qhop_db.h [moved from src/mdlib/gmx_qhop_db.h with 100% similarity]
src/gromacs/mdlib/gmx_qhop_db_test.c [moved from src/mdlib/gmx_qhop_db_test.c with 100% similarity]
src/gromacs/mdlib/gmx_qhop_parm.c [moved from src/mdlib/gmx_qhop_parm.c with 100% similarity]
src/gromacs/mdlib/gmx_qhop_parm.h [moved from src/mdlib/gmx_qhop_parm.h with 100% similarity]
src/gromacs/mdlib/gmx_qhop_xml.c [moved from src/mdlib/gmx_qhop_xml.c with 100% similarity]
src/gromacs/mdlib/gmx_qhop_xml.h [moved from src/mdlib/gmx_qhop_xml.h with 100% similarity]
src/gromacs/mdlib/gmx_wallcycle.c [new file with mode: 0644]
src/gromacs/mdlib/groupcoord.c [new file with mode: 0644]
src/gromacs/mdlib/groupcoord.h [moved from src/mdlib/groupcoord.h with 100% similarity]
src/gromacs/mdlib/init.c [moved from src/mdlib/init.c with 100% similarity]
src/gromacs/mdlib/iteratedconstraints.c [moved from src/mdlib/iteratedconstraints.c with 100% similarity]
src/gromacs/mdlib/md_support.c [new file with mode: 0644]
src/gromacs/mdlib/mdatom.c [moved from src/mdlib/mdatom.c with 100% similarity]
src/gromacs/mdlib/mdebin.c [new file with mode: 0644]
src/gromacs/mdlib/mdebin_bar.c [moved from src/mdlib/mdebin_bar.c with 100% similarity]
src/gromacs/mdlib/mdebin_bar.h [moved from src/mdlib/mdebin_bar.h with 100% similarity]
src/gromacs/mdlib/minimize.c [new file with mode: 0644]
src/gromacs/mdlib/mvxvf.c [moved from src/mdlib/mvxvf.c with 100% similarity]
src/gromacs/mdlib/nlistheuristics.c [moved from src/mdlib/nlistheuristics.c with 100% similarity]
src/gromacs/mdlib/ns.c [new file with mode: 0644]
src/gromacs/mdlib/nsgrid.c [moved from src/mdlib/nsgrid.c with 100% similarity]
src/gromacs/mdlib/partdec.c [moved from src/mdlib/partdec.c with 100% similarity]
src/gromacs/mdlib/perf_est.c [moved from src/mdlib/perf_est.c with 100% similarity]
src/gromacs/mdlib/pme.c [new file with mode: 0644]
src/gromacs/mdlib/pme_pp.c [new file with mode: 0644]
src/gromacs/mdlib/pppm.c [moved from src/mdlib/pppm.c with 100% similarity]
src/gromacs/mdlib/pull.c [moved from src/mdlib/pull.c with 100% similarity]
src/gromacs/mdlib/pull_rotation.c [new file with mode: 0644]
src/gromacs/mdlib/pullutil.c [moved from src/mdlib/pullutil.c with 100% similarity]
src/gromacs/mdlib/qm_gamess.c [moved from src/mdlib/qm_gamess.c with 100% similarity]
src/gromacs/mdlib/qm_gaussian.c [moved from src/mdlib/qm_gaussian.c with 100% similarity]
src/gromacs/mdlib/qm_mopac.c [moved from src/mdlib/qm_mopac.c with 100% similarity]
src/gromacs/mdlib/qm_orca.c [moved from src/mdlib/qm_orca.c with 100% similarity]
src/gromacs/mdlib/qmmm.c [moved from src/mdlib/qmmm.c with 100% similarity]
src/gromacs/mdlib/rf_util.c [moved from src/mdlib/rf_util.c with 100% similarity]
src/gromacs/mdlib/shakef.c [moved from src/mdlib/shakef.c with 100% similarity]
src/gromacs/mdlib/shellfc.c [moved from src/mdlib/shellfc.c with 100% similarity]
src/gromacs/mdlib/sim_util.c [new file with mode: 0644]
src/gromacs/mdlib/stat.c [moved from src/mdlib/stat.c with 100% similarity]
src/gromacs/mdlib/tables.c [moved from src/mdlib/tables.c with 100% similarity]
src/gromacs/mdlib/tgroup.c [moved from src/mdlib/tgroup.c with 100% similarity]
src/gromacs/mdlib/tpi.c [new file with mode: 0644]
src/gromacs/mdlib/update.c [moved from src/mdlib/update.c with 100% similarity]
src/gromacs/mdlib/vcm.c [moved from src/mdlib/vcm.c with 100% similarity]
src/gromacs/mdlib/vsite.c [moved from src/mdlib/vsite.c with 100% similarity]
src/gromacs/mdlib/wall.c [moved from src/mdlib/wall.c with 100% similarity]
src/gromacs/mdlib/wnblist.c [moved from src/mdlib/wnblist.c with 100% similarity]
src/gromacs/options.h [new file with mode: 0644]
src/gromacs/options/CMakeLists.txt [new file with mode: 0644]
src/gromacs/options/abstractoption.cpp [new file with mode: 0644]
src/gromacs/options/abstractoption.h [new file with mode: 0644]
src/gromacs/options/abstractoptionstorage.h [new file with mode: 0644]
src/gromacs/options/asciihelpwriter-impl.h [new file with mode: 0644]
src/gromacs/options/asciihelpwriter.cpp [new file with mode: 0644]
src/gromacs/options/asciihelpwriter.h [new file with mode: 0644]
src/gromacs/options/basicoptions.cpp [new file with mode: 0644]
src/gromacs/options/basicoptions.h [new file with mode: 0644]
src/gromacs/options/basicoptionstorage.h [new file with mode: 0644]
src/gromacs/options/cmdlineparser-impl.h [new file with mode: 0644]
src/gromacs/options/cmdlineparser.cpp [new file with mode: 0644]
src/gromacs/options/cmdlineparser.h [new file with mode: 0644]
src/gromacs/options/globalproperties.cpp [new file with mode: 0644]
src/gromacs/options/globalproperties.h [new file with mode: 0644]
src/gromacs/options/optionfiletype.h [new file with mode: 0644]
src/gromacs/options/optionflags.h [new file with mode: 0644]
src/gromacs/options/options-impl.h [new file with mode: 0644]
src/gromacs/options/options.cpp [new file with mode: 0644]
src/gromacs/options/options.h [new file with mode: 0644]
src/gromacs/options/optionsassigner-impl.h [new file with mode: 0644]
src/gromacs/options/optionsassigner.cpp [new file with mode: 0644]
src/gromacs/options/optionsassigner.h [new file with mode: 0644]
src/gromacs/options/optionstoragetemplate.h [new file with mode: 0644]
src/gromacs/options/optionsvisitor.cpp [new file with mode: 0644]
src/gromacs/options/optionsvisitor.h [new file with mode: 0644]
src/gromacs/options/tests/.gitignore [new file with mode: 0644]
src/gromacs/options/tests/CMakeLists.txt [new file with mode: 0644]
src/gromacs/options/tests/abstractoptionstorage.cpp [new file with mode: 0644]
src/gromacs/options/tests/cmdlineparser.cpp [new file with mode: 0644]
src/gromacs/options/tests/option.cpp [new file with mode: 0644]
src/gromacs/options/tests/optionsassigner.cpp [new file with mode: 0644]
src/gromacs/selection.h [new file with mode: 0644]
src/gromacs/selection/CMakeLists.txt [new file with mode: 0644]
src/gromacs/selection/centerofmass.cpp [new file with mode: 0644]
src/gromacs/selection/centerofmass.h [new file with mode: 0644]
src/gromacs/selection/compiler.cpp [new file with mode: 0644]
src/gromacs/selection/evaluate.cpp [new file with mode: 0644]
src/gromacs/selection/evaluate.h [new file with mode: 0644]
src/gromacs/selection/indexutil.cpp [new file with mode: 0644]
src/gromacs/selection/indexutil.h [new file with mode: 0644]
src/gromacs/selection/keywords.h [new file with mode: 0644]
src/gromacs/selection/mempool.cpp [new file with mode: 0644]
src/gromacs/selection/mempool.h [new file with mode: 0644]
src/gromacs/selection/nbsearch.cpp [new file with mode: 0644]
src/gromacs/selection/nbsearch.h [new file with mode: 0644]
src/gromacs/selection/params.cpp [new file with mode: 0644]
src/gromacs/selection/parser.cpp [new file with mode: 0644]
src/gromacs/selection/parser.h [new file with mode: 0644]
src/gromacs/selection/parser.y [new file with mode: 0644]
src/gromacs/selection/parsetree.cpp [new file with mode: 0644]
src/gromacs/selection/parsetree.h [new file with mode: 0644]
src/gromacs/selection/poscalc.cpp [new file with mode: 0644]
src/gromacs/selection/poscalc.h [new file with mode: 0644]
src/gromacs/selection/position.cpp [new file with mode: 0644]
src/gromacs/selection/position.h [new file with mode: 0644]
src/gromacs/selection/regenerate_parser.sh [new file with mode: 0755]
src/gromacs/selection/scanner.cpp [new file with mode: 0644]
src/gromacs/selection/scanner.h [new file with mode: 0644]
src/gromacs/selection/scanner.l [new file with mode: 0644]
src/gromacs/selection/scanner_flex.h [new file with mode: 0644]
src/gromacs/selection/scanner_internal.cpp [new file with mode: 0644]
src/gromacs/selection/scanner_internal.h [new file with mode: 0644]
src/gromacs/selection/selection.cpp [new file with mode: 0644]
src/gromacs/selection/selection.h [new file with mode: 0644]
src/gromacs/selection/selectioncollection-impl.h [new file with mode: 0644]
src/gromacs/selection/selectioncollection.cpp [new file with mode: 0644]
src/gromacs/selection/selectioncollection.h [new file with mode: 0644]
src/gromacs/selection/selectionenums.h [new file with mode: 0644]
src/gromacs/selection/selectionoption.cpp [new file with mode: 0644]
src/gromacs/selection/selectionoption.h [new file with mode: 0644]
src/gromacs/selection/selectionoptionstorage.h [new file with mode: 0644]
src/gromacs/selection/selelem.cpp [new file with mode: 0644]
src/gromacs/selection/selelem.h [new file with mode: 0644]
src/gromacs/selection/selhelp.cpp [new file with mode: 0644]
src/gromacs/selection/selhelp.h [new file with mode: 0644]
src/gromacs/selection/selmethod.cpp [new file with mode: 0644]
src/gromacs/selection/selmethod.h [new file with mode: 0644]
src/gromacs/selection/selparam.h [new file with mode: 0644]
src/gromacs/selection/selvalue.cpp [new file with mode: 0644]
src/gromacs/selection/selvalue.h [new file with mode: 0644]
src/gromacs/selection/sm_compare.cpp [new file with mode: 0644]
src/gromacs/selection/sm_distance.cpp [new file with mode: 0644]
src/gromacs/selection/sm_insolidangle.cpp [new file with mode: 0644]
src/gromacs/selection/sm_keywords.cpp [new file with mode: 0644]
src/gromacs/selection/sm_merge.cpp [new file with mode: 0644]
src/gromacs/selection/sm_permute.cpp [new file with mode: 0644]
src/gromacs/selection/sm_position.cpp [new file with mode: 0644]
src/gromacs/selection/sm_same.cpp [new file with mode: 0644]
src/gromacs/selection/sm_simple.cpp [new file with mode: 0644]
src/gromacs/selection/symrec.cpp [new file with mode: 0644]
src/gromacs/selection/symrec.h [new file with mode: 0644]
src/gromacs/selection/tests/.gitignore [new file with mode: 0644]
src/gromacs/selection/tests/CMakeLists.txt [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAllNone.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesArithmeticExpressions.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomname.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomnr.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBasicBoolean.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysis.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithMoreVariables.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithVariables.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesConstantPositions.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesCoordinateKeywords.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesDistanceKeyword.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMergeModifier.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMinDistanceKeyword.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPermuteModifier.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPlusModifier.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPositionKeywords.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesRegexMatching.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResname.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResnr.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidue.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidueName.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinConstantPositions.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinKeyword.xml [new file with mode: 0644]
src/gromacs/selection/tests/selectioncollection.cpp [new file with mode: 0644]
src/gromacs/selection/tests/selectionoption.cpp [new file with mode: 0644]
src/gromacs/selection/tests/simple.gro [new file with mode: 0644]
src/gromacs/trajectoryanalysis.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/CMakeLists.txt [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysismodule-impl.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysismodule.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysismodule.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysissettings-impl.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysissettings.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/analysissettings.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/cmdlinerunner.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/cmdlinerunner.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/angle.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/angle.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/distance.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/distance.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/select.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/modules/select.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/nbsearch.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/runnercommon.cpp [new file with mode: 0644]
src/gromacs/trajectoryanalysis/runnercommon.h [new file with mode: 0644]
src/gromacs/trajectoryanalysis/tests/CMakeLists.txt [new file with mode: 0644]
src/gromacs/trajectoryanalysis/tests/test_selection.cpp [new file with mode: 0644]
src/gromacs/utility/CMakeLists.txt [new file with mode: 0644]
src/gromacs/utility/flags.h [new file with mode: 0644]
src/gromacs/utility/format.cpp [new file with mode: 0644]
src/gromacs/utility/format.h [new file with mode: 0644]
src/gromacs/utility/path.cpp [new file with mode: 0644]
src/gromacs/utility/path.h [new file with mode: 0644]
src/gromacs/version.c.cmakein [new file with mode: 0644]
src/kernel/.cvsignore [deleted file]
src/kernel/.gitignore [new file with mode: 0644]
src/kernel/CMakeLists.txt
src/kernel/gctio.c [deleted file]
src/kernel/grompp.c [deleted file]
src/kernel/libgmxpreprocess.pc.cmakein [deleted file]
src/kernel/md.c [deleted file]
src/kernel/md_openmm.c [deleted file]
src/kernel/md_openmm.h [deleted file]
src/kernel/mdrun.c [deleted file]
src/kernel/readir.c [deleted file]
src/kernel/readir.h [deleted file]
src/kernel/runner.c [deleted file]
src/mdlib/.cvsignore [deleted file]
src/mdlib/CMakeLists.txt [deleted file]
src/mdlib/domdec.c [deleted file]
src/mdlib/edsam.c [deleted file]
src/mdlib/force.c [deleted file]
src/mdlib/gmx_wallcycle.c [deleted file]
src/mdlib/groupcoord.c [deleted file]
src/mdlib/libmd.pc.cmakein [deleted file]
src/mdlib/md_support.c [deleted file]
src/mdlib/mdebin.c [deleted file]
src/mdlib/minimize.c [deleted file]
src/mdlib/ns.c [deleted file]
src/mdlib/pme.c [deleted file]
src/mdlib/pme_pp.c [deleted file]
src/mdlib/sim_util.c [deleted file]
src/mdlib/tpi.c [deleted file]
src/ngmx/.cvsignore [deleted file]
src/ngmx/.gitignore [new file with mode: 0644]
src/ngmx/CMakeLists.txt
src/programs/CMakeLists.txt [new file with mode: 0644]
src/programs/g_ana/.gitignore [new file with mode: 0644]
src/programs/g_ana/CMakeLists.txt [new file with mode: 0644]
src/programs/g_ana/g_ana.cpp [new file with mode: 0644]
src/programs/g_protonate/CMakeLists.txt [new file with mode: 0644]
src/programs/g_protonate/g_protonate.c [moved from src/kernel/g_protonate.c with 100% similarity]
src/programs/g_x2top/CMakeLists.txt [new file with mode: 0644]
src/programs/g_x2top/g_x2top.c [moved from src/kernel/g_x2top.c with 100% similarity]
src/programs/g_x2top/g_x2top.h [moved from src/kernel/g_x2top.h with 100% similarity]
src/programs/g_x2top/nm2type.c [moved from src/kernel/nm2type.c with 100% similarity]
src/programs/gmxcheck/CMakeLists.txt [new file with mode: 0644]
src/programs/gmxcheck/gmxcheck.c [moved from src/kernel/gmxcheck.c with 100% similarity]
src/programs/gmxcheck/tpbcmp.c [moved from src/kernel/tpbcmp.c with 100% similarity]
src/programs/gmxcheck/tpbcmp.h [moved from src/kernel/tpbcmp.h with 100% similarity]
src/programs/gmxdump/CMakeLists.txt [new file with mode: 0644]
src/programs/gmxdump/gmxdump.c [moved from src/kernel/gmxdump.c with 100% similarity]
src/programs/grompp/CMakeLists.txt [new file with mode: 0644]
src/programs/grompp/convparm.c [moved from src/kernel/convparm.c with 100% similarity]
src/programs/grompp/convparm.h [moved from src/kernel/convparm.h with 100% similarity]
src/programs/grompp/gpp_tomorse.h [moved from src/kernel/gpp_tomorse.h with 100% similarity]
src/programs/grompp/grompp.c [new file with mode: 0644]
src/programs/grompp/tomorse.c [moved from src/kernel/tomorse.c with 100% similarity]
src/programs/mdrun/.gitignore [new file with mode: 0644]
src/programs/mdrun/CMakeLists.txt [new file with mode: 0644]
src/programs/mdrun/do_gct.c [moved from src/kernel/do_gct.c with 100% similarity]
src/programs/mdrun/gctio.c [new file with mode: 0644]
src/programs/mdrun/genalg.c [moved from src/kernel/genalg.c with 100% similarity]
src/programs/mdrun/genalg.h [moved from src/kernel/genalg.h with 100% similarity]
src/programs/mdrun/gmx_gpu_utils/CMakeLists.txt [moved from src/kernel/gmx_gpu_utils/CMakeLists.txt with 100% similarity]
src/programs/mdrun/gmx_gpu_utils/gmx_gpu_utils.cu [moved from src/kernel/gmx_gpu_utils/gmx_gpu_utils.cu with 100% similarity]
src/programs/mdrun/gmx_gpu_utils/gmx_gpu_utils.h [moved from src/kernel/gmx_gpu_utils/gmx_gpu_utils.h with 100% similarity]
src/programs/mdrun/gmx_gpu_utils/memtestG80_core.cu [moved from src/kernel/gmx_gpu_utils/memtestG80_core.cu with 100% similarity]
src/programs/mdrun/gmx_gpu_utils/memtestG80_core.h [moved from src/kernel/gmx_gpu_utils/memtestG80_core.h with 100% similarity]
src/programs/mdrun/ionize.c [moved from src/kernel/ionize.c with 100% similarity]
src/programs/mdrun/ionize.h [moved from src/kernel/ionize.h with 100% similarity]
src/programs/mdrun/md.c [new file with mode: 0644]
src/programs/mdrun/md_openmm.c [new file with mode: 0644]
src/programs/mdrun/md_openmm.h [new file with mode: 0644]
src/programs/mdrun/mdrun.c [new file with mode: 0644]
src/programs/mdrun/membed.c [new file with mode: 0644]
src/programs/mdrun/openmm_wrapper.cpp [moved from src/kernel/openmm_wrapper.cpp with 100% similarity]
src/programs/mdrun/openmm_wrapper.h [moved from src/kernel/openmm_wrapper.h with 100% similarity]
src/programs/mdrun/repl_ex.c [moved from src/kernel/repl_ex.c with 100% similarity]
src/programs/mdrun/repl_ex.h [moved from src/kernel/repl_ex.h with 100% similarity]
src/programs/mdrun/runner.c [new file with mode: 0644]
src/programs/mdrun/xmdrun.h [moved from src/kernel/xmdrun.h with 100% similarity]
src/programs/mdrun/xutils.c [moved from src/kernel/xutils.c with 100% similarity]
src/programs/pdb2gmx/CMakeLists.txt [new file with mode: 0644]
src/programs/pdb2gmx/hizzie.c [moved from src/kernel/hizzie.c with 100% similarity]
src/programs/pdb2gmx/hizzie.h [moved from src/kernel/hizzie.h with 100% similarity]
src/programs/pdb2gmx/pdb2gmx.c [moved from src/kernel/pdb2gmx.c with 100% similarity]
src/programs/pdb2gmx/specbond.c [moved from src/kernel/specbond.c with 100% similarity]
src/programs/pdb2gmx/specbond.h [moved from src/kernel/specbond.h with 100% similarity]
src/programs/pdb2gmx/xlate.c [moved from src/kernel/xlate.c with 100% similarity]
src/programs/pdb2gmx/xlate.h [moved from src/kernel/xlate.h with 100% similarity]
src/programs/tpbconv/CMakeLists.txt [new file with mode: 0644]
src/programs/tpbconv/tpbconv.c [moved from src/kernel/tpbconv.c with 100% similarity]
src/testutils/CMakeLists.txt [new file with mode: 0644]
src/testutils/TestMacros.cmake [new file with mode: 0644]
src/testutils/datapath.cpp [new file with mode: 0644]
src/testutils/datapath.h [new file with mode: 0644]
src/testutils/refdata-common.cpp [new file with mode: 0644]
src/testutils/refdata-impl.h [new file with mode: 0644]
src/testutils/refdata.cpp [new file with mode: 0644]
src/testutils/refdata.h [new file with mode: 0644]
src/testutils/test_main_gmock.cpp [new file with mode: 0644]
src/testutils/test_main_gtest.cpp [new file with mode: 0644]
src/testutils/testexceptions.h [new file with mode: 0644]
src/testutils/tests/.gitignore [new file with mode: 0644]
src/testutils/tests/CMakeLists.txt [new file with mode: 0644]
src/testutils/tests/refdata.cpp [new file with mode: 0644]
src/tools/.cvsignore [deleted file]
src/tools/.gitignore [new file with mode: 0644]
src/tools/CMakeLists.txt
src/tools/g_select.c [deleted file]
src/tools/gmx_density.c
src/tools/gmx_membed.c
src/tools/gmx_msd.c
src/tools/gmx_select.c [deleted file]
src/tools/gmx_tune_pme.c
src/tools/libgmxana.pc.cmakein
tests/CMakeLists.txt

index 317cd8eff165463821fc574208250a31d1c35f00..029396348f794c195b26c62eba8fc43ca109583a 100644 (file)
@@ -10,6 +10,8 @@ log
 Makefile
 lib*.pc
 Doxyfile
+Doxyfile-lib
+Doxyfile-user
 doxygen-doc
 .project
 .cproject
index b3f02403aff1fced8d0d107f99c8ee7bda2295d2..73f7889c47c70ae391fba20742317db201ea5aa4 100644 (file)
@@ -38,6 +38,7 @@ if(NOT CMAKE_BUILD_TYPE)
 endif(NOT CMAKE_BUILD_TYPE)
 
 enable_language(C)
+enable_language(CXX)
 
 set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
 set(CPACK_PACKAGE_VENDOR "gromacs.org")
@@ -512,6 +513,38 @@ else(GMX_DLOPEN)
     set(PKG_DL_LIBS)
 endif (GMX_DLOPEN)
 
+option(GMX_INTERNAL_BOOST "Use minimal internal version of boost" OFF)
+if ( NOT GMX_INTERNAL_BOOST )
+  find_package( Boost 1.36.0 )
+else ( NOT GMX_INTERNAL_BOOST )
+  set (Boost_FOUND FALSE)
+endif( NOT GMX_INTERNAL_BOOST )
+
+if(Boost_FOUND)
+  include_directories(${Boost_INCLUDE_DIRS})
+else()
+  message("Boost >= 1.36 not found. Using minimal internal version. Not recommended if GROMACS is used as library!")
+  include_directories(${CMAKE_SOURCE_DIR}/src/external/boost)
+  add_definitions( -DBOOST_NO_TYPEID )  #TYPEID not supported for minimal internal version (would add significant more code)
+  # TODO: Propagate the above settings to the installed CMakeFiles.txt template
+  # (from share/template/)
+  # TODO: Reorder stuff such that INCL_INSTALL_DIR could be used here
+  set(PKG_CFLAGS "${PKG_CFLAGS} -DBOOST_NO_TYPEID -I${CMAKE_INSTALL_PREFIX}/include/gromacs/external/boost")
+  install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/external/boost/boost
+          DESTINATION ${CMAKE_INSTALL_PREFIX}/include/gromacs/external/boost
+          COMPONENT development)
+endif()
+
+option(GMX_USE_GTEST "Build tests that require Google C++ Testing Framework" ON)
+option(GMX_USE_GMOCK "Build tests that require Google C++ Mocking Framework" ON)
+mark_as_advanced(GMX_USE_GTEST)
+mark_as_advanced(GMX_USE_GMOCK)
+if (BUILD_TESTING)
+    add_subdirectory(src/external/gmock-1.6.0)
+endif (BUILD_TESTING)
+
+find_package(Doxygen)
+
 ########################################################################
 # Generate development version info for cache
 ########################################################################
@@ -523,8 +556,11 @@ endif (GMX_DLOPEN)
 ########################################################################
 
 add_definitions( -DHAVE_CONFIG_H )
+include_directories(${CMAKE_SOURCE_DIR}/src)
+# Required for config.h, maybe should only be set in src/CMakeLists.txt
 include_directories(${CMAKE_BINARY_DIR}/src)
-include_directories(${CMAKE_SOURCE_DIR}/include)
+# Required for now to make old code compile
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
 
 include(gmxCheckBuildUserTime)
 gmx_check_build_user_time(BUILD_TIME BUILD_USER BUILD_MACHINE)
@@ -863,7 +899,6 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
 endif()
 
 add_subdirectory(share)
-add_subdirectory(include)
 add_subdirectory(man)
 add_subdirectory(src)
 add_subdirectory(scripts)
@@ -881,6 +916,25 @@ ADD_CUSTOM_TARGET(uninstall
                   "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake")
 ###########################
 
+########################################################################
+# Doxygen configuration
+########################################################################
+if (DOXYGEN_FOUND)
+    FILE(GLOB NB_KERNEL_DIRS src/gromacs/gmxlib/nonbonded/nb_kernel_*/)
+    LIST(REMOVE_ITEM NB_KERNEL_DIRS
+         ${CMAKE_SOURCE_DIR}/src/gromacs/gmxlib/nonbonded/nb_kernel_c)
+    FOREACH(NB_KERNEL_DIR ${NB_KERNEL_DIRS})
+        SET(NB_KERNEL_DIRS_TO_IGNORE_IN_DOXYGEN
+            "${NB_KERNEL_DIRS_TO_IGNORE_IN_DOXYGEN} \\\n                         ${NB_KERNEL_DIR}")
+    ENDFOREACH(NB_KERNEL_DIR)
+    CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/Doxyfile.cmakein
+                   ${CMAKE_BINARY_DIR}/Doxyfile)
+    CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/Doxyfile-lib.cmakein
+                   ${CMAKE_BINARY_DIR}/Doxyfile-lib)
+    CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/Doxyfile-user.cmakein
+                   ${CMAKE_BINARY_DIR}/Doxyfile-user)
+endif (DOXYGEN_FOUND)
+
 
 ########################################################################
 # Tests                                                                #
@@ -889,7 +943,7 @@ ADD_CUSTOM_TARGET(uninstall
 include(CTest)
 mark_as_advanced(BUILD_TESTING)
 IF(BUILD_TESTING)
-       enable_testing()
-       add_subdirectory(tests)
+    enable_testing()
+    add_subdirectory(tests)
 ENDIF()
 
diff --git a/Doxyfile-lib.cmakein b/Doxyfile-lib.cmakein
new file mode 100644 (file)
index 0000000..dceb4e2
--- /dev/null
@@ -0,0 +1,39 @@
+PROJECT_NAME           = @CMAKE_PROJECT_NAME@
+PROJECT_NUMBER         = @PROJECT_VERSION@
+OUTPUT_DIRECTORY       = doxygen-doc
+INPUT                  = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/share/template
+EXAMPLE_PATH           = @CMAKE_SOURCE_DIR@
+RECURSIVE              = YES
+EXCLUDE                = @CMAKE_SOURCE_DIR@/src/contrib \
+                         @CMAKE_SOURCE_DIR@/src/external @NB_KERNEL_DIRS_TO_IGNORE_IN_DOXYGEN@
+EXCLUDE_SYMBOLS        = YY* yy* _gmx_sel_yy*
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = @CMAKE_SOURCE_DIR@
+STRIP_FROM_INC_PATH    = @CMAKE_SOURCE_DIR@/src
+INCLUDE_PATH           = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/src/gromacs/legacyheaders
+HAVE_DOT               = @DOXYGEN_DOT_FOUND@
+DOT_PATH               = @DOXYGEN_DOT_PATH@
+
+ENABLED_SECTIONS       = libapi
+INTERNAL_DOCS          = NO
+HIDE_UNDOC_CLASSES     = YES
+WARN_LOGFILE           = doxygen-doc/doxygen-lib.log
+HTML_OUTPUT            = html-lib
+
+JAVADOC_AUTOBRIEF      = YES
+BUILTIN_STL_SUPPORT    = YES
+INLINE_INHERITED_MEMB  = YES
+SORT_BY_SCOPE_NAME     = YES
+ALPHABETICAL_INDEX     = YES
+SHOW_DIRECTORIES       = YES
+HTML_DYNAMIC_SECTIONS  = YES
+GENERATE_LATEX         = NO
+
+ALIASES               += inpublicapi="\ingroup group_publicapi"
+ALIASES               += inlibraryapi="\ingroup group_libraryapi"
+ALIASES               += addtopublicapi="\addtogroup group_publicapi"
+ALIASES               += addtolibraryapi="\addtogroup group_libraryapi"
+ALIASES               += libinternal=
+ALIASES               += endlibinternal=
diff --git a/Doxyfile-user.cmakein b/Doxyfile-user.cmakein
new file mode 100644 (file)
index 0000000..c97198c
--- /dev/null
@@ -0,0 +1,40 @@
+PROJECT_NAME           = @CMAKE_PROJECT_NAME@
+PROJECT_NUMBER         = @PROJECT_VERSION@
+OUTPUT_DIRECTORY       = doxygen-doc
+INPUT                  = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/share/template
+EXAMPLE_PATH           = @CMAKE_SOURCE_DIR@
+RECURSIVE              = YES
+EXCLUDE                = @CMAKE_SOURCE_DIR@/src/contrib \
+                         @CMAKE_SOURCE_DIR@/src/external @NB_KERNEL_DIRS_TO_IGNORE_IN_DOXYGEN@
+EXCLUDE_SYMBOLS        = YY* yy* _gmx_sel_yy*
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = @CMAKE_SOURCE_DIR@
+STRIP_FROM_INC_PATH    = @CMAKE_SOURCE_DIR@/src
+INCLUDE_PATH           = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/src/gromacs/legacyheaders
+HAVE_DOT               = @DOXYGEN_DOT_FOUND@
+DOT_PATH               = @DOXYGEN_DOT_PATH@
+
+ENABLED_SECTIONS       =
+INTERNAL_DOCS          = NO
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = YES
+WARN_LOGFILE           = doxygen-doc/doxygen-user.log
+HTML_OUTPUT            = html-user
+
+JAVADOC_AUTOBRIEF      = YES
+BUILTIN_STL_SUPPORT    = YES
+INLINE_INHERITED_MEMB  = YES
+SORT_BY_SCOPE_NAME     = YES
+ALPHABETICAL_INDEX     = YES
+SHOW_DIRECTORIES       = YES
+HTML_DYNAMIC_SECTIONS  = YES
+GENERATE_LATEX         = NO
+
+ALIASES               += inpublicapi="\ingroup group_publicapi"
+ALIASES               += inlibraryapi="\ingroup group_libraryapi"
+ALIASES               += addtopublicapi="\addtogroup group_publicapi"
+ALIASES               += addtolibraryapi="\addtogroup group_libraryapi"
+ALIASES               += libinternal="\internal"
+ALIASES               += endlibinternal="\endinternal"
diff --git a/Doxyfile.cmakein b/Doxyfile.cmakein
new file mode 100644 (file)
index 0000000..a4f859d
--- /dev/null
@@ -0,0 +1,38 @@
+PROJECT_NAME           = @CMAKE_PROJECT_NAME@
+PROJECT_NUMBER         = @PROJECT_VERSION@
+OUTPUT_DIRECTORY       = doxygen-doc
+INPUT                  = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/share/template
+EXAMPLE_PATH           = @CMAKE_SOURCE_DIR@
+RECURSIVE              = YES
+EXCLUDE                = @CMAKE_SOURCE_DIR@/src/contrib \
+                         @CMAKE_SOURCE_DIR@/src/external @NB_KERNEL_DIRS_TO_IGNORE_IN_DOXYGEN@
+EXCLUDE_SYMBOLS        = YY* yy* _gmx_sel_yy*
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = @CMAKE_SOURCE_DIR@
+STRIP_FROM_INC_PATH    = @CMAKE_SOURCE_DIR@/src
+INCLUDE_PATH           = @CMAKE_SOURCE_DIR@/src \
+                         @CMAKE_SOURCE_DIR@/src/gromacs/legacyheaders
+HAVE_DOT               = @DOXYGEN_DOT_FOUND@
+DOT_PATH               = @DOXYGEN_DOT_PATH@
+
+ENABLED_SECTIONS       = libapi internal
+INTERNAL_DOCS          = YES
+HIDE_UNDOC_CLASSES     = YES
+WARN_LOGFILE           = doxygen-doc/doxygen.log
+
+JAVADOC_AUTOBRIEF      = YES
+BUILTIN_STL_SUPPORT    = YES
+INLINE_INHERITED_MEMB  = NO  # Makes it easier to go through all documentation
+SORT_BY_SCOPE_NAME     = YES
+ALPHABETICAL_INDEX     = YES
+SHOW_DIRECTORIES       = YES
+HTML_DYNAMIC_SECTIONS  = YES
+GENERATE_LATEX         = NO
+
+ALIASES               += inpublicapi="\ingroup group_publicapi"
+ALIASES               += inlibraryapi="\ingroup group_libraryapi"
+ALIASES               += addtopublicapi="\addtogroup group_publicapi"
+ALIASES               += addtolibraryapi="\addtogroup group_libraryapi"
+ALIASES               += libinternal=
+ALIASES               += endlibinternal=
diff --git a/admin/.cvsignore b/admin/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/bootstrap b/bootstrap
deleted file mode 100755 (executable)
index 36218ee..0000000
--- a/bootstrap
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# This is a stub script to help developers during the final
-# part of the change-over from autotools to CMake.
-
-echo "\
-The use of autotools for installing GROMACS is deprecated for 4.6 onwards
-Please switch to CMake. Check http://www.gromacs.org/Developer_Zone/Cmake
-for instructions."
index 19e90c1b753621bac7e443290849084b9d42f6e1..da8a0d21fea4c77c598542c2dc4119ef60b387c3 100644 (file)
@@ -9,7 +9,7 @@ MACRO(TEST_TMPI_ATOMICS VARIABLE)
     if (NOT DEFINED TMPI_ATOMICS)
         try_compile(TEST_ATOMICS "${CMAKE_BINARY_DIR}"
                 "${CMAKE_SOURCE_DIR}/cmake/TestAtomics.c"
-                COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/include" )
+                COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders" )
 
         if (TEST_ATOMICS)
             message(STATUS "Atomics found")
diff --git a/include/.cvsignore b/include/.cvsignore
deleted file mode 100644 (file)
index fd19000..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile.in
-Makefile
-config.h
-stamp-h.in
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
deleted file mode 100644 (file)
index 05b41fd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# includes: Nothing to build, just installation
-install(DIRECTORY . DESTINATION ${INCL_INSTALL_DIR}/gromacs
-  COMPONENT development
-  PATTERN "Makefile*" EXCLUDE
-  PATTERN "CMake*" EXCLUDE
-  PATTERN "cmake*" EXCLUDE
-  PATTERN "*~" EXCLUDE
-)
diff --git a/include/centerofmass.h b/include/centerofmass.h
deleted file mode 100644 (file)
index b66ca76..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for calculation of centers of mass/geometry.
- *
- * This header defines a few functions that can be used to calculate
- * centers of mass/geometry for a group of atoms.
- * These routines can be used independently of the other parts of the
- * library, but they are also used internally by the selection engine.
- * In most cases, it should not be necessary to call these functions
- * directly.
- * Instead, one should write an analysis tool such that it gets all
- * positions through selections.
- *
- * The functions in the header can be divided into a few groups based on the
- * parameters they take. The simplest group of functions calculates the center
- * of a single group of atoms:
- *  - gmx_calc_cog(): Calculates the center of geometry (COG) of a given
- *    group of atoms.
- *  - gmx_calc_com(): Calculates the center of mass (COM) of a given group
- *    of atoms.
- *  - gmx_calc_comg(): Calculates either the COM or COG, based on a
- *    gmx_boolean flag.
- *
- * A second set of routines is provided for calculating the centers for groups
- * that wrap over periodic boundaries (gmx_calc_cog_pbc(), gmx_calc_com_pbc(),
- * gmx_calc_comg_pbc()). These functions are slower, because they need to
- * adjust the center iteratively.
- *
- * It is also possible to calculate centers for several groups of atoms in
- * one call. The functions gmx_calc_cog_block(), gmx_calc_com_block() and
- * gmx_calc_comg_block() take an index group and a partitioning of that index
- * group (as a \c t_block structure), and calculate the centers for
- * each group defined by the \c t_block structure separately.
- *
- * Finally, there is a function gmx_calc_comg_blocka() that takes both the
- * index group and the partitioning as a single \c t_blocka structure.
- */
-#ifndef CENTEROFMASS_H
-#define CENTEROFMASS_H
-
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/** Calculate a single center of geometry. */
-int
-gmx_calc_cog(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout);
-/** Calculate a single center of mass. */
-int
-gmx_calc_com(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout);
-/** Calculate force on a single center of geometry. */
-int
-gmx_calc_cog_f(t_topology *top, rvec f[], int nrefat, atom_id index[], rvec fout);
-/** Calculate a single center of mass/geometry. */
-int
-gmx_calc_comg(t_topology *top, rvec x[], int nrefat, atom_id index[],
-              gmx_bool bMass, rvec xout);
-/** Calculate force on a single center of mass/geometry. */
-int
-gmx_calc_comg_f(t_topology *top, rvec f[], int nrefat, atom_id index[],
-                gmx_bool bMass, rvec fout);
-
-/** Calculate a single center of geometry iteratively, taking PBC into account. */
-int
-gmx_calc_cog_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                 int nrefat, atom_id index[], rvec xout);
-/** Calculate a single center of mass iteratively, taking PBC into account. */
-int
-gmx_calc_com_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                 int nrefat, atom_id index[], rvec xout);
-/** Calculate a single center of mass/geometry iteratively with PBC. */
-int
-gmx_calc_comg_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                  int nrefat, atom_id index[], gmx_bool bMass, rvec xout);
-
-/** Calculate centers of geometry for a blocked index. */
-int
-gmx_calc_cog_block(t_topology *top, rvec x[], t_block *block,
-                   atom_id index[], rvec xout[]);
-/** Calculate centers of mass for a blocked index. */
-int
-gmx_calc_com_block(t_topology *top, rvec x[], t_block *block,
-                   atom_id index[], rvec xout[]);
-/** Calculate forces on centers of geometry for a blocked index. */
-int
-gmx_calc_cog_f_block(t_topology *top, rvec f[], t_block *block,
-                     atom_id index[], rvec fout[]);
-/** Calculate centers of mass/geometry for a blocked index. */
-int
-gmx_calc_comg_block(t_topology *top, rvec x[], t_block *block,
-                    atom_id index[], gmx_bool bMass, rvec xout[]);
-/** Calculate forces on centers of mass/geometry for a blocked index. */
-int
-gmx_calc_comg_f_block(t_topology *top, rvec f[], t_block *block,
-                      atom_id index[], gmx_bool bMass, rvec fout[]);
-/** Calculate centers of mass/geometry for a set of blocks; */
-int
-gmx_calc_comg_blocka(t_topology *top, rvec x[], t_blocka *block,
-                     gmx_bool bMass, rvec xout[]);
-/** Calculate forces on centers of mass/geometry for a set of blocks; */
-int
-gmx_calc_comg_f_blocka(t_topology *top, rvec x[], t_blocka *block,
-                       gmx_bool bMass, rvec xout[]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/gmx_statistics.h b/include/gmx_statistics.h
deleted file mode 100644 (file)
index 5d28891..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-#ifndef _GMX_STATS_H
-#define _GMX_STATS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "typedefs.h"
-
-typedef struct gmx_stats *gmx_stats_t;
-       
-/* Error codes returned by the routines */
-enum { estatsOK, estatsNO_POINTS, estatsNO_MEMORY, estatsERROR, 
-       estatsINVALID_INPUT, estatsNOT_IMPLEMENTED, estatsNR };
-       
-enum { elsqWEIGHT_NONE, elsqWEIGHT_X, elsqWEIGHT_Y, 
-       elsqWEIGHT_XY, elsqWEIGHT_NR  };
-
-enum { ehistoX, ehistoY, ehistoNR };
-  
-gmx_stats_t gmx_stats_init();
-
-int gmx_stats_done(gmx_stats_t stats);
-
-/* Remove outliers from a straight line, where level in units of
-   sigma. Level needs to be larger than one obviously. */
-int gmx_stats_remove_outliers(gmx_stats_t stats,double level);
-
-int gmx_stats_add_point(gmx_stats_t stats,double x,double y,
-                              double dx,double dy);
-
-/* The arrays dx and dy may be NULL if no uncertainties are available,
-   in that case zero uncertainties will be assumed. */
-int gmx_stats_add_points(gmx_stats_t stats,int n,real *x,real *y,
-                               real *dx,real *dy);
-
-/* Return the data points one by one. Return estatsOK while there are
-   more points, and returns estatsNOPOINTS when the last point has
-   been returned. Should be used in a while loop. Variables for either
-   pointer may be NULL, in which case the routine can be used as an
-   expensive point counter. */
-int gmx_stats_get_point(gmx_stats_t stats,real *x,real *y,
-                              real *dx,real *dy);
-
-/* Fit the data to y = ax + b, possibly weighted, if uncertainties
-   have been input. Returns slope in *a and intercept in b, *return
-   sigmas in *da and *db respectively. Returns normalized *quality of
-   fit in *chi2 and correlation of fit with data in Rfit. chi2, Rfit,
-   da and db may be NULL. */
-int gmx_stats_get_ab(gmx_stats_t stats,int weight,
-                           real *a,real *b,
-                           real *da,real *db,real *chi2,real *Rfit);
-
-/* Fit the data to y = ax, possibly weighted, if uncertainties have
-   been input. Returns slope in *a, sigma in a in *da, and normalized
-   quality of fit in *chi2 and correlation of fit with data in
-   Rfit. chi2, Rfit and da may be NULL. */
-int gmx_stats_get_a(gmx_stats_t stats,int weight,
-                          real *a,real *da,real *chi2,real *Rfit);
-
-/* Return the correlation coefficient between the data (x and y) as
-   input to the structure. */
-int gmx_stats_get_corr_coeff(gmx_stats_t stats,real *R);
-
-/* Returns the root mean square deviation between x and y values. */
-int gmx_stats_get_rmsd(gmx_stats_t gstats,real *rmsd);
-
-int gmx_stats_get_npoints(gmx_stats_t stats,int *N);
-
-int gmx_stats_get_average(gmx_stats_t stats,real *aver);
-
-int gmx_stats_get_sigma(gmx_stats_t stats,real *sigma);
-
-int gmx_stats_get_error(gmx_stats_t stats,real *error);
-
-/* Get all three of the above. Pointers may be null, in which case no
-   assignment will be done. */
-int gmx_stats_get_ase(gmx_stats_t gstats,real *aver,real *sigma,real *error);
-
-/* Dump the x, y, dx, dy data to a text file */
-int gmx_stats_dump_xy(gmx_stats_t gstats,FILE *fp);
-
-/* Make a histogram of the data present. Uses either bindwith to
-   determine the number of bins, or nbins to determine the binwidth,
-   therefore one of these should be zero, but not the other. If *nbins = 0
-   the number of bins will be returned in this variable. ehisto should be one of 
-   ehistoX or ehistoY. If
-   normalized not equal to zero, the integral of the histogram will be
-   normalized to one. The output is in two arrays, *x and *y, to which
-   you should pass a pointer. Memory for the arrays will be allocated
-   as needed. Function returns one of the estats codes. */
-int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nbins,
-                                   int ehisto,
-                                   int normalized,real **x,real **y);
-
-/* Return message belonging to error code */
-const char *gmx_stats_message(int estats);
-
-/****************************************************
- * Some statistics utilities for convenience: useful when a complete data
- * set is available already from another source, e.g. an xvg file.
- ****************************************************/
-int lsq_y_ax(int n, real x[], real y[], real *a);
-/* Fit a straight line y=ax thru the n data points x, y, return the
-   slope in *a. Return value can be estatsOK, or something else. */
-
-int lsq_y_ax_b(int n, real x[], real y[], real *a, real *b,real *r,
-                     real *chi2);
-/* Fit a straight line y=ax+b thru the n data points x,y.
- * Returns the "fit quality" sigma = sqrt(chi^2/(n-2)).
- * The correlation coefficient is returned in r.
- */
-
-int lsq_y_ax_b_xdouble(int n, double x[], real y[],
-                              real *a, real *b,real *r,real *chi2);
-/* As lsq_y_ax_b, but with x in double precision.
- */
-
-int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
-                            real *a, real *b, real *da, real *db,
-                            real *r,real *chi2);
-/* Fit a straight line y=ax+b thru the n data points x,y, with sigma dy
- * Returns the "fit quality" sigma = sqrt(chi^2/(n-2)).
- * The correlation coefficient is returned in r.
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/gmx_wallcycle.h b/include/gmx_wallcycle.h
deleted file mode 100644 (file)
index 9d5c5cf..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-
-#ifndef _gmx_wallcycle_h
-#define _gmx_wallcycle_h
-
-#include <stdio.h>
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  enum { ewcRUN, ewcSTEP, ewcPPDURINGPME, ewcDOMDEC, ewcDDCOMMLOAD, ewcDDCOMMBOUND, ewcVSITECONSTR, ewcPP_PMESENDX, ewcMOVEX, ewcNS, ewcGB, ewcFORCE, ewcMOVEF, ewcPMEMESH, ewcPME_REDISTXF, ewcPME_SPREADGATHER, ewcPME_FFT, ewcPME_SOLVE, ewcPMEWAITCOMM, ewcPP_PMEWAITRECVF, ewcVSITESPREAD, ewcTRAJ, ewcUPDATE, ewcCONSTR, ewcMoveE, ewcTEST, ewcNR };
-
-gmx_bool wallcycle_have_counter(void);
-/* Returns if cycle counting is supported */
-
-gmx_wallcycle_t wallcycle_init(FILE *fplog,int resetstep,t_commrec *cr);
-/* Returns the wall cycle structure.
- * Returns NULL when cycle counting is not supported.
- */
-
-void wallcycle_start(gmx_wallcycle_t wc, int ewc);
-/* Set the start cycle count for ewc */
-
-double wallcycle_stop(gmx_wallcycle_t wc, int ewc);
-/* Stop the cycle count for ewc, returns the last cycle count */
-
-void wallcycle_reset_all(gmx_wallcycle_t wc);
-/* Resets all cycle counters to zero */
-
-void wallcycle_sum(t_commrec *cr, gmx_wallcycle_t wc,double cycles[]);
-/* Sum the cycles over the nodes in cr->mpi_comm_mysim */
-
-void wallcycle_print(FILE *fplog, int nnodes, int npme, double realtime,
-                           gmx_wallcycle_t wc, double cycles[]);
-/* Print the cycle and time accounting */
-
-gmx_large_int_t wcycle_get_reset_counters(gmx_wallcycle_t wc);
-/* Return reset_counters from wc struct */
-
-void wcycle_set_reset_counters(gmx_wallcycle_t wc, gmx_large_int_t reset_counters);
-/* Set reset_counters */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _gmx_wallcycle_h */
diff --git a/include/gmxfio.h b/include/gmxfio.h
deleted file mode 100644 (file)
index da5acaa..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _gmxfio_h
-#define _gmxfio_h
-
-#include <stdio.h>
-#include "sysstuff.h"
-#include "typedefs.h"
-#include "xdrf.h"
-#include "futil.h"
-
-/* types */
-
-
-/* Enumerated for different items in files */
-enum { eitemHEADER, eitemIR, eitemBOX, 
-       eitemTOP, eitemX, eitemV, eitemF, eitemNR };
-       
-/* Enumerated for data types in files */
-enum { eioREAL, eioFLOAT, eioDOUBLE, eioINT, eioGMX_LARGE_INT,
-       eioUCHAR, eioNUCHAR, eioUSHORT,
-       eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR };
-
-typedef struct t_fileio t_fileio;
-
-extern const char *itemstr[eitemNR];
-extern const char *comment_str[eitemNR];
-
-/* NOTE ABOUT THREAD SAFETY:
-
-   The functions are all thread-safe, provided that two threads don't 
-   do something silly like closing the same file, or one thread 
-   accesses a file that has been closed by another.
-   */
-
-/********************************************************
- * Open and Close 
- ********************************************************/
-
-t_fileio *gmx_fio_open(const char *fn,const char *mode);
-/* Open a new file for reading or writing.
- * The file type will be deduced from the file name.
- * If fn is NULL, stdin / stdout will be used for Ascii I/O (TPA type)
- * mode may be "r", "w", or "a". You should append a "b" to the mode
- * if you are writing a binary file, but the routine will also 
- * doublecheck it and try to do it if you forgot. This has no effect on
- * unix, but is important on windows.
- */
-int gmx_fio_close(t_fileio *fp);
-/* Close the file corresponding to fp (if not stdio)
- * The routine will exit when an invalid fio is handled.
- * Returns 0 on success.
- */
-
-int gmx_fio_fp_close(t_fileio *fp);
-/* Close the file corresponding to fp without closing the FIO entry
- * Needed e.g. for trxio because the FIO entries are used to store 
- * additional data.
- * NOTE that the fp still needs to be properly closed with gmx_fio_close().
- * The routine will exit when an invalid fio is handled.
- * Returns 0 on success.
- */
-
-
-/* Open a file, return a stream, record the entry in internal FIO object */
-FILE* gmx_fio_fopen(const char *fn,const char *mode);
-
-/* Close a file previously opened with gmx_fio_fopen. 
- * Do not mix these calls with standard fopen/fclose ones!
- * Returns 0 on success.  */
-int gmx_fio_fclose(FILE *fp);
-
-
-
-/********************************************************
- * Change properties of the open file
- ********************************************************/
-
-void gmx_fio_setprecision(t_fileio *fio,gmx_bool bDouble);
-/* Select the floating point precision for reading and writing files */
-
-char *gmx_fio_getname(t_fileio *fio);
-/* Return the filename corresponding to the fio index */
-
-int gmx_fio_getftp(t_fileio *fio);
-/* Return the filetype corresponding to the fio index. 
-    There is as of now no corresponding setftp function because the file
-    was opened as a specific file type and changing that midway is most 
-    likely an evil hack. */
-
-void gmx_fio_setdebug(t_fileio *fio,gmx_bool bDebug);
-/* Set the debug mode */
-
-gmx_bool gmx_fio_getdebug(t_fileio *fio);
-/* Return  whether debug mode is on in fio  */
-
-gmx_bool gmx_fio_getread(t_fileio *fio);
-/* Return  whether read mode is on in fio  */
-
-
-void gmx_fio_checktype(t_fileio *fio);
-/* Check whether the fio is of a sane type */
-
-/***************************************************
- * FILE Operations
- ***************************************************/
-
-void gmx_fio_rewind(t_fileio *fio);
-/* Rewind the tpa file in fio */
-
-int gmx_fio_flush(t_fileio *fio);
-/* Flush the fio, returns 0 on success */
-
-int gmx_fio_fsync(t_fileio *fio);
-/* fsync the fio, returns 0 on success. 
-   NOTE: don't use fsync function unless you're absolutely sure you need it
-   because it deliberately interferes with the OS's caching mechanisms and
-   can cause dramatically slowed down IO performance. Some OSes (Linux, 
-   for example), may implement fsync as a full sync() point. */
-
-gmx_off_t gmx_fio_ftell(t_fileio *fio);
-/* Return file position if possible */
-
-int gmx_fio_seek(t_fileio *fio,gmx_off_t fpos);
-/* Set file position if possible, quit otherwise */
-
-FILE *gmx_fio_getfp(t_fileio *fio);
-/* Return the file pointer itself */
-
-XDR *gmx_fio_getxdr(t_fileio *fio);
-/* Return the file pointer itself */
-
-
-
-
-
-/* Element with information about position in a currently open file.
- * gmx_off_t should be defined by autoconf if your system does not have it.
- * If you do not have it on some other platform you do not have largefile 
- * support at all, and you can define it to int (or better, find out how to 
- * enable large files).  */
-typedef struct
-{
-       char      filename[STRLEN];
-       gmx_off_t offset; 
-       unsigned char chksum[16];
-       int       chksum_size;
-} 
-gmx_file_position_t;
-
-
-int gmx_fio_check_file_position(t_fileio *fio);
-/* Check if the file position is out of the range of off_t.
- * The result is stored along with the other file data of fio.
- */
-
-int gmx_fio_get_output_file_positions(gmx_file_position_t ** outputfiles,
-                                      int *nfiles );
-/* Return the name and file pointer positions for all currently open
- * output files. This is used for saving in the checkpoint files, so we
- * can truncate output files upon restart-with-appending.
- *
- * For the first argument you should use a pointer, which will be set to
- * point to a list of open files.
- */
-
-t_fileio *gmx_fio_all_output_fsync(void);
-/* fsync all open output files. This is used for checkpointing, where
-   we need to ensure that all output is actually written out to 
-   disk. 
-   This is most important in the case of some networked file systems, 
-   where data is not synced with the file server until close() or 
-   fsync(), so data could remain in cache for days.
-   Note the caveats reported with gmx_fio_fsync(). 
-   
-    returns: NULL if no error occurred, or a pointer to the first file that
-             failed if an error occurred 
-*/
-
-
-int gmx_fio_get_file_md5(t_fileio *fio, gmx_off_t offset,  
-                         unsigned char digest[]);
-
-
-int xtc_seek_frame(t_fileio *fio, int frame, int natoms);
-
-int xtc_seek_time(t_fileio *fio, real time, int natoms);
-
-       
-/* Add this to the comment string for debugging */
-void gmx_fio_set_comment(t_fileio *fio, const char *comment);
-
-/* Remove previously set comment */
-void gmx_fio_unset_comment(t_fileio *fio);
-
-
-
-
-/********************************************************
- * Read and write
- ********************************************************/
-
-
-/* basic reading & writing */
-gmx_bool gmx_fio_reade_real(t_fileio *fio, real *item, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_float(t_fileio *fio, float *item, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_double(t_fileio *fio, double *item, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_int(t_fileio *fio, int *item, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
-                                 const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_reade_string(t_fileio *fio, char *item, 
-                          const char *desc, const char *srcfile, int line);
-
-gmx_bool gmx_fio_writee_real(t_fileio *fio, real item, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_float(t_fileio *fio, float item, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_double(t_fileio *fio, double item, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_int(t_fileio *fio, int item, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item, 
-                                  const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_writee_string(t_fileio *fio, const char *item, 
-                           const char *desc, const char *srcfile, int line);
-
-/* reading or writing, depending on the file's opening mode string */
-gmx_bool gmx_fio_doe_real(t_fileio *fio, real *item, 
-                      const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_float(t_fileio *fio, float *item, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_double(t_fileio *fio, double *item, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_gmx_bool(t_fileio *fio, gmx_bool *item, 
-                     const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_int(t_fileio *fio, int *item, 
-                     const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
-                               const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item, 
-                      const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item, 
-                      const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_doe_string(t_fileio *fio, char *item, 
-                        const char *desc, const char *srcfile, int line);
-
-
-
-
-/* array reading & writing */
-gmx_bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_float(t_fileio *fio, float *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
-                                  const char *desc, const char *srcfile, 
-                                  int line);
-gmx_bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n, 
-                           const char *desc, const char *srcfile, int line);
-
-gmx_bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_float(t_fileio *fio, const float *item, int n, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n, 
-                            const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio, 
-                                   const gmx_large_int_t *item, int n,
-                                   const char *desc, const char *srcfile, 
-                                   int line);
-gmx_bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n, 
-                           const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n, 
-                          const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n, 
-                            const char *desc, const char *srcfile, int line);
-
-gmx_bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_float(t_fileio *fio, float *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n, 
-                         const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_gmx_bool(t_fileio *fio, gmx_bool *item, int n, 
-                      const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n, 
-                      const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
-                                const char *desc, const char *srcfile, 
-                                int line);
-gmx_bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n, 
-                        const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n, 
-                       const char *desc, const char *srcfile, int line);
-gmx_bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n, 
-                         const char *desc, const char *srcfile, int line);
-
-
-
-/* convenience macros */
-#define gmx_fio_read_real(fio, item)           gmx_fio_reade_real(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_float(fio, item)          gmx_fio_reade_float(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_double(fio, item)         gmx_fio_reade_double(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_int(fio, item)            gmx_fio_reade_int(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_gmx_large_int(fio, item)  gmx_fio_reade_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_uchar(fio, item)          gmx_fio_reade_uchar(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_ushort(fio, item)         gmx_fio_reade_ushort(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_rvec(fio, item)           gmx_fio_reade_rvec(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_ivec(fio, item)           gmx_fio_reade_ivec(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_read_string(fio, item)         gmx_fio_reade_string(fio, item, (#item), __FILE__, __LINE__)
-
-#define gmx_fio_write_real(fio, item)           gmx_fio_writee_real(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_float(fio, item)          gmx_fio_writee_float(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_double(fio, item)         gmx_fio_writee_double(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_int(fio, item)            gmx_fio_writee_int(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_gmx_large_int(fio, item)  gmx_fio_writee_gmx_large_int(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_uchar(fio, item)          gmx_fio_writee_uchar(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_ushort(fio, item)         gmx_fio_writee_ushort(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_rvec(fio, item)           gmx_fio_writee_rvec(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_ivec(fio, item)           gmx_fio_writee_ivec(fio, item, (#item), __FILE__, __LINE__)
-#define gmx_fio_write_string(fio, item)         gmx_fio_writee_string(fio, item, (#item), __FILE__, __LINE__)
-
-#define gmx_fio_do_real(fio, item)              gmx_fio_doe_real(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_float(fio, item)             gmx_fio_doe_float(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_double(fio, item)            gmx_fio_doe_double(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_gmx_bool(fio, item)              gmx_fio_doe_gmx_bool(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_int(fio, item)               gmx_fio_doe_int(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_gmx_large_int(fio, item)     gmx_fio_doe_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_uchar(fio, item)             gmx_fio_doe_uchar(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_ushort(fio, item)            gmx_fio_doe_ushort(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_rvec(fio, item)              gmx_fio_doe_rvec(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_ivec(fio, item)              gmx_fio_doe_ivec(fio, &item, (#item), __FILE__, __LINE__)
-#define gmx_fio_do_string(fio, item)            gmx_fio_doe_string(fio, item, (#item), __FILE__, __LINE__)
-
-
-
-
-#define gmx_fio_nread_real(fio, item, n)            gmx_fio_nreade_real(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_float(fio, item, n)           gmx_fio_nreade_float(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_double(fio, item, n)          gmx_fio_nreade_double(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_int(fio, item, n)             gmx_fio_nreade_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_gmx_large_int(fio, item, n)   gmx_fio_nreade_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_uchar(fio, item, n)           gmx_fio_nreade_uchar(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_ushort(fio, item, n)          gmx_fio_nreade_ushort(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_rvec(fio, item, n)            gmx_fio_nreade_rvec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_ivec(fio, item, n)            gmx_fio_nreade_ivec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nread_string(fio, item, n)          gmx_fio_nreade_string(fio, item, n, (#item), __FILE__, __LINE__)
-
-#define gmx_fio_nwrite_real(fio, item, n)           gmx_fio_nwritee_real(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_float(fio, item, n)          gmx_fio_nwritee_float(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_double(fio, item, n)         gmx_fio_nwritee_double(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_int(fio, item, n)            gmx_fio_nwritee_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_gmx_large_int(fio, item, n)  gmx_fio_nwritee_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_uchar(fio, item, n)          gmx_fio_nwritee_uchar(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_ushort(fio, item, n)         gmx_fio_nwritee_ushort(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_rvec(fio, item, n)           gmx_fio_nwritee_rvec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_ivec(fio, item, n)           gmx_fio_nwritee_ivec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_nwrite_string(fio, item, n)         gmx_fio_nwritee_string(fio, item, n, (#item), __FILE__, __LINE__)
-
-#define gmx_fio_ndo_real(fio, item, n)              gmx_fio_ndoe_real(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_float(fio, item, n)             gmx_fio_ndoe_float(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_double(fio, item, n)            gmx_fio_ndoe_double(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_gmx_bool(fio, item, n)              gmx_fio_ndoe_gmx_bool(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_int(fio, item, n)               gmx_fio_ndoe_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_gmx_large_int(fio, item, n)     gmx_fio_ndoe_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_uchar(fio, item, n)             gmx_fio_ndoe_uchar(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_ushort(fio, item, n)            gmx_fio_ndoe_ushort(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_rvec(fio, item, n)              gmx_fio_ndoe_rvec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_ivec(fio, item, n)              gmx_fio_ndoe_ivec(fio, item, n, (#item), __FILE__, __LINE__)
-#define gmx_fio_ndo_string(fio, item, n)            gmx_fio_ndoe_string(fio, item, n, (#item), __FILE__, __LINE__)
-
-
-
-#endif
diff --git a/include/indexutil.h b/include/indexutil.h
deleted file mode 100644 (file)
index 6af9d9d..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for handling index files and index groups.
- *
- * The API contains functions and data structures for handling index
- * files more conveniently than as several separate variables.
- * In addition to basic functions for initializing the data structures and
- * making copies, functions are provided for performing (most) set operations
- * on sorted index groups.
- * There is also a function for partitioning a index group based on
- * topology information such as residues or molecules.
- * Finally, there is a set of functions for constructing mappings between
- * an index group and its subgroups such.
- * These can be used with dynamic index group in calculations if one
- * needs to have a unique ID for each possible atom/residue/molecule in the
- * selection, e.g., for analysis of dynamics or for look-up tables.
- *
- * Mostly, these functions are used internally by the library and the
- * selection engine.
- * However, some of the checking functions can be useful in user code to
- * check the validity of input groups.
- * Also, the mapping functions are useful when dealing with dynamic index
- * groups.
- */
-#ifndef INDEXUTIL_H
-#define INDEXUTIL_H
-
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/** Stores a set of index groups. */
-typedef struct gmx_ana_indexgrps_t gmx_ana_indexgrps_t;
-
-/*! \brief
- * Specifies the type of index partition or index mapping in several contexts.
- *
- * \see gmx_ana_index_make_block(), gmx_ana_indexmap_init()
- */
-typedef enum
-{
-    INDEX_UNKNOWN, /**< Unknown index type.*/
-    INDEX_ATOM,    /**< Each atom in a separate block.*/
-    INDEX_RES,     /**< Each residue in a separate block.*/
-    INDEX_MOL,     /**< Each molecule in a separate block.*/
-    INDEX_ALL      /**< All atoms in a single block.*/
-} e_index_t;
-
-/*! \brief
- * Stores a single index group.
- */
-typedef struct gmx_ana_index_t
-{
-    /** Number of atoms. */
-    int                 isize;
-    /** List of atoms. */
-    atom_id            *index;
-    /** Group name. */
-    char               *name;
-    /** Number of items allocated for \p index. */
-    int                 nalloc_index;
-} gmx_ana_index_t;
-
-/*! \brief
- * Data structure for calculating index group mappings.
- */
-typedef struct gmx_ana_indexmap_t
-{
-    /** Type of the mapping. */
-    e_index_t           type;
-    /*! \brief
-     * Current number of mapped values.
-     *
-     * This is the current number of values in the \p refid and \p mapid
-     * arrays.
-     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), this
-     * is always equal to \p b.nr, i.e., the number of blocks in the
-     * original index group.
-     */
-    int                 nr;
-    /*! \brief
-     * Current reference IDs.
-     *
-     * This array provides a mapping from the current index group (last given
-     * to gmx_ana_indexmap_update()) to the blocks in \p b, i.e., the
-     * original index group used in gmx_ana_indexmap_init().
-     * The mapping is zero-based.
-     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), the indices
-     * for blocks not present in the current group are set to -1, otherwise
-     * they are removed completely and the \p nr field updated.
-     */
-    int                *refid;
-    /*! \brief
-     * Current mapped IDs.
-     *
-     * This array provides an arbitrary mapping from the current index group
-     * to the original index group. Instead of a zero-based mapping, the
-     * values from the \p orgid array are used. That is,
-     * \c mapid[i]=orgid[refid[i]].
-     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), this array
-     * equals \p orgid.
-     */
-    int                *mapid;
-    /*! \brief
-     * Mapped block structure.
-     *
-     * A block structure that corresponds to the current index group.
-     */
-    t_block             mapb;
-
-    /*! \brief
-     * Arbitrary ID numbers for the blocks.
-     *
-     * This array has \p b.nr elements, each defining an ID number for a
-     * block in \p b.
-     * These are initialized in gmx_ana_indexmap_init() based on the type:
-     *  - \ref INDEX_ATOM : the atom indices
-     *  - \ref INDEX_RES :  the residue numbers
-     *  - \ref INDEX_MOL :  the molecule numbers
-     *
-     * All the above numbers are zero-based.
-     * After gmx_ana_indexmap_init(), the user is free to change these values
-     * if the above are not appropriate.
-     * The mapped values can be read through \p mapid.
-     */
-    int                *orgid;
-
-    /*! \brief
-     * Block data that defines the mapping (internal use only).
-     *
-     * The data is initialized by gmx_ana_indexmap_init() and is not changed
-     * after that.
-     * Hence, it cannot be directly applied to the index group passed to
-     * gmx_ana_indexmap_update() unless \p bMaskOnly was specified or the
-     * index group is identical to the one provided to gmx_ana_indexmap_init().
-     */
-    t_blocka            b;
-    /*! \brief
-     * TRUE if the current reference IDs are for the whole group (internal use only).
-     *
-     * This is used internally to optimize the evaluation such that
-     * gmx_ana_indexmap_update() does not take any time if the group is
-     * actually static.
-     */
-    gmx_bool                bStatic;
-    /*! \brief
-     * TRUE if the current mapping is for the whole group (internal use only).
-     *
-     * This is used internally to optimize the evaluation such that
-     * gmx_ana_indexmap_update() does not take any time if the group is
-     * actually static.
-     */
-    gmx_bool                bMapStatic;
-} gmx_ana_indexmap_t;
-
-
-/*! \name Functions for handling gmx_ana_indexgrps_t
- */
-/*@{*/
-/** Allocate memory for index groups. */
-void
-gmx_ana_indexgrps_alloc(gmx_ana_indexgrps_t **g, int ngrps);
-/** Initializes index groups from arrays. */
-void
-gmx_ana_indexgrps_set(gmx_ana_indexgrps_t **g, int ngrps, int *isize,
-                      atom_id **index, char **name, gmx_bool bFree);
-/** Reads index groups from a file or constructs them from topology. */
-void
-gmx_ana_indexgrps_init(gmx_ana_indexgrps_t **g, t_topology *top, 
-                       const char *fnm);
-/** Ask user to select index groups, possibly constructing groups from 
- *  topology. */
-void
-gmx_ana_indexgrps_get(gmx_ana_indexgrps_t **g, t_topology *top, 
-                      const char *fnm, int ngrps);
-/** Ask user to select index groups from those specified in a file. */
-void
-gmx_ana_indexgrps_rd(gmx_ana_indexgrps_t **g, const char *fnm, int ngrps);
-/** Frees memory allocated for index groups. */
-void
-gmx_ana_indexgrps_free(gmx_ana_indexgrps_t *g);
-/** Create a deep copy of \c gmx_ana_indexgrps_t. */
-void
-gmx_ana_indexgrps_clone(gmx_ana_indexgrps_t **dest, gmx_ana_indexgrps_t *src);
-/** Returns TRUE if the index group structure is emtpy. */
-gmx_bool
-gmx_ana_indexgrps_is_empty(gmx_ana_indexgrps_t *g);
-
-/** Returns a pointer to an index group. */
-gmx_ana_index_t *
-gmx_ana_indexgrps_get_grp(gmx_ana_indexgrps_t *g, int n);
-/** Extracts a single index group. */
-gmx_bool
-gmx_ana_indexgrps_extract(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, int n);
-/** Finds and extracts a single index group by name. */
-gmx_bool
-gmx_ana_indexgrps_find(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, char *name);
-
-/** Writes out a list of index groups. */
-void
-gmx_ana_indexgrps_print(gmx_ana_indexgrps_t *g, int maxn);
-/*@}*/
-
-/*! \name Functions for handling gmx_ana_index_t
- */
-/*@{*/
-/** Reserves memory to store an index group of size \p isize. */
-void
-gmx_ana_index_reserve(gmx_ana_index_t *g, int isize);
-/** Frees any memory not necessary to hold the current contents. */
-void
-gmx_ana_index_squeeze(gmx_ana_index_t *g);
-/** Initializes an empty index group. */
-void
-gmx_ana_index_clear(gmx_ana_index_t *g);
-/** Constructs a \c gmx_ana_index_t from given values. */
-void
-gmx_ana_index_set(gmx_ana_index_t *g, int isize, atom_id *index, char *name,
-                  int nalloc);
-/** Creates a simple index group from the first to the \p natoms'th atom. */
-void
-gmx_ana_index_init_simple(gmx_ana_index_t *g, int natoms, char *name);
-/** Frees memory allocated for an index group. */
-void
-gmx_ana_index_deinit(gmx_ana_index_t *g);
-/** Copies a \c gmx_ana_index_t. */
-void
-gmx_ana_index_copy(gmx_ana_index_t *dest, gmx_ana_index_t *src, gmx_bool bAlloc);
-
-/** Writes out the contents of a index group. */
-void
-gmx_ana_index_dump(gmx_ana_index_t *g, int i, int maxn);
-
-/** Checks whether all indices are between 0 and \p natoms. */
-void
-gmx_ana_index_check(gmx_ana_index_t *g, int natoms);
-/** Checks whether an index group is sorted. */
-gmx_bool
-gmx_ana_index_check_sorted(gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Functions for set operations on gmx_ana_index_t
- */
-/*@{*/
-/** Sorts the indices within an index group. */
-void
-gmx_ana_index_sort(gmx_ana_index_t *g);
-/** Checks whether two index groups are equal. */
-gmx_bool
-gmx_ana_index_equals(gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Checks whether a sorted index group contains another sorted index group. */
-gmx_bool
-gmx_ana_index_contains(gmx_ana_index_t *a, gmx_ana_index_t *b);
-
-/** Calculates the intersection between two sorted index groups. */
-void
-gmx_ana_index_intersection(gmx_ana_index_t *dest,
-                           gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Calculates the set difference between two sorted index groups. */
-void
-gmx_ana_index_difference(gmx_ana_index_t *dest,
-                         gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Calculates the size of the difference between two sorted index groups. */
-int
-gmx_ana_index_difference_size(gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Calculates the union of two sorted index groups. */
-void
-gmx_ana_index_union(gmx_ana_index_t *dest,
-                    gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Merges two distinct sorted index groups. */
-void
-gmx_ana_index_merge(gmx_ana_index_t *dest,
-                    gmx_ana_index_t *a, gmx_ana_index_t *b);
-/** Calculates the intersection and the difference in one call. */
-void
-gmx_ana_index_partition(gmx_ana_index_t *dest1, gmx_ana_index_t *dest2,
-                        gmx_ana_index_t *src, gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Functions for handling gmx_ana_indexmap_t and related things
- */
-/*@{*/
-/** Partition a group based on topology information. */
-void
-gmx_ana_index_make_block(t_blocka *t, t_topology *top, gmx_ana_index_t *g,
-                         e_index_t type, gmx_bool bComplete);
-/** Checks whether a group consists of full blocks. */
-gmx_bool
-gmx_ana_index_has_full_blocks(gmx_ana_index_t *g, t_block *b);
-/** Checks whether a group consists of full blocks. */
-gmx_bool
-gmx_ana_index_has_full_ablocks(gmx_ana_index_t *g, t_blocka *b);
-/** Checks whether a group consists of full residues/molecules. */
-gmx_bool
-gmx_ana_index_has_complete_elems(gmx_ana_index_t *g, e_index_t type, t_topology *top);
-
-/** Initializes an empty index group mapping. */
-void
-gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m);
-/** Reserves memory for an index group mapping. */
-void
-gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize);
-/** Initializes an index group mapping. */
-void
-gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
-                      t_topology *top, e_index_t type);
-/** Sets an index group mapping to be static. */
-void
-gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b);
-/** Frees memory allocated for index group mapping. */
-void
-gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m);
-/** Makes a deep copy of an index group mapping. */
-void
-gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, gmx_bool bFirst);
-/** Updates an index group mapping. */
-void
-gmx_ana_indexmap_update(gmx_ana_indexmap_t *m, gmx_ana_index_t *g, gmx_bool bMaskOnly);
-/*@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/mainpage.h b/include/mainpage.h
deleted file mode 100644 (file)
index 4f48540..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*! \file
- * \brief Dummy header for Doxygen documentation.
- *
- * This file just holds the main page for doxygen. When, at some point in the
- * future, there is an obvious location for this documentation, we should
- * move it there.
- */
-
-/*! \mainpage Gromacs
-
-  GROMACS is a versatile package to perform molecular dynamics, i.e.  simulate 
-  the Newtonian equations of motion for systems with hundreds, to millions 
-  of particles.
-
-  Currently, there is documentation available (at least) on the following
-  parts of the source tree:
-   - \subpage thread_mpi
-   - \subpage libtrajana
-
-  */
-
-
diff --git a/include/mdrun.h b/include/mdrun.h
deleted file mode 100644 (file)
index d30fb0c..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _mdrun_h
-#define _mdrun_h
-
-#include <stdio.h>
-#include <time.h>
-#include "typedefs.h"
-#include "network.h"
-#include "tgroup.h"
-#include "filenm.h"
-#include "mshift.h"
-#include "force.h"
-#include "edsam.h"
-#include "mdebin.h"
-#include "vcm.h"
-#include "vsite.h"
-#include "pull.h"
-#include "update.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MD_POLARISE       (1<<2)
-#define MD_IONIZE         (1<<3)
-#define MD_RERUN          (1<<4)
-#define MD_RERUN_VSITE    (1<<5)
-#define MD_FFSCAN         (1<<6)
-#define MD_SEPPOT         (1<<7)
-#define MD_PARTDEC        (1<<9)
-#define MD_DDBONDCHECK    (1<<10)
-#define MD_DDBONDCOMM     (1<<11)
-#define MD_CONFOUT        (1<<12)
-#define MD_REPRODUCIBLE   (1<<13)
-#define MD_READ_RNG       (1<<14)
-#define MD_APPENDFILES    (1<<15)
-#define MD_KEEPANDNUMCPT  (1<<16)
-#define MD_READ_EKIN      (1<<17)
-#define MD_STARTFROMCPT   (1<<18)
-#define MD_RESETCOUNTERSHALFWAY (1<<19)
-
-/* Define a number of flags to better control the information
- * passed to compute_globals in md.c and global_stat.
- */
-
-/* We are rerunning the simulation */
-#define CGLO_RERUNMD        (1<<1)
-/* we are computing the kinetic energy from average velocities */
-#define CGLO_EKINAVEVEL     (1<<2)
-/* we are removing the center of mass momenta */
-#define CGLO_STOPCM         (1<<3)
-/* bGStat is defined in do_md */
-#define CGLO_GSTAT          (1<<4)
-/* Sum the energy terms in global computation */
-#define CGLO_ENERGY         (1<<6)
-/* Sum the kinetic energy terms in global computation */
-#define CGLO_TEMPERATURE    (1<<7)
-/* Sum the kinetic energy terms in global computation */
-#define CGLO_PRESSURE       (1<<8)
-/* Sum the constraint term in global computation */
-#define CGLO_CONSTRAINT     (1<<9)
-/* we are using an integrator that requires iteration over some steps - currently not used*/
-#define CGLO_ITERATE        (1<<10)
-/* it is the first time we are iterating (or, only once through is required */
-#define CGLO_FIRSTITERATE   (1<<11)
-/* Reading ekin from the trajectory */
-#define CGLO_READEKIN       (1<<12)
-/* we need to reset the ekin rescaling factor here */
-#define CGLO_SCALEEKIN      (1<<13)
-  
-enum {
-  ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
-};
-
-typedef struct {
-  double real;
-#ifdef GMX_CRAY_XT3
-  double proc;
-#else
-  clock_t proc;
-#endif
-  double realtime;
-  double proctime;
-  double time_per_step;
-  double last;
-  gmx_large_int_t nsteps_done;
-} gmx_runtime_t;
-
-typedef struct {
-  t_fileio *fp_trn;
-  t_fileio *fp_xtc;
-  int  xtc_prec;
-  ener_file_t fp_ene;
-  const char *fn_cpt;
-  gmx_bool bKeepAndNumCPT;
-  int  eIntegrator;
-  int  simulation_part;
-  FILE *fp_dhdl;
-  FILE *fp_field;
-} gmx_mdoutf_t;
-
-/* Variables for temporary use with the deform option,
- * used in runner.c and md.c.
- * (These variables should be stored in the tpx file.)
- */
-extern gmx_large_int_t     deform_init_init_step_tpx;
-extern matrix              deform_init_box_tpx;
-#ifdef GMX_THREADS
-extern tMPI_Thread_mutex_t deform_init_box_mutex;
-
-/* The minimum number of atoms per thread. With fewer atoms than this,
- * the number of threads will get lowered.
- */
-#define MIN_ATOMS_PER_THREAD    90
-#endif
-
-
-typedef double gmx_integrator_t(FILE *log,t_commrec *cr,
-                               int nfile,const t_filenm fnm[],
-                               const output_env_t oenv, gmx_bool bVerbose,
-                                gmx_bool bCompact, int nstglobalcomm,
-                               gmx_vsite_t *vsite,gmx_constr_t constr,
-                               int stepout,
-                               t_inputrec *inputrec,
-                               gmx_mtop_t *mtop,t_fcdata *fcd,
-                               t_state *state,
-                               t_mdatoms *mdatoms,
-                               t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                               gmx_edsam_t ed, 
-                               t_forcerec *fr,
-                               int repl_ex_nst,int repl_ex_seed,
-                               real cpt_period,real max_hours,
-                               const char *deviceOptions,
-                               unsigned long Flags,
-                               gmx_runtime_t *runtime);
-
-typedef struct gmx_global_stat *gmx_global_stat_t;
-
-/* ROUTINES from md.c */
-
-gmx_integrator_t do_md;
-
-gmx_integrator_t do_md_openmm;
-
-
-
-/* ROUTINES from minimize.c */
-
-gmx_integrator_t do_steep;
-/* Do steepest descents EM */
-
-gmx_integrator_t do_cg;
-/* Do conjugate gradient EM */
-
-gmx_integrator_t do_lbfgs;
-/* Do conjugate gradient L-BFGS */
-
-gmx_integrator_t do_nm;
-/* Do normal mode analysis */
-
-/* ROUTINES from tpi.c */
-
-gmx_integrator_t do_tpi;
-/* Do test particle insertion */
-
-
-/* ROUTINES from md_support.c */
-
-/* return the number of steps between global communcations */
-int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
-                        int nstglobalcomm,t_inputrec *ir);
-
-/* check whether an 'nst'-style parameter p is a multiple of nst, and
-   set it to be one if not, with a warning. */
-void check_nst_param(FILE *fplog,t_commrec *cr,
-                     const char *desc_nst,int nst,
-                     const char *desc_p,int *p);
-
-/* check which of the multisim simulations has the shortest number of
-   steps and return that number of nsteps */
-gmx_large_int_t get_multisim_nsteps(const t_commrec *cr,
-                                    gmx_large_int_t nsteps);
-
-void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
-                         gmx_bool *bNotLastFrame);
-
-/* get the conserved energy associated with the ensemble type*/
-real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state,           
-                                      t_extmass *MassQ);
-
-/* reset all cycle and time counters. */
-void reset_all_counters(FILE *fplog,t_commrec *cr,
-                        gmx_large_int_t step,
-                        gmx_large_int_t *step_rel,t_inputrec *ir,
-                        gmx_wallcycle_t wcycle,t_nrnb *nrnb,
-                        gmx_runtime_t *runtime);
-
-
-
-/* ROUTINES from sim_util.c */
-void do_pbc_first(FILE *log,matrix box,t_forcerec *fr,
-                        t_graph *graph,rvec x[]);
-
-void do_pbc_first_mtop(FILE *fplog,int ePBC,matrix box,
-                             gmx_mtop_t *mtop,rvec x[]);
-
-void do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
-                       gmx_mtop_t *mtop,rvec x[]);
-
-
-                    
-/* ROUTINES from stat.c */
-gmx_global_stat_t global_stat_init(t_inputrec *ir);
-
-void global_stat_destroy(gmx_global_stat_t gs);
-
-void global_stat(FILE *log,gmx_global_stat_t gs,
-                       t_commrec *cr,gmx_enerdata_t *enerd,
-                       tensor fvir,tensor svir,rvec mu_tot,
-                       t_inputrec *inputrec,
-                       gmx_ekindata_t *ekind,
-                       gmx_constr_t constr,t_vcm *vcm,
-                       int nsig,real *sig,
-                       gmx_mtop_t *top_global, t_state *state_local, 
-                       gmx_bool bSumEkinhOld, int flags);
-/* Communicate statistics over cr->mpi_comm_mysim */
-
-gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],
-                                int mdrun_flags,
-                                const t_commrec *cr,const t_inputrec *ir,
-                                const output_env_t oenv);
-/* Returns a pointer to a data structure with all output file pointers
- * and names required by mdrun.
- */
-
-void done_mdoutf(gmx_mdoutf_t *of);
-/* Close all open output files and free the of pointer */
-
-#define MDOF_X   (1<<0)
-#define MDOF_V   (1<<1)
-#define MDOF_F   (1<<2)
-#define MDOF_XTC (1<<3)
-#define MDOF_CPT (1<<4)
-
-void write_traj(FILE *fplog,t_commrec *cr,
-                      gmx_mdoutf_t *of,
-                      int mdof_flags,
-                      gmx_mtop_t *top_global,
-                      gmx_large_int_t step,double t,
-                      t_state *state_local,t_state *state_global,
-                      rvec *f_local,rvec *f_global,
-                      int *n_xtc,rvec **x_xtc);
-/* Routine that writes frames to trn, xtc and/or checkpoint.
- * What is written is determined by the mdof_flags defined above.
- * Data is collected to the master node only when necessary.
- */
-
-int do_per_step(gmx_large_int_t step,gmx_large_int_t nstep);
-/* Return TRUE if io should be done */
-
-int do_any_io(int step, t_inputrec *ir);
-
-/* ROUTINES from sim_util.c */
-
-double gmx_gettime();
-
-void print_time(FILE *out, gmx_runtime_t *runtime,
-                       gmx_large_int_t step,t_inputrec *ir, t_commrec *cr);
-
-void runtime_start(gmx_runtime_t *runtime);
-
-void runtime_end(gmx_runtime_t *runtime);
-
-void runtime_upd_proc(gmx_runtime_t *runtime);
-/* The processor time should be updated every once in a while,
- * since on 32-bit manchines it loops after 72 minutes.
- */
-  
-void print_date_and_time(FILE *log,int pid,const char *title,
-                               const gmx_runtime_t *runtime);
-  
-void nstop_cm(FILE *log,t_commrec *cr,
-                    int start,int nr_atoms,real mass[],rvec x[],rvec v[]);
-
-void finish_run(FILE *log,t_commrec *cr,const char *confout,
-                      t_inputrec *inputrec,
-                      t_nrnb nrnb[],gmx_wallcycle_t wcycle,
-                      gmx_runtime_t *runtime,
-                      gmx_bool bWriteStat);
-
-void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr);
-
-void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
-                         gmx_large_int_t step, int natoms, 
-                         matrix box,real lambda,tensor pres,tensor virial,
-                         real *prescorr, real *enercorr, real *dvdlcorr);
-
-typedef enum
-{
-  LIST_SCALARS =0001,
-  LIST_INPUTREC        =0002,
-  LIST_TOP     =0004,
-  LIST_X       =0010,
-  LIST_V       =0020,
-  LIST_F       =0040,
-  LIST_LOAD    =0100
-} t_listitem;
-
-void check_nnodes_top(char *fn,t_topology *top);
-/* Reset the tpr file to work with one node if necessary */
-
-
-/* check the version */
-void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
-                               t_inputrec *ir,gmx_mtop_t *mtop);
-
-/* Allocate and initialize node-local state entries. */
-void set_state_entries(t_state *state,const t_inputrec *ir,int nnodes);
-
-/* Broadcast the data for a simulation, and allocate node-specific settings
-   such as rng generators. */
-void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
-                          gmx_mtop_t *mtop);
-
-
-void do_constrain_first(FILE *log,gmx_constr_t constr,
-                              t_inputrec *inputrec,t_mdatoms *md,
-                              t_state *state,rvec *f,
-                              t_graph *graph,t_commrec *cr,t_nrnb *nrnb,
-                              t_forcerec *fr, gmx_localtop_t *top, tensor shake_vir); 
-                         
-void dynamic_load_balancing(gmx_bool bVerbose,t_commrec *cr,real capacity[],
-                                  int dimension,t_mdatoms *md,t_topology *top,
-                                  rvec x[],rvec v[],matrix box);
-/* Perform load balancing, i.e. split the particles over processors
- * based on their coordinates in the "dimension" direction.
- */
-
-int multisim_min(const gmx_multisim_t *ms,int nmin,int n);
-/* Set an appropriate value for n across the whole multi-simulation */
-
-int multisim_nstsimsync(const t_commrec *cr,
-                       const t_inputrec *ir,int repl_ex_nst);
-/* Determine the interval for inter-simulation communication */
-                                  
-void init_global_signals(globsig_t *gs,const t_commrec *cr,
-                        const t_inputrec *ir,int repl_ex_nst);
-/* Constructor for globsig_t */
-
-void copy_coupling_state(t_state *statea,t_state *stateb,
-                        gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts);
-/* Copy stuff from state A to state B */
-
-void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir,
-                    t_forcerec *fr, gmx_ekindata_t *ekind,
-                    t_state *state, t_state *state_global, t_mdatoms *mdatoms,
-                    t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
-                    gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir,
-                    tensor pres, rvec mu_tot, gmx_constr_t constr,
-                    globsig_t *gs,gmx_bool bInterSimGS,
-                    matrix box, gmx_mtop_t *top_global, real *pcurr,
-                    int natoms, gmx_bool *bSumEkinhOld, int flags);
-/* Compute global variables during integration */
-
-int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
-             const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
-             gmx_bool bCompact, int nstglobalcomm, ivec ddxyz,int dd_node_order,
-             real rdd, real rconstr, const char *dddlb_opt,real dlb_scale,
-            const char *ddcsx,const char *ddcsy,const char *ddcsz,
-            int nstepout, int resetstep, int nmultisim, int repl_ex_nst,
-             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
-            const char *deviceOptions, unsigned long Flags);
-/* Driver routine, that calls the different methods */
-
-void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf);
-/* Print a warning message to stderr on the master node
- * and to fplog if fplog!=NULL.
- */
-
-void init_md(FILE *fplog,
-                   t_commrec *cr,t_inputrec *ir, const output_env_t oenv, 
-                   double *t,double *t0,
-                   real *lambda,double *lam0,
-                   t_nrnb *nrnb,gmx_mtop_t *mtop,
-                   gmx_update_t *upd,
-                   int nfile,const t_filenm fnm[],
-                   gmx_mdoutf_t **outf,t_mdebin **mdebin,
-                   tensor force_vir,tensor shake_vir,
-                   rvec mu_tot,
-                   gmx_bool *bSimAnn,t_vcm **vcm, 
-                   t_state *state, unsigned long Flags);
-  /* Routine in sim_util.c */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _mdrun_h */
diff --git a/include/mpelogging.h b/include/mpelogging.h
deleted file mode 100644 (file)
index 5a5bea6..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* define USE_MPE if you want MPE logging 
- *
- * you then need to link with the appropriate libraries
- * that come with the mpich distribution (can be found in the
- * mpe subdirectory */
-/* #define USE_MPE */
-
-/* define BARRIERS if you want to have extra MPI_Barriers
- * in the code which might help analyzing the MPE logfiles 
- */
-/* #define BARRIERS */
-#ifdef BARRIERS
-#define GMX_BARRIER(communicator) MPI_Barrier(communicator)
-#else
-#define GMX_BARRIER(communicator)
-#endif
-
-#ifdef USE_MPE
-#define GMX_MPE_LOG(event) MPE_Log_event(event, 0, "")
-#else
-#define GMX_MPE_LOG(event)
-#endif
-
-#ifdef USE_MPE
-#include <mpe.h>
-     /* Define MPE logging events here */
-     /* General events */
-     int ev_timestep1,               ev_timestep2;
-     int ev_ns_start,                ev_ns_finish;
-     int ev_calc_bonds_start,        ev_calc_bonds_finish;
-     int ev_send_coordinates_start,  ev_send_coordinates_finish;
-     int ev_update_fr_start,         ev_update_fr_finish;
-     int ev_clear_rvecs_start,       ev_clear_rvecs_finish;
-     int ev_output_start,            ev_output_finish;
-     int ev_update_start,            ev_update_finish;     
-     int ev_force_start,             ev_force_finish;
-     int ev_do_fnbf_start,           ev_do_fnbf_finish;
-     
-     /* Shift related events*/
-     int ev_shift_start,             ev_shift_finish;     
-     int ev_unshift_start,           ev_unshift_finish;     
-     int ev_mk_mshift_start,         ev_mk_mshift_finish;
-     
-     /* PME related events */
-     int ev_pme_start,               ev_pme_finish;
-     int ev_spread_on_grid_start,    ev_spread_on_grid_finish;
-     int ev_sum_qgrid_start,         ev_sum_qgrid_finish;
-     int ev_gmxfft3d_start,          ev_gmxfft3d_finish;
-     int ev_solve_pme_start,         ev_solve_pme_finish;
-     int ev_gather_f_bsplines_start, ev_gather_f_bsplines_finish;
-     int ev_reduce_start,            ev_reduce_finish;
-     int ev_rscatter_start,          ev_rscatter_finish;
-     int ev_alltoall_start,          ev_alltoall_finish;
-     int ev_pmeredist_start,         ev_pmeredist_finish;
-     int ev_init_pme_start,          ev_init_pme_finish;
-     int ev_global_stat_start,       ev_global_stat_finish;
-     int ev_sum_lrforces_start,      ev_sum_lrforces_finish;
-     int ev_virial_start,            ev_virial_finish;
-     int ev_sort_start,              ev_sort_finish;
-     int ev_sum_qgrid_start,         ev_sum_qgrid_finish;
-     
-     /* Essential dynamics related events */
-     int ev_edsam_start,             ev_edsam_finish;
-     int ev_get_group_x_start,       ev_get_group_x_finish;
-     int ev_ed_apply_cons_start,     ev_ed_apply_cons_finish;
-     int ev_fit_to_reference_start,  ev_fit_to_reference_finish;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/names.h b/include/names.h
deleted file mode 100644 (file)
index a396bda..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _names_h
-#define _names_h
-
-
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* All string arrays are NULL terminated, and therefore have an
- * extra argument (the +1)
- * these should correspond to names.c and include/types/enums.h
- */
-extern const char *epbc_names[epbcNR+1];
-extern const char *etcoupl_names[etcNR+1];
-extern const char *epcoupl_names[epcNR+1];
-extern const char *epcoupltype_names[epctNR+1];
-extern const char *erefscaling_names[erscNR+1];
-extern const char *ens_names[ensNR+1];
-extern const char *ei_names[eiNR+1];
-extern const char *yesno_names[BOOL_NR+1];
-extern const char *bool_names[BOOL_NR+1];
-extern const char *eel_names[eelNR+1];
-extern const char *eewg_names[eewgNR+1];
-extern const char *evdw_names[evdwNR+1];
-extern const char *econstr_names[econtNR+1];
-extern const char *ptype_str[eptNR+1];
-extern const char *egrp_nm[egNR+1];
-extern const char *edisre_names[edrNR+1];
-extern const char *edisreweighting_names[edrwNR+1];
-extern const char *enbf_names[eNBF_NR+1];
-extern const char *ecomb_names[eCOMB_NR+1];
-extern const char *gtypes[egcNR+1];
-extern const char *efep_names[efepNR+1];
-extern const char *separate_dhdl_file_names[efepNR+1];
-extern const char *dhdl_derivatives_names[efepNR+1];
-extern const char *efep_names[efepNR+1];
-extern const char *esol_names[esolNR+1];
-extern const char *enlist_names[enlistNR+1];
-extern const char *edispc_names[edispcNR+1];
-extern const char *ecm_names[ecmNR+1];
-extern const char *eann_names[eannNR+1];
-extern const char *egb_names[egbNR+1];
-extern const char *eis_names[eisNR+1];
-extern const char *esa_names[esaNR+1];
-extern const char *ewt_names[ewtNR+1];
-extern const char *epull_names[epullNR+1];
-extern const char *epullg_names[epullgNR+1];
-extern const char *eQMmethod_names[eQMmethodNR+1];
-extern const char *eQMbasis_names[eQMbasisNR+1];
-extern const char *eQMMMscheme_names[eQMMMschemeNR+1];
-extern const char *eMultentOpt_names[eMultentOptNR+1];
-
-#define        UNDEFINED               "UNDEFINED"
-#define ENUM_NAME(e,max,names) ((((e)<0)||((e)>=(max)))?UNDEFINED:(names)[e])
-
-#define BOOL(e)        ENUM_NAME(e,BOOL_NR,bool_names)
-#define ENS(e)         ENUM_NAME(e,ensNR,ens_names)
-#define EI(e)          ENUM_NAME(e,eiNR,ei_names)
-#define EPBC(e)        ENUM_NAME(e,epbcNR,epbc_names)
-#define ETCOUPLTYPE(e) ENUM_NAME(e,etcNR,etcoupl_names)
-#define EPCOUPLTYPE(e) ENUM_NAME(e,epcNR,epcoupl_names)
-#define EPCOUPLTYPETYPE(e) ENUM_NAME(e,epctNR,epcoupltype_names)
-#define EREFSCALINGTYPE(e) ENUM_NAME(e,erscNR,erefscaling_names)
-#define EBLOCKS(e)     ENUM_NAME(e,ebNR,eblock_names)
-#define EPARAM(e)      ENUM_NAME(e,epNR,eparam_names)
-#define EELTYPE(e)     ENUM_NAME(e,eelNR,eel_names)
-#define EVDWTYPE(e)    ENUM_NAME(e,evdwNR,evdw_names)
-#define ECONSTRTYPE(e) ENUM_NAME(e,econtNR,econstr_names)
-#define EDISRETYPE(e)  ENUM_NAME(e,edrNR,edisre_names)
-#define EDISREWEIGHTING(e)  ENUM_NAME(e,edrwNR,edisreweighting_names)
-#define ENBFNAME(e)    ENUM_NAME(e,eNBF_NR,enbf_names)
-#define ECOMBNAME(e)   ENUM_NAME(e,eCOMB_NR,ecomb_names)
-#define EFEPTYPE(e)    ENUM_NAME(e,efepNR,efep_names)
-#define SEPDHDLFILETYPE(e) ENUM_NAME(e,sepdhdlfileNR,separate_dhdl_file_names)
-#define DHDLDERIVATIVESTYPE(e) ENUM_NAME(e,dhdlderivativesNR,dhdl_derivatives_names)
-#define ESOLTYPE(e)    ENUM_NAME(e,esolNR,esol_names)
-#define ENLISTTYPE(e)  ENUM_NAME(e,enlistNR,enlist_names)
-#define EDISPCORR(e)   ENUM_NAME(e,edispcNR,edispc_names)
-#define ECOM(e)        ENUM_NAME(e,ecmNR,ecm_names)
-#define EANNEAL(e)      ENUM_NAME(e,eannNR,eann_names)
-#define EGBALGORITHM(e) ENUM_NAME(e,egbNR,egb_names)
-#define ESAALGORITHM(e) ENUM_NAME(e,esaNR,esa_names)
-#define EIMPLICITSOL(e) ENUM_NAME(e,eisNR,eis_names)
-#define EWALLTYPE(e)   ENUM_NAME(e,ewtNR,ewt_names)
-#define EPULLTYPE(e)   ENUM_NAME(e,epullNR,epull_names)
-#define EPULLGEOM(e)   ENUM_NAME(e,epullgNR,epullg_names)
-#define EQMMETHOD(e)   ENUM_NAME(e,eQMmethodNR,eQMmethod_names)
-#define EQMBASIS(e)    ENUM_NAME(e,eQMbasisNR,eQMbasis_names)
-#define EQMMMSCHEME(e) ENUM_NAME(e,eQMMMschemeNR,eQMMMscheme_names)
-#define EMULTENTOPT(e) ENUM_NAME(e,eMultentOptNR,eMultentOpt_names)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _names_h */
diff --git a/include/nbsearch.h b/include/nbsearch.h
deleted file mode 100644 (file)
index 5dd7352..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for neighborhood searching.
- *
- * The API is documented in more detail on a separate page:
- * \ref nbsearch
- *
- * The functions within this file can be used independently of the other parts
- * of the library.
- * The library also uses the functions internally.
- */
-#ifndef NBSEARCH_H
-#define NBSEARCH_H
-
-#include "typedefs.h"
-
-#include "indexutil.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct gmx_ana_pos_t;
-
-/** Data structure for neighborhood searches. */
-typedef struct gmx_ana_nbsearch_t gmx_ana_nbsearch_t;
-
-/** Create a new neighborhood search data structure. */
-int
-gmx_ana_nbsearch_create(gmx_ana_nbsearch_t **d, real cutoff, int maxn);
-/** Free memory allocated for neighborhood search. */
-void
-gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d);
-
-/** Initializes neighborhood search for a new frame. */
-int
-gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, rvec x[]);
-/** Initializes neighborhood search for a frame using \c gmx_ana_pos_t.  */
-int
-gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc,
-                          struct gmx_ana_pos_t *p);
-/** Sets the exclusions for the next neighborhood search. */
-int
-gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[]);
-/** Check whether a point is within a neighborhood. */
-gmx_bool
-gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x);
-/** Check whether a position is within a neighborhood. */
-gmx_bool
-gmx_ana_nbsearch_pos_is_within(gmx_ana_nbsearch_t *d,
-                               struct gmx_ana_pos_t *p, int i);
-/** Calculates the minimun distance from the reference points. */
-real
-gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, rvec x);
-/** Calculates the minimun distance from the reference points. */
-real
-gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d,
-                             struct gmx_ana_pos_t *p, int i);
-/** Finds the first reference position within the cutoff. */
-gmx_bool
-gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp);
-/** Finds the first reference position within the cutoff. */
-gmx_bool
-gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d,
-                                  struct gmx_ana_pos_t *p, int i, int *jp);
-/** Finds the next reference position within the cutoff. */
-gmx_bool
-gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/physics.h b/include/physics.h
deleted file mode 100644 (file)
index e72608c..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _physics_h
-#define _physics_h
-
-/*
- * Physical constants to be used in Gromacs.
- * No constants (apart from 0, 1 or 2) should
- * be anywhere else in the code.
- */
-
-#include <math.h>
-
-/* we do it anyway. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef M_PI
-#ifdef _PI
-#define M_PI _PI
-#else
-#define M_PI        3.14159265358979323846
-#endif
-#endif
-
-#define ANGSTROM        (1e-10)                /* Old...       */
-#define KILO            (1e3)                  /* Thousand     */
-#define NANO            (1e-9)                 /* A Number     */
-#define PICO            (1e-12)                /* A Number     */
-#define A2NM            (ANGSTROM/NANO)        /* NANO         */
-#define NM2A            (NANO/ANGSTROM)        /* 10.0         */
-#define RAD2DEG                 (180.0/M_PI)           /* Conversion   */
-#define DEG2RAD                 (M_PI/180.0)           /* id           */
-#define CAL2JOULE       (4.184)                /* id           */
-#define E_CHARGE         (1.60217733e-19)      /* Coulomb      */
-
-#define AMU              (1.6605402e-27)        /* kg           */
-#define BOLTZMANN       (1.380658e-23)         /* (J/K)        */
-#define AVOGADRO        (6.0221367e23)         /* ()           */
-#define RGAS             (BOLTZMANN*AVOGADRO)   /* (J/(mol K))  */
-#define BOLTZ            (RGAS/KILO)            /* (kJ/(mol K)) */
-#define FARADAY          (E_CHARGE*AVOGADRO)    /* (C/mol)      */
-#define ELECTRONVOLT     (E_CHARGE*AVOGADRO/KILO) /* (kJ/mol)   */     
-#define PLANCK1          (6.6262e-34)           /* J s */
-#define PLANCK           (6.6262e-34*AVOGADRO/(PICO*KILO)) /* (kJ/mol) ps */
-
-#define EPSILON0        (5.72765E-4)           /* (e^2 / Na (kJ nm))     
-                                                  == (e^2 mol/(kJ nm)) */
-                                                
-#define SPEED_OF_LIGHT   (2.9979245800E05)      /* nm/ps                */
-#define ATOMICMASS_keV   (940000.0)             /* Atomic mass in keV   */
-#define ELECTRONMASS_keV (512.0)                /* Electron mas in keV  */
-
-/* Improved accuracy (PL & EL, 20090421) */
-#define FACEL           (332.0636930*CAL2JOULE)/* (10 * (ONE_4PI_EPS0)) */
-#define ONE_4PI_EPS0    (FACEL*0.1)            /* 1/(4*pi*e0)*/
-#define PRESFAC           (16.6054)             /* bar / pressure unity */
-#define ENM2DEBYE         48.0321               /* Convert electron nm  *
-                                                * to debye             */
-#define DEBYE2ENM         0.02081941
-/* to convert from a acceleration in (e V)/(amu nm) */
-/* FIELDFAC is also Faraday's constant and E_CHARGE/(1e6 AMU) */
-#define FIELDFAC          (FARADAY/KILO)
-
-/* to convert AU to MD units: */
-#define HARTREE2KJ        4.3597482e-21
-#define BOHR2NM           0.0529177249
-#define HARTREE_BOHR2MD   (HARTREE2KJ*AVOGADRO/BOHR2NM)
-
-
-/* The four basic units */
-#define unit_length   "nm"
-#define unit_time     "ps"
-#define unit_mass     "u"
-#define unit_energy   "kJ/mol"
-
-/* Temperature unit, T in this unit times BOLTZ give energy in unit_energy */
-#define unit_temp_K   "K"
-
-/* Charge unit, electron charge, involves ONE_4PI_EPS0 */
-#define unit_charge_e "e"
-
-/* Pressure unit, pressure in basic units times PRESFAC gives this unit */
-#define unit_pres_bar "bar"
-
-/* Dipole unit, debye, conversion from the unit_charge_e involves ENM2DEBYE */
-#define unit_dipole_D "D"
-
-/* Derived units from basic units only */
-#define unit_vel      unit_length "/" unit_time
-#define unit_volume   unit_length "^3"
-#define unit_invtime  "1/" unit_time
-
-/* Other derived units */
-#define unit_surft_bar unit_pres_bar " " unit_length
-
-/* SI units, conversion from basic units involves NANO, PICO and AMU */
-#define unit_length_SI  "m"
-#define unit_time_SI    "s"
-#define unit_mass_SI    "kg"
-
-#define unit_density_SI unit_mass_SI "/" unit_length_SI "^3"
-#define unit_invvisc_SI unit_length_SI " " unit_time_SI "/" unit_mass_SI
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _physics_h */
-
-
diff --git a/include/poscalc.h b/include/poscalc.h
deleted file mode 100644 (file)
index aaac183..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for structured and optimized calculation of positions.
- *
- * The functions in this header are used internally by the analysis library
- * to calculate positions.
- * They can also be used in user code, but in most cases there should be no
- * need. Instead, one should write an analysis tool such that it gets all
- * positions through selections.
- *
- * \internal
- *
- * The API is documented in more detail on a separate page:
- * \ref poscalcengine.
- */
-#ifndef POSCALC_H
-#define POSCALC_H
-
-#include "typedefs.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*! \name Flags for position calculation.
- * \anchor poscalc_flags
- */
-/*@{*/
-/*! \brief
- * Use mass weighting.
- *
- * If this flag is set, the positions will be calculated using mass weighting,
- * i.e., one gets center-of-mass positions.
- * Without the flag, center-of-geometry positions are calculated.
- * Does not have any effect if the calculation type is \ref POS_ATOM.
- */
-#define POS_MASS        1
-/*! \brief
- * Calculate positions for the same atoms in residues/molecules.
- *
- * If this flag is set, the positions are always calculated using the same
- * atoms for each residue/molecule, even if the evaluation group contains only
- * some of the atoms for some frames.
- * The group passed to gmx_ana_poscalc_set_maxindex() is used to determine
- * the atoms to use for the calculation.
- *
- * Has no effect unless \ref POS_DYNAMIC is set or if the calculation type
- * is not \ref POS_RES of \ref POS_MOL.
- */
-#define POS_COMPLMAX    2
-/*! \brief
- * Calculate positions for whole residues/molecules.
- *
- * If this flag is set, the positions will be calculated for whole
- * residues/molecules, even if the group contains only some of the atoms in
- * the residue/molecule.
- *
- * Has no effect unless the calculation type is \ref POS_RES or \ref POS_MOL.
- */
-#define POS_COMPLWHOLE  4
-/*! \brief
- * Enable handling of changing calculation groups.
- *
- * Can be used for static calculations as well, but implies a small
- * performance penalty.
- */
-#define POS_DYNAMIC     16
-/*! \brief
- * Update \c gmx_ana_pos_t::m dynamically for an otherwise static
- * calculation.
- *
- * Has effect only if \ref POS_DYNAMIC is not set.
- */
-#define POS_MASKONLY    32
-/*! \brief
- * Calculate velocities of the positions.
- */
-#define POS_VELOCITIES  64
-/*! \brief
- * Calculate forces on the positions.
- */
-#define POS_FORCES      128
-/*@}*/
-
-/** Specifies the type of positions to be calculated. */
-typedef enum
-{
-    POS_ATOM,    /**< Copy atomic coordinates. */
-    POS_RES,     /**< Calculate center for each residue. */
-    POS_MOL,     /**< Calculate center for each molecule. */
-    POS_ALL,     /**< Calculate center for the whole group. */
-    POS_ALL_PBC  /**< Calculate center for the whole group with PBC. */
-} e_poscalc_t;
-
-/** Collection of \c gmx_ana_poscalc_t structures for the same topology. */
-typedef struct gmx_ana_poscalc_coll_t gmx_ana_poscalc_coll_t;
-/** Data structure for position calculation. */
-typedef struct gmx_ana_poscalc_t gmx_ana_poscalc_t;
-
-struct gmx_ana_index_t;
-struct gmx_ana_pos_t;
-
-/** Converts a string to parameters for gmx_ana_poscalc_create(). */
-int
-gmx_ana_poscalc_type_from_enum(const char *post, e_poscalc_t *type, int *flags);
-/** Creates a list of strings for position enum parameter handling. */
-const char **
-gmx_ana_poscalc_create_type_enum(gmx_bool bAtom);
-
-/** Creates a new position calculation collection object. */
-int
-gmx_ana_poscalc_coll_create(gmx_ana_poscalc_coll_t **pccp);
-/** Sets the topology for a position calculation collection. */
-void
-gmx_ana_poscalc_coll_set_topology(gmx_ana_poscalc_coll_t *pcc, t_topology *top);
-/** Frees memory allocated for a position calculation collection. */
-void
-gmx_ana_poscalc_coll_free(gmx_ana_poscalc_coll_t *pcc);
-/** Prints information about calculations in a position calculation collection. */
-void
-gmx_ana_poscalc_coll_print_tree(FILE *fp, gmx_ana_poscalc_coll_t *pcc);
-
-/** Creates a new position calculation. */
-int
-gmx_ana_poscalc_create(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
-                       e_poscalc_t type, int flags);
-/** Creates a new position calculation based on an enum value. */
-int
-gmx_ana_poscalc_create_enum(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
-                            const char *post, int flags);
-/** Sets the flags for position calculation. */
-void
-gmx_ana_poscalc_set_flags(gmx_ana_poscalc_t *pc, int flags);
-/** Sets the maximum possible input index group for position calculation. */
-void
-gmx_ana_poscalc_set_maxindex(gmx_ana_poscalc_t *pc, struct gmx_ana_index_t *g);
-/** Initializes positions for position calculation output. */
-void
-gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, struct gmx_ana_pos_t *p);
-/** Frees the memory allocated for position calculation. */
-void
-gmx_ana_poscalc_free(gmx_ana_poscalc_t *pc);
-/** Returns TRUE if the position calculation requires topology information. */
-gmx_bool
-gmx_ana_poscalc_requires_top(gmx_ana_poscalc_t *pc);
-
-/** Initializes evaluation for a position calculation collection. */
-void
-gmx_ana_poscalc_init_eval(gmx_ana_poscalc_coll_t *pcc);
-/** Initializes a position calculation collection for a new frame. */
-void
-gmx_ana_poscalc_init_frame(gmx_ana_poscalc_coll_t *pcc);
-/** Updates a single COM/COG structure for a frame. */
-void
-gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc,
-                       struct gmx_ana_pos_t *p, struct gmx_ana_index_t *g,
-                       t_trxframe *fr, t_pbc *pbc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/position.h b/include/position.h
deleted file mode 100644 (file)
index 4e27d51..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for handling positions.
- */
-#ifndef POSITION_H
-#define POSITION_H
-
-#include "typedefs.h"
-
-#include "indexutil.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*! \brief
- * Stores a set of positions together with their origins.
- */
-typedef struct gmx_ana_pos_t
-{
-    /*! \brief
-     * Number of positions.
-     */
-    int                 nr;
-    /*! \brief
-     * Array of positions.
-     */
-    rvec               *x;
-    /*! \brief
-     * Velocities (can be NULL).
-     */
-    rvec               *v;
-    /*! \brief
-     * Forces (can be NULL).
-     */
-    rvec               *f;
-    /*! \brief
-     * Mapping of the current positions to the original group.
-     *
-     * \see gmx_ana_indexmap_t
-     */
-    gmx_ana_indexmap_t  m;
-    /*! \brief
-     * Pointer to the current evaluation group.
-     */
-    gmx_ana_index_t    *g;
-    /*! \brief
-     * Number of elements allocated for \c x.
-     */
-    int                 nalloc_x;
-} gmx_ana_pos_t;
-
-/** Initializes an empty position structure. */
-void
-gmx_ana_pos_clear(gmx_ana_pos_t *pos);
-/** Ensures that enough memory has been allocated to store positions. */
-void
-gmx_ana_pos_reserve(gmx_ana_pos_t *pos, int n, int isize);
-/** Request memory allocation for velocities. */
-void
-gmx_ana_pos_reserve_velocities(gmx_ana_pos_t *pos);
-/** Request memory allocation for forces. */
-void
-gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos);
-/** Initializes a \c gmx_ana_pos_t to represent a constant position. */
-void
-gmx_ana_pos_init_const(gmx_ana_pos_t *pos, rvec x);
-/** Frees the memory allocated for position storage. */
-void
-gmx_ana_pos_deinit(gmx_ana_pos_t *pos);
-/** Frees the memory allocated for positions. */
-void
-gmx_ana_pos_free(gmx_ana_pos_t *pos);
-/** Copies the evaluated positions to a preallocated data structure. */
-void
-gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, gmx_bool bFirst);
-
-/** Sets the number of positions in a position structure. */
-void
-gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int n);
-/** Sets the evaluation group of a position data structure. */
-void
-gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g);
-/** Empties a position data structure with full initialization. */
-void
-gmx_ana_pos_empty_init(gmx_ana_pos_t *pos);
-/** Empties a position data structure. */
-void
-gmx_ana_pos_empty(gmx_ana_pos_t *pos);
-/** Appends a position to a preallocated data structure with full
- * initialization. */
-void
-gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                        gmx_ana_pos_t *src, int i);
-/** Appends a position to a preallocated data structure. */
-void
-gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                   gmx_ana_pos_t *src, int i, int refid);
-/** Updates position data structure state after appends. */
-void
-gmx_ana_pos_append_finish(gmx_ana_pos_t *pos);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/selection.h b/include/selection.h
deleted file mode 100644 (file)
index 0b2fbe8..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for handling selection (the \c gmx_ana_selection_t structure and related functions).
- *
- * There should be no need to use the data structures or call the
- * functions in this file directly unless using the selection routines outside
- * the main trajectory analysis API.
- */
-#ifndef SELECTION_H
-#define SELECTION_H
-
-#include "position.h"
-#include "indexutil.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/** Information for a collection of selections. */
-typedef struct gmx_ana_selcollection_t gmx_ana_selcollection_t;
-
-struct gmx_ana_poscalc_coll_t;
-
-/** Defines the type of covered fraction. */
-typedef enum
-{
-    CFRAC_NONE,         /**< No covered fraction (everything covered). */
-    CFRAC_SOLIDANGLE    /**< Fraction of a solid (3D) angle covered. */
-} e_coverfrac_t;
-
-/*! \brief
- * Describes a single selection.
- */
-typedef struct gmx_ana_selection_t
-{
-    /** Name of the selection. */
-    char                   *name;
-    /** The actual selection string. */
-    char                   *selstr;
-    /** Selected positions. */
-    gmx_ana_pos_t           p;
-    /** Masses associated with the positions. */
-    real                   *m;
-    /** Charges associated with the positions. */
-    real                   *q;
-    /** Pointer to the index group that holds the selected atoms. */
-    struct gmx_ana_index_t *g;
-    /** TRUE if the value can change as a function of time. */
-    gmx_bool                    bDynamic;
-    /** Type of the covered fraction. */
-    e_coverfrac_t           cfractype;
-    /** TRUE if the covered fraction depends on the frame. */
-    gmx_bool                    bCFracDyn;
-    /** Covered fraction of the selection for the current frame. */
-    real                    cfrac;
-    /** The average covered fraction (over the trajectory). */
-    real                    avecfrac;
-
-    /*! \brief
-     * Pointer to the root of the selection element tree (internal use only).
-     *
-     * \internal
-     * This field is NULL if the selection has been loaded directly from an
-     * index file.
-     */
-    struct t_selelem       *selelem;
-    /** Original masses of all possible positions (internal use only). */
-    real                   *orgm;
-    /** Original charges of all possible positions (internal use only). */
-    real                   *orgq;
-} gmx_ana_selection_t;
-
-/** Frees the memory allocated for a selection. */
-void
-gmx_ana_selection_free(gmx_ana_selection_t *sel);
-/** Returns the name of a selection. */
-char *
-gmx_ana_selection_name(gmx_ana_selection_t *sel);
-/** Prints out the selection information. */
-void
-gmx_ana_selection_print_info(gmx_ana_selection_t *sel);
-/** Initializes the information for covered fraction. */
-gmx_bool
-gmx_ana_selection_init_coverfrac(gmx_ana_selection_t *sel, e_coverfrac_t type);
-
-/** Creates a new empty selection collection. */
-int
-gmx_ana_selcollection_create(gmx_ana_selcollection_t **sc,
-                             struct gmx_ana_poscalc_coll_t *pcc);
-/** Frees the memory allocated for a selection collection. */
-void
-gmx_ana_selcollection_free(gmx_ana_selcollection_t *sc);
-/** Sets the default reference position handling for a selection collection. */
-void
-gmx_ana_selcollection_set_refpostype(gmx_ana_selcollection_t *sc, const char *type);
-/** Sets the default output position handling for a selection collection. */
-void
-gmx_ana_selcollection_set_outpostype(gmx_ana_selcollection_t *sc,
-                                     const char *type, gmx_bool bMaskOnly);
-/** Request evaluation of velocities for selections. */
-void
-gmx_ana_selcollection_set_veloutput(gmx_ana_selcollection_t *sc,
-                                    gmx_bool bVelOut);
-/** Request evaluation of forces for selections. */
-void
-gmx_ana_selcollection_set_forceoutput(gmx_ana_selcollection_t *sc,
-                                      gmx_bool bForceOut);
-/** Sets the topology for a selection collection. */
-int
-gmx_ana_selcollection_set_topology(gmx_ana_selcollection_t *sc, t_topology *top,
-                                   int natoms);
-/** Returns the number of selections specified by a selection collection. */
-int
-gmx_ana_selcollection_get_count(gmx_ana_selcollection_t *sc);
-/** Returns a selection by index. */
-gmx_ana_selection_t *
-gmx_ana_selcollection_get_selection(gmx_ana_selcollection_t *sc, int i);
-/** Returns TRUE if the collection requires topology information for evaluation. */
-gmx_bool
-gmx_ana_selcollection_requires_top(gmx_ana_selcollection_t *sc);
-/** Prints a human-readable version of the internal selection element tree. */
-void
-gmx_ana_selcollection_print_tree(FILE *fp, gmx_ana_selcollection_t *sc, gmx_bool bValues);
-/** Prints the selection strings into an XVGR file as comments. */
-void
-xvgr_selcollection(FILE *fp, gmx_ana_selcollection_t *sc, 
-                   const output_env_t oenv);
-
-/* In parsetree.c */
-/** Parses selection(s) from standard input. */
-int
-gmx_ana_selcollection_parse_stdin(gmx_ana_selcollection_t *sc, int nr,
-                                  gmx_ana_indexgrps_t *grps,
-                                  gmx_bool bInteractive);
-/** Parses selection(s) from a file. */
-int
-gmx_ana_selcollection_parse_file(gmx_ana_selcollection_t *sc, const char *fnm,
-                                  gmx_ana_indexgrps_t *grps);
-/** Parses selection(s) from a string. */
-int
-gmx_ana_selcollection_parse_str(gmx_ana_selcollection_t *sc, const char *str,
-                                gmx_ana_indexgrps_t *grps);
-
-/* In compiler.c */
-/** Set debugging flag for selection compilation. */
-void
-gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, gmx_bool bDebug);
-/** Prepares the selections for evaluation and performs some optimizations. */
-int
-gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc);
-
-/* In evaluate.c */
-/** Evaluates the selection. */
-int
-gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
-                               t_trxframe *fr, t_pbc *pbc);
-/** Evaluates the largest possible index groups from dynamic selections. */
-int
-gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/selmethod.h b/include/selmethod.h
deleted file mode 100644 (file)
index f47dc37..0000000
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \page selmethods Custom selection methods
- *
- * Custom selection methods are defined by creating a new instance of 
- * \c gmx_ana_selmethod_t and filling it with the necessary data for handling
- * the selection.
- * The structure contains callback pointers that define the actual behavior
- * of the method.
- * The following sections discuss how the structure should be filled and how
- * to implement the callbacks.
- *
- *
- * \section selmethods_define \c gmx_ana_selmethod_t data structure
- *
- * An example \c gmx_ana_selmethod_t definition could look like this:
- *
- * \code
- * gmx_ana_selmethod_t sm_example = {
- *   "example", GROUP_VALUE, 0,
- *   asize(sm_params_example), sm_params_example,
- *   &init_data_example,
- *    NULL,
- *   &init_example,
- *    NULL,
- *   &free_data_example,
- *   &init_frame_example,
- *   &evaluate_example,
- *    NULL,
- *   {"example from POS_EXPR [cutoff REAL]", 0, NULL},
- * };
- * \endcode
- *
- * The first value defines the name of the method.
- * It is used mostly for informational purposes; the actual name(s) recognized
- * by the selection parser are defined by the call to
- * gmx_ana_selmethod_register() (see \ref selmethods_register).
- *
- * The second value defines the type of the value the method returns.
- * Possible values are
- *  - \ref NO_VALUE : This is allowed only for methods that have the flag
- *    \ref SMETH_MODIFIER set (see \ref selmethods_modifiers).
- *  - \ref INT_VALUE : The method returns one or more integer values.
- *  - \ref REAL_VALUE : The method returns one or more floating-point values.
- *  - \ref STR_VALUE : The method returns one or more strings.
- *  - \ref POS_VALUE : The method returns one or more 3D vectors.
- *  - \ref GROUP_VALUE : The method returns a single index group.
- *
- * The third value gives additional information about the method using
- * a combination of flags.
- * Possible flags are:
- *  - \ref SMETH_REQTOP : If set, the topology information is always loaded
- *    and the \p top pointer passed to the callbacks is guaranteed to be
- *    non-NULL. Should be set if the method requires topology information
- *    for evaluation.
- *  - \ref SMETH_DYNAMIC : If set, the method can only be evaluated dynamically,
- *    i.e., it requires data from the trajectory frame.
- *  - \ref SMETH_MODIFIER : If set, the method is a selection modifier and
- *    not an actual selection method.
- *    For more details, see \ref selmethods_modifiers.
- *
- * There are two additional flags that specify the number of values the
- * method returns. Only one of them can be set at a time.
- * If neither is set, the default behavior is to evaluate a value for each
- * input atom (except for \ref GROUP_VALUE methods, which always return a
- * single group).
- * Other behaviors can be specified with these flags:
- *  - \ref SMETH_SINGLEVAL : If set, the method evaluates to a single value.
- *    This is automatically set if the type is \ref GROUP_VALUE.
- *  - \ref SMETH_VARNUMVAL : If set, the method evaluates to an arbitrary
- *    number of values.
- *    The number of values is determined based on the values given by the user
- *    to the method parameters (see \ref selmethods_params).
- *  .
- * If either of these flags is specified (and the method type is not
- * \ref GROUP_VALUE), the group passed to the evaluation callback should not
- * be used as it can be NULL.
- * Currently, the above flags only work (have been tested) for \ref POS_VALUE
- * methods.
- *
- * There is one additional flag that can only be specified for \ref STR_VALUE
- * methods: \ref SMETH_CHARVAL . It is meant for to ease implementation of
- * methods that evaluate to strings consisting of single characters.
- *
- * The next two values determine the number of parameters and a pointer to
- * the parameter array. The contents of the parameter array are described in
- * \ref selmethods_params. If the method does not take parameters, the first
- * value should be 0 and the second can be NULL.
- * Currently, \ref STR_VALUE methods cannot take parameters, but this limitation
- * should be easy to lift if required.
- *
- * These are followed by function callbacks that determine the
- * actual behavior of the method. Any of these except the evaluation callback
- * can be NULL (the evaluation callback can also be NULL if \ref NO_VALUE is
- * specified for a selection modifier). However, the presence of parameters
- * can require some of the callbacks to be implemented.
- * The details are described in \ref selmethods_callbacks.
- *
- * Finally, there is a data structure that gives help texts for the method.
- *
- * The \c gmx_ana_selmethod_t variable should be declared as a global variable
- * or it should be otherwise ensured that the structure is not freed: only a
- * pointer to the structure is stored by the library.
- *
- *
- * \section selmethods_params Defining parameters
- *
- * Parameters to selection methods are defined in a separate array of
- * \c gmx_ana_selparam_t structures.
- * The order of the parameters does not matter (except possibly for callback
- * implementation), with one important exception:
- * If the method evaluates to a \ref POS_VALUE, the first parameter should 
- * have \ref GROUP_VALUE and be the one that is used to calculate the
- * positions.
- *
- * An example parameter definition:
- * \code
- * static gmx_ana_selparam_t sm_params_example[] = {
- *   {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
- *   {"from",   {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
- * };
- * \endcode
- *
- * The first value gives the name of the parameter.
- * The first parameter can have a NULL name, which means that the value should
- * immediately follow the method name. This can be used to specify methods
- * of the type 'within 5 of ...'.
- *
- * The second value specifies the type of the value that the parameter accepts.
- * \ref NO_VALUE can be used to specify a boolean parameter, other possibilities
- * are the same as for the selection method type.
- *
- * The third value gives the number of values that the parameter accepts.
- * For boolean parameters (\ref NO_VALUE), it should be 0.
- * For parameters with \ref SPAR_VARNUM of \ref SPAR_ATOMVAL, it should be set
- * to -1 for consistency (it is not used).
- * If \ref SPAR_RANGES is specified, it should be either 1 (to accept a single
- * continuous range) or -1 (if combined with \ref SPAR_VARNUM).
- * In all other cases, it should be a positive integer; in most cases, it
- * should be 1.
- *
- * The nest two pointers should always be NULL (they should be initialized in
- * the callbacks), except the first pointer in the case of \ref SPAR_ENUMVAL
- * (see below).
- *
- * The final value gives additional information about the acceptable values
- * for the parameter using a combination of flags.
- * The possible flags are:
- *  - \ref SPAR_OPTIONAL : If set, the user does not need to provide a value
- *    for the parameter. If not set, an error is reported if the parameter
- *    is not specified by the user.
- *  - \ref SPAR_DYNAMIC : If set, the method can handle dynamic values for
- *    the parameter, i.e., the value(s) can be given by an expression that
- *    evaluates to different values for different frames.
- *  - \ref SPAR_RANGES : Can be set only for \ref INT_VALUE and
- *    \ref REAL_VALUE parameters,
- *    and cannot be combined with \ref SPAR_DYNAMIC.
- *    If set, the parameter accepts ranges of values.
- *    The ranges are automatically sorted and compacted such that a minimum
- *    amount of non-overlapping ranges are given for the method.
- *  - \ref SPAR_VARNUM : If set, the parameter can have a variable number
- *    of values. These can be provided by the user as a list of values, or
- *    using a single \ref SMETH_VARNUMVAL (or a single \ref SMETH_SINGLEVAL)
- *    method.
- *  - \ref SPAR_ATOMVAL : If set, the parameter accepts either a single value
- *    or an expression that evaluates to a value for each input atom.
- *    The single input value is treated as if the same value was returned for
- *    each atom.
- *    Cannot be combined with \ref SPAR_RANGES or \ref SPAR_VARNUM.
- *  - \ref SPAR_ENUMVAL : Can only be set for \ref STR_VALUE parameters that
- *    take a single value, and cannot be combined with any other flag than
- *    \ref SPAR_OPTIONAL. If set, the parameter only accepts one of predefined
- *    string values. See \ref SPAR_ENUMVAL documentation for details on how
- *    to specify the acceptable values.
- *
- *
- * \section selmethods_callbacks Implementing callbacks
- *
- * There are eight differen callback functions that can be implemented for
- * selection methods: sel_datafunc(), sel_posfunc(), sel_initfunc(),
- * sel_outinitfunc(), sel_freefunc(), sel_framefunc(), and two update functions.
- * They are in this order in the \c gmx_ana_selmethod_t data structure.
- * In general, any of the callbacks can be NULL, but the presence of
- * parameters or other callbacks imposes some restrictions:
- *  - sel_datafunc() should be provided if the method takes parameters.
- *  - sel_initfunc() should be provided if the method takes
- *    any parameters with the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flags,
- *    except if those parameters have a \ref POS_VALUE.
- *  - sel_outinitfunc() should be provided for \ref POS_VALUE methods
- *    and \ref SMETH_VARNUMVAL methods.
- *  - sel_freefunc() should be provided if sel_datafunc() and/or
- *    sel_initfunc() allocate any dynamic memory in addition to the data
- *    structure itself.
- *  - sel_updatefunc_pos() only makes sense for methods with \ref SMETH_DYNAMIC
- *    set.
- *  - At least one update function should be provided unless the method type is
- *    \ref NO_VALUE.
- *
- * The documentations for the function pointer types provide more information
- * about how the callbacks should be implemented.
- *
- *
- * \section selmethods_modifiers Selection modifiers
- *
- * Selection modifiers are a special kind of selection methods that can be
- * appended to the end of a selection. They are specified by adding the
- * \ref SMETH_MODIFIER flag to the \c gmx_ana_selmethod_t.
- * They can have two different types:
- *  - \ref POS_VALUE : These modifiers are given the final positions
- *    as an input, and they can make modifications to the selection that are
- *    not possible otherwise (e.g., permute the atoms).
- *    The modifier should implement sel_updatefunc_pos() and also have
- *    one NULL parameter in the beginning of the parameter list that takes
- *    \ref POS_VALUE and is used to give the input positions.
- *  - \ref NO_VALUE : These modifiers do not modify the final selection, but
- *    can be used to implement per-selection options for analysis tools
- *    or to control the default behavior of the selection engine
- *    (currently, such a framework is not implemented, but should be easy to
- *    implement if required).
- *    
- * In addition to restricting the type of the method, selection modifiers
- * do not allow the flags \ref SMETH_SINGLEVAL and \ref SMETH_VARNUMVAL
- * (they would not make sense).
- *
- * Parameters and callbacks should be implemented as with normal selection
- * method, but beware that very little of the functionality has been tested.
- * 
- * \todo
- * The modifier handling could be made more flexible and more generic;
- * the current implementation does not allow many things which would be
- * possible with slight changes in the internals of the library.
- *
- *
- * \section selmethods_register Registering the method
- *
- * After defining the method with \c gmx_ana_selmethod_t, it should be
- * registered with the selection engine.
- * In analysis programs, this can be done by calling
- * gmx_ana_selmethod_register().
- * If adding the method to the library, you should add a pointer to the new
- * method structure into the \c smtable_def array (in \ref selmethod.c
- * "selmethod.c"), and it is registered automatically.
- * In both cases, gmx_ana_selmethod_register() does several checks on the
- * structure and reports any errors or inconsistencies it finds.
- */
-/*! \file
- * \brief API for handling selection methods.
- *
- * There should be no need to use the data structures or call the
- * functions in this file directly unless implementing a custom selection
- * method.
- *
- * Instructions for implementing custom selection methods can be found
- * on a separate page: \ref selmethods
- */
-#ifndef SELMETHOD_H
-#define SELMETHOD_H
-
-#include "typedefs.h"
-
-#include "indexutil.h"
-#include "selparam.h"
-#include "selvalue.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-struct gmx_ana_pos_t;
-struct gmx_ana_poscalc_coll_t;
-struct gmx_ana_selcollection_t;
-
-/*! \name Selection method flags
- * \anchor selmethod_flags
- */
-/*@{*/
-/*! \brief
- * If set, the method requires topology information.
- */
-#define SMETH_REQTOP     1
-/*! \brief
- * If set, the method can only be evaluated dynamically.
- */
-#define SMETH_DYNAMIC    2
-/*! \brief
- * If set, the method evaluates to a single value.
- *
- * The default is that the method evaluates to a value for each input atom.
- * Cannot be combined with \ref SMETH_VARNUMVAL.
- */
-#define SMETH_SINGLEVAL  4
-/*! \brief
- * If set, the method evaluates to an arbitrary number of values.
- *
- * The default is that the method evaluates to a value for each input atom.
- * Cannot be combined with \ref SMETH_SINGLEVAL or with \ref GROUP_VALUE.
- */
-#define SMETH_VARNUMVAL  8
-/*! \brief
- * If set, the method evaluates to single-character strings.
- *
- * This flag can only be set for \ref STR_VALUE methods. If it is set, the
- * selection engine automatically allocates and frees the required strings.
- * The evaluation function should store the character values as the first
- * character in the strings in the output data structure and should not change
- * the string pointers.
- */
-#define SMETH_CHARVAL    64
-/*! \brief
- * If set, the method is a selection modifier.
- *
- * The method type should be \ref GROUP_VALUE or \ref NO_VALUE .
- * Cannot be combined with \ref SMETH_SINGLEVAL or \ref SMETH_VARNUMVAL .
- */
-#define SMETH_MODIFIER   256
-/*@}*/
-
-/*! \brief
- * Allocates and initializes internal data and parameter values.
- *
- * \param[in]     npar  Number of parameters in \p param.
- * \param[in,out] param Pointer to (a copy of) the method's
- *   \c gmx_ana_selmethod_t::param.
- * \returns       Pointer to method-specific data structure.
- *   This pointer will be passed as the last parameter of all other function
- *   calls.
- *   Should return NULL on error (only error that should occur is out of
- *   memory).
- *
- * Should allocate and initialize any internal data required by the method.
- * Should also initialize the value pointers (\c gmx_ana_selparam_t::val) in
- * \p param to point to variables within the internal data structure,
- * with the exception of parameters that specify the \ref SPAR_VARNUM or
- * the \ref SPAR_ATOMVAL flag (these should be handled in sel_initfunc()).
- * However, parameters with a position value should be initialized.
- * It is also possible to initialize \ref SPAR_ENUMVAL statically outside
- * this function (see \ref SPAR_ENUMVAL).
- * The \c gmx_ana_selparam_t::nvalptr should also be initialized for
- * non-position-valued parameters that have both \ref SPAR_VARNUM and
- * \ref SPAR_DYNAMIC set (it can also be initialized for other parameters if
- * desired, but the same information will be available through other means).
- * For optional parameters, the default values can (and should) be initialized
- * here, as the parameter values are not changed if the parameter is not
- * provided.
- *
- * For boolean parameters (type equals \ref NO_VALUE), the default value
- * should be set here. The user can override the value by giving the parameter
- * either as 'NAME'/'noNAME', or as 'NAME on/off/yes/no'.
- *
- * If the method takes any parameters, this function must be provided.
- */
-typedef void *(*sel_datafunc)(int npar, gmx_ana_selparam_t *param);
-/*! \brief
- * Sets the position calculation collection for the method.
- *
- * \param[in]  pcc   Position calculation collection that the method should use
- *   for position calculations.
- * \param      data  Internal data structure from sel_datafunc().
- *
- * This function should be provided if the method uses the routines from
- * poscalc.h for calculating positions.
- * The pointer \p pcc should then be stored and used for initialization for
- * any position calculation structures.
- */
-typedef void  (*sel_posfunc)(struct gmx_ana_poscalc_coll_t *pcc, void *data);
-/*! \brief
- * Does initialization based on topology and/or parameter values.
- *
- * \param[in]  top   Topology structure
- *   (can be NULL if \ref SMETH_REQTOP is not set).
- * \param[in]  npar  Number of parameters in \p param.
- * \param[in]  param Pointer to (an initialized copy of) the method's
- *   \c gmx_ana_selmethod_t::param.
- * \param      data  Internal data structure from sel_datafunc().
- * \returns    0 on success, a non-zero error code on failure.
- *
- * This function is called after the parameters have been processed:
- * the values of the parameters are stored at the locations set in
- * sel_datafunc().
- * The flags \ref SPAR_DYNAMIC and \ref SPAR_ATOMVAL are cleared before
- * calling the function if the value is static or single-valued, respectively.
- * If a parameter had the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flag (and
- * is not \ref POS_VALUE), a pointer to the memory allocated for the values is
- * found in \c gmx_ana_selparam_t::val.
- * The pointer should be stored by this function, otherwise the values
- * cannot be accessed.
- * For \ref SPAR_VARNUM parameters, the number of values can be accessed
- * through \c gmx_ana_selparam_t::val. For parameters with \ref SPAR_DYNAMIC,
- * the number is the maximum number of values (the actual number can be
- * accessed in sel_framefunc() and in the update callback through the value
- * pointed by \c gmx_ana_selparam_t::nvalptr).
- * For \ref SPAR_ATOMVAL parameters, \c gmx_ana_selparam_t::val::nr is set to
- * 1 if a single value was provided, otherwise it is set to the maximum number
- * of values possibly passed to the method.
- * The value pointed by \c gmx_ana_selparam_t::nvalptr always contains the same
- * value as \c gmx_ana_selparam_t::val::nr.
- *
- * For dynamic \ref GROUP_VALUE parameters (\ref SPAR_DYNAMIC set), the value
- * will be the largest possible selection that may occur during the
- * evaluation. For other types of dynamic parameters, the values are
- * undefined.
- *
- * If the method takes any parameters with the \ref SPAR_VARNUM or
- * \ref SPAR_ATOMVAL flags, this function must be provided, except if these
- * parameters all have \ref POS_VALUE.
- *
- * This function may be called multiple times for the same method if the
- * method takes parameters with \ref SPAR_ATOMVAL set.
- */
-typedef int   (*sel_initfunc)(t_topology *top, int npar,
-                              gmx_ana_selparam_t *param, void *data);
-/*! \brief
- * Initializes output data structure.
- *
- * \param[in]     top   Topology structure
- *   (can be NULL if \ref SMETH_REQTOP is not set).
- * \param[in,out] out   Output data structure.
- * \param[in]     data  Internal data structure from sel_datafunc().
- * \returns       0 on success, an error code on error.
- *
- * This function is called immediately after sel_initfunc().
- *
- * If the method evaluates to a position (\ref POS_VALUE), this function
- * should be provided, and it should initialize the \c gmx_ana_pos_t data
- * structure pointed by \p out.p (the pointer is guaranteed to be non-NULL).
- * The \p out.p->g pointer should be initialized to the group that is used
- * to evaluate positions in sel_updatefunc() or sel_updatefunc_pos().
- *
- * The function should also be provided for non-position-valued
- * \ref SMETH_VARNUMVAL methods. For these methods, it suffices to set the
- * \p out->nr field to reflect the maximum number of values returned by the
- * method.
- *
- * Currently, this function is not needed for other types of methods.
- *
- * This function may be called multiple times for the same method if the
- * method takes parameters with \ref SPAR_ATOMVAL set.
- */
-typedef int   (*sel_outinitfunc)(t_topology *top, gmx_ana_selvalue_t *out,
-                                 void *data);
-/*! \brief
- * Frees the internal data.
- *
- * \param[in] data Internal data structure from sel_datafunc().
- *
- * This function should be provided if the internal data structure contains
- * dynamically allocated data, and should free any such data.
- * The data structure itself should not be freed; this is handled automatically.
- * If there is no dynamically allocated data within the structure,
- * this function is not needed.
- * Any memory pointers received as values of parameters are managed externally,
- * and should not be freed.
- * Pointers set as the value pointer of \ref SPAR_ENUMVAL parameters should not
- * be freed.
- */
-typedef void  (*sel_freefunc)(void *data);
-
-/*! \brief
- * Initializes the evaluation for a new frame.
- *
- * \param[in]  top  Topology structure
- *   (can be NULL if \ref SMETH_REQTOP is not set).
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  Initialized periodic boundary condition structure,
- *   or NULL if PBC should not be used.
- * \param      data Internal data structure from sel_datafunc().
- * \returns    0 on success, a non-zero error code on failure.
- *
- * This function should be implemented if the selection method needs to
- * do some preprocessing for each frame, and the preprocessing does not
- * depend on the evaluation group.
- * Because \p sel_updatefunc_* can be called more than once for a frame,
- * it is inefficient do the preprocessing there.
- * It is ensured that this function will be called before
- * \p sel_updatefunc_* for each frame, and that it will be called at most
- * once for each frame.
- * For static methods, it is called once, with \p fr and \p pbc set to
- * NULL.
- */
-typedef int   (*sel_framefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                               void *data);
-/*! \brief
- * Evaluates a selection method.
- *
- * \param[in]  top  Topology structure
- *   (can be NULL if \ref SMETH_REQTOP is not set).
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  Initialized periodic boundary condition structure,
- *   or NULL if PBC should not be used.
- * \param[in]  g    Index group for which the method should be evaluated.
- * \param[out] out  Output data structure.
- * \param      data Internal data structure from sel_datafunc().
- * \returns    0 on success, a non-zero error code on error.
- *
- * This function should evaluate the method for each atom included in \p g,
- * and write the output to \p out. The pointer in the union \p out->u that
- * corresponds to the type of the method should be used.
- * Enough memory has been allocated to store the output values.
- * The number of values in \p out should also be updated if necessary.
- * However, \ref POS_VALUE or \ref GROUP_VALUE methods should not touch
- * \p out->nr (it should be 1 anyways).
- *
- * For \ref STR_VALUE methods, the pointers stored in \p out->s are discarded
- * without freeing; it is the responsibility of this function to provide
- * pointers that can be discarded without memory leaks.
- */
-typedef int   (*sel_updatefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                                gmx_ana_index_t *g, gmx_ana_selvalue_t *out,
-                                void *data);
-/*! \brief
- * Evaluates a selection method using positions.
- *
- * \param[in]  top  Topology structure
- *   (can be NULL if \ref SMETH_REQTOP is not set).
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  Initialized periodic boundary condition structure,
- *   or NULL if PBC should not be used.
- * \param[in]  pos  Positions for which the method should be evaluated.
- * \param[out] out  Output data structure.
- * \param      data Internal data structure from sel_datafunc().
- * \returns    0 on success, a non-zero error code on error.
- *
- * This function should evaluate the method for each position in \p g,
- * and write the output values to \p out. The pointer in the union \p out->u
- * that corresponds to the type of the method should be used.
- * Enough memory has been allocated to store the output values.
- * The number of values in \p out should also be updated if necessary.
- * However, \ref POS_VALUE or \ref GROUP_VALUE methods should not touch
- * \p out->nr (it should be 1 anyways).
- *
- * For \ref STR_VALUE methods, the pointers stored in \p out->s are discarded
- * without freeing; it is the responsibility of this function to provide
- * pointers that can be discarded without memory leaks.
- */
-typedef int   (*sel_updatefunc_pos)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                                    struct gmx_ana_pos_t *pos,
-                                    gmx_ana_selvalue_t *out,
-                                    void *data);
-
-/*! \brief
- * Help information for a selection method.
- *
- * If some information is not available, the corresponding field can be set to
- * 0/NULL.
- */
-typedef struct gmx_ana_selmethod_help_t
-{
-    /*! \brief
-     * One-line description of the syntax of the method.
-     *
-     * If NULL, the name of the method is used.
-     */
-    const char         *syntax;
-    /*! \brief
-     * Number of strings in \p help.
-     *
-     * Set to 0 if \p help is NULL.
-     */
-    int                 nlhelp;
-    /*! \brief
-     * Detailed help for the method.
-     *
-     * If there is no help available in addition to \p syntax, this can be set
-     * to NULL.
-     */
-    const char        **help;
-} gmx_ana_selmethod_help_t;
-
-/*! \brief
- * Describes a selection method.
- *
- * Any of the function pointers except the update call can be NULL if the
- * operation is not required or not supported. In this case,
- * corresponding function calls are skipped.
- *
- * See the function pointer type documentation for details of how the
- * functions should be implemented.
- * More details on implementing new selection methods can be found on a 
- * separate page: \ref selmethods.
- */
-typedef struct gmx_ana_selmethod_t
-{
-    /** Name of the method. */
-    const char         *name;
-    /** Type which the method returns. */
-    e_selvalue_t        type;
-    /*! \brief
-     * Flags to specify how the method should be handled.
-     *
-     * See \ref selmethod_flags for allowed values.
-     */
-    int                 flags;
-    /** Number of parameters the method takes. */
-    int                 nparams;
-    /** Pointer to the array of parameter descriptions. */
-    gmx_ana_selparam_t *param;
-
-    /** Function for allocating and initializing internal data and parameters. */
-    sel_datafunc        init_data;
-    /** Function to set the position calculation collection. */
-    sel_posfunc         set_poscoll;
-    /** Function to do initialization based on topology and/or parameter values. */
-    sel_initfunc        init;
-    /** Function to initialize output data structure. */
-    sel_outinitfunc     outinit;
-    /** Function to free the internal data. */
-    sel_freefunc        free;
-
-    /** Function to initialize the calculation for a new frame. */
-    sel_framefunc       init_frame;
-    /** Function to evaluate the value. */
-    sel_updatefunc      update;
-    /** Function to evaluate the value using positions. */
-    sel_updatefunc_pos  pupdate;
-
-    /** Help data for the method. */
-    gmx_ana_selmethod_help_t help;
-} gmx_ana_selmethod_t;
-
-/** Registers a selection method. */
-int
-gmx_ana_selmethod_register(struct gmx_ana_selcollection_t *sc,
-                           const char *name, gmx_ana_selmethod_t *method);
-/** Registers all selection methods in the library. */
-int
-gmx_ana_selmethod_register_defaults(struct gmx_ana_selcollection_t *sc);
-
-/** Finds a parameter from a selection method by name. */
-gmx_ana_selparam_t *
-gmx_ana_selmethod_find_param(const char *name, gmx_ana_selmethod_t *method);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/selparam.h b/include/selparam.h
deleted file mode 100644 (file)
index a10b609..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief API for handling parameters used in selections.
- *
- * There should be no need to use the data structures or call the
- * functions in this file directly unless implementing a custom selection
- * method.
- *
- * More details can be found on the page discussing
- * \ref selmethods "custom selection methods".
- */
-#ifndef SELPARAM_H
-#define SELPARAM_H
-
-#include "typedefs.h"
-
-#include "indexutil.h"
-#include "selvalue.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/*! \name Parameter flags
- * \anchor selparam_flags
- */
-/*@{*/
-/*! \brief
- * This flag is set if the user has provided the parameter.
- *
- * This flag is set automatically, and should not be set by the user.
- */
-#define SPAR_SET      1
-/*! \brief
- * If not set, an error is reported if the parameter is not specified by the
- * user.
- */
-#define SPAR_OPTIONAL 2
-/*! \brief
- * If set, the parameter value can be dynamic, i.e., be different for
- * different frames.
- *
- * If set, the parameter value should only be accessed in the update function
- * of \c gmx_ana_selmethod_t.
- * The flag is cleared before sel_initfunc() if the value provided is actually
- * static.
- */
-#define SPAR_DYNAMIC  4
-/*! \brief
- * If set, the parameter value is parsed into sorted ranges.
- *
- * Can only be specified for integer parameters.
- * If specified, the value of the parameter (\c gmx_ana_selparam_t::val)
- * consists of sets of two integers, each specifying a range.
- * The values give the endpoints of the ranges (inclusive).
- * The ranges are sorted and overlapping/continuous ranges are merged into
- * a single range to minimize the number of ranges.
- *
- * If this flag is specified, \c gmx_ana_selparam_t::nval gives the number of
- * ranges. \p gmx_ana_selparam_t::nval should be 1 or \ref SPAR_VARNUM should be
- * specified; other values would lead to unpredictable behavior.
- */
-#define SPAR_RANGES   8
-/*! \brief
- * If set, the parameter can have any number of values.
- *
- * If specified, the data pointer in \c gmx_ana_selparam_t::val should be NULL;
- * the memory is allocated by the parameter parser.
- * The implementation of the method should ensure that the pointer to the
- * allocated memory is stored somewhere in sel_initfunc();
- * otherwise, the memory is lost.
- *
- * The initial value of \c gmx_ana_selparam_t::nval is not used with this flag.
- * Instead, it will give the number of actual values provided by the user
- * after the parameters have been parsed.
- * For consistency, it should be initialized to -1.
- *
- * Cannot be combined with \ref GROUP_VALUE parameters.
- */
-#define SPAR_VARNUM   16
-/*! \brief
- * If set, the parameter can have a separate value for each atom.
- *
- * The flag is cleared before sel_initfunc() if the value provided is actually
- * a single value.
- *
- * Cannot be combined with \ref POS_VALUE or \ref GROUP_VALUE parameters.
- */
-#define SPAR_ATOMVAL  32
-/*! \brief
- * If set, the parameter takes one of a set of predefined strings.
- *
- * Can only be specified for a \ref STR_VALUE parameter that takes a single
- * string.
- * The data pointer in \c gmx_ana_selparam_t::val should be initialized into an
- * array of strings such that the first and last elements are NULL, and the
- * rest give the possible values. For optional values, the second element in
- * the array should give the default value. The string given by the user is
- * matched against the beginnings of the given strings, and if a unique match
- * is found, the first pointer in the array will be initialized to point to
- * the matching string.
- * The data pointer can be initialized as a static array; duplication of the
- * array for multiple instances of the same method is automatically taken care
- * of.
- */
-#define SPAR_ENUMVAL  128
-/*@}*/
-
-/*! \brief
- * Describes a single parameter for a selection method.
- */
-typedef struct gmx_ana_selparam_t
-{
-    /** Name of the parameter. */
-    const char         *name;
-    /*! \brief
-     * The parameter value.
-     *
-     * Type \ref NO_VALUE can be used to define a boolean parameter.
-     * The number of values should be 0 for boolean parameters.
-     *
-     * The value pointer be initialized to NULL in the definition of a
-     * \c gmx_ana_selmethod_t and initialized in the
-     * \c gmx_ana_selmethod_t::init_data call
-     * (see sel_datafunc()).
-     * However, if \ref SPAR_VARNUM is provided and the parameter is not
-     * \ref POS_VALUE, this field should not be initialized. Instead,
-     * sufficient memory is allocated automatically and the pointer should be
-     * stored in \c gmx_ana_selmethod_t::init
-     * (see sel_initfunc()).
-     *
-     * The values cannot be accessed outside these two functions: the compiler
-     * makes a copy of the parameter structure for each instance of the
-     * method, and the original parameter array is not changed.
-     */
-    gmx_ana_selvalue_t  val;
-    /*! \brief
-     * Pointer to store the number of values.
-     *
-     * If not NULL, the number of values for the parameter is stored in the
-     * pointed value.
-     * Should be specified if \ref SPAR_VARNUM and \ref SPAR_DYNAMIC are both
-     * set.
-     *
-     * Should be initialized to NULL in the definition a \c gmx_ana_selmethod_t
-     * and initialized in sel_datafunc().
-     */
-    int                *nvalptr;
-    /*! \brief
-     * Flags that alter the way the parameter is parsed/handled.
-     *
-     * See \ref selparam_flags for allowed values.
-     */
-    int                 flags;
-} gmx_ana_selparam_t;
-
-/** Finds a parameter from an array by name. */
-gmx_ana_selparam_t *
-gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/selvalue.h b/include/selvalue.h
deleted file mode 100644 (file)
index 8460fe8..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief Declaration of \c gmx_ana_selvalue_t.
- *
- * There should be no need to use the data structures in this file directly
- * unless implementing a custom selection routine.
- */
-#ifndef SELVALUE_H
-#define SELVALUE_H
-
-#include "types/simple.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/** Defines the value type of a different selection objects. */
-typedef enum
-{
-    NO_VALUE,           /**< No value; either an error condition or an gmx_boolean 
-                             parameter. */
-    INT_VALUE,          /**< One or more integer values. */
-    REAL_VALUE,         /**< One or more real values. */
-    STR_VALUE,          /**< One or more string values. */
-    POS_VALUE,          /**< One or more position values. */
-    GROUP_VALUE         /**< One group of atoms. */
-} e_selvalue_t;
-
-/*! \brief
- * Describes a value of a selection expression or of a selection method
- * parameter.
- *
- * Which field in the union is used depends on the \p type.
- */
-typedef struct gmx_ana_selvalue_t
-{
-    /** Type of the value. */
-    e_selvalue_t                type;
-    /*! \brief
-     * Number of values in the array pointed by the union.
-     *
-     * Note that for position and group values, it is the number of
-     * data structures in the array, not the number of positions or
-     * the number of atoms in the group.
-     */
-    int                         nr;
-    /** Pointer to the value. */
-    union {
-        /*! \brief
-         * Generic pointer for operations that do not need type information.
-         *
-         * Needs to be the first member to be able to use initialized arrays.
-         */
-        void                   *ptr;
-        /** Integer value(s) (type \ref INT_VALUE). */
-        int                    *i;
-        /** Real value(s) (type \ref REAL_VALUE). */
-        real                   *r;
-        /** String value(s) (type \ref STR_VALUE). */
-        char                  **s;
-        /** Structure for the position value(s) (type \ref POS_VALUE). */
-        struct gmx_ana_pos_t   *p;
-        /** Group value (type \ref GROUP_VALUE). */
-        struct gmx_ana_index_t *g;
-        /** Boolean value (only parameters of type \ref NO_VALUE); */
-        gmx_bool                   *b;
-    }                           u;
-    /*! \brief
-     * Number of elements allocated for the value array.
-     */
-    int                         nalloc;
-} gmx_ana_selvalue_t;
-
-/** Initializes an empty selection value structure. */
-void
-_gmx_selvalue_clear(gmx_ana_selvalue_t *val);
-/** Reserve memory for storing selection values. */
-int
-_gmx_selvalue_reserve(gmx_ana_selvalue_t *val, int n);
-/** Sets the memory for storing selection values. */
-int
-_gmx_selvalue_setstore(gmx_ana_selvalue_t *val, void *ptr);
-/** Sets the memory for storing selection values and marks it for automatic freeing. */
-int
-_gmx_selvalue_setstore_alloc(gmx_ana_selvalue_t *val, void *ptr, int nalloc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/string2.h b/include/string2.h
deleted file mode 100644 (file)
index 4f1f49a..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-/*! \file
- * \brief Generic string handling functions.
- */
-#ifndef _string2_h
-#define _string2_h
-
-/*
- *
- * string2.h
- * David van der Spoel
- *
- */
-
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <time.h>
-#include <errno.h>
-
-/*#include "typedefs.h"*/
-#include "types/simple.h"
-
-/* Suppress Cygwin compiler warnings from using newlib version of
- * ctype.h */
-#ifdef GMX_CYGWIN
-#undef isdigit
-#undef isstring
-#undef isspace
-#undef isalnum
-#undef isalpha
-#undef ispunct
-#undef isxdigit
-#undef isupper
-#undef islower
-#undef toupper
-#undef tolower
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define CONTINUE    '\\'
-#define COMMENTSIGN ';'
-
-int continuing(char *s);
-
-char *fgets2(char *s, int n, FILE *stream);
-
-void strip_comment (char *line);
-
-int break_line (char *line,
-                      char *variable,
-                      char *value);
-
-void upstring (char *str);
-
-void ltrim (char *str);
-
-void rtrim (char *str);
-
-void trim (char *str);
-
-void nice_header (FILE *out,const char *fn);
-
-int gmx_strcasecmp_min(const char *str1, const char *str2);
-int gmx_strncasecmp_min(const char *str1, const char *str2, int n);
-/* This funny version of strcasecmp, is not only case-insensitive,
- * but also ignores '-' and '_'.
- */
-
-int gmx_strcasecmp(const char *str1, const char *str2);
-int gmx_strncasecmp(const char *str1, const char *str2, int n);
-
-char *gmx_strdup(const char *src);
-char *gmx_strndup(const char *src, int n);
-    
-/** Pattern matcing with wildcards. */
-int gmx_wcmatch(const char *pattern, const char *src);
-
-/** Return value for gmx_wcmatch() when there is no match. */
-#define GMX_NO_WCMATCH 1
-
-
-/* this is our implementation of strsep, the thread-safe replacement for
-   strtok */
-char *gmx_strsep(char **stringp, const char *delim);
-
-
-char *wrap_lines(const char *buf,int line_width, int indent,
-                       gmx_bool bIndentFirst);
-/* wraps lines at 'linewidth', indenting all following
- * lines by 'indent' spaces. A temp buffer is allocated and returned,
- * which can be disposed of if no longer needed.
- * If !bIndentFirst, then the first line will not be indented, only 
- * the lines that are created due to wapping.
- */
-
-
-char **split(char sep,char *str);
-/* Implementation of the well-known Perl function split */
-
-gmx_large_int_t str_to_large_int_t(const char *str, char **endptr);
-
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-#define snprintf _snprintf
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _string2_h */
diff --git a/include/thread_mpi/CMakeLists.txt b/include/thread_mpi/CMakeLists.txt
deleted file mode 100644 (file)
index a14e8ad..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# includes: Nothing to build, just installation
-install(DIRECTORY . DESTINATION include/thread_mpi
-
-        PATTERN "Makefile*" EXCLUDE
-        PATTERN "CMake*" EXCLUDE
-        PATTERN "cmake*" EXCLUDE
-        PATTERN "*~" EXCLUDE
-)
-
-
diff --git a/include/thread_mpi/atomic/CMakeLists.txt b/include/thread_mpi/atomic/CMakeLists.txt
deleted file mode 100644 (file)
index 8a54324..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# includes: Nothing to build, just installation
-install(DIRECTORY . DESTINATION include/thread_mpi/atomic
-
-        PATTERN "Makefile*" EXCLUDE
-        PATTERN "CMake*" EXCLUDE
-        PATTERN "cmake*" EXCLUDE
-        PATTERN "*~" EXCLUDE
-)
-
-
diff --git a/include/thread_mpi/atomic/gcc_x86.h b/include/thread_mpi/atomic/gcc_x86.h
deleted file mode 100644 (file)
index ea0e677..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
-This source code file is part of thread_mpi.  
-Written by Sander Pronk, Erik Lindahl, and possibly others. 
-
-Copyright (c) 2009, Sander Pronk, Erik Lindahl.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-1) Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2) Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3) Neither the name of the copyright holders nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-If you want to redistribute modifications, please consider that
-scientific software is very special. Version control is crucial -
-bugs must be traceable. We will be happy to consider code for
-inclusion in the official distribution, but derived work should not
-be called official thread_mpi. Details are found in the README & COPYING
-files.
-*/
-
-
-
-#include <limits.h>
-#include <stdint.h>
-/* This code is executed for x86 and x86-64, with these compilers:
- * GNU
- * Intel 
- * Pathscale
- * All these support GCC-style inline assembly. 
- * We also use this section for the documentation.
- */
-
-
-#if 0
-/* Only gcc and Intel support this check, otherwise set it to true (skip doc) */
-#if (!defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined DOXYGEN)
-#define __builtin_constant_p(i) (1)
-#endif
-#endif
-
-/* we put all of these on their own cache line by specifying an alignment: */
-typedef struct tMPI_Atomic
-{
-    int value __attribute__ ((aligned(64))); 
-} tMPI_Atomic_t;
-
-typedef struct tMPI_Atomic_ptr
-{
-    void* value __attribute__ ((aligned(64)));   
-} tMPI_Atomic_ptr_t;
-
-typedef struct tMPI_Spinlock
-{
-    unsigned int lock __attribute__ ((aligned(64)));
-} tMPI_Spinlock_t;
-
-
-#define TMPI_SPINLOCK_INITIALIZER   { 0 }
-
-
-
-/* these are guaranteed to be  atomic on x86 and x86_64 */
-#define tMPI_Atomic_get(a)  ((a)->value) 
-#define tMPI_Atomic_set(a,i)  (((a)->value) = (i))
-
-#define tMPI_Atomic_ptr_get(a)  ((a)->value) 
-#define tMPI_Atomic_ptr_set(a,i)  (((a)->value) = (void*)(i))
-
-
-/* do the intrinsics. 
-   
-   We disable this for 32-bit builds because the target may be 80386, 
-   which didn't have cmpxchg, etc (they were introduced as only as 'recently' 
-   as the 486, and gcc on some Linux versions still target 80386 by default). 
-  
-   We also specifically check for icc, because intrinsics are not always
-   supported there. */
-#if ( (TMPI_GCC_VERSION >= 40100) && defined(__x86_64__) &&  \
-     !defined(__INTEL_COMPILER) ) 
-#include "gcc_intrinsics.h"
-
-#else
-/* older versions of gcc don't support atomic intrinsics */
-
-
-#define tMPI_Atomic_memory_barrier() __asm__ __volatile__("sfence;": : :"memory")
-static inline int tMPI_Atomic_add_return(tMPI_Atomic_t *a, int i)
-{
-    int __i;
-    
-    __i = i;
-    __asm__ __volatile__("lock ; xaddl %0, %1;"
-                         :"=r"(i) :"m"(a->value), "0"(i) : "memory");
-    return i + __i;
-}  
-
-static inline int tMPI_Atomic_fetch_add(tMPI_Atomic_t *a, int i)
-{
-    __asm__ __volatile__("lock ; xaddl %0, %1;"
-                         :"=r"(i) :"m"(a->value), "0"(i) : "memory");
-    return i;
-}
-
-static inline int tMPI_Atomic_cas(tMPI_Atomic_t *a, int oldval, int newval)
-{
-    unsigned int prev;
-    
-    __asm__ __volatile__("lock ; cmpxchgl %1,%2"
-                         : "=a"(prev)
-                         : "q"(newval), "m"(a->value), "0"(oldval)
-                         : "memory");
-    
-    return prev==oldval;
-}
-
-static inline int tMPI_Atomic_ptr_cas(tMPI_Atomic_ptr_t *a, 
-                                      void *oldval,
-                                      void *newval)
-{
-    void* prev;
-#ifndef __x86_64__ 
-    __asm__ __volatile__("lock ; cmpxchgl %1,%2"
-                         : "=a"(prev)
-                         : "q"(newval), "m"(a->value), "0"(oldval)
-                         : "memory");
-#else 
-    __asm__ __volatile__("lock ; cmpxchgq %1,%2"
-                         : "=a"(prev)
-                         : "q"(newval), "m"(a->value), "0"(oldval)
-                         : "memory");
-#endif
-    return prev==oldval;
-}
-
-#endif /* end of check for gcc intrinsics */
-
-#define TMPI_HAVE_SWAP
-/* do the swap fns; we told the intrinsics that we have them. */
-static inline int tMPI_Atomic_swap(tMPI_Atomic_t *a, int b)
-{
-    volatile int ret=b;
-    __asm__ __volatile__("\txchgl %0, %1;" 
-                         :"=r"(ret)
-                         :"m"(a->value), "0"(ret)
-                         :"memory");
-    return (int)ret;
-}
-
-static inline void *tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
-{
-    void *volatile *ret=(void* volatile*)b;
-#ifndef __x86_64__ 
-/*    __asm__ __volatile__("\txchgl %0, %1;" 
-                         :"=m"(a->value),"=q"(b) 
-                         :"q"(b)
-                         :"memory");
-*/
-    __asm__ __volatile__("\txchgl %0, %1;" 
-                         :"=r"(ret)
-                         :"m"(a->value), "0"(ret)
-                         :"memory");
-
-#else
-    __asm__ __volatile__("\txchgq %0, %1;" 
-                         :"=r"(ret)
-                         :"m"(a->value), "0"(ret)
-                         :"memory");
-#endif
-    return (void*)ret;
-}
-
-
-
-/* spinlocks : */
-
-static inline void tMPI_Spinlock_init(tMPI_Spinlock_t *x)
-{
-    x->lock = 0;
-}
-
-
-
-static inline void tMPI_Spinlock_lock(tMPI_Spinlock_t *x)
-{
-    /* this is a spinlock with a double loop, as recommended by Intel
-       it pauses in the outer loop (the one that just checks for the 
-       availability of the lock), and thereby reduces bus contention and
-       prevents the pipeline from flushing. */
-    __asm__ __volatile__("1:\tcmpl $0, %0\n"      /* check the lock */
-                         "\tje 2f\n"              /* try to lock if it is
-                                                     free by jumping forward */
-                         "\tpause\n"              /* otherwise: small pause
-                                                     as recommended by Intel */
-                         "\tjmp 1b\n"             /* and jump back */  
-
-                         "2:\tmovl $1, %%eax\n"   /* set eax to 1, the locked
-                                                     value of the lock */
-                         "\txchgl %%eax, %0\n"    /* atomically exchange 
-                                                     eax with the lock value */
-                         "\tcmpl $0, %%eax\n"     /* compare the exchanged
-                                                     value with 0 */
-                         "\tjne 1b"               /* jump backward if we didn't
-                                                     just lock */
-                         : "=m" (x->lock)         /* input & output var */
-                         : 
-                         : "%eax", "memory"/* we changed memory */
-                        );
-}
-
-
-
-static inline void tMPI_Spinlock_unlock(tMPI_Spinlock_t *  x)
-{
-    /* this is apparently all that is needed for unlocking a lock */
-    __asm__ __volatile__(
-                     "\n\tmovl $0, %0\n"
-                     : "=m"(x->lock) : : "memory" );
-}
-
-
-
-static inline int tMPI_Spinlock_trylock(tMPI_Spinlock_t *x)
-{
-    int old_value;
-        
-    __asm__ __volatile__("\tmovl $1, %0\n"     /* set eax to 1, the locked
-                                                  value of the lock */
-                         "\txchgl %0, %1\n"    /* atomically exchange 
-                                                  eax with the address in
-                                                  rdx. */
-                         :"=r" (old_value), "=m" (x->lock)
-                         : : "memory");
-    return (old_value);
-}
-
-
-static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
-{
-    return ( (*((volatile int*)(&(x->lock)))) != 0);
-}
-
-
-static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
-{
-    /* this is the spinlock without the xchg.  */
-    __asm__ __volatile__("1:\tcmpl $0, %0\n"      /* check the lock */
-                         "\tje 2f\n"              /* try to lock if it is
-                                                     free by jumping forward */
-                         "\tpause\n"              /* otherwise: small pause
-                                                     as recommended by Intel */
-                         "\tjmp 1b\n"             /* and jump back */  
-                         "2:\tnop\n"              /* jump target for end 
-                                                     of wait */
-                         : "=m"(x->lock)         /* input & output var */
-                         : 
-                         : "memory"/* we changed memory */
-                        );
-#if 0
-    do 
-    {
-        tMPI_Atomic_memory_barrier(); 
-    } 
-    while(tMPI_Spinlock_islocked(x));
-#endif
-}
-
diff --git a/include/trajana.h b/include/trajana.h
deleted file mode 100644 (file)
index 8000a81..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief Main API of the trajectory analysis library.
- *
- * Contains the API for the core analysis library.
- *
- * \todo
- * Better handling of reference groups.
- * It would be nice to be able to provide a string that would be used in
- * prompting the groups, and also in automatic reporting of what the tool
- * is about to do.
- *
- * Most analysis tools should include trajana.h
- * (which automatically includes indexutil.h, selection.h, position.h)
- * and possibly one or more of the following headers:
- * displacement.h, histogram.h, nbsearch.h.
- * If the tool implements custom selection methods, it should also include
- * selmethod.h (which automatically includes selparam.h and selvalue.h).
- *
- * Other headers (centerofmass.h, poscalc.h) are used internally by the
- * library to calculate positions.
- * Analysis tools should preferably not use the routines in these headers
- * directly, but instead get all positions through selections. This makes
- * them more flexible with a minimal amount of work.
- */
-#ifndef TRAJANA_H
-#define TRAJANA_H
-
-#include "typedefs.h"
-#include "filenm.h"
-#include "readinp.h"
-
-#include "indexutil.h"
-#include "selection.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Data structure for trajectory analysis tools. */
-typedef struct gmx_ana_traj_t gmx_ana_traj_t;
-
-/*! \name Flags for gmx_ana_traj_create()
- * \anchor analysis_flags
- * These flags can be used to alter the behavior of the analysis library to
- * suit the analysis tool.
- * They are given to the gmx_ana_traj_create() when creating the 
- * \c gmx_ana_traj_t data structure, and affect the behavior of the other
- * functions in this header.
- */
-/*@{*/
-/*! \brief
- * Force loading of a topology file.
- *
- * If this flag is not specified, the topology file is loaded only if it is
- * provided on the command line explicitly.
- *
- * \see gmx_ana_get_topology()
- */
-#define ANA_REQUIRE_TOP      (1<<0)
-/*! \brief
- * Do no free the coordinates loaded from the topology.
- *
- * If this flag is specified, the coordinates loaded from the topology can
- * be accessed with gmx_ana_get_topconf().
- *
- * \see gmx_ana_get_topconf()
- */
-#define ANA_USE_TOPX         (1<<1)
-/*! \brief
- * Disallows the user from changing PBC handling.
- *
- * If this option is not specified, the analysis program (see gmx_analysisfunc())
- * may be passed a NULL PBC structure, and it should be able to handle such a
- * situation.
- */
-#define ANA_NOUSER_PBC       (1<<4)
-/*! \brief
- * Disallows the user from changing PBC removal.
- */
-#define ANA_NOUSER_RMPBC     (1<<5)
-/*! \brief
- * Disallows dynamic selections.
- *
- * If this flag is specified, an error is reported if the user specifies
- * any dynamic selections.
- */
-#define ANA_NO_DYNSEL        (1<<8)
-/*! \brief
- * Disallows breaking of residues in dynamic selections.
- *
- * Makes it impossible for the user to select atom-based dynamic selections.
- *
- * Only has effect if \ref ANA_NO_DYNSEL is not specified.
- */
-#define ANA_REQUIRE_WHOLE    (1<<9)
-/*! \brief
- * Disables automatic initialization of selection groups.
- *
- * If this flag is specified, parse_trjana_args() does not call
- * gmx_ana_init_selections(), allowing the program to do some initialization
- * before the call.
- * In particular, the program can use gmx_ana_set_nrefgprs() and
- * gmx_ana_set_nanagrps() before calling gmx_ana_init_selections() to
- * control the number of selections to expect.
- * This is useful if the program requires a different number of index groups
- * with different command-line arguments.
- * If the flag is specified, the program should call gmx_ana_init_selections()
- * exactly once after the parse_trjana_args() call.
- */
-#define ANA_USER_SELINIT     (1<<10)
-/*! \brief
- * Allow only atomic positions to be selected.
- *
- * Note that this flag only applies to the analysis groups, not the reference
- * groups. The reference groups should be checked in the analysis program
- * if some limitations are imposed on them.
- */
-#define ANA_ONLY_ATOMPOS     (1<<11)
-/*! \brief
- * Use masks in the positions to convey dynamic information.
- *
- * If this flag is specified, the positions calculated for the selections
- * are calculated always for the same group of atoms, even if the selection is
- * dynamic.
- * Dynamic selections only affect the \p refid field of the indexgroup map
- * given in the positions.
- */
-#define ANA_USE_POSMASK      (1<<12)
-/*! \brief
- * Pass the reference groups to gmx_analysisfunc().
- *
- * If this flag is specified, the reference groups are passed on to
- * gmx_analysisfunc().
- * Similarly, the arrays returned by gmx_ana_get_anagrps() and
- * gmx_ana_get_grpnames() contain the reference groups in the beginning.
- */
-#define ANA_USE_FULLGRPS     (1<<13)
-/*! \brief
- * Dump the parsed and compiled selection trees.
- *
- * This flag is used by internal debugging tools to make
- * gmx_ana_init_selections() dump the selection trees to stderr.
- */
-#define ANA_DEBUG_SELECTION  (1<<16)
-/*@}*/
-
-
-/*! \name Functions for initialization */
-/*@{*/
-
-/** Allocates and initializes data structure for trajectory analysis. */
-int
-gmx_ana_traj_create(gmx_ana_traj_t **data, unsigned long flags);
-/** Frees the memory allocated for trajectory analysis data. */
-void
-gmx_ana_traj_free(gmx_ana_traj_t *d);
-/** Sets additional flags after gmx_ana_traj_create() has been called. */
-int
-gmx_ana_add_flags(gmx_ana_traj_t *d, unsigned long flags);
-/** Sets the number of reference groups required. */
-int
-gmx_ana_set_nrefgrps(gmx_ana_traj_t *d, int nrefgrps);
-/** Sets the number of analysis groups required. */
-int
-gmx_ana_set_nanagrps(gmx_ana_traj_t *d, int nanagrps);
-/** Sets whether PBC are used. */
-int
-gmx_ana_set_pbc(gmx_ana_traj_t *d, gmx_bool bPBC);
-/** Sets whether molecules are made whole. */
-int
-gmx_ana_set_rmpbc(gmx_ana_traj_t *d, gmx_bool bRmPBC);
-/** Sets flags that determine what to read from the trajectory. */
-int
-gmx_ana_set_frflags(gmx_ana_traj_t *d, int frflags);
-/** Parses command-line arguments and performs some initialization. */
-int
-parse_trjana_args(gmx_ana_traj_t *d, int *argc, char *argv[],
-                  unsigned long pca_flags, int nfile, t_filenm fnm[],
-                  int npargs, t_pargs *pa,
-                 int ndesc, const char **desc,
-                  int nbugs, const char **bugs,
-                  output_env_t *oenv);
-/** Initializes selection information. */
-int
-gmx_ana_init_selections(gmx_ana_traj_t *d);
-/** Initializes calculation of covered fractions for selections. */
-int
-gmx_ana_init_coverfrac(gmx_ana_traj_t *d, e_coverfrac_t type);
-
-/** Returns whether PBC should be used. */
-gmx_bool
-gmx_ana_has_pbc(gmx_ana_traj_t *d);
-/** Gets the topology information. */
-int
-gmx_ana_get_topology(gmx_ana_traj_t *d, gmx_bool bReq, t_topology **top, gmx_bool *bTop);
-/** Gets the configuration from the topology. */
-int
-gmx_ana_get_topconf(gmx_ana_traj_t *d, rvec **x, matrix box, int *ePBC);
-/** Gets the first frame to be analyzed. */
-int
-gmx_ana_get_first_frame(gmx_ana_traj_t *d, t_trxframe **fr);
-
-/** Gets the total number of selections provided by the user. */
-int
-gmx_ana_get_ngrps(gmx_ana_traj_t *d, int *ngrps);
-/** Gets the number of analysis groups provided by the user. */
-int
-gmx_ana_get_nanagrps(gmx_ana_traj_t *d, int *nanagrps);
-/** Gets the selection object for a reference selection. */
-int
-gmx_ana_get_refsel(gmx_ana_traj_t *d, int i, gmx_ana_selection_t **sel);
-/** Gets the selection object for a reference selection. */
-int
-gmx_ana_get_anagrps(gmx_ana_traj_t *d, gmx_ana_selection_t ***sel);
-/** Gets an array of names for the selections. */
-int
-gmx_ana_get_grpnames(gmx_ana_traj_t *d, char ***grpnames);
-/** Gets the selection collection object that contains all the selections. */
-int
-gmx_ana_get_selcollection(gmx_ana_traj_t *d, gmx_ana_selcollection_t **sc);
-/** Prints the selection strings into an XVGR file as comments. */
-int
-xvgr_selections(FILE *out, gmx_ana_traj_t *d);
-
-/*@}*/
-
-
-/*! \name Functions for reading and analyzing the trajectory
- */
-/*@{*/
-
-/*! \brief
- * Function pointer type for frame analysis functions.
- *
- * \param[in] top  Topology structure.
- * \param[in] fr   Current frame.
- * \param[in] pbc  Initialized PBC structure for this frame.
- * \param[in] nr   Number of selections in the \p sel array.
- * \param[in] sel  Array of selections.
- * \param     data User data as provided to gmx_ana_do().
- * \returns   0 on success, a non-zero error code on error.
- *
- * This function is called by gmx_ana_do() for each frame that
- * needs to be analyzed.
- * Positions to be analyzed can be found in the \p sel array.
- * The selection array \p sel also provides information about the atoms that
- * have been used to evaluate the positions.
- * If a non-zero value is returned, gmx_ana_do() immediately exits and returns
- * the same value to the caller.
- */
-typedef int (*gmx_analysisfunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                               int nr, gmx_ana_selection_t *sel[], void *data);
-
-/** Loops through all frames in the trajectory. */
-int
-gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *data);
-/** Gets the total number of frames analyzed. */
-int
-gmx_ana_get_nframes(gmx_ana_traj_t *d, int *nframes);
-
-/*@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/types/.cvsignore b/include/types/.cvsignore
deleted file mode 100644 (file)
index b840c21..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile.in
-Makefile
\ No newline at end of file
diff --git a/include/types/enums.h b/include/types/enums.h
deleted file mode 100644 (file)
index a12c307..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GRoups of Organic Molecules in ACtion for Science
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* note: these enums should correspond to the names in gmxlib/names.c */
-
-enum {
-  epbcXYZ, epbcNONE, epbcXY, epbcSCREW, epbcNR
-};
-
-enum {
-  etcNO, etcBERENDSEN, etcNOSEHOOVER, etcYES, etcANDERSEN, etcANDERSENINTERVAL, etcVRESCALE, etcNR
-}; /* yes is an alias for berendsen */
-
-enum {
-  epcNO, epcBERENDSEN, epcPARRINELLORAHMAN, epcISOTROPIC, epcMTTK, epcNR
-}; /* isotropic is an alias for berendsen */
-
-/* trotter decomposition extended variable parts */
-enum {
-  etrtNONE, etrtNHC, etrtBAROV, etrtBARONHC, etrtNHC2, etrtBAROV2, etrtBARONHC2, 
-  etrtVELOCITY1, etrtVELOCITY2, etrtPOSITION, etrtSKIPALL, etrtNR
-};
-
-/* sequenced parts of the trotter decomposition */
-enum {
-  ettTSEQ0,  ettTSEQ1,  ettTSEQ2,  ettTSEQ3,  ettTSEQ4, ettTSEQMAX
-};
-
-enum {
-  epctISOTROPIC, epctSEMIISOTROPIC, epctANISOTROPIC,
-  epctSURFACETENSION, epctNR
-};
-
-enum {
-  erscNO, erscALL, erscCOM, erscNR
-};
-
-/*
- * eelNOTUSED1 used to be GB, but to enable generalized born with different
- * forms of electrostatics (RF, switch, etc.) in the future it is now selected
- * separately (through the implicit_solvent option).
- */
-enum {
-  eelCUT,     eelRF,     eelGRF,   eelPME,  eelEWALD,  eelPPPM, 
-  eelPOISSON, eelSWITCH, eelSHIFT, eelUSER, eelGB_NOTUSED, eelRF_NEC, eelENCADSHIFT, 
-  eelPMEUSER, eelPMESWITCH, eelPMEUSERSWITCH, eelRF_ZERO, eelNR
-};
-
-/* Ewald geometry */
-enum { 
-  eewg3D, eewg3DC, eewgNR
-};
-
-#define EEL_RF(e) ((e) == eelRF || (e) == eelGRF || (e) == eelRF_NEC || (e) == eelRF_ZERO )
-
-#define EEL_PME(e)  ((e) == eelPME || (e) == eelPMESWITCH || (e) == eelPMEUSER || (e) == eelPMEUSERSWITCH)
-#define EEL_FULL(e) (EEL_PME(e) || (e) == eelPPPM || (e) == eelPOISSON || (e) == eelEWALD)
-
-#define EEL_SWITCHED(e) ((e) == eelSWITCH || (e) == eelSHIFT || (e) == eelENCADSHIFT || (e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
-
-#define EEL_IS_ZERO_AT_CUTOFF(e) (EEL_SWITCHED(e) || (e) == eelRF_ZERO)
-
-#define EEL_MIGHT_BE_ZERO_AT_CUTOFF(e) (EEL_IS_ZERO_AT_CUTOFF(e) || (e) == eelUSER || (e) == eelPMEUSER)
-
-enum {
-  evdwCUT, evdwSWITCH, evdwSHIFT, evdwUSER, evdwENCADSHIFT, evdwNR
-};
-
-#define EVDW_SWITCHED(e) ((e) == evdwSWITCH || (e) == evdwSHIFT || (e) == evdwENCADSHIFT)
-
-#define EVDW_IS_ZERO_AT_CUTOFF(e) EVDW_SWITCHED(e)
-
-#define EVDW_MIGHT_BE_ZERO_AT_CUTOFF(e) (EVDW_IS_ZERO_AT_CUTOFF(e) || (e) == evdwUSER)
-
-enum { 
-  ensGRID, ensSIMPLE, ensNR
-};
-
-/* eiVV is normal velocity verlet -- eiVVAK uses 1/2*(KE(t-dt/2)+KE(t+dt/2)) as the kinetic energy, and the half step kinetic
-   energy for temperature control */
-
-enum {
-  eiMD, eiSteep, eiCG, eiBD, eiSD2, eiNM, eiLBFGS, eiTPI, eiTPIC, eiSD1, eiVV, eiVVAK, eiNR
-};
-#define EI_VV(e) ((e) == eiVV || (e) == eiVVAK)
-#define EI_SD(e) ((e) == eiSD1 || (e) == eiSD2)
-#define EI_RANDOM(e) (EI_SD(e) || (e) == eiBD)
-/*above integrators may not conserve momenta*/
-#define EI_DYNAMICS(e) ((e) == eiMD || EI_SD(e) || (e) == eiBD || EI_VV(e))
-#define EI_ENERGY_MINIMIZATION(e) ((e) == eiSteep || (e) == eiCG || (e) == eiLBFGS)
-#define EI_TPI(e) ((e) == eiTPI || (e) == eiTPIC)
-
-#define EI_STATE_VELOCITY(e) ((e) == eiMD || EI_VV(e) || EI_SD(e))
-
-enum {
-  econtLINCS, econtSHAKE, econtNR
-};
-
-enum {
-  edrNone, edrSimple, edrEnsemble, edrNR
-};
-
-enum {
-  edrwConservative, edrwEqual, edrwNR
-};
-
-/* Combination rule things */
-enum { 
-  eCOMB_NONE, eCOMB_GEOMETRIC, eCOMB_ARITHMETIC, eCOMB_GEOM_SIG_EPS, eCOMB_NR 
-};
-
-/* NBF selection */
-enum { 
-  eNBF_NONE, eNBF_LJ, eNBF_BHAM, eNBF_NR 
-};
-
-/* FEP selection */
-enum {
-  efepNO, efepYES, efepNR
-};
-
-/* separate_dhdl_file selection */
-enum
-{
-    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
-    sepdhdlfileYES, sepdhdlfileNO, sepdhdlfileNR
-};
-
-/* dhdl_derivatives selection */
-enum
-{
-    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
-    dhdlderivativesYES, dhdlderivativesNO, dhdlderivativesNR
-};
-
-/* Solvent model */
-enum {
-  esolNO, esolSPC, esolTIP4P, esolNR
-};
-
-/* Dispersion correction */
-enum {
-  edispcNO, edispcEnerPres, edispcEner, edispcAllEnerPres, edispcAllEner, edispcNR
-}; 
-
-/* Shell types, for completion stuff */
-enum {
-  eshellCSH, eshellBASH, eshellZSH, eshellNR
-}; 
-
-/* Center of mass motion selection */
-enum { 
-  ecmLINEAR, ecmANGULAR, ecmNO, ecmNR 
-};
-
-/* New version of simulated annealing */
-enum { 
-  eannNO, eannSINGLE, eannPERIODIC, eannNR 
-};
-
-/* Implicit solvent algorithms */
-enum { 
-       eisNO, eisGBSA, eisNR 
-};
-
-/* Algorithms for calculating GB radii */
-enum { 
-  egbSTILL, egbHCT, egbOBC, egbNR 
-};
-
-enum {
-  esaAPPROX, esaNO, esaSTILL, esaNR
-};
-
-/* Wall types */
-enum {
-  ewt93, ewt104, ewtTABLE, ewt126, ewtNR
-};
-
-/* Pull stuff */
-enum {
-  epullNO, epullUMBRELLA, epullCONSTRAINT, epullCONST_F, epullNR
-};
-
-enum {
-  epullgDIST, epullgDIR, epullgCYL, epullgPOS, epullgDIRPBC, epullgNR
-};
-
-#define PULL_CYL(pull) ((pull)->eGeom == epullgCYL)
-
-/* QMMM */
-enum {
-  eQMmethodAM1, eQMmethodPM3, eQMmethodRHF, 
-  eQMmethodUHF, eQMmethodDFT, eQMmethodB3LYP, eQMmethodMP2, eQMmethodCASSCF, eQMmethodB3LYPLAN,
-  eQMmethodDIRECT, eQMmethodNR
-};
-
-enum {
-  eQMbasisSTO3G, eQMbasisSTO3G2, eQMbasis321G, 
-  eQMbasis321Gp, eQMbasis321dGp, eQMbasis621G,
-  eQMbasis631G, eQMbasis631Gp, eQMbasis631dGp, 
-  eQMbasis6311G, eQMbasisNR
-};
-
-enum {
-  eQMMMschemenormal,eQMMMschemeoniom,eQMMMschemeNR
-};
-
-enum {
-  eMultentOptName, eMultentOptNo, eMultentOptLast, eMultentOptNR
-};
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/include/types/inputrec.h b/include/types/inputrec.h
deleted file mode 100644 (file)
index 7c99363..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GRoups of Organic Molecules in ACtion for Science
- */
-#ifndef _inputrec_h_
-#define _inputrec_h_
-
-
-#include "simple.h"
-#include "../sysstuff.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-typedef struct {
-  int  n;              /* Number of terms                              */
-  real *a;             /* Coeffients (V / nm )                         */
-  real *phi;           /* Phase angles                                 */
-} t_cosines;
-
-typedef struct {
-  real E0;              /* Field strength (V/nm)                        */
-  real omega;           /* Frequency (1/ps)                             */
-  real t0;              /* Centre of the Gaussian pulse (ps)            */
-  real sigma;           /* Width of the Gaussian pulse (FWHM) (ps)      */
-} t_efield;
-
-#define EGP_EXCL  (1<<0)
-#define EGP_TABLE (1<<1)
-
-typedef struct {
-  int     ngtc;                  /* # T-Coupl groups                        */
-  int     nhchainlength;         /* # of nose-hoover chains per group       */
-  int     ngacc;                 /* # Accelerate groups                     */
-  int     ngfrz;                 /* # Freeze groups                         */
-  int     ngener;               /* # Ener groups                           */
-  real    *nrdf;                /* Nr of degrees of freedom in a group     */
-  real    *ref_t;               /* Coupling temperature        per group   */
-  int     *annealing;            /* No/simple/periodic SA for each group    */
-  int     *anneal_npoints;       /* Number of annealing time points per grp */    
-  real    **anneal_time;         /* For ea. group: Time points              */
-  real    **anneal_temp;         /* For ea. grp: Temperature at these times */
-                                 /* Final temp after all intervals is ref_t */ 
-  real    *tau_t;               /* Tau coupling time                       */
-  rvec    *acc;                         /* Acceleration per group                  */
-  ivec    *nFreeze;             /* Freeze the group in each direction ?    */
-  int     *egp_flags;            /* Exclusions/tables of energy group pairs */
-
-  /* QMMM stuff */
-  int     ngQM;         /* nr of QM groups                              */
-  int     *QMmethod;    /* Level of theory in the QM calculation        */
-  int     *QMbasis;     /* Basisset in the QM calculation               */
-  int     *QMcharge;    /* Total charge in the QM region                */
-  int     *QMmult;      /* Spin multiplicicty in the QM region          */
-  gmx_bool    *bSH;         /* surface hopping (diabatic hop only)          */
-  int     *CASorbitals; /* number of orbiatls in the active space       */
-  int     *CASelectrons;/* number of electrons in the active space      */
-  real    *SAon;        /* at which gap (A.U.) the SA is switched on    */
-  real    *SAoff;
-  int     *SAsteps;     /* in how many steps SA goes from 1-1 to 0.5-0.5*/
-  gmx_bool    *bOPT;
-  gmx_bool    *bTS;
-} t_grpopts;
-
-enum { epgrppbcNONE, epgrppbcREFAT, epgrppbcCOS };
-
-typedef struct {
-  int        nat;      /* Number of atoms in the pull group */
-  atom_id    *ind;     /* The global atoms numbers */
-  int        nat_loc;  /* Number of local pull atoms */
-  int        nalloc_loc; /* Allocation size for ind_loc and weight_loc */ 
-  atom_id    *ind_loc; /* Local pull indices */
-  int        nweight;  /* The number of weights (0 or nat) */
-  real       *weight;  /* Weights (use all 1 when weight==NULL) */
-  real       *weight_loc; /* Weights for the local indices */
-  int        epgrppbc; /* The type of pbc for this pull group, see enum above */
-  atom_id    pbcatom;  /* The reference atom for pbc (global number) */
-  rvec       vec;      /* The pull vector, direction or position */
-  rvec       init;     /* Initial reference displacement */
-  real       rate;     /* Rate of motion (nm/ps) */
-  real       k;        /* force constant */
-  real       kB;       /* force constant for state B */
-  real       wscale;   /* scaling factor for the weights: sum w m/sum w w m */
-  real       invtm;    /* inverse total mass of the group: 1/wscale sum w m */
-  dvec       x;        /* center of mass before update */
-  dvec       xp;       /* center of mass after update before constraining */
-  dvec       dr;       /* The distance from the reference group */
-  double     f_scal;   /* Scalar force for directional pulling */
-  dvec       f;        /* force due to the pulling/constraining */
-} t_pullgrp; 
-
-typedef struct {
-  int        ngrp;        /* number of groups */
-  int        eGeom;       /* pull geometry */
-  ivec       dim;         /* used to select components for constraint */
-  real       cyl_r1;      /* radius of cylinder for dynamic COM */
-  real       cyl_r0;      /* radius of cylinder including switch length */
-  real       constr_tol;  /* absolute tolerance for constraints in (nm) */
-  int        nstxout;     /* Output frequency for pull x */
-  int        nstfout;     /* Output frequency for pull f */
-  int        ePBC;        /* the boundary conditions */
-  int        npbcdim;     /* do pbc in dims 0 <= dim < npbcdim */
-  gmx_bool       bRefAt;      /* do we need reference atoms for a group COM ? */
-  int        cosdim;      /* dimension for cosine weighting, -1 if none */
-  gmx_bool       bVirial;     /* do we need to add the pull virial? */
-  t_pullgrp  *grp;        /* groups to pull/restrain/etc/ */
-  t_pullgrp  *dyna;       /* dynamic groups for use with local constraints */
-  rvec       *rbuf;       /* COM calculation buffer */
-  dvec       *dbuf;       /* COM calculation buffer */
-  double     *dbuf_cyl;   /* cylinder ref. groups COM calculation buffer */
-
-  FILE       *out_x;      /* output file for pull data */
-  FILE       *out_f;      /* output file for pull data */
-} t_pull;
-
-typedef struct {
-  int  eI;              /* Integration method                          */
-  gmx_large_int_t nsteps;      /* number of steps to be taken                  */
-  int  simulation_part; /* Used in checkpointing to separate chunks */
-  gmx_large_int_t init_step;   /* start at a stepcount >0 (used w. tpbconv)    */
-  int  nstcalcenergy;  /* fequency of energy calc. and T/P coupl. upd. */
-  int  ns_type;                /* which ns method should we use?               */
-  int  nstlist;                /* number of steps before pairlist is generated */
-  int  ndelta;         /* number of cells per rlong                    */
-  int  nstcomm;                /* number of steps after which center of mass   */
-                        /* motion is removed                           */
-  int  comm_mode;       /* Center of mass motion removal algorithm      */
-  int nstcheckpoint;    /* checkpointing frequency                      */
-  int nstlog;          /* number of steps after which print to logfile */
-  int nstxout;         /* number of steps after which X is output      */
-  int nstvout;         /* id. for V                                    */
-  int nstfout;         /* id. for F                                    */
-  int nstenergy;       /* number of steps after which energies printed */
-  int nstxtcout;       /* id. for compressed trj (.xtc)                */
-  double init_t;       /* initial time (ps)                            */
-  double delta_t;      /* time step (ps)                               */
-  real xtcprec;         /* precision of xtc file                        */
-  int  nkx,nky,nkz;     /* number of k vectors in each spatial dimension*/
-                        /* for fourier methods for long range electrost.*/
-  int  pme_order;       /* interpolation order for PME                  */
-  real ewald_rtol;      /* Real space tolerance for Ewald, determines   */
-                        /* the real/reciprocal space relative weight    */
-  int  ewald_geometry;  /* normal/3d ewald, or pseudo-2d LR corrections */
-  real epsilon_surface; /* Epsilon for PME dipole correction            */
-  gmx_bool bOptFFT;         /* optimize the fft plan at start               */
-  int  ePBC;           /* Type of periodic boundary conditions         */
-  int  bPeriodicMols;   /* Periodic molecules                           */
-  gmx_bool bContinuation;   /* Continuation run: starting state is correct     */
-  int  etc;            /* temperature coupling                         */
-  int  nsttcouple;      /* interval in steps for temperature coupling   */
-  int  epc;            /* pressure coupling                            */
-  int  epct;           /* pressure coupling type                       */
-  int  nstpcouple;      /* interval in steps for pressure coupling      */
-  real tau_p;          /* pressure coupling time (ps)                  */
-  tensor ref_p;                /* reference pressure (kJ/(mol nm^3))           */
-  tensor compress;     /* compressability ((mol nm^3)/kJ)              */
-  int  refcoord_scaling;/* How to scale absolute reference coordinates  */
-  rvec posres_com;      /* The COM of the posres atoms                  */
-  rvec posres_comB;     /* The B-state COM of the posres atoms          */
-  int  andersen_seed;   /* Random seed for Andersen thermostat.         */
-  real rlist;          /* short range pairlist cut-off (nm)            */
-  real rlistlong;      /* long range pairlist cut-off (nm)             */
-  real rtpi;            /* Radius for test particle insertion           */
-  int  coulombtype;    /* Type of electrostatics treatment             */
-  real rcoulomb_switch; /* Coulomb switch range start (nm)             */
-  real rcoulomb;        /* Coulomb cutoff (nm)                         */
-  real epsilon_r;       /* relative dielectric constant                 */ 
-  real epsilon_rf;      /* relative dielectric constant of the RF       */ 
-  int  implicit_solvent;/* No (=explicit water), or GBSA solvent models */
-  int  gb_algorithm;    /* Algorithm to use for calculation Born radii  */
-  int  nstgbradii;      /* Frequency of updating Generalized Born radii */
-  real rgbradii;        /* Cutoff for GB radii calculation              */
-  real gb_saltconc;     /* Salt concentration (M) for GBSA models       */
-  real gb_epsilon_solvent; /* dielectric coeff. of implicit solvent     */
-  real gb_obc_alpha;    /* 1st scaling factor for Bashford-Case GB      */
-  real gb_obc_beta;     /* 2nd scaling factor for Bashford-Case GB      */
-  real gb_obc_gamma;    /* 3rd scaling factor for Bashford-Case GB      */
-  real gb_dielectric_offset; /* Dielectric offset for Still/HCT/OBC     */
-  int  sa_algorithm;    /* Algorithm for SA part of GBSA                */
-  real sa_surface_tension; /* Energy factor for SA part of GBSA */
-  int  vdwtype;         /* Type of Van der Waals treatment              */
-  real rvdw_switch;     /* Van der Waals switch range start (nm)        */
-  real rvdw;               /* Van der Waals cutoff (nm)                */
-  int  eDispCorr;       /* Perform Long range dispersion corrections    */
-  real tabext;          /* Extension of the table beyond the cut-off,   *
-                        * as well as the table length for 1-4 interac. */
-  real shake_tol;      /* tolerance for shake                          */
-  int  efep;                   /* free energy interpolation no/yes             */
-  double init_lambda;  /* initial value for perturbation variable      */
-  double delta_lambda; /* change of lambda per time step (1/dt)        */
-  int  n_flambda;       /* The number of foreign lambda points          */
-  double *flambda;      /* The foreign lambda values                    */
-  real sc_alpha;        /* free energy soft-core parameter              */
-  int  sc_power;        /* lambda power for soft-core interactions      */
-  real sc_sigma;        /* free energy soft-core sigma when c6 or c12=0 */
-  real sc_sigma_min;    /* minimum FE sc sigma (default: =sg_sigma)     */
-  int  nstdhdl;         /* The frequency for writing to dhdl.xvg        */
-  int  separate_dhdl_file; /* whether to write a separate dhdl.xvg file 
-                              note: NOT a gmx_bool, but an enum */
-  int  dhdl_derivatives;/* whether to calculate+write dhdl derivatives 
-                              note: NOT a gmx_bool, but an enum */
-  int  dh_hist_size;    /* The maximum size for the dH histogram        */
-  double dh_hist_spacing; /* The spacing for the dH histogram           */
-  int  eDisre;          /* Type of distance restraining                 */
-  real dr_fc;              /* force constant for ta_disre                      */
-  int  eDisreWeighting; /* type of weighting of pairs in one restraints        */
-  gmx_bool bDisreMixed;     /* Use comb of time averaged and instan. viol's    */
-  int  nstdisreout;     /* frequency of writing pair distances to enx   */ 
-  real dr_tau;             /* time constant for memory function in disres      */
-  real orires_fc;          /* force constant for orientational restraints  */
-  real orires_tau;         /* time constant for memory function in orires      */
-  int  nstorireout;     /* frequency of writing tr(SD) to enx           */ 
-  real dihre_fc;        /* force constant for dihedral restraints      */
-  real em_stepsize;        /* The stepsize for updating                        */
-  real em_tol;             /* The tolerance                            */
-  int  niter;           /* Number of iterations for convergence of      */
-                        /* steepest descent in relax_shells             */
-  real fc_stepsize;     /* Stepsize for directional minimization        */
-                        /* in relax_shells                              */
-  int  nstcgsteep;      /* number of steps after which a steepest       */
-                        /* descents step is done while doing cg         */
-  int  nbfgscorr;       /* Number of corrections to the hessian to keep */
-  int  eConstrAlg;      /* Type of constraint algorithm                 */
-  int  nProjOrder;      /* Order of the LINCS Projection Algorithm      */
-  real LincsWarnAngle;  /* If bond rotates more than %g degrees, warn   */
-  int  nLincsIter;      /* Number of iterations in the final Lincs step */
-  gmx_bool bShakeSOR;       /* Use successive overrelaxation for shake      */
-  real bd_fric;         /* Friction coefficient for BD (amu/ps)         */
-  int  ld_seed;         /* Random seed for SD and BD                    */
-  int  nwall;           /* The number of walls                          */
-  int  wall_type;       /* The type of walls                            */
-  real wall_r_linpot;   /* The potentail is linear for r<=wall_r_linpot */
-  int  wall_atomtype[2];/* The atom type for walls                      */
-  real wall_density[2]; /* Number density for walls                     */
-  real wall_ewald_zfac; /* Scaling factor for the box for Ewald         */
-  int  ePull;           /* Type of pulling: no, umbrella or constraint  */
-  t_pull *pull;         /* The data for center of mass pulling          */
-  real cos_accel;       /* Acceleration for viscosity calculation       */
-  tensor deform;        /* Triclinic deformation velocities (nm/ps)     */
-  int  userint1;        /* User determined parameters                   */
-  int  userint2;
-  int  userint3;
-  int  userint4;
-  real userreal1;
-  real userreal2;
-  real userreal3;
-  real userreal4;
-  t_grpopts opts;      /* Group options                                */
-  t_cosines ex[DIM];   /* Electric field stuff (spatial part)          */
-  t_cosines et[DIM];   /* Electric field stuff (time part)             */
-  gmx_bool bQMMM;           /* QM/MM calculation                            */ 
-  int  QMconstraints;   /* constraints on QM bonds                      */
-  int  QMMMscheme;      /* Scheme: ONIOM or normal                      */
-  real scalefactor;     /* factor for scaling the MM charges in QM calc.*/
-} t_inputrec;
-
-#define DEFORM(ir) ((ir).deform[XX][XX]!=0 || (ir).deform[YY][YY]!=0 || (ir).deform[ZZ][ZZ]!=0 || (ir).deform[YY][XX]!=0 || (ir).deform[ZZ][XX]!=0 || (ir).deform[ZZ][YY]!=0)
-
-#define DYNAMIC_BOX(ir) ((ir).epc!=epcNO || (ir).eI==eiTPI || DEFORM(ir))
-
-#define PRESERVE_SHAPE(ir) ((ir).epc != epcNO && (ir).deform[XX][XX] == 0 && ((ir).epct == epctISOTROPIC || (ir).epct == epctSEMIISOTROPIC))
-
-#define NEED_MUTOT(ir) (((ir).coulombtype==eelEWALD || EEL_PME((ir).coulombtype)) && ((ir).ewald_geometry==eewg3DC || (ir).epsilon_surface!=0))
-
-#define IR_TWINRANGE(ir) ((ir).rlist > 0 && ((ir).rlistlong == 0 || (ir).rlistlong > (ir).rlist))
-
-#define IR_ELEC_FIELD(ir) ((ir).ex[XX].n > 0 || (ir).ex[YY].n > 0 || (ir).ex[ZZ].n > 0)
-
-#define IR_EXCL_FORCES(ir) (EEL_FULL((ir).coulombtype) || (EEL_RF((ir).coulombtype) && (ir).coulombtype != eelRF_NEC) || (ir).implicit_solvent != eisNO)
-/* use pointer definitions of ir here, since that's what's usually used in the code */
-#define IR_NVT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->etc == etcNOSEHOOVER))
-
-#define IR_NPT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->epc == epcMTTK))
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
diff --git a/include/vec.h b/include/vec.h
deleted file mode 100644 (file)
index 139a9c4..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-#ifndef _vec_h
-#define _vec_h
-
-/*
-  collection of in-line ready operations:
-  
-  lookup-table optimized scalar operations:
-  real gmx_invsqrt(real x)
-  void vecinvsqrt(real in[],real out[],int n)
-  void vecrecip(real in[],real out[],int n)
-  real sqr(real x)
-  double dsqr(double x)
-  
-  vector operations:
-  void rvec_add(const rvec a,const rvec b,rvec c)  c = a + b
-  void dvec_add(const dvec a,const dvec b,dvec c)  c = a + b
-  void ivec_add(const ivec a,const ivec b,ivec c)  c = a + b
-  void rvec_inc(rvec a,const rvec b)               a += b
-  void dvec_inc(dvec a,const dvec b)               a += b
-  void ivec_inc(ivec a,const ivec b)               a += b
-  void rvec_sub(const rvec a,const rvec b,rvec c)  c = a - b
-  void dvec_sub(const dvec a,const dvec b,dvec c)  c = a - b
-  void rvec_dec(rvec a,rvec b)                     a -= b
-  void copy_rvec(const rvec a,rvec b)              b = a (reals)
-  void copy_dvec(const dvec a,dvec b)              b = a (reals)
-  void copy_ivec(const ivec a,ivec b)              b = a (integers)
-  void ivec_sub(const ivec a,const ivec b,ivec c)  c = a - b
-  void svmul(real a,rvec v1,rvec v2)               v2 = a * v1
-  void dsvmul(double a,dvec v1,dvec v2)            v2 = a * v1
-  void clear_rvec(rvec a)                          a = 0
-  void clear_dvec(dvec a)                          a = 0
-  void clear_ivec(rvec a)                          a = 0
-  void clear_rvecs(int n,rvec v[])
-  real iprod(rvec a,rvec b)                        = a . b (inner product)
-  double diprod(dvec a,dvec b)                     = a . b (inner product)
-  real iiprod(ivec a,ivec b)                       = a . b (integers)
-  real norm2(rvec a)                               = | a |^2 ( = x*y*z )
-  double dnorm2(dvec a)                            = | a |^2 ( = x*y*z )
-  real norm(rvec a)                                = | a |
-  double dnorm(dvec a)                             = | a |
-  void cprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
-  void dprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
-  void dprod(rvec a,rvec b,rvec c)                 c = a * b (direct product)
-  real cos_angle(rvec a,rvec b)
-  real cos_angle_no_table(rvec a,rvec b)
-  real distance2(rvec v1, rvec v2)                 = | v2 - v1 |^2
-  void unitv(rvec src,rvec dest)                   dest = src / |src|
-  void unitv_no_table(rvec src,rvec dest)          dest = src / |src|
-  
-  matrix (3x3) operations:
-    ! indicates that dest should not be the same as a, b or src
-    the _ur0 varieties work on matrices that have only zeros
-    in the upper right part, such as box matrices, these varieties
-    could produce less rounding errors, not due to the operations themselves,
-    but because the compiler can easier recombine the operations
-  void copy_mat(matrix a,matrix b)                 b = a
-  void clear_mat(matrix a)                        a = 0
-  void mmul(matrix a,matrix b,matrix dest)     !  dest = a . b
-  void mmul_ur0(matrix a,matrix b,matrix dest)     dest = a . b
-  void transpose(matrix src,matrix dest)       !  dest = src*
-  void tmmul(matrix a,matrix b,matrix dest)    !  dest = a* . b
-  void mtmul(matrix a,matrix b,matrix dest)    !  dest = a . b*
-  real det(matrix a)                              = det(a)
-  void m_add(matrix a,matrix b,matrix dest)       dest = a + b
-  void m_sub(matrix a,matrix b,matrix dest)       dest = a - b
-  void msmul(matrix m1,real r1,matrix dest)       dest = r1 * m1
-  void m_inv_ur0(matrix src,matrix dest)           dest = src^-1
-  void m_inv(matrix src,matrix dest)           !  dest = src^-1
-  void mvmul(matrix a,rvec src,rvec dest)      !  dest = a . src
-  void mvmul_ur0(matrix a,rvec src,rvec dest)      dest = a . src
-  void tmvmul_ur0(matrix a,rvec src,rvec dest)     dest = a* . src
-  real trace(matrix m)                             = trace(m)
-*/
-
-#include "types/simple.h"
-#include "maths.h"
-#include "typedefs.h"
-#include "sysstuff.h"
-#include "macros.h"
-#include "gmx_fatal.h"
-#include "mpelogging.h"
-#include "physics.h"
-
-#ifdef __cplusplus
-extern "C" {
-#elif 0
-} /* avoid screwing up indentation */
-#endif
-
-
-#define EXP_LSB         0x00800000
-#define EXP_MASK        0x7f800000
-#define EXP_SHIFT       23
-#define FRACT_MASK      0x007fffff
-#define FRACT_SIZE      11              /* significant part of fraction */
-#define FRACT_SHIFT     (EXP_SHIFT-FRACT_SIZE)
-#define EXP_ADDR(val)   (((val)&EXP_MASK)>>EXP_SHIFT)
-#define FRACT_ADDR(val) (((val)&(FRACT_MASK|EXP_LSB))>>FRACT_SHIFT)
-
-#define PR_VEC(a)       a[XX],a[YY],a[ZZ]
-
-#ifdef GMX_SOFTWARE_INVSQRT
-extern const unsigned int *  gmx_invsqrt_exptab;
-extern const unsigned int *  gmx_invsqrt_fracttab;
-#endif
-
-
-typedef union 
-{
-  unsigned int bval;
-  float fval;
-} t_convert;
-
-
-#ifdef GMX_SOFTWARE_INVSQRT
-static real gmx_invsqrt(real x)
-{
-  const real  half=0.5;
-  const real  three=3.0;
-  t_convert   result,bit_pattern;
-  unsigned int exp,fract;
-  real        lu;
-  real        y;
-#ifdef GMX_DOUBLE
-  real        y2;
-#endif
-  bit_pattern.fval=x;
-  exp   = EXP_ADDR(bit_pattern.bval);
-  fract = FRACT_ADDR(bit_pattern.bval);
-  result.bval=gmx_invsqrt_exptab[exp] | gmx_invsqrt_fracttab[fract];
-  lu    = result.fval;
-  
-  y=(half*lu*(three-((x*lu)*lu)));
-#ifdef GMX_DOUBLE
-  y2=(half*y*(three-((x*y)*y)));
-  
-  return y2;                    /* 10 Flops */
-#else
-  return y;                     /* 5  Flops */
-#endif
-}
-#define INVSQRT_DONE 
-#endif /* gmx_invsqrt */
-
-#ifdef GMX_POWERPC_SQRT
-static real gmx_invsqrt(real x)
-{
-  const real  half=0.5;
-  const real  three=3.0;
-  t_convert   result,bit_pattern;
-  unsigned int exp,fract;
-  real        lu;
-  real        y;
-#ifdef GMX_DOUBLE
-  real        y2;
-#endif
-
-  lu = __frsqrte((double)x);
-
-  y=(half*lu*(three-((x*lu)*lu)));
-
-#if (GMX_POWERPC_SQRT==2)
-  /* Extra iteration required */
-  y=(half*y*(three-((x*y)*y)));
-#endif
-
-#ifdef GMX_DOUBLE
-  y2=(half*y*(three-((x*y)*y)));
-
-  return y2;                    /* 10 Flops */
-#else
-  return y;                     /* 5  Flops */
-#endif
-}
-#define INVSQRT_DONE
-#endif /* powerpc_invsqrt */
-
-
-#ifndef INVSQRT_DONE
-#define gmx_invsqrt(x) (1.0f/sqrt(x))
-#endif
-
-
-
-
-
-static real sqr(real x)
-{
-  return (x*x);
-}
-
-static gmx_inline double dsqr(double x)
-{
-  return (x*x);
-}
-
-/* Maclaurin series for sinh(x)/x, useful for NH chains and MTTK pressure control 
-   Here, we compute it to 10th order, which might be overkill, 8th is probably enough, 
-   but it's not very much more expensive. */
-
-static gmx_inline real series_sinhx(real x) 
-{
-  real x2 = x*x;
-  return (1 + (x2/6.0)*(1 + (x2/20.0)*(1 + (x2/42.0)*(1 + (x2/72.0)*(1 + (x2/110.0))))));
-}
-
-void vecinvsqrt(real in[],real out[],int n);
-/* Perform out[i]=1.0/sqrt(in[i]) for n elements */
-
-
-void vecrecip(real in[],real out[],int n);
-/* Perform out[i]=1.0/(in[i]) for n elements */
-
-/* Note: If you need a fast version of vecinvsqrt 
- * and/or vecrecip, call detectcpu() and run the SSE/3DNow/SSE2/Altivec
- * versions if your hardware supports it.
- *
- * To use those routines, your memory HAS TO BE CACHE-ALIGNED.
- * Use snew_aligned(ptr,size,32) to allocate and sfree_aligned to free.
- */
-
-
-static gmx_inline void rvec_add(const rvec a,const rvec b,rvec c)
-{
-  real x,y,z;
-  
-  x=a[XX]+b[XX];
-  y=a[YY]+b[YY];
-  z=a[ZZ]+b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void dvec_add(const dvec a,const dvec b,dvec c)
-{
-  double x,y,z;
-  
-  x=a[XX]+b[XX];
-  y=a[YY]+b[YY];
-  z=a[ZZ]+b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void ivec_add(const ivec a,const ivec b,ivec c)
-{
-  int x,y,z;
-  
-  x=a[XX]+b[XX];
-  y=a[YY]+b[YY];
-  z=a[ZZ]+b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void rvec_inc(rvec a,const rvec b)
-{
-  real x,y,z;
-  
-  x=a[XX]+b[XX];
-  y=a[YY]+b[YY];
-  z=a[ZZ]+b[ZZ];
-  
-  a[XX]=x;
-  a[YY]=y;
-  a[ZZ]=z;
-}
-
-static gmx_inline void dvec_inc(dvec a,const dvec b)
-{
-  double x,y,z;
-
-  x=a[XX]+b[XX];
-  y=a[YY]+b[YY];
-  z=a[ZZ]+b[ZZ];
-
-  a[XX]=x;
-  a[YY]=y;
-  a[ZZ]=z;
-}
-
-static gmx_inline void rvec_sub(const rvec a,const rvec b,rvec c)
-{
-  real x,y,z;
-  
-  x=a[XX]-b[XX];
-  y=a[YY]-b[YY];
-  z=a[ZZ]-b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void dvec_sub(const dvec a,const dvec b,dvec c)
-{
-  double x,y,z;
-  
-  x=a[XX]-b[XX];
-  y=a[YY]-b[YY];
-  z=a[ZZ]-b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void rvec_dec(rvec a,const rvec b)
-{
-  real x,y,z;
-  
-  x=a[XX]-b[XX];
-  y=a[YY]-b[YY];
-  z=a[ZZ]-b[ZZ];
-  
-  a[XX]=x;
-  a[YY]=y;
-  a[ZZ]=z;
-}
-
-static gmx_inline void copy_rvec(const rvec a,rvec b)
-{
-  b[XX]=a[XX];
-  b[YY]=a[YY];
-  b[ZZ]=a[ZZ];
-}
-
-static gmx_inline void copy_rvecn(rvec *a,rvec *b,int startn, int endn)
-{
-  int i;
-  for (i=startn;i<endn;i++) {
-    b[i][XX]=a[i][XX];
-    b[i][YY]=a[i][YY];
-    b[i][ZZ]=a[i][ZZ];
-  }
-}
-
-static gmx_inline void copy_dvec(const dvec a,dvec b)
-{
-  b[XX]=a[XX];
-  b[YY]=a[YY];
-  b[ZZ]=a[ZZ];
-}
-
-static gmx_inline void copy_ivec(const ivec a,ivec b)
-{
-  b[XX]=a[XX];
-  b[YY]=a[YY];
-  b[ZZ]=a[ZZ];
-}
-
-static gmx_inline void ivec_sub(const ivec a,const ivec b,ivec c)
-{
-  int x,y,z;
-  
-  x=a[XX]-b[XX];
-  y=a[YY]-b[YY];
-  z=a[ZZ]-b[ZZ];
-  
-  c[XX]=x;
-  c[YY]=y;
-  c[ZZ]=z;
-}
-
-static gmx_inline void copy_mat(matrix a,matrix b)
-{
-  copy_rvec(a[XX],b[XX]);
-  copy_rvec(a[YY],b[YY]);
-  copy_rvec(a[ZZ],b[ZZ]);
-}
-
-static gmx_inline void svmul(real a,const rvec v1,rvec v2)
-{
-  v2[XX]=a*v1[XX];
-  v2[YY]=a*v1[YY];
-  v2[ZZ]=a*v1[ZZ];
-}
-
-static gmx_inline void dsvmul(double a,const dvec v1,dvec v2)
-{
-  v2[XX]=a*v1[XX];
-  v2[YY]=a*v1[YY];
-  v2[ZZ]=a*v1[ZZ];
-}
-
-static gmx_inline real distance2(const rvec v1,const rvec v2)
-{
-  return sqr(v2[XX]-v1[XX]) + sqr(v2[YY]-v1[YY]) + sqr(v2[ZZ]-v1[ZZ]);
-}
-
-static gmx_inline void clear_rvec(rvec a)
-{
-  /* The ibm compiler has problems with inlining this 
-   * when we use a const real variable
-   */
-  a[XX]=0.0;
-  a[YY]=0.0;
-  a[ZZ]=0.0;
-}
-
-static gmx_inline void clear_dvec(dvec a)
-{
-  /* The ibm compiler has problems with inlining this 
-   * when we use a const real variable
-   */
-  a[XX]=0.0;
-  a[YY]=0.0;
-  a[ZZ]=0.0;
-}
-
-static gmx_inline void clear_ivec(ivec a)
-{
-  a[XX]=0;
-  a[YY]=0;
-  a[ZZ]=0;
-}
-
-static gmx_inline void clear_rvecs(int n,rvec v[])
-{
-/*  memset(v[0],0,DIM*n*sizeof(v[0][0])); */
-  int i;
-
-  GMX_MPE_LOG(ev_clear_rvecs_start);
-    
-  for(i=0; (i<n); i++) 
-    clear_rvec(v[i]);
-    
-  GMX_MPE_LOG(ev_clear_rvecs_finish);  
-}
-
-static gmx_inline void clear_mat(matrix a)
-{
-/*  memset(a[0],0,DIM*DIM*sizeof(a[0][0])); */
-  
-  const real nul=0.0;
-  
-  a[XX][XX]=a[XX][YY]=a[XX][ZZ]=nul;
-  a[YY][XX]=a[YY][YY]=a[YY][ZZ]=nul;
-  a[ZZ][XX]=a[ZZ][YY]=a[ZZ][ZZ]=nul;
-}
-
-static gmx_inline real iprod(const rvec a,const rvec b)
-{
-  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
-}
-
-static gmx_inline double diprod(const dvec a,const dvec b)
-{
-  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
-}
-
-static gmx_inline int iiprod(const ivec a,const ivec b)
-{
-  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
-}
-
-static gmx_inline real norm2(const rvec a)
-{
-  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
-}
-
-static gmx_inline double dnorm2(const dvec a)
-{
-  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
-}
-
-static gmx_inline real norm(const rvec a)
-{
-  return (real)sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
-}
-
-static gmx_inline double dnorm(const dvec a)
-{
-  return sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
-}
-
-/* WARNING:
- * Do _not_ use these routines to calculate the angle between two vectors
- * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
- * is very flat close to -1 and 1, which will lead to accuracy-loss.
- * Instead, use the new gmx_angle() function directly.
- */
-static gmx_inline real 
-cos_angle(const rvec a,const rvec b)
-{
-  /* 
-   *                  ax*bx + ay*by + az*bz
-   * cos-vec (a,b) =  ---------------------
-   *                      ||a|| * ||b||
-   */
-  real   cosval;
-  int    m;
-  double aa,bb,ip,ipa,ipb,ipab; /* For accuracy these must be double! */
-  
-  ip=ipa=ipb=0.0;
-  for(m=0; (m<DIM); m++) {             /* 18           */
-    aa   = a[m];
-    bb   = b[m];
-    ip  += aa*bb;
-    ipa += aa*aa;
-    ipb += bb*bb;
-  }
-  ipab = ipa*ipb;
-  if (ipab > 0)
-    cosval = ip*gmx_invsqrt(ipab);             /*  7           */
-  else 
-    cosval = 1;
-                                       /* 25 TOTAL     */
-  if (cosval > 1.0) 
-    return  1.0; 
-  if (cosval <-1.0) 
-    return -1.0;
-  
-  return cosval;
-}
-
-/* WARNING:
- * Do _not_ use these routines to calculate the angle between two vectors
- * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
- * is very flat close to -1 and 1, which will lead to accuracy-loss.
- * Instead, use the new gmx_angle() function directly.
- */
-static gmx_inline real 
-cos_angle_no_table(const rvec a,const rvec b)
-{
-  /* This version does not need the invsqrt lookup table */
-  real   cosval;
-  int    m;
-  double aa,bb,ip,ipa,ipb; /* For accuracy these must be double! */
-  
-  ip=ipa=ipb=0.0;
-  for(m=0; (m<DIM); m++) {             /* 18           */
-    aa   = a[m];
-    bb   = b[m];
-    ip  += aa*bb;
-    ipa += aa*aa;
-    ipb += bb*bb;
-  }
-  cosval=ip/sqrt(ipa*ipb);             /* 12           */
-                                       /* 30 TOTAL     */
-  if (cosval > 1.0) 
-    return  1.0; 
-  if (cosval <-1.0) 
-    return -1.0;
-  
-  return cosval;
-}
-
-
-static gmx_inline void cprod(const rvec a,const rvec b,rvec c)
-{
-  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
-  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
-  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
-}
-
-static gmx_inline void dcprod(const dvec a,const dvec b,dvec c)
-{
-  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
-  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
-  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
-}
-
-/* This routine calculates the angle between a & b without any loss of accuracy close to 0/PI.
- * If you only need cos(theta), use the cos_angle() routines to save a few cycles.
- * This routine is faster than it might appear, since atan2 is accelerated on many CPUs (e.g. x86).
- */
-static gmx_inline real 
-gmx_angle(const rvec a, const rvec b)
-{
-    rvec w;
-    real wlen,s;
-    
-    cprod(a,b,w);
-    
-    wlen  = norm(w);
-    s     = iprod(a,b);
-    
-    return atan2(wlen,s);
-}
-
-static gmx_inline void mmul_ur0(matrix a,matrix b,matrix dest)
-{
-  dest[XX][XX]=a[XX][XX]*b[XX][XX];
-  dest[XX][YY]=0.0;
-  dest[XX][ZZ]=0.0;
-  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX];
-  dest[YY][YY]=                    a[YY][YY]*b[YY][YY];
-  dest[YY][ZZ]=0.0;
-  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
-  dest[ZZ][YY]=                    a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
-  dest[ZZ][ZZ]=                                        a[ZZ][ZZ]*b[ZZ][ZZ];
-}
-
-static gmx_inline void mmul(matrix a,matrix b,matrix dest)
-{
-  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[YY][XX]+a[XX][ZZ]*b[ZZ][XX];
-  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[YY][ZZ]*b[ZZ][XX];
-  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
-  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[ZZ][YY];
-  dest[YY][YY]=a[YY][XX]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[ZZ][YY];
-  dest[ZZ][YY]=a[ZZ][XX]*b[XX][YY]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
-  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[XX][YY]*b[YY][ZZ]+a[XX][ZZ]*b[ZZ][ZZ];
-  dest[YY][ZZ]=a[YY][XX]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[YY][ZZ]*b[ZZ][ZZ];
-  dest[ZZ][ZZ]=a[ZZ][XX]*b[XX][ZZ]+a[ZZ][YY]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
-}
-
-static gmx_inline void transpose(matrix src,matrix dest)
-{
-  dest[XX][XX]=src[XX][XX];
-  dest[YY][XX]=src[XX][YY];
-  dest[ZZ][XX]=src[XX][ZZ];
-  dest[XX][YY]=src[YY][XX];
-  dest[YY][YY]=src[YY][YY];
-  dest[ZZ][YY]=src[YY][ZZ];
-  dest[XX][ZZ]=src[ZZ][XX];
-  dest[YY][ZZ]=src[ZZ][YY];
-  dest[ZZ][ZZ]=src[ZZ][ZZ];
-}
-
-static gmx_inline void tmmul(matrix a,matrix b,matrix dest)
-{
-  /* Computes dest=mmul(transpose(a),b,dest) - used in do_pr_pcoupl */
-  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[YY][XX]*b[YY][XX]+a[ZZ][XX]*b[ZZ][XX];
-  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[YY][XX]*b[YY][YY]+a[ZZ][XX]*b[ZZ][YY];
-  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[YY][XX]*b[YY][ZZ]+a[ZZ][XX]*b[ZZ][ZZ];
-  dest[YY][XX]=a[XX][YY]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[ZZ][YY]*b[ZZ][XX];
-  dest[YY][YY]=a[XX][YY]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[ZZ][YY]*b[ZZ][YY];
-  dest[YY][ZZ]=a[XX][YY]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[ZZ][YY]*b[ZZ][ZZ];
-  dest[ZZ][XX]=a[XX][ZZ]*b[XX][XX]+a[YY][ZZ]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
-  dest[ZZ][YY]=a[XX][ZZ]*b[XX][YY]+a[YY][ZZ]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
-  dest[ZZ][ZZ]=a[XX][ZZ]*b[XX][ZZ]+a[YY][ZZ]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
-}
-
-static gmx_inline void mtmul(matrix a,matrix b,matrix dest)
-{
-  /* Computes dest=mmul(a,transpose(b),dest) - used in do_pr_pcoupl */
-  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[XX][YY]+a[XX][ZZ]*b[XX][ZZ];
-  dest[XX][YY]=a[XX][XX]*b[YY][XX]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[YY][ZZ];
-  dest[XX][ZZ]=a[XX][XX]*b[ZZ][XX]+a[XX][YY]*b[ZZ][YY]+a[XX][ZZ]*b[ZZ][ZZ];
-  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[XX][YY]+a[YY][ZZ]*b[XX][ZZ];
-  dest[YY][YY]=a[YY][XX]*b[YY][XX]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[YY][ZZ];
-  dest[YY][ZZ]=a[YY][XX]*b[ZZ][XX]+a[YY][YY]*b[ZZ][YY]+a[YY][ZZ]*b[ZZ][ZZ];
-  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[XX][YY]+a[ZZ][ZZ]*b[XX][ZZ];
-  dest[ZZ][YY]=a[ZZ][XX]*b[YY][XX]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[YY][ZZ];
-  dest[ZZ][ZZ]=a[ZZ][XX]*b[ZZ][XX]+a[ZZ][YY]*b[ZZ][YY]+a[ZZ][ZZ]*b[ZZ][ZZ];
-}
-
-static gmx_inline real det(matrix a)
-{
-  return ( a[XX][XX]*(a[YY][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[YY][ZZ])
-         -a[YY][XX]*(a[XX][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[XX][ZZ])
-         +a[ZZ][XX]*(a[XX][YY]*a[YY][ZZ]-a[YY][YY]*a[XX][ZZ]));
-}
-
-static gmx_inline void m_add(matrix a,matrix b,matrix dest)
-{
-  dest[XX][XX]=a[XX][XX]+b[XX][XX];
-  dest[XX][YY]=a[XX][YY]+b[XX][YY];
-  dest[XX][ZZ]=a[XX][ZZ]+b[XX][ZZ];
-  dest[YY][XX]=a[YY][XX]+b[YY][XX];
-  dest[YY][YY]=a[YY][YY]+b[YY][YY];
-  dest[YY][ZZ]=a[YY][ZZ]+b[YY][ZZ];
-  dest[ZZ][XX]=a[ZZ][XX]+b[ZZ][XX];
-  dest[ZZ][YY]=a[ZZ][YY]+b[ZZ][YY];
-  dest[ZZ][ZZ]=a[ZZ][ZZ]+b[ZZ][ZZ];
-}
-
-static gmx_inline void m_sub(matrix a,matrix b,matrix dest)
-{
-  dest[XX][XX]=a[XX][XX]-b[XX][XX];
-  dest[XX][YY]=a[XX][YY]-b[XX][YY];
-  dest[XX][ZZ]=a[XX][ZZ]-b[XX][ZZ];
-  dest[YY][XX]=a[YY][XX]-b[YY][XX];
-  dest[YY][YY]=a[YY][YY]-b[YY][YY];
-  dest[YY][ZZ]=a[YY][ZZ]-b[YY][ZZ];
-  dest[ZZ][XX]=a[ZZ][XX]-b[ZZ][XX];
-  dest[ZZ][YY]=a[ZZ][YY]-b[ZZ][YY];
-  dest[ZZ][ZZ]=a[ZZ][ZZ]-b[ZZ][ZZ];
-}
-
-static gmx_inline void msmul(matrix m1,real r1,matrix dest)
-{
-  dest[XX][XX]=r1*m1[XX][XX];
-  dest[XX][YY]=r1*m1[XX][YY];
-  dest[XX][ZZ]=r1*m1[XX][ZZ];
-  dest[YY][XX]=r1*m1[YY][XX];
-  dest[YY][YY]=r1*m1[YY][YY];
-  dest[YY][ZZ]=r1*m1[YY][ZZ];
-  dest[ZZ][XX]=r1*m1[ZZ][XX];
-  dest[ZZ][YY]=r1*m1[ZZ][YY];
-  dest[ZZ][ZZ]=r1*m1[ZZ][ZZ];
-}
-
-static gmx_inline void m_inv_ur0(matrix src,matrix dest)
-{
-  double tmp = src[XX][XX]*src[YY][YY]*src[ZZ][ZZ];
-  if (fabs(tmp) <= 100*GMX_REAL_MIN)
-    gmx_fatal(FARGS,"Can not invert matrix, determinant is zero");
-
-  dest[XX][XX] = 1/src[XX][XX];
-  dest[YY][YY] = 1/src[YY][YY];
-  dest[ZZ][ZZ] = 1/src[ZZ][ZZ];
-  dest[ZZ][XX] = (src[YY][XX]*src[ZZ][YY]*dest[YY][YY]
-                 - src[ZZ][XX])*dest[XX][XX]*dest[ZZ][ZZ];
-  dest[YY][XX] = -src[YY][XX]*dest[XX][XX]*dest[YY][YY];
-  dest[ZZ][YY] = -src[ZZ][YY]*dest[YY][YY]*dest[ZZ][ZZ];
-  dest[XX][YY] = 0.0;
-  dest[XX][ZZ] = 0.0;
-  dest[YY][ZZ] = 0.0;
-}
-
-static gmx_inline void m_inv(matrix src,matrix dest)
-{
-  const real smallreal = (real)1.0e-24;
-  const real largereal = (real)1.0e24;
-  real  deter,c,fc;
-
-  deter = det(src);
-  c     = (real)1.0/deter;
-  fc    = (real)fabs(c);
-  
-  if ((fc <= smallreal) || (fc >= largereal)) 
-    gmx_fatal(FARGS,"Can not invert matrix, determinant = %e",deter);
-
-  dest[XX][XX]= c*(src[YY][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[YY][ZZ]);
-  dest[XX][YY]=-c*(src[XX][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[XX][ZZ]);
-  dest[XX][ZZ]= c*(src[XX][YY]*src[YY][ZZ]-src[YY][YY]*src[XX][ZZ]);
-  dest[YY][XX]=-c*(src[YY][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[YY][ZZ]);
-  dest[YY][YY]= c*(src[XX][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[XX][ZZ]);
-  dest[YY][ZZ]=-c*(src[XX][XX]*src[YY][ZZ]-src[YY][XX]*src[XX][ZZ]);
-  dest[ZZ][XX]= c*(src[YY][XX]*src[ZZ][YY]-src[ZZ][XX]*src[YY][YY]);
-  dest[ZZ][YY]=-c*(src[XX][XX]*src[ZZ][YY]-src[ZZ][XX]*src[XX][YY]);
-  dest[ZZ][ZZ]= c*(src[XX][XX]*src[YY][YY]-src[YY][XX]*src[XX][YY]);
-}
-
-static gmx_inline void mvmul(matrix a,const rvec src,rvec dest)
-{
-  dest[XX]=a[XX][XX]*src[XX]+a[XX][YY]*src[YY]+a[XX][ZZ]*src[ZZ];
-  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY]+a[YY][ZZ]*src[ZZ];
-  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
-}
-
-static gmx_inline void mvmul_ur0(matrix a,const rvec src,rvec dest)
-{
-  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
-  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY];
-  dest[XX]=a[XX][XX]*src[XX];
-}
-
-static gmx_inline void tmvmul_ur0(matrix a,const rvec src,rvec dest)
-{
-  dest[XX]=a[XX][XX]*src[XX]+a[YY][XX]*src[YY]+a[ZZ][XX]*src[ZZ];
-  dest[YY]=                  a[YY][YY]*src[YY]+a[ZZ][YY]*src[ZZ];
-  dest[ZZ]=                                    a[ZZ][ZZ]*src[ZZ];
-}
-
-static gmx_inline void unitv(const rvec src,rvec dest)
-{
-  real linv;
-  
-  linv=gmx_invsqrt(norm2(src));
-  dest[XX]=linv*src[XX];
-  dest[YY]=linv*src[YY];
-  dest[ZZ]=linv*src[ZZ];
-}
-
-static gmx_inline void unitv_no_table(const rvec src,rvec dest)
-{
-  real linv;
-  
-  linv=1.0/sqrt(norm2(src));
-  dest[XX]=linv*src[XX];
-  dest[YY]=linv*src[YY];
-  dest[ZZ]=linv*src[ZZ];
-}
-
-static void calc_lll(rvec box,rvec lll)
-{
-  lll[XX] = 2.0*M_PI/box[XX];
-  lll[YY] = 2.0*M_PI/box[YY];
-  lll[ZZ] = 2.0*M_PI/box[ZZ];
-}
-
-static gmx_inline real trace(matrix m)
-{
-  return (m[XX][XX]+m[YY][YY]+m[ZZ][ZZ]);
-}
-
-static gmx_inline real _divide(real a,real b,const char *file,int line)
-{
-    if (fabs(b) <= GMX_REAL_MIN) 
-        gmx_fatal(FARGS,"Dividing by zero, file %s, line %d",file,line);
-    return a/b;
-}
-
-static gmx_inline int _mod(int a,int b,char *file,int line)
-{
-  if(b==0)
-    gmx_fatal(FARGS,"Modulo zero, file %s, line %d",file,line);
-  return a % b;
-}
-
-/* Operations on multidimensional rvecs, used e.g. in edsam.c */
-static void m_rveccopy(int dim, rvec *a, rvec *b)
-{
-    /* b = a */
-    int i;
-
-    for (i=0; i<dim; i++)
-        copy_rvec(a[i],b[i]);
-} 
-
-/*computer matrix vectors from base vectors and angles */
-static void matrix_convert(matrix box, rvec vec, rvec angle)
-{
-    svmul(DEG2RAD,angle,angle);
-    box[XX][XX] = vec[XX];
-    box[YY][XX] = vec[YY]*cos(angle[ZZ]);
-    box[YY][YY] = vec[YY]*sin(angle[ZZ]);
-    box[ZZ][XX] = vec[ZZ]*cos(angle[YY]);
-    box[ZZ][YY] = vec[ZZ]
-                         *(cos(angle[XX])-cos(angle[YY])*cos(angle[ZZ]))/sin(angle[ZZ]);
-    box[ZZ][ZZ] = sqrt(sqr(vec[ZZ])
-                       -box[ZZ][XX]*box[ZZ][XX]-box[ZZ][YY]*box[ZZ][YY]);
-}
-
-#define divide(a,b) _divide((a),(b),__FILE__,__LINE__)
-#define mod(a,b)    _mod((a),(b),__FILE__,__LINE__)
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _vec_h */
diff --git a/man/.cvsignore b/man/.cvsignore
deleted file mode 100644 (file)
index 3dda729..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile.in
-Makefile
diff --git a/man/man1/.cvsignore b/man/man1/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/scripts/.cvsignore b/scripts/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/scripts/.gitignore b/scripts/.gitignore
new file mode 100644 (file)
index 0000000..a478607
--- /dev/null
@@ -0,0 +1,2 @@
+GMXRC
+GMXRC.*
index 34941bd5a63a1e97e434d01113c2313c62663abe..9fa09605756d270ed18c0c1c58325a91e10bb63b 100644 (file)
@@ -1,12 +1,17 @@
-# bash configuration file for Gromacs
+# sh/bash/zsh configuration file for Gromacs
 # First we remove old gromacs stuff from the paths
 # by selecting everything else.
 # This is not 100% necessary, but very useful when we
 # repeatedly switch between gmx versions in a shell.
 
+#we make use of IFS, which needs shwordsplit in zsh
+test -n "${ZSH_VERSION+set}" && setopt shwordsplit
+old_IFS="$IFS"
+IFS=":"
+
 # First remove gromacs part of ld_library_path
 tmppath=""
-for i in `echo $LD_LIBRARY_PATH | sed "s/:/ /g"`; do
+for i in $LD_LIBRARY_PATH; do
   if test "$i" != "$GMXLDLIB"; then
     tmppath="${tmppath}${tmppath:+:}${i}"
   fi
@@ -15,7 +20,7 @@ LD_LIBRARY_PATH=$tmppath
 
 # remove gromacs part of PKG_CONFIG_PATH
 tmppath=""
-for i in `echo $PKG_CONFIG_PATH | sed "s/:/ /g"`; do
+for i in $PKG_CONFIG_PATH; do
   if test "$i" != "$GMXLDLIB/pkgconfig"; then
     tmppath="${tmppath}${tmppath:+:}${i}"
   fi
@@ -24,7 +29,7 @@ PKG_CONFIG_PATH=$tmppath
 
 # remove gromacs part of path
 tmppath=""
-for i in `echo $PATH | sed "s/:/ /g"`; do
+for i in $PATH; do
   if test "$i" != "$GMXBIN"; then
     tmppath="${tmppath}${tmppath:+:}${i}"
   fi
@@ -33,7 +38,7 @@ PATH=$tmppath
 
 # and remove the gmx part of manpath
 tmppath=""
-for i in `echo $MANPATH | sed "s/:/ /g"`; do
+for i in $MANPATH; do
   if test "$i" != "$GMXMAN"; then
     tmppath="${tmppath}${tmppath:+:}${i}"
   fi
@@ -59,14 +64,20 @@ MANPATH=${GMXMAN}:${MANPATH}
 # export should be separate, so /bin/sh understands it
 export GMXBIN GMXLDLIB GMXMAN GMXDATA LD_LIBRARY_PATH PATH MANPATH PKG_CONFIG_PATH
 
+IFS="$old_IFS"
+unset old_IFS
+
 # read bash completions if understand how to use them
 # and this shell supports extended globbing
-if (complete) > /dev/null 2>&1; then
+if test -n "${BASH_VERSION+set}" && (complete) > /dev/null 2>&1; then
   if (shopt -s extglob) > /dev/null 2>&1; then
     if [ -f $GMXBIN/completion.bash ]; then
       source $GMXBIN/completion.bash; 
     fi
   fi
+# read zsh completions if understand how to use them
+elif test -n "${ZSH_VERSION+set}" && compctl >& /dev/null; then
+  if [ -f $GMXBIN/completion.zsh ]; then
+    source $GMXBIN/completion.zsh; 
+  fi
 fi
-
-
index de457e2b1b8b7a0921b3bada649bc0b3556af23b..9917088959a64eb63ea7fee6b1894c1e0c0497b1 100644 (file)
@@ -10,37 +10,10 @@ set is_csh = 123
 test "$is_csh" = 123 && goto CSH
 
 # if we got here, shell is bsh/bash/zsh/ksh
-# bsh cannot remove part of a variable with %%
-shtst="A.B"
-if [ "`(echo ${shtst%%.*}) 2>/dev/null`" = A ]; then
-
-  # shell is bash/zsh/ksh
-  # bash/zsh use $[...] for arithmetic evaluation, ksh doesn't
-  if [ "`echo $[0+1]`" = 1 ]; then
-    
-    # shell is zsh/bash
-    # zsh can test if the variable shtst is set with ${+shtst}
-    if [ "`(echo ${+shtst}) 2>/dev/null`" = 1 ]; then
-      # shell is zsh
-      source @BIN_INSTALL_DIR@/GMXRC.zsh
-    else  
-      # shell is bash
-      source @BIN_INSTALL_DIR@/GMXRC.bash      
-    fi
-
-  else    
-    # shell is ksh - use bash setup, completions won't be read.
-     . @BIN_INSTALL_DIR@/GMXRC.bash
-  fi
-  return
-else
-  # shell is bsh - use bash setup, completions won't be read.
-  . @BIN_INSTALL_DIR@/GMXRC.bash
-  exit
-fi
+. @BIN_INSTALL_DIR@/GMXRC.bash
+return
 
 # csh/tcsh jump here
-
 CSH:
 source @BIN_INSTALL_DIR@/GMXRC.csh
 
index af52294e6f53acfc201788125778be205f0f9142..29278ce441412068cd6fa157ad65f9ee8ce74b44 100644 (file)
@@ -1,74 +1,3 @@
 # zsh configuration file for Gromacs
-# First we remove old gromacs stuff from the paths
-# by selecting everything else.
-# This is not 100% necessary, but very useful when we
-# repeatedly switch between gmx versions in a shell.
-
-# ATTENTION
-# zsh understands sh syntax - so this is just a copy from GMXRC.bash.in
-# BEGIN COPY
-
-# First remove gromacs part of ld_library_path
-tmppath=""
-for i in `echo $LD_LIBRARY_PATH | sed "s/:/ /g"`; do
-  if test "$i" != "$GMXLDLIB"; then
-    tmppath="${tmppath}${tmppath:+:}${i}"
-  fi
-done
-LD_LIBRARY_PATH=$tmppath
-
-# remove gromacs part of PKG_CONFIG_PATH
-tmppath=""
-for i in `echo $PKG_CONFIG_PATH | sed "s/:/ /g"`; do
-  if test "$i" != "$GMXLDLIB/pkgconfig"; then
-    tmppath="${tmppath}${tmppath:+:}${i}"
-  fi
-done
-PKG_CONFIG_PATH=$tmppath
-
-# remove gromacs part of path
-tmppath=""
-for i in `echo $PATH | sed "s/:/ /g"`; do
-  if test "$i" != "$GMXBIN"; then
-    tmppath="${tmppath}${tmppath:+:}${i}"
-  fi
-done
-PATH=$tmppath
-
-# and remove the gmx part of manpath
-tmppath=""
-for i in `echo $MANPATH | sed "s/:/ /g"`; do
-  if test "$i" != "$GMXMAN"; then
-    tmppath="${tmppath}${tmppath:+:}${i}"
-  fi
-done
-MANPATH=$tmppath
-
-##########################################################
-# This is the real configuration part. We save the Gromacs
-# things in separate vars, so we can remove them later.
-# If you move gromacs, change the next four line.
-##########################################################
-GMXBIN=@BIN_INSTALL_DIR@
-GMXLDLIB=@LIB_INSTALL_DIR@
-GMXMAN=@MAN_INSTALL_DIR@
-GMXDATA=@DATA_INSTALL_DIR@
-       
-LD_LIBRARY_PATH=${GMXLDLIB}${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH}
-PKG_CONFIG_PATH=${GMXLDLIB}/pkgconfig${PKG_CONFIG_PATH:+:}${PKG_CONFIG_PATH}
-PATH=${GMXBIN}${PATH:+:}${PATH}
-#debian/ubuntu needs a : at the end
-MANPATH=${GMXMAN}:${MANPATH}
-
-# export should be separate, so /bin/sh understands it
-export GMXBIN GMXLDLIB GMXMAN GMXDATA LD_LIBRARY_PATH PATH MANPATH PKG_CONFIG_PATH
-
-# END COPY
-
-# read zsh completions if understand how to use them
-if compctl >& /dev/null; then
-  if [ -f $GMXBIN/completion.zsh ]; then
-    source $GMXBIN/completion.zsh; 
-  fi
-fi
-
+# only kept for backwards compatibility
+source @BIN_INSTALL_DIR@/GMXRC.bash 
diff --git a/share/.cvsignore b/share/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
index 0fd88a476b73b74c2cc1cb7f06d6e661f4f9466b..2c966d728038389f1f610695b858a52dd77f144e 100644 (file)
@@ -1,4 +1,5 @@
-# Data: Nothing to build, just installation
+add_subdirectory(template)
+
 install(DIRECTORY . DESTINATION ${DATA_INSTALL_DIR}
   COMPONENT data
   PATTERN "Makefile*" EXCLUDE
diff --git a/share/html/.cvsignore b/share/html/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/html/images/.cvsignore b/share/html/images/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/html/online/.cvsignore b/share/html/online/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/template/.cvsignore b/share/template/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
index 3236cba6d6ebe89a13ca485fe17c890548d23da5..2d63f39b8c4a2f800858e612c2d0160ee1e0e662 100644 (file)
@@ -1 +1,2 @@
 template
+Makefile.*-*
diff --git a/share/template/CMakeLists.txt b/share/template/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6665d12
--- /dev/null
@@ -0,0 +1,2 @@
+add_executable(template template.cpp)
+target_link_libraries(template libgromacs)
diff --git a/share/template/template.cpp b/share/template/template.cpp
new file mode 100644 (file)
index 0000000..246e669
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <gromacs/trajectoryanalysis.h>
+
+using namespace gmx;
+
+/*! \brief
+ * Template class to serve as a basis for user analysis tools.
+ */
+class AnalysisTemplate : public TrajectoryAnalysisModule
+{
+    public:
+        AnalysisTemplate();
+
+        virtual Options *initOptions(TrajectoryAnalysisSettings *settings);
+        virtual void initAnalysis(const TopologyInformation &top);
+
+        virtual TrajectoryAnalysisModuleData *startFrames(
+                    AnalysisDataParallelOptions opt,
+                    const SelectionCollection &selections);
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata);
+
+        virtual void finishAnalysis(int nframes);
+        virtual void writeOutput();
+
+    private:
+        class ModuleData;
+
+        Options                      _options;
+        std::string                  _fnDist;
+        double                       _cutoff;
+        Selection                   *_refsel;
+        std::vector<Selection *>     _sel;
+        AnalysisData                 _data;
+        AnalysisDataAverageModule   *_avem;
+};
+
+/*! \brief
+ * Frame-local data needed in analysis.
+ */
+class AnalysisTemplate::ModuleData : public TrajectoryAnalysisModuleData
+{
+    public:
+        ModuleData(TrajectoryAnalysisModule *module,
+                   AnalysisDataParallelOptions opt,
+                   const SelectionCollection &selections)
+            : TrajectoryAnalysisModuleData(module, opt, selections),
+              _nb(NULL)
+        {
+        }
+
+        virtual ~ModuleData()
+        {
+            delete _nb;
+        }
+
+        virtual void finish()
+        {
+            finishDataHandles();
+        }
+
+        NeighborhoodSearch          *_nb;
+};
+
+
+AnalysisTemplate::AnalysisTemplate()
+    : _options("template", "Template options"), _cutoff(0.0),
+      _refsel(NULL), _avem(NULL)
+{
+}
+
+
+Options *
+AnalysisTemplate::initOptions(TrajectoryAnalysisSettings *settings)
+{
+    static const char *const desc[] = {
+        "This is a template for writing your own analysis tools for",
+        "Gromacs. The advantage of using Gromacs for this is that you",
+        "have access to all information in the topology, and your",
+        "program will be able to handle all types of coordinates and",
+        "trajectory files supported by Gromacs. In addition,",
+        "you get a lot of functionality for free from the trajectory",
+        "analysis library, including support for flexible dynamic",
+        "selections. Go ahead an try it![PAR]",
+        "To get started with implementing your own analysis program,",
+        "follow the instructions in the README file provided.",
+        "This template implements a simple analysis programs that calculates",
+        "average distances from the a reference group to one or more",
+        "analysis groups.",
+        NULL
+    };
+
+    _options.setDescription(desc);
+
+    _options.addOption(FileNameOption("o")
+        .filetype(eftPlot).writeOnly()
+        .store(&_fnDist).defaultValueIfSet("avedist")
+        .description("Average distances from reference group"));
+
+    _options.addOption(SelectionOption("reference")
+        .store(&_refsel).required()
+        .description("Reference group to calculate distances from"));
+    _options.addOption(SelectionOption("select")
+        .storeVector(&_sel).required().multiValue()
+        .description("Groups to calculate distances to"));
+
+    _options.addOption(DoubleOption("cutoff").store(&_cutoff)
+        .description("Cutoff for distance calculation (0 = no cutoff)"));
+
+    settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
+
+    return &_options;
+}
+
+
+void
+AnalysisTemplate::initAnalysis(const TopologyInformation & /*top*/)
+{
+    _data.setColumns(_sel.size());
+    registerAnalysisDataset(&_data, "avedist");
+
+    _avem = new AnalysisDataAverageModule();
+    _data.addModule(_avem);
+
+    if (!_fnDist.empty())
+    {
+        AnalysisDataPlotModule *plotm = new AnalysisDataPlotModule(_options);
+        plotm->setFileName(_fnDist);
+        plotm->setTitle("Average distance");
+        plotm->setXLabel("Time (ps)");
+        plotm->setYLabel("Distance (nm)");
+        _data.addModule(plotm);
+    }
+}
+
+
+TrajectoryAnalysisModuleData *
+AnalysisTemplate::startFrames(AnalysisDataParallelOptions opt,
+                              const SelectionCollection &selections)
+{
+    std::auto_ptr<ModuleData> pdata(new ModuleData(this, opt, selections));
+    pdata->_nb = new NeighborhoodSearch(_cutoff, _refsel->posCount());
+    return pdata.release();
+}
+
+
+void
+AnalysisTemplate::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                               TrajectoryAnalysisModuleData *pdata)
+{
+    AnalysisDataHandle *dh = pdata->dataHandle("avedist");
+    NeighborhoodSearch *nb = static_cast<ModuleData *>(pdata)->_nb;
+
+    nb->init(pbc, _refsel->positions());
+    dh->startFrame(frnr, fr.time);
+    for (size_t g = 0; g < _sel.size(); ++g)
+    {
+        Selection *sel = pdata->parallelSelection(_sel[g]);
+        int   nr = sel->posCount();
+        real  frave = 0.0;
+        for (int i = 0; i < nr; ++i)
+        {
+            frave += nb->minimumDistance(sel->x(i));
+        }
+        frave /= nr;
+        dh->addPoint(g, frave);
+    }
+    dh->finishFrame();
+}
+
+
+void
+AnalysisTemplate::finishAnalysis(int /*nframes*/)
+{
+}
+
+
+void
+AnalysisTemplate::writeOutput()
+{
+    // We print out the average of the mean distances for each group.
+    for (size_t g = 0; g < _sel.size(); ++g)
+    {
+        fprintf(stderr, "Average mean distance for '%s': %.3f nm\n",
+                _sel[g]->name(), _avem->average(g));
+    }
+}
+
+/*! \brief
+ * The main function for the analysis template.
+ */
+int
+main(int argc, char *argv[])
+{
+    try
+    {
+        AnalysisTemplate module;
+        TrajectoryAnalysisCommandLineRunner runner(&module);
+        return runner.run(argc, argv);
+    }
+    catch (std::exception &ex)
+    {
+        fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
+        return 1;
+    }
+}
diff --git a/share/template/template_doc.cpp b/share/template/template_doc.cpp
new file mode 100644 (file)
index 0000000..2f6907b
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \dir share/template
+ * \brief Template code for writing analysis programs.
+ */
+/*! \example template.cpp
+ * \brief Template code for writing analysis programs.
+ *
+ * See \ref share/template/template.cpp "documentation" of the template for
+ * more information.
+ */
+/*! \internal \file
+ * \brief Doxygen documentation source for template.cpp.
+ */
+/*! \file template.cpp
+ * \brief Template code for writing analysis programs.
+ *
+ * The full source code for the file: \ref template.cpp "template.cpp"
+ *
+ * \dontinclude template.cpp
+ *
+ * \section template_global Global definitions
+ *
+ * We start by including some generic C++ headers:
+ * \skip  <string>
+ * \until <vector>
+ * and continue by including the header for the analysis library:
+ * \until <gromacs/trajectoryanalysis.h>
+ * This header includes other headers that together define all the basic data
+ * types needed for writing trajectory analysis tools.
+ * For convenience, we also import all names from the ::gmx namespace into the
+ * global scope to avoid repeating the name everywhere:
+ * \skipline using namespace
+ *
+ *
+ * \section template_class Tool module class declaration
+ *
+ * We then define a class that implements our analysis tool:
+ * \until };
+ * The analysis tool class inherits gmx::TrajectoryAnalysisModule, which is
+ * an interface with a few convenience functions for easier interfacing
+ * with other code.
+ * Below, we walk through the different methods as implemented in the
+ * template (note that the template does not implement some of the virtual
+ * methods because they are less often needed), discussing some issues that can
+ * arise in more complex cases.
+ * See documentation of gmx::TrajectoryAnalysisModule for a full description of
+ * the available virtual methods and convenience functions.
+ *
+ * We also declare a helper class, AnalysisTemplate::ModuleData, that derives
+ * from gmx::TrajectoryAnalysisModuleData and will contain any data that needs
+ * to be frame-local in parallel analysis (if you don't care about
+ * parallelization, you can just include these variables in the module class
+ * itself, initialize them in gmx::TrajectoryAnalysisModule::initAnalysis(),
+ * and do any postprocessing in
+ * gmx::TrajectoryAnalysisModule::finishAnalysis()).
+ * \until };
+ * See documentation of gmx::TrajectoryAnalysisModuleData for more details of
+ * how this data can be used.
+ *
+ *
+ * \section template_ctor Construction
+ *
+ * The constructor (and possible destructor) of the analysis module should be
+ * simple: the constructor should just initialize default values, and the
+ * destructor should free any memory managed by the module.  For the template,
+ * we have no attributes in our class that need to be explicitly freed, so we
+ * declare only a constructor:
+ * \skip  AnalysisTemplate
+ * \until }
+ * In addition to initializing local variables that don't have default
+ * constructors, we also provide a title and one-line description of our module
+ * to the \p _options object.  These values will only affect the help output.
+ *
+ *
+ * \section template_initialization Initialization methods
+ *
+ * Initialization of the module is split into a few methods, two of which are
+ * used in the template.  gmx::TrajectoryAnalysisModule::initOptions() is used
+ * to set up options understood by the module, as well as for setting up
+ * different options through gmx::TrajectoryAnalysisSettings (see the
+ * documentation of that class for more details):
+ * \skip  Options *
+ * \until return &_options;
+ * \until }
+ * For additional documentation on how to define different kinds of options, see
+ * gmx::Options, basicoptions.h, and gmx::SelectionOption.
+ *
+ * If you need to set up settings based on option values, you can also override
+ * gmx::TrajectoryAnalysisModule::initOptionsDone().  For simplicity,
+ * this is not done in the template.
+ *
+ * The actual analysis is initialized in
+ * gmx::TrajectoryAnalysisModule::initAnalysis():
+ * \skip  int
+ * \until return 0;
+ * \until }
+ * Information about the topology is passed as a parameter.
+ * If the analysis module needs some temporary storage during processing of a
+ * frame, this should be allocated in gmx::TrajectoryAnalysisModule::startFrames()
+ * (see below) if parallelization is to be supported.
+ *
+ * There is also a gmx::TrajectoryAnalysisModule::initAfterFirstFrame() method
+ * that can be overridden if the module needs to do some initialization based
+ * on data from the first frame (most commonly, based on the box size), but it
+ * is not used in the template.
+ *
+ *
+ * \section template_analysis Actual trajectory analysis
+ *
+ * There is one more initialization method that needs to be overridden to
+ * support automatic parallelization.  If you do not need custom data (or
+ * parallelization at all), you can skip this method and ignore the last
+ * parameter to gmx::TrajectoryAnalysisModule::analyzeFrame() to make things
+ * simpler.  In the template, we do include it:
+ * \skip  int
+ * \until return rc;
+ * \until }
+ *
+ * The main part of the analysis is (in most analysis codes) done in the
+ * gmx::TrajectoryAnalysisModule::analyzeFrame() method, which is called once
+ * for each frame:
+ * \skip  int
+ * \until {
+ * The \p frnr parameter gives a zero-based index of the current frame
+ * (mostly for use with gmx::AnalysisData), \p pbc contains the PBC
+ * information for the current frame for distance calculations with,
+ * e.g., pbc_dx(), and \p pdata points to a data structure created in
+ * gmx::TrajectoryAnalysisModule::startFrames().
+ * Although usually not necessary (except for the time field), raw frame
+ * data can be accessed through \p fr.
+ * In most cases, the analysis should be written such that it gets all
+ * position data through selections, and does not assume a constant size for
+ * them.  This is all that is required to support the full flexibility of the
+ * selection engine.
+ *
+ * First, we get data from our custom data structure (note the cast on the
+ * second line to access our custom data) for shorthand access:
+ * \skip  AnalysisDataHandle
+ * \until NeighborhoodSearch
+ *
+ * For the template, we do a simple calculation:
+ * \skip  nb
+ * \until finishFrame()
+ * Finally, we return zero to indicate that all went well.
+ * \skipline return 0;
+ *
+ * After all the frames have been processed,
+ * gmx::TrajectoryAnalysisModule::finishAnalysis() is called once.  This is the
+ * place to do any custom postprocessing of the data.  For the template, we do
+ * nothing, because all necessary processing is done in the data modules:
+ * \skip  int
+ * \until }
+ *
+ * There is one additional method that can be implemented if custom data from
+ * frames is aggregated in the frame-local data structures created in
+ * gmx::TrajectoryAnalysisModule::startFrames().  In such cases,
+ * gmx::TrajectoryAnalysisModule::finishFrames() can be overridden to combine
+ * the data from the data structures (see documentation of the method for
+ * details).
+ *
+ *
+ * \section template_output Output
+ *
+ * Finally, most programs need to write out some values after the analysis is
+ * complete.  In some cases, this can be achieved with proper chaining of data
+ * modules, but often it is necessary to do some custom processing.
+ * All such activities should be done in
+ * gmx::TrajectoryAnalysisModule::writeOutput().  This makes it easier to reuse
+ * analysis modules in, e.g., scripting languages, where output into files
+ * might not be desired.  The template simply prints out the average distances
+ * for each analysis group:
+ * \skipline int
+ * \until return 0;
+ * \until }
+ *
+ *
+ * \section template_main Definition of main()
+ *
+ * Now, the only thing remaining is to define the main() function.
+ * To implement a command-line tool, it should create a module and run it using
+ * gmx::TrajectoryAnalysisCommandLineRunner:
+ * \skip  int
+ * \until }
+ */
diff --git a/share/top/.cvsignore b/share/top/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
index 4253b6c12775cb40f6429d345f84f7cbf52cd17a..bcff4fb59e08163c606e1f1a832817841c6c4f37 100644 (file)
 �����،ߑ�߈��߆��ߜ��ߍ���ߐ�ߞ�ߚ����������׸�����߸��������
 �ߓ���ߋ�߈����ߋ���߶ߙ���ߓ���߶ߛ�ߌ���������׼���߼�������
 ���߶ߗ���ߚ���������ߓ�����ߋ���ߚ���������ߚ����׻���߯������
+�����ߐ�ߜ�����������ߞ��ߋ��ߌ������߲�ߌ������ߖ�߈�������ߑ�����ߜ��������ײ�������
 ��،ߊ����ߜ���ߋ���ߐ���߆��ߞ��߶ߔ����״���߽����
 ��������ߘ����ߙ������ߓ����ߐ�ߓ�����ߐ����׽����ߺ���߯����
 �؉�ߝ��������ߝ�����ߞ߉���������ߌ����ߋ��ߐ���ߒ���߶ؒߚ�����ߖ�ߙ���ߞ������߶؉�ߔ�����ߒ������ײ���ߥ����������
diff --git a/share/tutor/.cvsignore b/share/tutor/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/gmxdemo/.cvsignore b/share/tutor/gmxdemo/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/methanol/.cvsignore b/share/tutor/methanol/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/mixed/.cvsignore b/share/tutor/mixed/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/nmr1/.cvsignore b/share/tutor/nmr1/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/nmr2/.cvsignore b/share/tutor/nmr2/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/speptide/.cvsignore b/share/tutor/speptide/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/share/tutor/water/.cvsignore b/share/tutor/water/.cvsignore
deleted file mode 100644 (file)
index 282522d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644 (file)
index 98a0226..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Makefile
-Makefile.in
-stamp-h.in
-stamp-h
-config.h
-config.h.in
index f07b127abce58c996aceb42598ab600e4040c53f..495c8aeef40bdba1f0caaf93e424d71e33829c05 100644 (file)
@@ -1,9 +1,13 @@
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
+if (BUILD_TESTING)
+    include(testutils/TestMacros.cmake)
+    add_subdirectory(testutils)
+endif (BUILD_TESTING)
 
-add_subdirectory(gmxlib)
-add_subdirectory(mdlib)
+add_subdirectory(gromacs)
 add_subdirectory(kernel)
+add_subdirectory(programs)
 
 if(NOT GMX_FAHCORE)
   add_subdirectory(tools)
diff --git a/src/contrib/.cvsignore b/src/contrib/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/external/boost/README b/src/external/boost/README
new file mode 100644 (file)
index 0000000..f174a90
--- /dev/null
@@ -0,0 +1,5 @@
+Steps to produce minimal version of BOOST:
+1) Download Boost (current minimal version is derived from 1.46_1)
+2) Extract
+3) Edit Boost files to uncomment unnessary includes (search for GMX in minimal version and copy all changes)
+4) run bcp with required files (currently exception/all.hpp)
diff --git a/src/external/boost/boost/assert.hpp b/src/external/boost/boost/assert.hpp
new file mode 100644 (file)
index 0000000..dca23af
--- /dev/null
@@ -0,0 +1,131 @@
+//\r
+//  boost/assert.hpp - BOOST_ASSERT(expr)\r
+//                     BOOST_ASSERT_MSG(expr, msg)\r
+//                     BOOST_VERIFY(expr)\r
+//\r
+//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.\r
+//  Copyright (c) 2007 Peter Dimov\r
+//  Copyright (c) Beman Dawes 2011\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  Note: There are no include guards. This is intentional.\r
+//\r
+//  See http://www.boost.org/libs/utility/assert.html for documentation.\r
+//\r
+\r
+//\r
+// Stop inspect complaining about use of 'assert':\r
+//\r
+// boostinspect:naassert_macro\r
+//\r
+\r
+//--------------------------------------------------------------------------------------//\r
+//                                     BOOST_ASSERT                                     //\r
+//--------------------------------------------------------------------------------------//\r
+\r
+#undef BOOST_ASSERT\r
+\r
+#if defined(BOOST_DISABLE_ASSERTS)\r
+\r
+# define BOOST_ASSERT(expr) ((void)0)\r
+\r
+#elif defined(BOOST_ENABLE_ASSERT_HANDLER)\r
+\r
+#include <boost/current_function.hpp>\r
+\r
+namespace boost\r
+{\r
+  void assertion_failed(char const * expr,\r
+                        char const * function, char const * file, long line); // user defined\r
+} // namespace boost\r
+\r
+#define BOOST_ASSERT(expr) ((expr) \\r
+  ? ((void)0) \\r
+  : ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))\r
+\r
+#else\r
+# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same\r
+# define BOOST_ASSERT(expr) assert(expr)\r
+#endif\r
+\r
+//--------------------------------------------------------------------------------------//\r
+//                                   BOOST_ASSERT_MSG                                   //\r
+//--------------------------------------------------------------------------------------//\r
+\r
+# undef BOOST_ASSERT_MSG\r
+\r
+#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)\r
+\r
+  #define BOOST_ASSERT_MSG(expr, msg) ((void)0)\r
+\r
+#elif defined(BOOST_ENABLE_ASSERT_HANDLER)\r
+\r
+  #include <boost/current_function.hpp>\r
+\r
+  namespace boost\r
+  {\r
+    void assertion_failed_msg(char const * expr, char const * msg,\r
+                              char const * function, char const * file, long line); // user defined\r
+  } // namespace boost\r
+\r
+  #define BOOST_ASSERT_MSG(expr, msg) ((expr) \\r
+    ? ((void)0) \\r
+    : ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))\r
+\r
+#else\r
+  #ifndef BOOST_ASSERT_HPP\r
+    #define BOOST_ASSERT_HPP\r
+    #include <cstdlib>\r
+    #include <iostream>\r
+    #include <boost/current_function.hpp>\r
+\r
+    //  IDE's like Visual Studio perform better if output goes to std::cout or\r
+    //  some other stream, so allow user to configure output stream:\r
+    #ifndef BOOST_ASSERT_MSG_OSTREAM\r
+    # define BOOST_ASSERT_MSG_OSTREAM std::cerr\r
+    #endif\r
+\r
+    namespace boost\r
+    { \r
+      namespace assertion \r
+      { \r
+        namespace detail\r
+        {\r
+          inline void assertion_failed_msg(char const * expr, char const * msg, char const * function,\r
+            char const * file, long line)\r
+          {\r
+            BOOST_ASSERT_MSG_OSTREAM\r
+              << "***** Internal Program Error - assertion (" << expr << ") failed in "\r
+              << function << ":\n"\r
+              << file << '(' << line << "): " << msg << std::endl;\r
+            std::abort();\r
+          }\r
+        } // detail\r
+      } // assertion\r
+    } // detail\r
+  #endif\r
+\r
+  #define BOOST_ASSERT_MSG(expr, msg) ((expr) \\r
+    ? ((void)0) \\r
+    : ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \\r
+          BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))\r
+#endif\r
+\r
+//--------------------------------------------------------------------------------------//\r
+//                                     BOOST_VERIFY                                     //\r
+//--------------------------------------------------------------------------------------//\r
+\r
+#undef BOOST_VERIFY\r
+\r
+#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )\r
+\r
+# define BOOST_VERIFY(expr) ((void)(expr))\r
+\r
+#else\r
+\r
+# define BOOST_VERIFY(expr) BOOST_ASSERT(expr)\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/checked_delete.hpp b/src/external/boost/boost/checked_delete.hpp
new file mode 100644 (file)
index 0000000..e8f479f
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED\r
+#define BOOST_CHECKED_DELETE_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/checked_delete.hpp\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov\r
+//  Copyright (c) 2003 Daniel Frey\r
+//  Copyright (c) 2003 Howard Hinnant\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  See http://www.boost.org/libs/utility/checked_delete.html for documentation.\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+// verify that types are complete for increased safety\r
+\r
+template<class T> inline void checked_delete(T * x)\r
+{\r
+    // intentionally complex - simplification causes regressions\r
+    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];\r
+    (void) sizeof(type_must_be_complete);\r
+    delete x;\r
+}\r
+\r
+template<class T> inline void checked_array_delete(T * x)\r
+{\r
+    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];\r
+    (void) sizeof(type_must_be_complete);\r
+    delete [] x;\r
+}\r
+\r
+template<class T> struct checked_deleter\r
+{\r
+    typedef void result_type;\r
+    typedef T * argument_type;\r
+\r
+    void operator()(T * x) const\r
+    {\r
+        // boost:: disables ADL\r
+        boost::checked_delete(x);\r
+    }\r
+};\r
+\r
+template<class T> struct checked_array_deleter\r
+{\r
+    typedef void result_type;\r
+    typedef T * argument_type;\r
+\r
+    void operator()(T * x) const\r
+    {\r
+        boost::checked_array_delete(x);\r
+    }\r
+};\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/config.hpp b/src/external/boost/boost/config.hpp
new file mode 100644 (file)
index 0000000..cb5037a
--- /dev/null
@@ -0,0 +1,70 @@
+//  Boost config.hpp configuration header file  ------------------------------//\r
+\r
+//  (C) Copyright John Maddock 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org/libs/config for most recent version.\r
+\r
+//  Boost config.hpp policy and rationale documentation has been moved to\r
+//  http://www.boost.org/libs/config\r
+//\r
+//  CAUTION: This file is intended to be completely stable -\r
+//           DO NOT MODIFY THIS FILE!\r
+//\r
+\r
+#ifndef BOOST_CONFIG_HPP\r
+#define BOOST_CONFIG_HPP\r
+\r
+// if we don't have a user config, then use the default location:\r
+#if !defined(BOOST_USER_CONFIG) && !defined(BOOST_NO_USER_CONFIG)\r
+#  define BOOST_USER_CONFIG <boost/config/user.hpp>\r
+#endif\r
+// include it first:\r
+#ifdef BOOST_USER_CONFIG\r
+#  include BOOST_USER_CONFIG\r
+#endif\r
+\r
+// if we don't have a compiler config set, try and find one:\r
+#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG)\r
+#  include <boost/config/select_compiler_config.hpp>\r
+#endif\r
+// if we have a compiler config, include it now:\r
+#ifdef BOOST_COMPILER_CONFIG\r
+#  include BOOST_COMPILER_CONFIG\r
+#endif\r
+\r
+// if we don't have a std library config set, try and find one:\r
+#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG)\r
+#  include <boost/config/select_stdlib_config.hpp>\r
+#endif\r
+// if we have a std library config, include it now:\r
+#ifdef BOOST_STDLIB_CONFIG\r
+#  include BOOST_STDLIB_CONFIG\r
+#endif\r
+\r
+// if we don't have a platform config set, try and find one:\r
+#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG)\r
+#  include <boost/config/select_platform_config.hpp>\r
+#endif\r
+// if we have a platform config, include it now:\r
+#ifdef BOOST_PLATFORM_CONFIG\r
+#  include BOOST_PLATFORM_CONFIG\r
+#endif\r
+\r
+// get config suffix code:\r
+#include <boost/config/suffix.hpp>\r
+\r
+#endif  // BOOST_CONFIG_HPP\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/abi/borland_prefix.hpp b/src/external/boost/boost/config/abi/borland_prefix.hpp
new file mode 100644 (file)
index 0000000..4db9b8a
--- /dev/null
@@ -0,0 +1,27 @@
+//  (C) Copyright John Maddock 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  for C++ Builder the following options effect the ABI:\r
+//\r
+//  -b (on or off - effect emum sizes)\r
+//  -Vx  (on or off - empty members)\r
+//  -Ve (on or off - empty base classes)\r
+//  -aX (alignment - 5 options).\r
+//  -pX (Calling convention - 4 options)\r
+//  -VmX (member pointer size and layout - 5 options)\r
+//  -VC (on or off, changes name mangling)\r
+//  -Vl (on or off, changes struct layout).\r
+\r
+//  In addition the following warnings are sufficiently annoying (and\r
+//  unfixable) to have them turned off by default:\r
+//\r
+//  8027 - functions containing [for|while] loops are not expanded inline\r
+//  8026 - functions taking class by value arguments are not expanded inline\r
+\r
+#pragma nopushoptwarn\r
+#  pragma option push -a8 -Vx- -Ve- -b- -pc -Vmv -VC- -Vl- -w-8027 -w-8026\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/abi/borland_suffix.hpp b/src/external/boost/boost/config/abi/borland_suffix.hpp
new file mode 100644 (file)
index 0000000..110b3c3
--- /dev/null
@@ -0,0 +1,12 @@
+//  (C) Copyright John Maddock 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#  pragma option pop\r
+#pragma nopushoptwarn\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/abi/msvc_prefix.hpp b/src/external/boost/boost/config/abi/msvc_prefix.hpp
new file mode 100644 (file)
index 0000000..417e0dd
--- /dev/null
@@ -0,0 +1,22 @@
+//  (C) Copyright John Maddock 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//\r
+// Boost binaries are built with the compiler's default ABI settings,\r
+// if the user changes their default alignment in the VS IDE then their\r
+// code will no longer be binary compatible with the bjam built binaries\r
+// unless this header is included to force Boost code into a consistent ABI.\r
+//\r
+// Note that inclusion of this header is only necessary for libraries with \r
+// separate source, header only libraries DO NOT need this as long as all\r
+// translation units are built with the same options.\r
+//\r
+#if defined(_M_X64)\r
+#  pragma pack(push,16)\r
+#else\r
+#  pragma pack(push,8)\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/abi/msvc_suffix.hpp b/src/external/boost/boost/config/abi/msvc_suffix.hpp
new file mode 100644 (file)
index 0000000..8c1edd0
--- /dev/null
@@ -0,0 +1,8 @@
+//  (C) Copyright John Maddock 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#pragma pack(pop)\r
+\r
+\r
diff --git a/src/external/boost/boost/config/abi_prefix.hpp b/src/external/boost/boost/config/abi_prefix.hpp
new file mode 100644 (file)
index 0000000..10cf51d
--- /dev/null
@@ -0,0 +1,25 @@
+//  abi_prefix header  -------------------------------------------------------//\r
+\r
+// (c) Copyright John Maddock 2003\r
+   \r
+// Use, modification and distribution are subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt).\r
+\r
+#ifndef BOOST_CONFIG_ABI_PREFIX_HPP\r
+# define BOOST_CONFIG_ABI_PREFIX_HPP\r
+#else\r
+# error double inclusion of header boost/config/abi_prefix.hpp is an error\r
+#endif\r
+\r
+#include <boost/config.hpp>\r
+\r
+// this must occur after all other includes and before any code appears:\r
+#ifdef BOOST_HAS_ABI_HEADERS\r
+#  include BOOST_ABI_PREFIX\r
+#endif\r
+\r
+#if defined( __BORLANDC__ )\r
+#pragma nopushoptwarn\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/abi_suffix.hpp b/src/external/boost/boost/config/abi_suffix.hpp
new file mode 100644 (file)
index 0000000..21da961
--- /dev/null
@@ -0,0 +1,27 @@
+//  abi_sufffix header  -------------------------------------------------------//\r
+\r
+// (c) Copyright John Maddock 2003\r
+   \r
+// Use, modification and distribution are subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt).\r
+\r
+// This header should be #included AFTER code that was preceded by a #include\r
+// <boost/config/abi_prefix.hpp>.\r
+\r
+#ifndef BOOST_CONFIG_ABI_PREFIX_HPP\r
+# error Header boost/config/abi_suffix.hpp must only be used after boost/config/abi_prefix.hpp\r
+#else\r
+# undef BOOST_CONFIG_ABI_PREFIX_HPP\r
+#endif\r
+\r
+// the suffix header occurs after all of our code:\r
+#ifdef BOOST_HAS_ABI_HEADERS\r
+#  include BOOST_ABI_SUFFIX\r
+#endif\r
+\r
+#if defined( __BORLANDC__ )\r
+#pragma nopushoptwarn\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/auto_link.hpp b/src/external/boost/boost/config/auto_link.hpp
new file mode 100644 (file)
index 0000000..e07795a
--- /dev/null
@@ -0,0 +1,417 @@
+//  (C) Copyright John Maddock 2003.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+ /*\r
+  *   LOCATION:    see http://www.boost.org for most recent version.\r
+  *   FILE         auto_link.hpp\r
+  *   VERSION      see <boost/version.hpp>\r
+  *   DESCRIPTION: Automatic library inclusion for Borland/Microsoft compilers.\r
+  */\r
+\r
+/*************************************************************************\r
+\r
+USAGE:\r
+~~~~~~\r
+\r
+Before including this header you must define one or more of define the following macros:\r
+\r
+BOOST_LIB_NAME:           Required: A string containing the basename of the library,\r
+                          for example boost_regex.\r
+BOOST_LIB_TOOLSET:        Optional: the base name of the toolset.\r
+BOOST_DYN_LINK:           Optional: when set link to dll rather than static library.\r
+BOOST_LIB_DIAGNOSTIC:     Optional: when set the header will print out the name\r
+                          of the library selected (useful for debugging).\r
+BOOST_AUTO_LINK_NOMANGLE: Specifies that we should link to BOOST_LIB_NAME.lib,\r
+                          rather than a mangled-name version.\r
+BOOST_AUTO_LINK_TAGGED:   Specifies that we link to libraries built with the --layout=tagged option.\r
+                          This is essentially the same as the default name-mangled version, but without\r
+                          the compiler name and version, or the Boost version.  Just the build options.\r
+\r
+These macros will be undef'ed at the end of the header, further this header\r
+has no include guards - so be sure to include it only once from your library!\r
+\r
+Algorithm:\r
+~~~~~~~~~~\r
+\r
+Libraries for Borland and Microsoft compilers are automatically\r
+selected here, the name of the lib is selected according to the following\r
+formula:\r
+\r
+BOOST_LIB_PREFIX\r
+   + BOOST_LIB_NAME\r
+   + "_"\r
+   + BOOST_LIB_TOOLSET\r
+   + BOOST_LIB_THREAD_OPT\r
+   + BOOST_LIB_RT_OPT\r
+   "-"\r
+   + BOOST_LIB_VERSION\r
+\r
+These are defined as:\r
+\r
+BOOST_LIB_PREFIX:     "lib" for static libraries otherwise "".\r
+\r
+BOOST_LIB_NAME:       The base name of the lib ( for example boost_regex).\r
+\r
+BOOST_LIB_TOOLSET:    The compiler toolset name (vc6, vc7, bcb5 etc).\r
+\r
+BOOST_LIB_THREAD_OPT: "-mt" for multithread builds, otherwise nothing.\r
+\r
+BOOST_LIB_RT_OPT:     A suffix that indicates the runtime library used,\r
+                      contains one or more of the following letters after\r
+                      a hiphen:\r
+\r
+                      s      static runtime (dynamic if not present).\r
+                      g      debug/diagnostic runtime (release if not present).\r
+                      y      Python debug/diagnostic runtime (release if not present).\r
+                      d      debug build (release if not present).\r
+                      g      debug/diagnostic runtime (release if not present).\r
+                      p      STLPort Build.\r
+\r
+BOOST_LIB_VERSION:    The Boost version, in the form x_y, for Boost version x.y.\r
+\r
+\r
+***************************************************************************/\r
+\r
+#ifdef __cplusplus\r
+#  ifndef BOOST_CONFIG_HPP\r
+#     include <boost/config.hpp>\r
+#  endif\r
+#elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__)\r
+//\r
+// C language compatability (no, honestly)\r
+//\r
+#  define BOOST_MSVC _MSC_VER\r
+#  define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)\r
+#  define BOOST_DO_STRINGIZE(X) #X\r
+#endif\r
+//\r
+// Only include what follows for known and supported compilers:\r
+//\r
+#if defined(BOOST_MSVC) \\r
+    || defined(__BORLANDC__) \\r
+    || (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) \\r
+    || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200))\r
+\r
+#ifndef BOOST_VERSION_HPP\r
+#  include <boost/version.hpp>\r
+#endif\r
+\r
+#ifndef BOOST_LIB_NAME\r
+#  error "Macro BOOST_LIB_NAME not set (internal error)"\r
+#endif\r
+\r
+//\r
+// error check:\r
+//\r
+#if defined(__MSVC_RUNTIME_CHECKS) && !defined(_DEBUG)\r
+#  pragma message("Using the /RTC option without specifying a debug runtime will lead to linker errors")\r
+#  pragma message("Hint: go to the code generation options and switch to one of the debugging runtimes")\r
+#  error "Incompatible build options"\r
+#endif\r
+//\r
+// select toolset if not defined already:\r
+//\r
+#ifndef BOOST_LIB_TOOLSET\r
+// Note: no compilers before 1200 are supported\r
+#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)\r
+\r
+#  ifdef UNDER_CE\r
+     // vc6:\r
+#    define BOOST_LIB_TOOLSET "evc4"\r
+#  else\r
+     // vc6:\r
+#    define BOOST_LIB_TOOLSET "vc6"\r
+#  endif\r
+\r
+#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1300)\r
+\r
+   // vc7:\r
+#  define BOOST_LIB_TOOLSET "vc7"\r
+\r
+#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1310)\r
+\r
+   // vc71:\r
+#  define BOOST_LIB_TOOLSET "vc71"\r
+\r
+#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1400)\r
+\r
+   // vc80:\r
+#  define BOOST_LIB_TOOLSET "vc80"\r
+\r
+#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1500)\r
+\r
+   // vc90:\r
+#  define BOOST_LIB_TOOLSET "vc90"\r
+\r
+#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)\r
+\r
+   // vc10:\r
+#  define BOOST_LIB_TOOLSET "vc100"\r
+\r
+#elif defined(__BORLANDC__)\r
+\r
+   // CBuilder 6:\r
+#  define BOOST_LIB_TOOLSET "bcb"\r
+\r
+#elif defined(__ICL)\r
+\r
+   // Intel C++, no version number:\r
+#  define BOOST_LIB_TOOLSET "iw"\r
+\r
+#elif defined(__MWERKS__) && (__MWERKS__ <= 0x31FF )\r
+\r
+   // Metrowerks CodeWarrior 8.x\r
+#  define BOOST_LIB_TOOLSET "cw8"\r
+\r
+#elif defined(__MWERKS__) && (__MWERKS__ <= 0x32FF )\r
+\r
+   // Metrowerks CodeWarrior 9.x\r
+#  define BOOST_LIB_TOOLSET "cw9"\r
+\r
+#endif\r
+#endif // BOOST_LIB_TOOLSET\r
+\r
+//\r
+// select thread opt:\r
+//\r
+#if defined(_MT) || defined(__MT__)\r
+#  define BOOST_LIB_THREAD_OPT "-mt"\r
+#else\r
+#  define BOOST_LIB_THREAD_OPT\r
+#endif\r
+\r
+#if defined(_MSC_VER) || defined(__MWERKS__)\r
+\r
+#  ifdef _DLL\r
+\r
+#     if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS))\r
+\r
+#        if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-gydp"\r
+#        elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\r
+#            define BOOST_LIB_RT_OPT "-gdp"\r
+#        elif defined(_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-gydp"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        elif defined(_DEBUG)\r
+#            define BOOST_LIB_RT_OPT "-gdp"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT "-p"\r
+#        endif\r
+\r
+#     elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)\r
+\r
+#        if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-gydpn"\r
+#        elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\r
+#            define BOOST_LIB_RT_OPT "-gdpn"\r
+#        elif defined(_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-gydpn"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        elif defined(_DEBUG)\r
+#            define BOOST_LIB_RT_OPT "-gdpn"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT "-pn"\r
+#        endif\r
+\r
+#     else\r
+\r
+#        if defined(_DEBUG) && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-gyd"\r
+#        elif defined(_DEBUG)\r
+#            define BOOST_LIB_RT_OPT "-gd"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT\r
+#        endif\r
+\r
+#     endif\r
+\r
+#  else\r
+\r
+#     if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS))\r
+\r
+#        if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-sgydp"\r
+#        elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\r
+#            define BOOST_LIB_RT_OPT "-sgdp"\r
+#        elif defined(_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#             define BOOST_LIB_RT_OPT "-sgydp"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        elif defined(_DEBUG)\r
+#             define BOOST_LIB_RT_OPT "-sgdp"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT "-sp"\r
+#        endif\r
+\r
+#     elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)\r
+\r
+#        if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#            define BOOST_LIB_RT_OPT "-sgydpn"\r
+#        elif defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG))\r
+#            define BOOST_LIB_RT_OPT "-sgdpn"\r
+#        elif defined(_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#             define BOOST_LIB_RT_OPT "-sgydpn"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        elif defined(_DEBUG)\r
+#             define BOOST_LIB_RT_OPT "-sgdpn"\r
+#            pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1")\r
+#            error "Build options aren't compatible with pre-built libraries"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT "-spn"\r
+#        endif\r
+\r
+#     else\r
+\r
+#        if defined(_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#             define BOOST_LIB_RT_OPT "-sgyd"\r
+#        elif defined(_DEBUG)\r
+#             define BOOST_LIB_RT_OPT "-sgd"\r
+#        else\r
+#            define BOOST_LIB_RT_OPT "-s"\r
+#        endif\r
+\r
+#     endif\r
+\r
+#  endif\r
+\r
+#elif defined(__BORLANDC__)\r
+\r
+//\r
+// figure out whether we want the debug builds or not:\r
+//\r
+#if __BORLANDC__ > 0x561\r
+#pragma defineonoption BOOST_BORLAND_DEBUG -v\r
+#endif\r
+//\r
+// sanity check:\r
+//\r
+#if defined(__STL_DEBUG) || defined(_STLP_DEBUG)\r
+#error "Pre-built versions of the Boost libraries are not provided in STLPort-debug form"\r
+#endif\r
+\r
+#  ifdef _RTLDLL\r
+\r
+#     if defined(BOOST_BORLAND_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#         define BOOST_LIB_RT_OPT "-yd"\r
+#     elif defined(BOOST_BORLAND_DEBUG)\r
+#         define BOOST_LIB_RT_OPT "-d"\r
+#     elif defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#         define BOOST_LIB_RT_OPT -y\r
+#     else\r
+#         define BOOST_LIB_RT_OPT\r
+#     endif\r
+\r
+#  else\r
+\r
+#     if defined(BOOST_BORLAND_DEBUG)\\r
+               && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#         define BOOST_LIB_RT_OPT "-syd"\r
+#     elif defined(BOOST_BORLAND_DEBUG)\r
+#         define BOOST_LIB_RT_OPT "-sd"\r
+#     elif defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)\r
+#         define BOOST_LIB_RT_OPT "-sy"\r
+#     else\r
+#         define BOOST_LIB_RT_OPT "-s"\r
+#     endif\r
+\r
+#  endif\r
+\r
+#endif\r
+\r
+//\r
+// select linkage opt:\r
+//\r
+#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK)\r
+#  define BOOST_LIB_PREFIX\r
+#elif defined(BOOST_DYN_LINK)\r
+#  error "Mixing a dll boost library with a static runtime is a really bad idea..."\r
+#else\r
+#  define BOOST_LIB_PREFIX "lib"\r
+#endif\r
+\r
+//\r
+// now include the lib:\r
+//\r
+#if defined(BOOST_LIB_NAME) \\r
+      && defined(BOOST_LIB_PREFIX) \\r
+      && defined(BOOST_LIB_TOOLSET) \\r
+      && defined(BOOST_LIB_THREAD_OPT) \\r
+      && defined(BOOST_LIB_RT_OPT) \\r
+      && defined(BOOST_LIB_VERSION)\r
+\r
+#ifdef BOOST_AUTO_LINK_TAGGED\r
+#  pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT ".lib")\r
+#  ifdef BOOST_LIB_DIAGNOSTIC\r
+#     pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")\r
+#  endif\r
+#elif defined(BOOST_AUTO_LINK_NOMANGLE)\r
+#  pragma comment(lib, BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib")\r
+#  ifdef BOOST_LIB_DIAGNOSTIC\r
+#     pragma message ("Linking to lib file: " BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib")\r
+#  endif\r
+#else\r
+#  pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")\r
+#  ifdef BOOST_LIB_DIAGNOSTIC\r
+#     pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")\r
+#  endif\r
+#endif\r
+\r
+#else\r
+#  error "some required macros where not defined (internal logic error)."\r
+#endif\r
+\r
+\r
+#endif // _MSC_VER || __BORLANDC__\r
+\r
+//\r
+// finally undef any macros we may have set:\r
+//\r
+#ifdef BOOST_LIB_PREFIX\r
+#  undef BOOST_LIB_PREFIX\r
+#endif\r
+#if defined(BOOST_LIB_NAME)\r
+#  undef BOOST_LIB_NAME\r
+#endif\r
+// Don't undef this one: it can be set by the user and should be the \r
+// same for all libraries:\r
+//#if defined(BOOST_LIB_TOOLSET)\r
+//#  undef BOOST_LIB_TOOLSET\r
+//#endif\r
+#if defined(BOOST_LIB_THREAD_OPT)\r
+#  undef BOOST_LIB_THREAD_OPT\r
+#endif\r
+#if defined(BOOST_LIB_RT_OPT)\r
+#  undef BOOST_LIB_RT_OPT\r
+#endif\r
+#if defined(BOOST_LIB_LINK_OPT)\r
+#  undef BOOST_LIB_LINK_OPT\r
+#endif\r
+#if defined(BOOST_LIB_DEBUG_OPT)\r
+#  undef BOOST_LIB_DEBUG_OPT\r
+#endif\r
+#if defined(BOOST_DYN_LINK)\r
+#  undef BOOST_DYN_LINK\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/compiler/borland.hpp b/src/external/boost/boost/config/compiler/borland.hpp
new file mode 100644 (file)
index 0000000..dae5dd7
--- /dev/null
@@ -0,0 +1,277 @@
+//  (C) Copyright John Maddock 2001 - 2003.\r
+//  (C) Copyright David Abrahams 2002 - 2003.\r
+//  (C) Copyright Aleksey Gurtovoy 2002.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Borland C++ compiler setup:\r
+\r
+//\r
+// versions check:\r
+// we don't support Borland prior to version 5.4:\r
+#if __BORLANDC__ < 0x540\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+\r
+// last known compiler version:\r
+#if (__BORLANDC__ > 0x613)\r
+//#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+//#  else\r
+//#     pragma message( "Unknown compiler version - please run the configure tests and report the results")\r
+//#  endif\r
+#elif (__BORLANDC__ == 0x600)\r
+#  error "CBuilderX preview compiler is no longer supported"\r
+#endif\r
+\r
+//\r
+// Support macros to help with standard library detection\r
+#if (__BORLANDC__ < 0x560) || defined(_USE_OLD_RW_STL)\r
+#  define BOOST_BCB_WITH_ROGUE_WAVE\r
+#elif __BORLANDC__ < 0x570\r
+#  define BOOST_BCB_WITH_STLPORT\r
+#else\r
+#  define BOOST_BCB_WITH_DINKUMWARE\r
+#endif\r
+\r
+//\r
+// Version 5.0 and below:\r
+#   if __BORLANDC__ <= 0x0550\r
+// Borland C++Builder 4 and 5:\r
+#     define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#     if __BORLANDC__ == 0x0550\r
+// Borland C++Builder 5, command-line compiler 5.5:\r
+#       define BOOST_NO_OPERATORS_IN_NAMESPACE\r
+#     endif\r
+// Variadic macros do not exist for C++ Builder versions 5 and below\r
+#define BOOST_NO_VARIADIC_MACROS\r
+#   endif\r
+\r
+// Version 5.51 and below:\r
+#if (__BORLANDC__ <= 0x551)\r
+#  define BOOST_NO_CV_SPECIALIZATIONS\r
+#  define BOOST_NO_CV_VOID_SPECIALIZATIONS\r
+#  define BOOST_NO_DEDUCED_TYPENAME\r
+// workaround for missing WCHAR_MAX/WCHAR_MIN:\r
+#include <climits>\r
+#include <cwchar>\r
+#ifndef WCHAR_MAX\r
+#  define WCHAR_MAX 0xffff\r
+#endif\r
+#ifndef WCHAR_MIN\r
+#  define WCHAR_MIN 0\r
+#endif\r
+#endif\r
+\r
+// Borland C++ Builder 6 and below:\r
+#if (__BORLANDC__ <= 0x564)\r
+\r
+#  ifdef NDEBUG\r
+      // fix broken <cstring> so that Boost.test works:\r
+#     include <cstring>\r
+#     undef strcmp\r
+#  endif\r
+   // fix broken errno declaration:\r
+#  include <errno.h>\r
+#  ifndef errno\r
+#     define errno errno\r
+#  endif\r
+\r
+#endif\r
+\r
+//\r
+// new bug in 5.61:\r
+#if (__BORLANDC__ >= 0x561) && (__BORLANDC__ <= 0x580)\r
+   // this seems to be needed by the command line compiler, but not the IDE:\r
+#  define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS\r
+#endif\r
+\r
+// Borland C++ Builder 2006 Update 2 and below:\r
+#if (__BORLANDC__ <= 0x582)\r
+#  define BOOST_NO_SFINAE\r
+#  define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG\r
+#  define BOOST_NO_TEMPLATE_TEMPLATES\r
+\r
+#  define BOOST_NO_PRIVATE_IN_AGGREGATE\r
+\r
+#  ifdef _WIN32\r
+#     define BOOST_NO_SWPRINTF\r
+#  elif defined(linux) || defined(__linux__) || defined(__linux)\r
+      // we should really be able to do without this\r
+      // but the wcs* functions aren't imported into std::\r
+#     define BOOST_NO_STDC_NAMESPACE\r
+      // _CPPUNWIND doesn't get automatically set for some reason:\r
+#     pragma defineonoption BOOST_CPPUNWIND -x\r
+#  endif\r
+#endif\r
+\r
+#if (__BORLANDC__ <= 0x613)  // Beman has asked Alisdair for more info\r
+   // we shouldn't really need this - but too many things choke\r
+   // without it, this needs more investigation:\r
+#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#  define BOOST_NO_IS_ABSTRACT\r
+#  define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS\r
+#  define BOOST_NO_USING_TEMPLATE\r
+#  define BOOST_SP_NO_SP_CONVERTIBLE\r
+\r
+// Temporary workaround\r
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS\r
+#endif\r
+\r
+// Borland C++ Builder 2008 and below:\r
+#  define BOOST_NO_INTEGRAL_INT64_T\r
+#  define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#  define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS\r
+#  define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#  define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE\r
+#  define BOOST_NO_NESTED_FRIENDSHIP\r
+#  define BOOST_NO_TYPENAME_WITH_CTOR\r
+#if (__BORLANDC__ < 0x600)\r
+#  define BOOST_ILLEGAL_CV_REFERENCES\r
+#endif\r
+\r
+//\r
+//  Positive Feature detection\r
+//\r
+// Borland C++ Builder 2008 and below:\r
+#if (__BORLANDC__ >= 0x599)\r
+#  pragma defineonoption BOOST_CODEGEAR_0X_SUPPORT -Ax\r
+#endif\r
+//\r
+// C++0x Macros:\r
+//\r
+#if !defined( BOOST_CODEGEAR_0X_SUPPORT ) || (__BORLANDC__ < 0x610)\r
+#  define BOOST_NO_CHAR16_T\r
+#  define BOOST_NO_CHAR32_T\r
+#  define BOOST_NO_DECLTYPE\r
+#  define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#  define BOOST_NO_EXTERN_TEMPLATE\r
+#  define BOOST_NO_RVALUE_REFERENCES \r
+#  define BOOST_NO_SCOPED_ENUMS\r
+#  define BOOST_NO_STATIC_ASSERT\r
+#else\r
+#  define BOOST_HAS_ALIGNOF\r
+#  define BOOST_HAS_CHAR16_T\r
+#  define BOOST_HAS_CHAR32_T\r
+#  define BOOST_HAS_DECLTYPE\r
+#  define BOOST_HAS_EXPLICIT_CONVERSION_OPS\r
+#  define BOOST_HAS_REF_QUALIFIER\r
+#  define BOOST_HAS_RVALUE_REFS\r
+#  define BOOST_HAS_STATIC_ASSERT\r
+#endif\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS    // UTF-8 still not supported\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+\r
+#if __BORLANDC__ >= 0x590\r
+#  define BOOST_HAS_TR1_HASH\r
+\r
+#  define BOOST_HAS_MACRO_USE_FACET\r
+#endif\r
+\r
+//\r
+// Post 0x561 we have long long and stdint.h:\r
+#if __BORLANDC__ >= 0x561\r
+#  ifndef __NO_LONG_LONG\r
+#     define BOOST_HAS_LONG_LONG\r
+#  else\r
+#     define BOOST_NO_LONG_LONG\r
+#  endif\r
+   // On non-Win32 platforms let the platform config figure this out:\r
+#  ifdef _WIN32\r
+#      define BOOST_HAS_STDINT_H\r
+#  endif\r
+#endif\r
+\r
+// Borland C++Builder 6 defaults to using STLPort.  If _USE_OLD_RW_STL is\r
+// defined, then we have 0x560 or greater with the Rogue Wave implementation\r
+// which presumably has the std::DBL_MAX bug.\r
+#if defined( BOOST_BCB_WITH_ROGUE_WAVE )\r
+// <climits> is partly broken, some macros define symbols that are really in\r
+// namespace std, so you end up having to use illegal constructs like\r
+// std::DBL_MAX, as a fix we'll just include float.h and have done with:\r
+#include <float.h>\r
+#endif\r
+//\r
+// __int64:\r
+//\r
+#if (__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)\r
+#  define BOOST_HAS_MS_INT64\r
+#endif\r
+//\r
+// check for exception handling support:\r
+//\r
+#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)\r
+#  define BOOST_NO_EXCEPTIONS\r
+#endif\r
+//\r
+// all versions have a <dirent.h>:\r
+//\r
+#ifndef __STRICT_ANSI__\r
+#  define BOOST_HAS_DIRENT_H\r
+#endif\r
+//\r
+// all versions support __declspec:\r
+//\r
+#if defined(__STRICT_ANSI__)\r
+// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined  \r
+#  define BOOST_SYMBOL_EXPORT\r
+#endif\r
+//\r
+// ABI fixing headers:\r
+//\r
+#if __BORLANDC__ != 0x600 // not implemented for version 6 compiler yet\r
+#ifndef BOOST_ABI_PREFIX\r
+#  define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp"\r
+#endif\r
+#ifndef BOOST_ABI_SUFFIX\r
+#  define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp"\r
+#endif\r
+#endif\r
+//\r
+// Disable Win32 support in ANSI mode:\r
+//\r
+#if __BORLANDC__ < 0x600\r
+#  pragma defineonoption BOOST_DISABLE_WIN32 -A\r
+#elif defined(__STRICT_ANSI__)\r
+#  define BOOST_DISABLE_WIN32\r
+#endif\r
+//\r
+// MSVC compatibility mode does some nasty things:\r
+// TODO: look up if this doesn't apply to the whole 12xx range\r
+//\r
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)\r
+#  define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP\r
+#  define BOOST_NO_VOID_RETURNS\r
+#endif\r
+\r
+// Borland did not implement value-initialization completely, as I reported\r
+// in 2007, Borland Report 51854, "Value-initialization: POD struct should be\r
+// zero-initialized", http://qc.embarcadero.com/wc/qcmain.aspx?d=51854\r
+// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues\r
+// (Niels Dekker, LKEB, April 2010)\r
+#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+\r
+#define BOOST_COMPILER "Borland C++ version " BOOST_STRINGIZE(__BORLANDC__)\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/clang.hpp b/src/external/boost/boost/config/compiler/clang.hpp
new file mode 100644 (file)
index 0000000..f95a72a
--- /dev/null
@@ -0,0 +1,84 @@
+// (C) Copyright Douglas Gregor 2010\r
+//\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+// Clang compiler setup.\r
+\r
+#if __has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)\r
+#else\r
+#  define BOOST_NO_EXCEPTIONS\r
+#endif\r
+\r
+#if !__has_feature(cxx_rtti)\r
+#  define BOOST_NO_RTTI\r
+#endif\r
+\r
+#if defined(__int64)\r
+#  define BOOST_HAS_MS_INT64\r
+#endif\r
+\r
+#define BOOST_HAS_NRVO\r
+\r
+// Clang supports "long long" in all compilation modes.\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+\r
+#if !__has_feature(cxx_decltype)\r
+#  define BOOST_NO_DECLTYPE\r
+#endif\r
+\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+\r
+#if !__has_feature(cxx_deleted_functions)\r
+#  define BOOST_NO_DELETED_FUNCTIONS\r
+#endif\r
+\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+\r
+#if !__has_feature(cxx_default_function_template_args)\r
+  #define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#endif\r
+\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+\r
+#if !__has_feature(cxx_rvalue_references)\r
+#  define BOOST_NO_RVALUE_REFERENCES\r
+#endif\r
+\r
+#if !__has_feature(cxx_strong_enums)\r
+#  define BOOST_NO_SCOPED_ENUMS\r
+#endif\r
+\r
+#if !__has_feature(cxx_static_assert)\r
+#  define BOOST_NO_STATIC_ASSERT\r
+#endif\r
+\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+\r
+#if !__has_feature(cxx_variadic_templates)\r
+#  define BOOST_NO_VARIADIC_TEMPLATES\r
+#endif\r
+\r
+// Clang always supports variadic macros\r
+// Clang always supports extern templates\r
+\r
+#ifndef BOOST_COMPILER\r
+#  define BOOST_COMPILER "Clang version " __clang_version__\r
+#endif\r
+\r
+// Macro used to identify the Clang compiler.\r
+#define BOOST_CLANG 1\r
+\r
diff --git a/src/external/boost/boost/config/compiler/codegear.hpp b/src/external/boost/boost/config/compiler/codegear.hpp
new file mode 100644 (file)
index 0000000..440be7c
--- /dev/null
@@ -0,0 +1,177 @@
+//  (C) Copyright John Maddock 2001 - 2003.\r
+//  (C) Copyright David Abrahams 2002 - 2003.\r
+//  (C) Copyright Aleksey Gurtovoy 2002.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  CodeGear C++ compiler setup:\r
+\r
+#if !defined( BOOST_WITH_CODEGEAR_WARNINGS )\r
+// these warnings occur frequently in optimized template code\r
+# pragma warn -8004 // var assigned value, but never used\r
+# pragma warn -8008 // condition always true/false\r
+# pragma warn -8066 // dead code can never execute\r
+# pragma warn -8104 // static members with ctors not threadsafe\r
+# pragma warn -8105 // reference member in class without ctors\r
+#endif\r
+//\r
+// versions check:\r
+// last known and checked version is 0x621\r
+#if (__CODEGEARC__ > 0x621)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  else\r
+#     pragma message( "Unknown compiler version - please run the configure tests and report the results")\r
+#  endif\r
+#endif\r
+\r
+// CodeGear C++ Builder 2009\r
+#if (__CODEGEARC__ <= 0x613)\r
+#  define BOOST_NO_INTEGRAL_INT64_T\r
+#  define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS\r
+#  define BOOST_NO_PRIVATE_IN_AGGREGATE\r
+#  define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE\r
+   // we shouldn't really need this - but too many things choke\r
+   // without it, this needs more investigation:\r
+#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#  define BOOST_SP_NO_SP_CONVERTIBLE\r
+#endif\r
+\r
+// CodeGear C++ Builder 2010\r
+#if (__CODEGEARC__ <= 0x621)\r
+#  define BOOST_NO_TYPENAME_WITH_CTOR    // Cannot use typename keyword when making temporaries of a dependant type\r
+#  define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#  define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#  define BOOST_NO_NESTED_FRIENDSHIP     // TC1 gives nested classes access rights as any other member\r
+#  define BOOST_NO_USING_TEMPLATE\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+// Temporary hack, until specific MPL preprocessed headers are generated\r
+#  define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS\r
+\r
+// CodeGear has not yet completely implemented value-initialization, for\r
+// example for array types, as I reported in 2010: Embarcadero Report 83751,\r
+// "Value-initialization: arrays should have each element value-initialized",\r
+// http://qc.embarcadero.com/wc/qcmain.aspx?d=83751\r
+// Last checked version: Embarcadero C++ 6.21\r
+// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues\r
+// (Niels Dekker, LKEB, April 2010)\r
+#  define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+\r
+#  ifdef NDEBUG\r
+      // fix broken <cstring> so that Boost.test works:\r
+#     include <cstring>\r
+#     undef strcmp\r
+#  endif\r
+   // fix broken errno declaration:\r
+#  include <errno.h>\r
+#  ifndef errno\r
+#     define errno errno\r
+#  endif\r
+\r
+#endif\r
+//\r
+// C++0x macros:\r
+//\r
+#if (__CODEGEARC__ <= 0x620)\r
+#define BOOST_NO_STATIC_ASSERT\r
+#else\r
+#define BOOST_HAS_STATIC_ASSERT\r
+#endif\r
+#define BOOST_HAS_CHAR16_T\r
+#define BOOST_HAS_CHAR32_T\r
+#define BOOST_HAS_LONG_LONG\r
+// #define BOOST_HAS_ALIGNOF\r
+#define BOOST_HAS_DECLTYPE\r
+#define BOOST_HAS_EXPLICIT_CONVERSION_OPS\r
+// #define BOOST_HAS_RVALUE_REFS\r
+#define BOOST_HAS_SCOPED_ENUM\r
+// #define BOOST_HAS_STATIC_ASSERT\r
+#define BOOST_HAS_STD_TYPE_TRAITS\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+\r
+//\r
+// TR1 macros:\r
+//\r
+#define BOOST_HAS_TR1_HASH\r
+#define BOOST_HAS_TR1_TYPE_TRAITS\r
+#define BOOST_HAS_TR1_UNORDERED_MAP\r
+#define BOOST_HAS_TR1_UNORDERED_SET\r
+\r
+#define BOOST_HAS_MACRO_USE_FACET\r
+\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+\r
+// On non-Win32 platforms let the platform config figure this out:\r
+#ifdef _WIN32\r
+#  define BOOST_HAS_STDINT_H\r
+#endif\r
+\r
+//\r
+// __int64:\r
+//\r
+#if !defined(__STRICT_ANSI__)\r
+#  define BOOST_HAS_MS_INT64\r
+#endif\r
+//\r
+// check for exception handling support:\r
+//\r
+#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)\r
+#  define BOOST_NO_EXCEPTIONS\r
+#endif\r
+//\r
+// all versions have a <dirent.h>:\r
+//\r
+#if !defined(__STRICT_ANSI__)\r
+#  define BOOST_HAS_DIRENT_H\r
+#endif\r
+//\r
+// all versions support __declspec:\r
+//\r
+#if defined(__STRICT_ANSI__)\r
+// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined  \r
+#  define BOOST_SYMBOL_EXPORT\r
+#endif\r
+//\r
+// ABI fixing headers:\r
+//\r
+#ifndef BOOST_ABI_PREFIX\r
+#  define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp"\r
+#endif\r
+#ifndef BOOST_ABI_SUFFIX\r
+#  define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp"\r
+#endif\r
+//\r
+// Disable Win32 support in ANSI mode:\r
+//\r
+#  pragma defineonoption BOOST_DISABLE_WIN32 -A\r
+//\r
+// MSVC compatibility mode does some nasty things:\r
+// TODO: look up if this doesn't apply to the whole 12xx range\r
+//\r
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)\r
+#  define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP\r
+#  define BOOST_NO_VOID_RETURNS\r
+#endif\r
+\r
+#define BOOST_COMPILER "CodeGear C++ version " BOOST_STRINGIZE(__CODEGEARC__)\r
+\r
diff --git a/src/external/boost/boost/config/compiler/comeau.hpp b/src/external/boost/boost/config/compiler/comeau.hpp
new file mode 100644 (file)
index 0000000..c2cb68c
--- /dev/null
@@ -0,0 +1,59 @@
+//  (C) Copyright John Maddock 2001. \r
+//  (C) Copyright Douglas Gregor 2001. \r
+//  (C) Copyright Peter Dimov 2001. \r
+//  (C) Copyright Aleksey Gurtovoy 2003. \r
+//  (C) Copyright Beman Dawes 2003. \r
+//  (C) Copyright Jens Maurer 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Comeau C++ compiler setup:\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+#if (__COMO_VERSION__ <= 4245)\r
+\r
+#  if defined(_MSC_VER) && _MSC_VER <= 1300\r
+#     if _MSC_VER > 100\r
+         // only set this in non-strict mode:\r
+#        define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP\r
+#     endif\r
+#  endif\r
+\r
+// Void returns don't work when emulating VC 6 (Peter Dimov)\r
+// TODO: look up if this doesn't apply to the whole 12xx range\r
+#  if defined(_MSC_VER) && (_MSC_VER < 1300)\r
+#     define BOOST_NO_VOID_RETURNS\r
+#  endif\r
+\r
+#endif  // version 4245\r
+\r
+//\r
+// enable __int64 support in VC emulation mode\r
+//\r
+#  if defined(_MSC_VER) && (_MSC_VER >= 1200)\r
+#     define BOOST_HAS_MS_INT64\r
+#  endif\r
+\r
+#define BOOST_COMPILER "Comeau compiler version " BOOST_STRINGIZE(__COMO_VERSION__)\r
+\r
+//\r
+// versions check:\r
+// we don't know Comeau prior to version 4245:\r
+#if __COMO_VERSION__ < 4245\r
+#  error "Compiler not configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 4245:\r
+#if (__COMO_VERSION__ > 4245)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/common_edg.hpp b/src/external/boost/boost/config/compiler/common_edg.hpp
new file mode 100644 (file)
index 0000000..c59e70e
--- /dev/null
@@ -0,0 +1,99 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  (C) Copyright Jens Maurer 2001. \r
+//  (C) Copyright David Abrahams 2002. \r
+//  (C) Copyright Aleksey Gurtovoy 2002. \r
+//  (C) Copyright Markus Schoepflin 2005.\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//\r
+// Options common to all edg based compilers.\r
+//\r
+// This is included from within the individual compiler mini-configs.\r
+\r
+#ifndef  __EDG_VERSION__\r
+#  error This file requires that __EDG_VERSION__ be defined.\r
+#endif\r
+\r
+#if (__EDG_VERSION__ <= 238)\r
+#   define BOOST_NO_INTEGRAL_INT64_T\r
+#   define BOOST_NO_SFINAE\r
+#endif\r
+\r
+#if (__EDG_VERSION__ <= 240)\r
+#   define BOOST_NO_VOID_RETURNS\r
+#endif\r
+\r
+#if (__EDG_VERSION__ <= 241) && !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)\r
+#   define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP\r
+#endif\r
+\r
+#if (__EDG_VERSION__ <= 244) && !defined(BOOST_NO_TEMPLATE_TEMPLATES)\r
+#   define BOOST_NO_TEMPLATE_TEMPLATES\r
+#endif \r
+\r
+#if (__EDG_VERSION__ < 300) && !defined(BOOST_NO_IS_ABSTRACT)\r
+#   define BOOST_NO_IS_ABSTRACT\r
+#endif \r
+\r
+#if (__EDG_VERSION__ <= 303) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)\r
+#   define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#endif \r
+\r
+// See also kai.hpp which checks a Kai-specific symbol for EH\r
+# if !defined(__KCC) && !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)\r
+#     define BOOST_NO_EXCEPTIONS\r
+# endif\r
+\r
+# if !defined(__NO_LONG_LONG)\r
+#     define BOOST_HAS_LONG_LONG\r
+# else\r
+#     define BOOST_NO_LONG_LONG\r
+# endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See above for BOOST_NO_LONG_LONG\r
+//\r
+#if (__EDG_VERSION__ < 310)\r
+#  define BOOST_NO_EXTERN_TEMPLATE\r
+#endif\r
+#if (__EDG_VERSION__ <= 310)\r
+// No support for initializer lists\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#endif\r
+#if (__EDG_VERSION__ < 400)\r
+#  define BOOST_NO_VARIADIC_MACROS\r
+#endif\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+\r
+#ifdef c_plusplus\r
+// EDG has "long long" in non-strict mode\r
+// However, some libraries have insufficient "long long" support\r
+// #define BOOST_HAS_LONG_LONG\r
+#endif\r
diff --git a/src/external/boost/boost/config/compiler/compaq_cxx.hpp b/src/external/boost/boost/config/compiler/compaq_cxx.hpp
new file mode 100644 (file)
index 0000000..8fb73fb
--- /dev/null
@@ -0,0 +1,19 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Tru64 C++ compiler setup (now HP):\r
+\r
+#define BOOST_COMPILER "HP Tru64 C++ " BOOST_STRINGIZE(__DECCXX_VER)\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+//\r
+// versions check:\r
+// Nothing to do here?\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/digitalmars.hpp b/src/external/boost/boost/config/compiler/digitalmars.hpp
new file mode 100644 (file)
index 0000000..3ec44e1
--- /dev/null
@@ -0,0 +1,96 @@
+//  Copyright (C) Christof Meerwald 2003\r
+//  Copyright (C) Dan Watkins 2003\r
+//\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  Digital Mars C++ compiler setup:\r
+#define BOOST_COMPILER __DMC_VERSION_STRING__\r
+\r
+#define BOOST_HAS_LONG_LONG\r
+#define BOOST_HAS_PRAGMA_ONCE\r
+\r
+#if (__DMC__ <= 0x833)\r
+#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#define BOOST_NO_TEMPLATE_TEMPLATES\r
+#define BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING\r
+#define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS\r
+#define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+#endif\r
+#if (__DMC__ <= 0x840) || !defined(BOOST_STRICT_CONFIG)\r
+#define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+#define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#define BOOST_NO_OPERATORS_IN_NAMESPACE\r
+#define BOOST_NO_UNREACHABLE_RETURN_DETECTION\r
+#define BOOST_NO_SFINAE\r
+#define BOOST_NO_USING_TEMPLATE\r
+#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#endif\r
+\r
+//\r
+// has macros:\r
+#if (__DMC__ >= 0x840)\r
+#define BOOST_HAS_DIRENT_H\r
+#define BOOST_HAS_STDINT_H\r
+#define BOOST_HAS_WINTHREADS\r
+#endif\r
+\r
+#if (__DMC__ >= 0x847)\r
+#define BOOST_HAS_EXPM1\r
+#define BOOST_HAS_LOG1P\r
+#endif\r
+\r
+//\r
+// Is this really the best way to detect whether the std lib is in namespace std?\r
+//\r
+#include <cstddef>\r
+#if !defined(__STL_IMPORT_VENDOR_CSTD) && !defined(_STLP_IMPORT_VENDOR_CSTD)\r
+#  define BOOST_NO_STDC_NAMESPACE\r
+#endif\r
+\r
+\r
+// check for exception handling support:\r
+#if !defined(_CPPUNWIND) && !defined(BOOST_NO_EXCEPTIONS)\r
+#  define BOOST_NO_EXCEPTIONS\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#if (__DMC__ < 0x812)\r
+#define BOOST_NO_VARIADIC_MACROS\r
+#endif\r
+\r
+#if __DMC__ < 0x800\r
+#error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is ...:\r
+#if (__DMC__ > 0x848)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
diff --git a/src/external/boost/boost/config/compiler/gcc.hpp b/src/external/boost/boost/config/compiler/gcc.hpp
new file mode 100644 (file)
index 0000000..9e37e82
--- /dev/null
@@ -0,0 +1,250 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Darin Adler 2001 - 2002. \r
+//  (C) Copyright Jens Maurer 2001 - 2002. \r
+//  (C) Copyright Beman Dawes 2001 - 2003. \r
+//  (C) Copyright Douglas Gregor 2002. \r
+//  (C) Copyright David Abrahams 2002 - 2003. \r
+//  (C) Copyright Synge Todo 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  GNU C++ compiler setup:\r
+\r
+#if __GNUC__ < 3\r
+#   if __GNUC_MINOR__ == 91\r
+       // egcs 1.1 won't parse shared_ptr.hpp without this:\r
+#      define BOOST_NO_AUTO_PTR\r
+#   endif\r
+#   if __GNUC_MINOR__ < 95\r
+      //\r
+      // Prior to gcc 2.95 member templates only partly\r
+      // work - define BOOST_MSVC6_MEMBER_TEMPLATES\r
+      // instead since inline member templates mostly work.\r
+      //\r
+#     define BOOST_NO_MEMBER_TEMPLATES\r
+#     if __GNUC_MINOR__ >= 9\r
+#       define BOOST_MSVC6_MEMBER_TEMPLATES\r
+#     endif\r
+#   endif\r
+\r
+#   if __GNUC_MINOR__ < 96\r
+#     define BOOST_NO_SFINAE\r
+#   endif\r
+\r
+#   if __GNUC_MINOR__ <= 97\r
+#     define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#     define BOOST_NO_OPERATORS_IN_NAMESPACE\r
+#   endif\r
+\r
+#   define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE\r
+#   define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#   define BOOST_NO_IS_ABSTRACT\r
+#   define BOOST_NO_EXTERN_TEMPLATE\r
+// Variadic macros do not exist for gcc versions before 3.0\r
+#   define BOOST_NO_VARIADIC_MACROS\r
+#elif __GNUC__ == 3\r
+#  if defined (__PATHSCALE__)\r
+#     define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#     define BOOST_NO_IS_ABSTRACT\r
+#  endif\r
+   //\r
+   // gcc-3.x problems:\r
+   //\r
+   // Bug specific to gcc 3.1 and 3.2:\r
+   //\r
+#  if ((__GNUC_MINOR__ == 1) || (__GNUC_MINOR__ == 2))\r
+#     define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+#  endif\r
+#  if __GNUC_MINOR__ < 4\r
+#     define BOOST_NO_IS_ABSTRACT\r
+#  endif\r
+#  define BOOST_NO_EXTERN_TEMPLATE\r
+#endif\r
+#if __GNUC__ < 4\r
+//\r
+// All problems to gcc-3.x and earlier here:\r
+//\r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#  ifdef __OPEN64__\r
+#     define BOOST_NO_IS_ABSTRACT\r
+#  endif\r
+#endif\r
+\r
+#if __GNUC__ < 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ < 4 )\r
+// Previous versions of GCC did not completely implement value-initialization:\r
+// GCC Bug 30111, "Value-initialization of POD base class doesn't initialize\r
+// members", reported by Jonathan Wakely in 2006,\r
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 (fixed for GCC 4.4)\r
+// GCC Bug 33916, "Default constructor fails to initialize array members",\r
+// reported by Michael Elizabeth Chastain in 2007,\r
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 (fixed for GCC 4.2.4)\r
+// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues\r
+#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#endif\r
+\r
+#if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)\r
+# define BOOST_NO_EXCEPTIONS\r
+#endif\r
+\r
+\r
+//\r
+// Threading support: Turn this on unconditionally here (except for\r
+// those platforms where we can know for sure). It will get turned off again\r
+// later if no threading API is detected.\r
+//\r
+#if !defined(__MINGW32__) && !defined(linux) && !defined(__linux) && !defined(__linux__)\r
+# define BOOST_HAS_THREADS\r
+#endif \r
+\r
+//\r
+// gcc has "long long"\r
+//\r
+#define BOOST_HAS_LONG_LONG\r
+\r
+//\r
+// gcc implements the named return value optimization since version 3.1\r
+//\r
+#if __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 )\r
+#define BOOST_HAS_NRVO\r
+#endif\r
+\r
+//\r
+// Dynamic shared object (DSO) and dynamic-link library (DLL) support\r
+//\r
+#if __GNUC__ >= 4\r
+#  if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(__CYGWIN__)\r
+     // All Win32 development environments, including 64-bit Windows and MinGW, define \r
+     // _WIN32 or one of its variant spellings. Note that Cygwin is a POSIX environment,\r
+     // so does not define _WIN32 or its variants.\r
+#    define BOOST_HAS_DECLSPEC\r
+#    define BOOST_SYMBOL_EXPORT __attribute__((dllexport))\r
+#    define BOOST_SYMBOL_IMPORT __attribute__((dllimport))\r
+#  else\r
+#    define BOOST_SYMBOL_EXPORT __attribute__((visibility("default")))\r
+#    define BOOST_SYMBOL_IMPORT\r
+#  endif\r
+#  define BOOST_SYMBOL_VISIBLE __attribute__((visibility("default")))\r
+#else\r
+// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined  \r
+#  define BOOST_SYMBOL_EXPORT\r
+#endif\r
+\r
+//\r
+// RTTI and typeinfo detection is possible post gcc-4.3:\r
+//\r
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 403\r
+#  ifndef __GXX_RTTI\r
+#     ifndef BOOST_NO_TYPEID\r
+#        define BOOST_NO_TYPEID\r
+#     endif\r
+#     ifndef BOOST_NO_RTTI\r
+#        define BOOST_NO_RTTI\r
+#     endif\r
+#  endif\r
+#endif\r
+\r
+// C++0x features not implemented in any GCC version\r
+//\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+\r
+// C++0x features in 4.3.n and later\r
+//\r
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are\r
+// passed on the command line, which in turn defines\r
+// __GXX_EXPERIMENTAL_CXX0X__.\r
+#  define BOOST_HAS_DECLTYPE\r
+#  define BOOST_HAS_RVALUE_REFS\r
+#  define BOOST_HAS_STATIC_ASSERT\r
+#  define BOOST_HAS_VARIADIC_TMPL\r
+#else\r
+#  define BOOST_NO_DECLTYPE\r
+#  define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#  define BOOST_NO_RVALUE_REFERENCES\r
+#  define BOOST_NO_STATIC_ASSERT\r
+\r
+// Variadic templates compiler: \r
+//   http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html\r
+#  ifdef __VARIADIC_TEMPLATES\r
+#    define BOOST_HAS_VARIADIC_TMPL\r
+#  else\r
+#    define BOOST_NO_VARIADIC_TEMPLATES\r
+#  endif\r
+#endif\r
+\r
+// C++0x features in 4.4.n and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#  define BOOST_NO_AUTO_DECLARATIONS\r
+#  define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#  define BOOST_NO_CHAR16_T\r
+#  define BOOST_NO_CHAR32_T\r
+#  define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#  define BOOST_NO_DELETED_FUNCTIONS\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#  define BOOST_NO_SCOPED_ENUMS  \r
+#endif\r
+\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)\r
+#  define BOOST_NO_SFINAE_EXPR\r
+#endif\r
+\r
+// C++0x features in 4.4.1 and later\r
+//\r
+#if (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40401) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+// scoped enums have a serious bug in 4.4.0, so define BOOST_NO_SCOPED_ENUMS before 4.4.1\r
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38064\r
+#  define BOOST_NO_SCOPED_ENUMS\r
+#endif\r
+\r
+// C++0x features in 4.5.n and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#  define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#  define BOOST_NO_LAMBDAS\r
+#  define BOOST_NO_RAW_LITERALS\r
+#  define BOOST_NO_UNICODE_LITERALS\r
+#endif\r
+\r
+// C++0x features in 4.5.n and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_NULLPTR\r
+#endif\r
+\r
+// ConceptGCC compiler:\r
+//   http://www.generic-programming.org/software/ConceptGCC/\r
+#ifdef __GXX_CONCEPTS__\r
+#  define BOOST_HAS_CONCEPTS\r
+#  define BOOST_COMPILER "ConceptGCC version " __VERSION__\r
+#else\r
+#  define BOOST_NO_CONCEPTS\r
+#endif\r
+\r
+#ifndef BOOST_COMPILER\r
+#  define BOOST_COMPILER "GNU C++ version " __VERSION__\r
+#endif\r
+\r
+//\r
+// versions check:\r
+// we don't know gcc prior to version 2.90:\r
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ < 90)\r
+#  error "Compiler not configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 4.6 (Pre-release):\r
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6))\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  else\r
+// we don't emit warnings here anymore since there are no defect macros defined for\r
+// gcc post 3.4, so any failures are gcc regressions...\r
+//#     warning "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/gcc_xml.hpp b/src/external/boost/boost/config/compiler/gcc_xml.hpp
new file mode 100644 (file)
index 0000000..8b57952
--- /dev/null
@@ -0,0 +1,56 @@
+//  (C) Copyright John Maddock 2006. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  GCC-XML C++ compiler setup:\r
+\r
+#  if !defined(__GCCXML_GNUC__) || ((__GCCXML_GNUC__ <= 3) && (__GCCXML_GNUC_MINOR__ <= 3))\r
+#     define BOOST_NO_IS_ABSTRACT\r
+#  endif\r
+\r
+//\r
+// Threading support: Turn this on unconditionally here (except for\r
+// those platforms where we can know for sure). It will get turned off again\r
+// later if no threading API is detected.\r
+//\r
+#if !defined(__MINGW32__) && !defined(_MSC_VER) && !defined(linux) && !defined(__linux) && !defined(__linux__)\r
+# define BOOST_HAS_THREADS\r
+#endif \r
+\r
+//\r
+// gcc has "long long"\r
+//\r
+#define BOOST_HAS_LONG_LONG\r
+\r
+// C++0x features:\r
+//\r
+#  define BOOST_NO_CONSTEXPR\r
+#  define BOOST_NO_NULLPTR\r
+#  define BOOST_NO_TEMPLATE_ALIASES\r
+#  define BOOST_NO_DECLTYPE\r
+#  define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#  define BOOST_NO_RVALUE_REFERENCES\r
+#  define BOOST_NO_STATIC_ASSERT\r
+#  define BOOST_NO_VARIADIC_TEMPLATES\r
+#  define BOOST_NO_VARIADIC_MACROS\r
+#  define BOOST_NO_AUTO_DECLARATIONS\r
+#  define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#  define BOOST_NO_CHAR16_T\r
+#  define BOOST_NO_CHAR32_T\r
+#  define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#  define BOOST_NO_DELETED_FUNCTIONS\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#  define BOOST_NO_SCOPED_ENUMS  \r
+#  define BOOST_NO_SFINAE_EXPR\r
+#  define BOOST_NO_SCOPED_ENUMS\r
+#  define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#  define BOOST_NO_LAMBDAS\r
+#  define BOOST_NO_RAW_LITERALS\r
+#  define BOOST_NO_UNICODE_LITERALS\r
+\r
+#define BOOST_COMPILER "GCC-XML C++ version " __GCCXML__\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/greenhills.hpp b/src/external/boost/boost/config/compiler/greenhills.hpp
new file mode 100644 (file)
index 0000000..1dd89d1
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Greenhills C++ compiler setup:\r
+\r
+#define BOOST_COMPILER "Greenhills C++ version " BOOST_STRINGIZE(__ghs)\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+//\r
+// versions check:\r
+// we don't support Greenhills prior to version 0:\r
+#if __ghs < 0\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 0:\r
+#if (__ghs > 0)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/hp_acc.hpp b/src/external/boost/boost/config/compiler/hp_acc.hpp
new file mode 100644 (file)
index 0000000..1cc457b
--- /dev/null
@@ -0,0 +1,137 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  (C) Copyright Aleksey Gurtovoy 2002. \r
+//  (C) Copyright David Abrahams 2002 - 2003. \r
+//  (C) Copyright Toon Knapen 2003. \r
+//  (C) Copyright Boris Gubenko 2006 - 2007.\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  HP aCC C++ compiler setup:\r
+\r
+#if defined(__EDG__)\r
+#include "boost/config/compiler/common_edg.hpp"\r
+#endif\r
+\r
+#if (__HP_aCC <= 33100)\r
+#    define BOOST_NO_INTEGRAL_INT64_T\r
+#    define BOOST_NO_OPERATORS_IN_NAMESPACE\r
+#  if !defined(_NAMESPACE_STD)\r
+#     define BOOST_NO_STD_LOCALE\r
+#     define BOOST_NO_STRINGSTREAM\r
+#  endif\r
+#endif\r
+\r
+#if (__HP_aCC <= 33300)\r
+// member templates are sufficiently broken that we disable them for now\r
+#    define BOOST_NO_MEMBER_TEMPLATES\r
+#    define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS\r
+#    define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE\r
+#endif\r
+\r
+#if (__HP_aCC <= 38000)\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#endif\r
+\r
+#if (__HP_aCC > 50000) && (__HP_aCC < 60000)\r
+#    define BOOST_NO_UNREACHABLE_RETURN_DETECTION\r
+#    define BOOST_NO_TEMPLATE_TEMPLATES\r
+#    define BOOST_NO_SWPRINTF\r
+#    define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS\r
+#    define BOOST_NO_IS_ABSTRACT\r
+#    define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#endif \r
+\r
+// optional features rather than defects:\r
+#if (__HP_aCC >= 33900)\r
+#    define BOOST_HAS_LONG_LONG\r
+#    define BOOST_HAS_PARTIAL_STD_ALLOCATOR\r
+#endif\r
+\r
+#if (__HP_aCC >= 50000 ) && (__HP_aCC <= 53800 ) || (__HP_aCC < 31300 )\r
+#    define BOOST_NO_MEMBER_TEMPLATE_KEYWORD\r
+#endif\r
+\r
+// This macro should not be defined when compiling in strict ansi\r
+// mode, but, currently, we don't have the ability to determine\r
+// what standard mode we are compiling with. Some future version\r
+// of aCC6 compiler will provide predefined macros reflecting the\r
+// compilation options, including the standard mode.\r
+#if (__HP_aCC >= 60000) || ((__HP_aCC > 38000) && defined(__hpxstd98))\r
+#    define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#endif\r
+\r
+#define BOOST_COMPILER "HP aCC version " BOOST_STRINGIZE(__HP_aCC)\r
+\r
+//\r
+// versions check:\r
+// we don't support HP aCC prior to version 33000:\r
+#if __HP_aCC < 33000\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+\r
+//\r
+// Extended checks for supporting aCC on PA-RISC\r
+#if __HP_aCC > 30000 && __HP_aCC < 50000\r
+#  if __HP_aCC < 38000\r
+      // versions prior to version A.03.80 not supported\r
+#     error "Compiler version not supported - version A.03.80 or higher is required"\r
+#  elif !defined(__hpxstd98)\r
+      // must compile using the option +hpxstd98 with version A.03.80 and above\r
+#     error "Compiler option '+hpxstd98' is required for proper support"\r
+#  endif //PA-RISC\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG\r
+//\r
+#if !defined(__EDG__)\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+\r
+/* \r
+  See https://forums13.itrc.hp.com/service/forums/questionanswer.do?threadId=1443331 and\r
+      https://forums13.itrc.hp.com/service/forums/questionanswer.do?threadId=1443436\r
+*/\r
+\r
+#if (__HP_aCC < 62500) || !defined(HP_CXX0x_SOURCE)\r
+  #define BOOST_NO_VARIADIC_MACROS\r
+#endif\r
+\r
+#endif\r
+\r
+//\r
+// last known and checked version for HP-UX/ia64 is 61300\r
+// last known and checked version for PA-RISC is 38000\r
+#if ((__HP_aCC > 61300) || ((__HP_aCC > 38000) && defined(__hpxstd98)))\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
diff --git a/src/external/boost/boost/config/compiler/intel.hpp b/src/external/boost/boost/config/compiler/intel.hpp
new file mode 100644 (file)
index 0000000..8dbc727
--- /dev/null
@@ -0,0 +1,234 @@
+//  (C) Copyright John Maddock 2001-8.\r
+//  (C) Copyright Peter Dimov 2001.\r
+//  (C) Copyright Jens Maurer 2001.\r
+//  (C) Copyright David Abrahams 2002 - 2003.\r
+//  (C) Copyright Aleksey Gurtovoy 2002 - 2003.\r
+//  (C) Copyright Guillaume Melquiond 2002 - 2003.\r
+//  (C) Copyright Beman Dawes 2003.\r
+//  (C) Copyright Martin Wille 2003.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Intel compiler setup:\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+#if defined(__INTEL_COMPILER)\r
+#  define BOOST_INTEL_CXX_VERSION __INTEL_COMPILER\r
+#elif defined(__ICL)\r
+#  define BOOST_INTEL_CXX_VERSION __ICL\r
+#elif defined(__ICC)\r
+#  define BOOST_INTEL_CXX_VERSION __ICC\r
+#elif defined(__ECC)\r
+#  define BOOST_INTEL_CXX_VERSION __ECC\r
+#endif\r
+\r
+// Flags determined by comparing output of 'icpc -dM -E' with and without '-std=c++0x'\r
+#if (!(defined(_WIN32) || defined(_WIN64)) && defined(__STDC_HOSTED__) && __STDC_HOSTED__) || defined(__GXX_EXPERIMENTAL_CPP0X__)\r
+#  define BOOST_INTEL_STDCXX0X\r
+#endif\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)\r
+#  define BOOST_INTEL_STDCXX0X\r
+#endif\r
+\r
+#ifdef BOOST_INTEL_STDCXX0X\r
+#define BOOST_COMPILER "Intel C++ C++0x mode version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION)\r
+#else\r
+#define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION)\r
+#endif\r
+#define BOOST_INTEL BOOST_INTEL_CXX_VERSION\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+#  define BOOST_INTEL_WIN BOOST_INTEL\r
+#else\r
+#  define BOOST_INTEL_LINUX BOOST_INTEL\r
+#endif\r
+\r
+#if (BOOST_INTEL_CXX_VERSION <= 500) && defined(_MSC_VER)\r
+#  define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+#  define BOOST_NO_TEMPLATE_TEMPLATES\r
+#endif\r
+\r
+#if (BOOST_INTEL_CXX_VERSION <= 600)\r
+\r
+#  if defined(_MSC_VER) && (_MSC_VER <= 1300) // added check for <= VC 7 (Peter Dimov)\r
+\r
+// Boost libraries assume strong standard conformance unless otherwise\r
+// indicated by a config macro. As configured by Intel, the EDG front-end\r
+// requires certain compiler options be set to achieve that strong conformance.\r
+// Particularly /Qoption,c,--arg_dep_lookup (reported by Kirk Klobe & Thomas Witt)\r
+// and /Zc:wchar_t,forScope. See boost-root/tools/build/intel-win32-tools.jam for\r
+// details as they apply to particular versions of the compiler. When the\r
+// compiler does not predefine a macro indicating if an option has been set,\r
+// this config file simply assumes the option has been set.\r
+// Thus BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP will not be defined, even if\r
+// the compiler option is not enabled.\r
+\r
+#     define BOOST_NO_SWPRINTF\r
+#  endif\r
+\r
+// Void returns, 64 bit integrals don't work when emulating VC 6 (Peter Dimov)\r
+\r
+#  if defined(_MSC_VER) && (_MSC_VER <= 1200)\r
+#     define BOOST_NO_VOID_RETURNS\r
+#     define BOOST_NO_INTEGRAL_INT64_T\r
+#  endif\r
+\r
+#endif\r
+\r
+#if (BOOST_INTEL_CXX_VERSION <= 710) && defined(_WIN32)\r
+#  define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS\r
+#endif\r
+\r
+// See http://aspn.activestate.com/ASPN/Mail/Message/boost/1614864\r
+#if BOOST_INTEL_CXX_VERSION < 600\r
+#  define BOOST_NO_INTRINSIC_WCHAR_T\r
+#else\r
+// We should test the macro _WCHAR_T_DEFINED to check if the compiler\r
+// supports wchar_t natively. *BUT* there is a problem here: the standard\r
+// headers define this macro if they typedef wchar_t. Anyway, we're lucky\r
+// because they define it without a value, while Intel C++ defines it\r
+// to 1. So we can check its value to see if the macro was defined natively\r
+// or not.\r
+// Under UNIX, the situation is exactly the same, but the macro _WCHAR_T\r
+// is used instead.\r
+#  if ((_WCHAR_T_DEFINED + 0) == 0) && ((_WCHAR_T + 0) == 0)\r
+#    define BOOST_NO_INTRINSIC_WCHAR_T\r
+#  endif\r
+#endif\r
+\r
+#if defined(__GNUC__) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)\r
+//\r
+// Figure out when Intel is emulating this gcc bug\r
+// (All Intel versions prior to 9.0.26, and versions\r
+// later than that if they are set up to emulate gcc 3.2\r
+// or earlier):\r
+//\r
+#  if ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 2)) || (BOOST_INTEL < 900) || (__INTEL_COMPILER_BUILD_DATE < 20050912)\r
+#     define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#  endif\r
+#endif\r
+#if (defined(__GNUC__) && (__GNUC__ < 4)) || defined(_WIN32) || (BOOST_INTEL_CXX_VERSION <= 1200)\r
+// GCC or VC emulation:\r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#endif\r
+//\r
+// Verify that we have actually got BOOST_NO_INTRINSIC_WCHAR_T\r
+// set correctly, if we don't do this now, we will get errors later\r
+// in type_traits code among other things, getting this correct\r
+// for the Intel compiler is actually remarkably fragile and tricky:\r
+//\r
+#if defined(BOOST_NO_INTRINSIC_WCHAR_T)\r
+#include <cwchar>\r
+template< typename T > struct assert_no_intrinsic_wchar_t;\r
+template<> struct assert_no_intrinsic_wchar_t<wchar_t> { typedef void type; };\r
+// if you see an error here then you need to unset BOOST_NO_INTRINSIC_WCHAR_T\r
+// where it is defined above:\r
+typedef assert_no_intrinsic_wchar_t<unsigned short>::type assert_no_intrinsic_wchar_t_;\r
+#else\r
+template< typename T > struct assert_intrinsic_wchar_t;\r
+template<> struct assert_intrinsic_wchar_t<wchar_t> {};\r
+// if you see an error here then define BOOST_NO_INTRINSIC_WCHAR_T on the command line:\r
+template<> struct assert_intrinsic_wchar_t<unsigned short> {};\r
+#endif\r
+\r
+#if _MSC_VER+0 >= 1000\r
+#  if _MSC_VER >= 1200\r
+#     define BOOST_HAS_MS_INT64\r
+#  endif\r
+#  define BOOST_NO_SWPRINTF\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#elif defined(_WIN32)\r
+#  define BOOST_DISABLE_WIN32\r
+#endif\r
+\r
+// I checked version 6.0 build 020312Z, it implements the NRVO.\r
+// Correct this as you find out which version of the compiler\r
+// implemented the NRVO first.  (Daniel Frey)\r
+#if (BOOST_INTEL_CXX_VERSION >= 600)\r
+#  define BOOST_HAS_NRVO\r
+#endif\r
+\r
+//\r
+// versions check:\r
+// we don't support Intel prior to version 5.0:\r
+#if BOOST_INTEL_CXX_VERSION < 500\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+\r
+// Intel on MacOS requires\r
+#if defined(__APPLE__) && defined(__INTEL_COMPILER)\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#endif\r
+\r
+// Intel on Altix Itanium\r
+#if defined(__itanium__) && defined(__INTEL_COMPILER)\r
+#  define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#endif\r
+\r
+//\r
+// An attempt to value-initialize a pointer-to-member may trigger an\r
+// internal error on Intel <= 11.1 (last checked version), as was \r
+// reported by John Maddock, Intel support issue 589832, May 2010.\r
+// Moreover, according to test results from Huang-Vista-x86_32_intel,\r
+// intel-vc9-win-11.1 may leave a non-POD array uninitialized, in some \r
+// cases when it should be value-initialized.\r
+// (Niels Dekker, LKEB, May 2010)\r
+#if defined(__INTEL_COMPILER)\r
+#  if __INTEL_COMPILER <= 1110\r
+#    define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#  endif\r
+#endif\r
+\r
+//\r
+// Dynamic shared object (DSO) and dynamic-link library (DLL) support\r
+//\r
+#if defined(__GNUC__) && (__GNUC__ >= 4)\r
+#  define BOOST_SYMBOL_EXPORT __attribute__((visibility("default")))\r
+#  define BOOST_SYMBOL_IMPORT\r
+#  define BOOST_SYMBOL_VISIBLE __attribute__((visibility("default")))\r
+#endif\r
+//\r
+// C++0x features\r
+//     - ICC added static_assert in 11.0 (first version with C++0x support)\r
+//\r
+#if defined(BOOST_INTEL_STDCXX0X)\r
+#  undef  BOOST_NO_STATIC_ASSERT\r
+//\r
+// These pass our test cases, but aren't officially supported according to:\r
+// http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/\r
+//\r
+//#  undef  BOOST_NO_LAMBDAS\r
+//#  undef  BOOST_NO_DECLTYPE\r
+//#  undef  BOOST_NO_AUTO_DECLARATIONS\r
+//#  undef  BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#endif\r
+\r
+#if defined(BOOST_INTEL_STDCXX0X) && (BOOST_INTEL_CXX_VERSION >= 1200)\r
+#  undef  BOOST_NO_RVALUE_REFERENCES\r
+#  undef  BOOST_NO_SCOPED_ENUMS\r
+#  undef  BOOST_NO_DELETED_FUNCTIONS\r
+#  undef  BOOST_NO_DEFAULTED_FUNCTIONS\r
+#  undef  BOOST_NO_LAMBDAS\r
+#  undef  BOOST_NO_DECLTYPE\r
+#  undef  BOOST_NO_AUTO_DECLARATIONS\r
+#  undef  BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#endif\r
+\r
+//\r
+// last known and checked version:\r
+#if (BOOST_INTEL_CXX_VERSION > 1110)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  elif defined(_MSC_VER)\r
+//\r
+//      We don't emit this warning any more, since we have so few\r
+//      defect macros set anyway (just the one).\r
+//\r
+//#     pragma message("Unknown compiler version - please run the configure tests and report the results")\r
+#  endif\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/compiler/kai.hpp b/src/external/boost/boost/config/compiler/kai.hpp
new file mode 100644 (file)
index 0000000..f9c49ca
--- /dev/null
@@ -0,0 +1,33 @@
+//  (C) Copyright John Maddock 2001. \r
+//  (C) Copyright David Abrahams 2002. \r
+//  (C) Copyright Aleksey Gurtovoy 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Kai C++ compiler setup:\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+#   if (__KCC_VERSION <= 4001) || !defined(BOOST_STRICT_CONFIG)\r
+      // at least on Sun, the contents of <cwchar> is not in namespace std\r
+#     define BOOST_NO_STDC_NAMESPACE\r
+#   endif\r
+\r
+// see also common_edg.hpp which needs a special check for __KCC\r
+# if !defined(_EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)\r
+#     define BOOST_NO_EXCEPTIONS\r
+# endif\r
+\r
+//\r
+// last known and checked version is 4001:\r
+#if (__KCC_VERSION > 4001)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/metrowerks.hpp b/src/external/boost/boost/config/compiler/metrowerks.hpp
new file mode 100644 (file)
index 0000000..df7893d
--- /dev/null
@@ -0,0 +1,140 @@
+//  (C) Copyright John Maddock 2001. \r
+//  (C) Copyright Darin Adler 2001. \r
+//  (C) Copyright Peter Dimov 2001. \r
+//  (C) Copyright David Abrahams 2001 - 2002. \r
+//  (C) Copyright Beman Dawes 2001 - 2003. \r
+//  (C) Copyright Stefan Slapeta 2004. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Metrowerks C++ compiler setup:\r
+\r
+// locale support is disabled when linking with the dynamic runtime\r
+#   ifdef _MSL_NO_LOCALE\r
+#     define BOOST_NO_STD_LOCALE\r
+#   endif \r
+\r
+#   if __MWERKS__ <= 0x2301  // 5.3\r
+#     define BOOST_NO_FUNCTION_TEMPLATE_ORDERING\r
+#     define BOOST_NO_POINTER_TO_MEMBER_CONST\r
+#     define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS\r
+#     define BOOST_NO_MEMBER_TEMPLATE_KEYWORD\r
+#   endif\r
+\r
+#   if __MWERKS__ <= 0x2401  // 6.2\r
+//#     define BOOST_NO_FUNCTION_TEMPLATE_ORDERING\r
+#   endif\r
+\r
+#   if(__MWERKS__ <= 0x2407)  // 7.x\r
+#     define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS\r
+#     define BOOST_NO_UNREACHABLE_RETURN_DETECTION\r
+#   endif\r
+\r
+#   if(__MWERKS__ <= 0x3003)  // 8.x\r
+#     define BOOST_NO_SFINAE\r
+#    endif\r
+\r
+// the "|| !defined(BOOST_STRICT_CONFIG)" part should apply to the last\r
+// tested version *only*:\r
+#   if(__MWERKS__ <= 0x3207) || !defined(BOOST_STRICT_CONFIG) // 9.6\r
+#     define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#     define BOOST_NO_IS_ABSTRACT\r
+#    endif\r
+\r
+#if !__option(wchar_type)\r
+#   define BOOST_NO_INTRINSIC_WCHAR_T\r
+#endif\r
+\r
+#if !__option(exceptions) && !defined(BOOST_NO_EXCEPTIONS)\r
+#   define BOOST_NO_EXCEPTIONS\r
+#endif\r
+\r
+#if (__INTEL__ && _WIN32) || (__POWERPC__ && macintosh)\r
+#   if __MWERKS__ == 0x3000\r
+#     define BOOST_COMPILER_VERSION 8.0\r
+#   elif __MWERKS__ == 0x3001\r
+#     define BOOST_COMPILER_VERSION 8.1\r
+#   elif __MWERKS__ == 0x3002\r
+#     define BOOST_COMPILER_VERSION 8.2\r
+#   elif __MWERKS__ == 0x3003\r
+#     define BOOST_COMPILER_VERSION 8.3\r
+#   elif __MWERKS__ == 0x3200\r
+#     define BOOST_COMPILER_VERSION 9.0\r
+#   elif __MWERKS__ == 0x3201\r
+#     define BOOST_COMPILER_VERSION 9.1\r
+#   elif __MWERKS__ == 0x3202\r
+#     define BOOST_COMPILER_VERSION 9.2\r
+#   elif __MWERKS__ == 0x3204\r
+#     define BOOST_COMPILER_VERSION 9.3\r
+#   elif __MWERKS__ == 0x3205\r
+#     define BOOST_COMPILER_VERSION 9.4\r
+#   elif __MWERKS__ == 0x3206\r
+#     define BOOST_COMPILER_VERSION 9.5\r
+#   elif __MWERKS__ == 0x3207\r
+#     define BOOST_COMPILER_VERSION 9.6\r
+#   else\r
+#     define BOOST_COMPILER_VERSION __MWERKS__\r
+#   endif\r
+#else\r
+#  define BOOST_COMPILER_VERSION __MWERKS__\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG\r
+//\r
+#if __MWERKS__ > 0x3206 && __option(rvalue_refs)\r
+#  define BOOST_HAS_RVALUE_REFS\r
+#else\r
+#  define BOOST_NO_RVALUE_REFERENCES              \r
+#endif\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#define BOOST_NO_VARIADIC_MACROS\r
+\r
+#define BOOST_COMPILER "Metrowerks CodeWarrior C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)\r
+\r
+//\r
+// versions check:\r
+// we don't support Metrowerks prior to version 5.3:\r
+#if __MWERKS__ < 0x2301\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version:\r
+#if (__MWERKS__ > 0x3205)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/mpw.hpp b/src/external/boost/boost/config/compiler/mpw.hpp
new file mode 100644 (file)
index 0000000..049251b
--- /dev/null
@@ -0,0 +1,82 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  (C) Copyright Aleksey Gurtovoy 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  MPW C++ compilers setup:\r
+\r
+#   if    defined(__SC__)\r
+#     define BOOST_COMPILER "MPW SCpp version " BOOST_STRINGIZE(__SC__)\r
+#   elif defined(__MRC__)\r
+#     define BOOST_COMPILER "MPW MrCpp version " BOOST_STRINGIZE(__MRC__)\r
+#   else\r
+#     error "Using MPW compiler configuration by mistake.  Please update."\r
+#   endif\r
+\r
+//\r
+// MPW 8.90:\r
+//\r
+#if (MPW_CPLUS <= 0x890) || !defined(BOOST_STRICT_CONFIG)\r
+#  define BOOST_NO_CV_SPECIALIZATIONS\r
+#  define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS\r
+#  define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS\r
+#  define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+#  define BOOST_NO_INTRINSIC_WCHAR_T\r
+#  define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+#  define BOOST_NO_USING_TEMPLATE\r
+\r
+#  define BOOST_NO_CWCHAR\r
+#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+\r
+#  define BOOST_NO_STD_ALLOCATOR /* actually a bug with const reference overloading */\r
+\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG\r
+//\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#define BOOST_NO_VARIADIC_MACROS\r
+\r
+//\r
+// versions check:\r
+// we don't support MPW prior to version 8.9:\r
+#if MPW_CPLUS < 0x890\r
+#  error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 0x890:\r
+#if (MPW_CPLUS > 0x890)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/nvcc.hpp b/src/external/boost/boost/config/compiler/nvcc.hpp
new file mode 100644 (file)
index 0000000..3e8d5a9
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright Eric Jourdanneau, Joel Falcou 2010\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  NVIDIA CUDA C++ compiler setup\r
+\r
+#ifndef BOOST_COMPILER\r
+#  define BOOST_COMPILER "NVIDIA CUDA C++ Compiler"\r
+#endif\r
+\r
+// NVIDIA Specific support\r
+// BOOST_GPU_ENABLED : Flag a function or a method as being enabled on the host and device\r
+#define BOOST_GPU_ENABLED __host__ __device__\r
+\r
+// Boost support macro for NVCC \r
+// NVCC Basically behaves like some flavor of MSVC6 + some specific quirks\r
+#ifdef __GNUC__\r
+\r
+#include <boost/config/compiler/gcc.hpp>\r
+\r
+#elif defined(_MSC_VER)\r
+\r
+#include <boost/config/compiler/visualc.hpp>\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/compiler/pathscale.hpp b/src/external/boost/boost/config/compiler/pathscale.hpp
new file mode 100644 (file)
index 0000000..2ab9d2a
--- /dev/null
@@ -0,0 +1,82 @@
+//  (C) Copyright Bryce Lelbach 2011\r
+\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+// PathScale EKOPath C++ Compiler\r
+\r
+#ifndef BOOST_COMPILER\r
+#  define BOOST_COMPILER "PathScale EKOPath C++ Compiler version " __PATHSCALE__\r
+#endif\r
+\r
+#if __PATHCC__ >= 4\r
+#  define BOOST_MSVC6_MEMBER_TEMPLATES\r
+#  define BOOST_HAS_UNISTD_H\r
+#  define BOOST_HAS_STDINT_H\r
+#  define BOOST_HAS_SIGACTION\r
+#  define BOOST_HAS_SCHED_YIELD\r
+#  define BOOST_HAS_THREADS\r
+#  define BOOST_HAS_PTHREADS\r
+#  define BOOST_HAS_PTHREAD_YIELD\r
+#  define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#  define BOOST_HAS_PARTIAL_STD_ALLOCATOR\r
+#  define BOOST_HAS_NRVO\r
+#  define BOOST_HAS_NL_TYPES_H\r
+#  define BOOST_HAS_NANOSLEEP\r
+#  define BOOST_HAS_LONG_LONG\r
+#  define BOOST_HAS_LOG1P\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#  define BOOST_HAS_EXPM1\r
+#  define BOOST_HAS_DIRENT_H\r
+#  define BOOST_HAS_CLOCK_GETTIME\r
+#  define BOOST_NO_VARIADIC_TEMPLATES\r
+#  define BOOST_NO_UNICODE_LITERALS\r
+#  define BOOST_NO_TEMPLATE_ALIASES\r
+#  define BOOST_NO_STD_UNORDERED\r
+#  define BOOST_NO_STATIC_ASSERT\r
+#  define BOOST_NO_SFINAE_EXPR\r
+#  define BOOST_NO_SCOPED_ENUMS\r
+#  define BOOST_NO_RVALUE_REFERENCES\r
+#  define BOOST_NO_RAW_LITERALS\r
+#  define BOOST_NO_NULLPTR\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+#  define BOOST_NO_LAMBDAS\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#  define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#  define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#  define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#  define BOOST_NO_DELETED_FUNCTIONS\r
+#  define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#  define BOOST_NO_DECLTYPE\r
+#  define BOOST_NO_CONSTEXPR\r
+#  define BOOST_NO_CONCEPTS\r
+#  define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#  define BOOST_NO_CHAR32_T\r
+#  define BOOST_NO_CHAR16_T\r
+#  define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#  define BOOST_NO_AUTO_DECLARATIONS\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/compiler/pgi.hpp b/src/external/boost/boost/config/compiler/pgi.hpp
new file mode 100644 (file)
index 0000000..add5a4d
--- /dev/null
@@ -0,0 +1,78 @@
+//  (C) Copyright Noel Belcourt 2007.\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  PGI C++ compiler setup:\r
+\r
+#define BOOST_COMPILER_VERSION __PGIC__##__PGIC_MINOR__\r
+#define BOOST_COMPILER "PGI compiler version " BOOST_STRINGIZE(_COMPILER_VERSION)\r
+\r
+//\r
+// Threading support:\r
+// Turn this on unconditionally here, it will get turned off again later\r
+// if no threading API is detected.\r
+//\r
+\r
+// PGI 10.x doesn't seem to define __PGIC__\r
+\r
+// versions earlier than 10.x do define __PGIC__\r
+#if __PGIC__ >= 10\r
+\r
+// options requested by configure --enable-test\r
+#define BOOST_HAS_PTHREADS\r
+#define BOOST_HAS_NRVO\r
+#define BOOST_HAS_LONG_LONG\r
+\r
+// options --enable-test wants undefined\r
+#undef BOOST_NO_STDC_NAMESPACE\r
+#undef BOOST_NO_EXCEPTION_STD_NAMESPACE\r
+#undef BOOST_DEDUCED_TYPENAME\r
+\r
+#elif __PGIC__ >= 7\r
+\r
+#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL \r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#define BOOST_NO_SWPRINTF\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+\r
+#else\r
+\r
+#  error "Pgi compiler not configured - please reconfigure"\r
+\r
+#endif\r
+//\r
+// C++0x features\r
+//\r
+//   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG\r
+//\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#define BOOST_NO_VARIADIC_MACROS\r
+\r
+//\r
+// version check:\r
+// probably nothing to do here?\r
+\r
diff --git a/src/external/boost/boost/config/compiler/sgi_mipspro.hpp b/src/external/boost/boost/config/compiler/sgi_mipspro.hpp
new file mode 100644 (file)
index 0000000..da028e2
--- /dev/null
@@ -0,0 +1,29 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  SGI C++ compiler setup:\r
+\r
+#define BOOST_COMPILER "SGI Irix compiler version " BOOST_STRINGIZE(_COMPILER_VERSION)\r
+\r
+#include "boost/config/compiler/common_edg.hpp"\r
+\r
+//\r
+// Threading support:\r
+// Turn this on unconditionally here, it will get turned off again later\r
+// if no threading API is detected.\r
+//\r
+#define BOOST_HAS_THREADS\r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+\r
+#undef BOOST_NO_SWPRINTF\r
+#undef BOOST_DEDUCED_TYPENAME\r
+\r
+//\r
+// version check:\r
+// probably nothing to do here?\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/sunpro_cc.hpp b/src/external/boost/boost/config/compiler/sunpro_cc.hpp
new file mode 100644 (file)
index 0000000..2fc8866
--- /dev/null
@@ -0,0 +1,145 @@
+//  (C) Copyright John Maddock 2001. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  (C) Copyright Peter Dimov 2002. \r
+//  (C) Copyright Aleksey Gurtovoy 2002 - 2003. \r
+//  (C) Copyright David Abrahams 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Sun C++ compiler setup:\r
+\r
+#    if __SUNPRO_CC <= 0x500\r
+#      define BOOST_NO_MEMBER_TEMPLATES\r
+#      define BOOST_NO_FUNCTION_TEMPLATE_ORDERING\r
+#    endif\r
+\r
+#    if (__SUNPRO_CC <= 0x520)\r
+       //\r
+       // Sunpro 5.2 and earler:\r
+       //\r
+       // although sunpro 5.2 supports the syntax for\r
+       // inline initialization it often gets the value\r
+       // wrong, especially where the value is computed\r
+       // from other constants (J Maddock 6th May 2001)\r
+#      define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+\r
+       // Although sunpro 5.2 supports the syntax for\r
+       // partial specialization, it often seems to\r
+       // bind to the wrong specialization.  Better\r
+       // to disable it until suppport becomes more stable\r
+       // (J Maddock 6th May 2001).\r
+#      define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+#    endif\r
+\r
+#    if (__SUNPRO_CC <= 0x530) \r
+       // Requesting debug info (-g) with Boost.Python results\r
+       // in an internal compiler error for "static const"\r
+       // initialized in-class.\r
+       //    >> Assertion:   (../links/dbg_cstabs.cc, line 611)\r
+       //         while processing ../test.cpp at line 0.\r
+       // (Jens Maurer according to Gottfried Ganssauge 04 Mar 2002)\r
+#      define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+\r
+       // SunPro 5.3 has better support for partial specialization,\r
+       // but breaks when compiling std::less<shared_ptr<T> >\r
+       // (Jens Maurer 4 Nov 2001).\r
+\r
+       // std::less specialization fixed as reported by George\r
+       // Heintzelman; partial specialization re-enabled\r
+       // (Peter Dimov 17 Jan 2002)\r
+\r
+//#      define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+\r
+       // integral constant expressions with 64 bit numbers fail\r
+#      define BOOST_NO_INTEGRAL_INT64_T\r
+#    endif\r
+\r
+#    if (__SUNPRO_CC < 0x570) \r
+#      define BOOST_NO_TEMPLATE_TEMPLATES\r
+       // see http://lists.boost.org/MailArchives/boost/msg47184.php\r
+       // and http://lists.boost.org/MailArchives/boost/msg47220.php\r
+#      define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+#      define BOOST_NO_SFINAE\r
+#      define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS\r
+#    endif\r
+#    if (__SUNPRO_CC <= 0x580) \r
+#      define BOOST_NO_IS_ABSTRACT\r
+#    endif\r
+\r
+#    if (__SUNPRO_CC <= 0x5100)\r
+       // Sun 5.10 may not correctly value-initialize objects of\r
+       // some user defined types, as was reported in April 2010\r
+       // (CR 6947016), and confirmed by Steve Clamage.\r
+       // (Niels Dekker, LKEB, May 2010).\r
+#      define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#    endif\r
+\r
+//\r
+// Dynamic shared object (DSO) and dynamic-link library (DLL) support\r
+//\r
+#if __SUNPRO_CC > 0x500\r
+#  define BOOST_SYMBOL_EXPORT __global\r
+#  define BOOST_SYMBOL_IMPORT __global\r
+#  define BOOST_SYMBOL_VISIBLE __global\r
+#endif\r
+\r
+\r
+\r
+//\r
+// Issues that effect all known versions:\r
+//\r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+#define BOOST_NO_ADL_BARRIER\r
+\r
+//\r
+// C++0x features\r
+//\r
+#  define BOOST_HAS_LONG_LONG\r
+\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_EXTERN_TEMPLATE\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#define BOOST_NO_VARIADIC_MACROS\r
+\r
+//\r
+// Version\r
+//\r
+\r
+#define BOOST_COMPILER "Sun compiler version " BOOST_STRINGIZE(__SUNPRO_CC)\r
+\r
+//\r
+// versions check:\r
+// we don't support sunpro prior to version 4:\r
+#if __SUNPRO_CC < 0x400\r
+#error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 0x590:\r
+#if (__SUNPRO_CC > 0x590)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
diff --git a/src/external/boost/boost/config/compiler/vacpp.hpp b/src/external/boost/boost/config/compiler/vacpp.hpp
new file mode 100644 (file)
index 0000000..fa9ba20
--- /dev/null
@@ -0,0 +1,118 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Toon Knapen 2001 - 2003. \r
+//  (C) Copyright Lie-Quan Lee 2001. \r
+//  (C) Copyright Markus Schoepflin 2002 - 2003. \r
+//  (C) Copyright Beman Dawes 2002 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Visual Age (IBM) C++ compiler setup:\r
+\r
+#if __IBMCPP__ <= 501\r
+#  define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#  define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS\r
+#endif\r
+\r
+#if (__IBMCPP__ <= 502) \r
+// Actually the compiler supports inclass member initialization but it\r
+// requires a definition for the class member and it doesn't recognize\r
+// it as an integral constant expression when used as a template argument.\r
+#  define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+#  define BOOST_NO_INTEGRAL_INT64_T\r
+#  define BOOST_NO_MEMBER_TEMPLATE_KEYWORD\r
+#endif\r
+\r
+#if (__IBMCPP__ <= 600) || !defined(BOOST_STRICT_CONFIG)\r
+#  define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS\r
+#endif\r
+\r
+#if (__IBMCPP__ <= 1110)\r
+// XL C++ V11.1 and earlier versions may not always value-initialize  \r
+// a temporary object T(), when T is a non-POD aggregate class type. \r
+// Michael Wong (IBM Canada Ltd) has confirmed this issue and gave it \r
+// high priority. -- Niels Dekker (LKEB), May 2010.\r
+#  define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#endif\r
+\r
+//\r
+// On AIX thread support seems to be indicated by _THREAD_SAFE:\r
+//\r
+#ifdef _THREAD_SAFE\r
+#  define BOOST_HAS_THREADS\r
+#endif\r
+\r
+#define BOOST_COMPILER "IBM Visual Age version " BOOST_STRINGIZE(__IBMCPP__)\r
+\r
+//\r
+// versions check:\r
+// we don't support Visual age prior to version 5:\r
+#if __IBMCPP__ < 500\r
+#error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 1110:\r
+#if (__IBMCPP__ > 1110)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  endif\r
+#endif\r
+\r
+// Some versions of the compiler have issues with default arguments on partial specializations\r
+#if __IBMCPP__ <= 1010\r
+#define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See boost\config\suffix.hpp for BOOST_NO_LONG_LONG\r
+//\r
+#if ! __IBMCPP_AUTO_TYPEDEDUCTION\r
+#  define BOOST_NO_AUTO_DECLARATIONS\r
+#  define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#endif\r
+#if ! __IBMCPP_UTF_LITERAL__\r
+#  define BOOST_NO_CHAR16_T\r
+#  define BOOST_NO_CHAR32_T\r
+#endif\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#if ! __IBMCPP_DECLTYPE\r
+#  define BOOST_NO_DECLTYPE\r
+#else\r
+#  define BOOST_HAS_DECLTYPE\r
+#endif\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#if ! __IBMCPP_EXTERN_TEMPLATE\r
+#  define BOOST_NO_EXTERN_TEMPLATE\r
+#endif\r
+#if ! __IBMCPP_VARIADIC_TEMPLATES\r
+// not enabled separately at this time\r
+#  define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#endif\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_NULLPTR\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_SFINAE_EXPR\r
+#if ! __IBMCPP_STATIC_ASSERT\r
+#  define BOOST_NO_STATIC_ASSERT\r
+#endif\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#if ! __IBMCPP_VARIADIC_TEMPLATES\r
+#  define BOOST_NO_VARIADIC_TEMPLATES\r
+#endif\r
+#if ! __C99_MACRO_WITH_VA_ARGS\r
+#  define BOOST_NO_VARIADIC_MACROS\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/compiler/visualc.hpp b/src/external/boost/boost/config/compiler/visualc.hpp
new file mode 100644 (file)
index 0000000..bcdc91b
--- /dev/null
@@ -0,0 +1,277 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Darin Adler 2001 - 2002. \r
+//  (C) Copyright Peter Dimov 2001. \r
+//  (C) Copyright Aleksey Gurtovoy 2002. \r
+//  (C) Copyright David Abrahams 2002 - 2003. \r
+//  (C) Copyright Beman Dawes 2002 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Microsoft Visual C++ compiler setup:\r
+\r
+#define BOOST_MSVC _MSC_VER\r
+\r
+#if _MSC_FULL_VER > 100000000\r
+#  define BOOST_MSVC_FULL_VER _MSC_FULL_VER\r
+#else\r
+#  define BOOST_MSVC_FULL_VER (_MSC_FULL_VER * 10)\r
+#endif\r
+\r
+// turn off the warnings before we #include anything\r
+#pragma warning( disable : 4503 ) // warning: decorated name length exceeded\r
+\r
+#if _MSC_VER < 1300  // 1200 == VC++ 6.0, 1200-1202 == eVC++4\r
+#  pragma warning( disable : 4786 ) // ident trunc to '255' chars in debug info\r
+#  define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS\r
+#  define BOOST_NO_VOID_RETURNS\r
+#  define BOOST_NO_EXCEPTION_STD_NAMESPACE\r
+\r
+#  if BOOST_MSVC == 1202\r
+#    define BOOST_NO_STD_TYPEINFO\r
+#  endif\r
+\r
+   // disable min/max macro defines on vc6:\r
+   //\r
+#endif\r
+\r
+/// Visual Studio has no fenv.h\r
+#define BOOST_NO_FENV_H\r
+\r
+#if (_MSC_VER <= 1300)  // 1300 == VC++ 7.0\r
+\r
+#  if !defined(_MSC_EXTENSIONS) && !defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS)      // VC7 bug with /Za\r
+#    define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS\r
+#  endif\r
+\r
+#  define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+#  define BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+#  define BOOST_NO_PRIVATE_IN_AGGREGATE\r
+#  define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP\r
+#  define BOOST_NO_INTEGRAL_INT64_T\r
+#  define BOOST_NO_DEDUCED_TYPENAME\r
+#  define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE\r
+\r
+//    VC++ 6/7 has member templates but they have numerous problems including\r
+//    cases of silent failure, so for safety we define:\r
+#  define BOOST_NO_MEMBER_TEMPLATES\r
+//    For VC++ experts wishing to attempt workarounds, we define:\r
+#  define BOOST_MSVC6_MEMBER_TEMPLATES\r
+\r
+#  define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#  define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+#  define BOOST_NO_CV_VOID_SPECIALIZATIONS\r
+#  define BOOST_NO_FUNCTION_TEMPLATE_ORDERING\r
+#  define BOOST_NO_USING_TEMPLATE\r
+#  define BOOST_NO_SWPRINTF\r
+#  define BOOST_NO_TEMPLATE_TEMPLATES\r
+#  define BOOST_NO_SFINAE\r
+#  define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS\r
+#  define BOOST_NO_IS_ABSTRACT\r
+#  define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS\r
+// TODO: what version is meant here? Have there really been any fixes in cl 12.01 (as e.g. shipped with eVC4)?\r
+#  if (_MSC_VER > 1200)\r
+#     define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS\r
+#  endif\r
+\r
+#endif\r
+\r
+#if _MSC_VER < 1400 \r
+// although a conforming signature for swprint exists in VC7.1\r
+// it appears not to actually work:\r
+#  define BOOST_NO_SWPRINTF\r
+// Our extern template tests also fail for this compiler:\r
+#  define BOOST_NO_EXTERN_TEMPLATE\r
+// Variadic macros do not exist for VC7.1 and lower\r
+#  define BOOST_NO_VARIADIC_MACROS\r
+#endif\r
+\r
+#if defined(UNDER_CE)\r
+// Windows CE does not have a conforming signature for swprintf\r
+#  define BOOST_NO_SWPRINTF\r
+#endif\r
+\r
+#if _MSC_VER <= 1400  // 1400 == VC++ 8.0\r
+#  define BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+#endif\r
+\r
+#if _MSC_VER == 1500  // 1500 == VC++ 9.0\r
+   // A bug in VC9:\r
+#  define BOOST_NO_ADL_BARRIER\r
+#endif\r
+\r
+\r
+#if (_MSC_VER <= 1600)\r
+// MSVC (including the latest checked version) has not yet completely \r
+// implemented value-initialization, as is reported:\r
+// "VC++ does not value-initialize members of derived classes without \r
+// user-declared constructor", reported in 2009 by Sylvester Hesp:\r
+// https://connect.microsoft.com/VisualStudio/feedback/details/484295\r
+// "Presence of copy constructor breaks member class initialization",\r
+// reported in 2009 by Alex Vakulenko:\r
+// https://connect.microsoft.com/VisualStudio/feedback/details/499606\r
+// "Value-initialization in new-expression", reported in 2005 by\r
+// Pavel Kuznetsov (MetaCommunications Engineering):\r
+// https://connect.microsoft.com/VisualStudio/feedback/details/100744\r
+// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues\r
+// (Niels Dekker, LKEB, May 2010)\r
+#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION\r
+#endif\r
+\r
+#if _MSC_VER <= 1500  || !defined(BOOST_STRICT_CONFIG) // 1500 == VC++ 9.0\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#endif\r
+\r
+#ifndef _NATIVE_WCHAR_T_DEFINED\r
+#  define BOOST_NO_INTRINSIC_WCHAR_T\r
+#endif\r
+\r
+#if defined(_WIN32_WCE) || defined(UNDER_CE)\r
+#  define BOOST_NO_THREADEX\r
+#  define BOOST_NO_GETSYSTEMTIMEASFILETIME\r
+#  define BOOST_NO_SWPRINTF\r
+#endif\r
+\r
+//   \r
+// check for exception handling support:   \r
+#if !defined(_CPPUNWIND) && !defined(BOOST_NO_EXCEPTIONS)\r
+#  define BOOST_NO_EXCEPTIONS   \r
+#endif \r
+\r
+//\r
+// __int64 support:\r
+//\r
+#if (_MSC_VER >= 1200)\r
+#   define BOOST_HAS_MS_INT64\r
+#endif\r
+#if (_MSC_VER >= 1310) && (defined(_MSC_EXTENSIONS) || (_MSC_VER >= 1400))\r
+#   define BOOST_HAS_LONG_LONG\r
+#else\r
+#   define BOOST_NO_LONG_LONG\r
+#endif\r
+#if (_MSC_VER >= 1400) && !defined(_DEBUG)\r
+#   define BOOST_HAS_NRVO\r
+#endif\r
+//\r
+// disable Win32 API's if compiler extentions are\r
+// turned off:\r
+//\r
+#if !defined(_MSC_EXTENSIONS) && !defined(BOOST_DISABLE_WIN32)\r
+#  define BOOST_DISABLE_WIN32\r
+#endif\r
+#if !defined(_CPPRTTI) && !defined(BOOST_NO_RTTI)\r
+#  define BOOST_NO_RTTI\r
+#endif\r
+\r
+//\r
+// C++0x features\r
+//\r
+//   See above for BOOST_NO_LONG_LONG\r
+\r
+// C++ features supported by VC++ 10 (aka 2010)\r
+//\r
+#if _MSC_VER < 1600\r
+#define BOOST_NO_AUTO_DECLARATIONS\r
+#define BOOST_NO_AUTO_MULTIDECLARATIONS\r
+#define BOOST_NO_LAMBDAS\r
+#define BOOST_NO_RVALUE_REFERENCES\r
+#define BOOST_NO_STATIC_ASSERT\r
+#define BOOST_NO_NULLPTR\r
+#endif // _MSC_VER < 1600\r
+\r
+#if _MSC_VER >= 1600\r
+#define BOOST_HAS_STDINT_H\r
+#endif\r
+\r
+// C++0x features not supported by any versions\r
+#define BOOST_NO_CHAR16_T\r
+#define BOOST_NO_CHAR32_T\r
+#define BOOST_NO_CONCEPTS\r
+#define BOOST_NO_CONSTEXPR\r
+#define BOOST_NO_DEFAULTED_FUNCTIONS\r
+#define BOOST_NO_DECLTYPE\r
+#define BOOST_NO_DELETED_FUNCTIONS\r
+#define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS\r
+#define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS\r
+#define BOOST_NO_INITIALIZER_LISTS\r
+#define BOOST_NO_RAW_LITERALS\r
+#define BOOST_NO_SCOPED_ENUMS\r
+#define BOOST_NO_TEMPLATE_ALIASES\r
+#define BOOST_NO_UNICODE_LITERALS\r
+#define BOOST_NO_VARIADIC_TEMPLATES\r
+#define BOOST_NO_SFINAE_EXPR\r
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP\r
+//\r
+// prefix and suffix headers:\r
+//\r
+#ifndef BOOST_ABI_PREFIX\r
+#  define BOOST_ABI_PREFIX "boost/config/abi/msvc_prefix.hpp"\r
+#endif\r
+#ifndef BOOST_ABI_SUFFIX\r
+#  define BOOST_ABI_SUFFIX "boost/config/abi/msvc_suffix.hpp"\r
+#endif\r
+\r
+// TODO:\r
+// these things are mostly bogus. 1200 means version 12.0 of the compiler. The \r
+// artificial versions assigned to them only refer to the versions of some IDE\r
+// these compilers have been shipped with, and even that is not all of it. Some\r
+// were shipped with freely downloadable SDKs, others as crosscompilers in eVC.\r
+// IOW, you can't use these 'versions' in any sensible way. Sorry.\r
+# if defined(UNDER_CE)\r
+#   if _MSC_VER < 1200\r
+      // Note: these are so far off, they are not really supported\r
+#   elif _MSC_VER < 1300 // eVC++ 4 comes with 1200-1202\r
+#     define BOOST_COMPILER_VERSION evc4.0\r
+#   elif _MSC_VER == 1400\r
+#     define BOOST_COMPILER_VERSION evc8\r
+#   elif _MSC_VER == 1500\r
+#     define BOOST_COMPILER_VERSION evc9\r
+#   elif _MSC_VER == 1600\r
+#     define BOOST_COMPILER_VERSION evc10\r
+#   else\r
+#      if defined(BOOST_ASSERT_CONFIG)\r
+#         error "Unknown EVC++ compiler version - please run the configure tests and report the results"\r
+#      else\r
+#         pragma message("Unknown EVC++ compiler version - please run the configure tests and report the results")\r
+#      endif\r
+#   endif\r
+# else\r
+#   if _MSC_VER < 1200\r
+      // Note: these are so far off, they are not really supported\r
+#     define BOOST_COMPILER_VERSION 5.0\r
+#   elif _MSC_VER < 1300\r
+#       define BOOST_COMPILER_VERSION 6.0\r
+#   elif _MSC_VER == 1300\r
+#     define BOOST_COMPILER_VERSION 7.0\r
+#   elif _MSC_VER == 1310\r
+#     define BOOST_COMPILER_VERSION 7.1\r
+#   elif _MSC_VER == 1400\r
+#     define BOOST_COMPILER_VERSION 8.0\r
+#   elif _MSC_VER == 1500\r
+#     define BOOST_COMPILER_VERSION 9.0\r
+#   elif _MSC_VER == 1600\r
+#     define BOOST_COMPILER_VERSION 10.0\r
+#   else\r
+#     define BOOST_COMPILER_VERSION _MSC_VER\r
+#   endif\r
+# endif\r
+\r
+#define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION)\r
+\r
+//\r
+// versions check:\r
+// we don't support Visual C++ prior to version 6:\r
+#if _MSC_VER < 1200\r
+#error "Compiler not supported or configured - please reconfigure"\r
+#endif\r
+//\r
+// last known and checked version is 1600 (VC10, aka 2010):\r
+#if (_MSC_VER > 1600)\r
+#  if defined(BOOST_ASSERT_CONFIG)\r
+#     error "Unknown compiler version - please run the configure tests and report the results"\r
+#  else\r
+#     pragma message("Unknown compiler version - please run the configure tests and report the results")\r
+#  endif\r
+#endif\r
diff --git a/src/external/boost/boost/config/no_tr1/cmath.hpp b/src/external/boost/boost/config/no_tr1/cmath.hpp
new file mode 100644 (file)
index 0000000..19ff526
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2008.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// The aim of this header is just to include <cmath> but to do\r
+// so in a way that does not result in recursive inclusion of\r
+// the Boost TR1 components if boost/tr1/tr1/cmath is in the\r
+// include search path.  We have to do this to avoid circular\r
+// dependencies:\r
+//\r
+\r
+#ifndef BOOST_CONFIG_CMATH\r
+#  define BOOST_CONFIG_CMATH\r
+\r
+#  ifndef BOOST_TR1_NO_RECURSION\r
+#     define BOOST_TR1_NO_RECURSION\r
+#     define BOOST_CONFIG_NO_CMATH_RECURSION\r
+#  endif\r
+\r
+#  include <cmath>\r
+\r
+#  ifdef BOOST_CONFIG_NO_CMATH_RECURSION\r
+#     undef BOOST_TR1_NO_RECURSION\r
+#     undef BOOST_CONFIG_NO_CMATH_RECURSION\r
+#  endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/no_tr1/complex.hpp b/src/external/boost/boost/config/no_tr1/complex.hpp
new file mode 100644 (file)
index 0000000..c6f4254
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2005.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// The aim of this header is just to include <complex> but to do\r
+// so in a way that does not result in recursive inclusion of\r
+// the Boost TR1 components if boost/tr1/tr1/complex is in the\r
+// include search path.  We have to do this to avoid circular\r
+// dependencies:\r
+//\r
+\r
+#ifndef BOOST_CONFIG_COMPLEX\r
+#  define BOOST_CONFIG_COMPLEX\r
+\r
+#  ifndef BOOST_TR1_NO_RECURSION\r
+#     define BOOST_TR1_NO_RECURSION\r
+#     define BOOST_CONFIG_NO_COMPLEX_RECURSION\r
+#  endif\r
+\r
+#  include <complex>\r
+\r
+#  ifdef BOOST_CONFIG_NO_COMPLEX_RECURSION\r
+#     undef BOOST_TR1_NO_RECURSION\r
+#     undef BOOST_CONFIG_NO_COMPLEX_RECURSION\r
+#  endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/no_tr1/functional.hpp b/src/external/boost/boost/config/no_tr1/functional.hpp
new file mode 100644 (file)
index 0000000..08d46fc
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2005.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// The aim of this header is just to include <functional> but to do\r
+// so in a way that does not result in recursive inclusion of\r
+// the Boost TR1 components if boost/tr1/tr1/functional is in the\r
+// include search path.  We have to do this to avoid circular\r
+// dependencies:\r
+//\r
+\r
+#ifndef BOOST_CONFIG_FUNCTIONAL\r
+#  define BOOST_CONFIG_FUNCTIONAL\r
+\r
+#  ifndef BOOST_TR1_NO_RECURSION\r
+#     define BOOST_TR1_NO_RECURSION\r
+#     define BOOST_CONFIG_NO_FUNCTIONAL_RECURSION\r
+#  endif\r
+\r
+#  include <functional>\r
+\r
+#  ifdef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION\r
+#     undef BOOST_TR1_NO_RECURSION\r
+#     undef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION\r
+#  endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/no_tr1/memory.hpp b/src/external/boost/boost/config/no_tr1/memory.hpp
new file mode 100644 (file)
index 0000000..d998a54
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2005.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// The aim of this header is just to include <memory> but to do\r
+// so in a way that does not result in recursive inclusion of\r
+// the Boost TR1 components if boost/tr1/tr1/memory is in the\r
+// include search path.  We have to do this to avoid circular\r
+// dependencies:\r
+//\r
+\r
+#ifndef BOOST_CONFIG_MEMORY\r
+#  define BOOST_CONFIG_MEMORY\r
+\r
+#  ifndef BOOST_TR1_NO_RECURSION\r
+#     define BOOST_TR1_NO_RECURSION\r
+#     define BOOST_CONFIG_NO_MEMORY_RECURSION\r
+#  endif\r
+\r
+#  include <memory>\r
+\r
+#  ifdef BOOST_CONFIG_NO_MEMORY_RECURSION\r
+#     undef BOOST_TR1_NO_RECURSION\r
+#     undef BOOST_CONFIG_NO_MEMORY_RECURSION\r
+#  endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/no_tr1/utility.hpp b/src/external/boost/boost/config/no_tr1/utility.hpp
new file mode 100644 (file)
index 0000000..40f2234
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2005.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// The aim of this header is just to include <utility> but to do\r
+// so in a way that does not result in recursive inclusion of\r
+// the Boost TR1 components if boost/tr1/tr1/utility is in the\r
+// include search path.  We have to do this to avoid circular\r
+// dependencies:\r
+//\r
+\r
+#ifndef BOOST_CONFIG_UTILITY\r
+#  define BOOST_CONFIG_UTILITY\r
+\r
+#  ifndef BOOST_TR1_NO_RECURSION\r
+#     define BOOST_TR1_NO_RECURSION\r
+#     define BOOST_CONFIG_NO_UTILITY_RECURSION\r
+#  endif\r
+\r
+#  include <utility>\r
+\r
+#  ifdef BOOST_CONFIG_NO_UTILITY_RECURSION\r
+#     undef BOOST_TR1_NO_RECURSION\r
+#     undef BOOST_CONFIG_NO_UTILITY_RECURSION\r
+#  endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/platform/aix.hpp b/src/external/boost/boost/config/platform/aix.hpp
new file mode 100644 (file)
index 0000000..36b6ab2
--- /dev/null
@@ -0,0 +1,33 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  IBM/Aix specific config options:\r
+\r
+#define BOOST_PLATFORM "IBM Aix"\r
+\r
+#define BOOST_HAS_UNISTD_H\r
+#define BOOST_HAS_NL_TYPES_H\r
+#define BOOST_HAS_NANOSLEEP\r
+#define BOOST_HAS_CLOCK_GETTIME\r
+\r
+// This needs support in "boost/cstdint.hpp" exactly like FreeBSD.\r
+// This platform has header named <inttypes.h> which includes all\r
+// the things needed.\r
+#define BOOST_HAS_STDINT_H\r
+\r
+// Threading API's:\r
+#define BOOST_HAS_PTHREADS\r
+#define BOOST_HAS_PTHREAD_DELAY_NP\r
+#define BOOST_HAS_SCHED_YIELD\r
+//#define BOOST_HAS_PTHREAD_YIELD\r
+\r
+// boilerplate code:\r
+#include <boost/config/posix_features.hpp>\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/amigaos.hpp b/src/external/boost/boost/config/platform/amigaos.hpp
new file mode 100644 (file)
index 0000000..fe22635
--- /dev/null
@@ -0,0 +1,15 @@
+//  (C) Copyright John Maddock 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+#define BOOST_PLATFORM "AmigaOS"\r
+\r
+#define BOOST_DISABLE_THREADS\r
+#define BOOST_NO_CWCHAR\r
+#define BOOST_NO_STD_WSTRING\r
+#define BOOST_NO_INTRINSIC_WCHAR_T\r
\r
+\r
diff --git a/src/external/boost/boost/config/platform/beos.hpp b/src/external/boost/boost/config/platform/beos.hpp
new file mode 100644 (file)
index 0000000..507ef82
--- /dev/null
@@ -0,0 +1,26 @@
+//  (C) Copyright John Maddock 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  BeOS specific config options:\r
+\r
+#define BOOST_PLATFORM "BeOS"\r
+\r
+#define BOOST_NO_CWCHAR\r
+#define BOOST_NO_CWCTYPE\r
+#define BOOST_HAS_UNISTD_H\r
+\r
+#define BOOST_HAS_BETHREADS\r
+\r
+#ifndef BOOST_DISABLE_THREADS\r
+#  define BOOST_HAS_THREADS\r
+#endif\r
+\r
+// boilerplate code:\r
+#include <boost/config/posix_features.hpp>\r
\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/bsd.hpp b/src/external/boost/boost/config/platform/bsd.hpp
new file mode 100644 (file)
index 0000000..9d86e94
--- /dev/null
@@ -0,0 +1,86 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Darin Adler 2001. \r
+//  (C) Copyright Douglas Gregor 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  generic BSD config options:\r
+\r
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)\r
+#error "This platform is not BSD"\r
+#endif\r
+\r
+#ifdef __FreeBSD__\r
+#define BOOST_PLATFORM "FreeBSD " BOOST_STRINGIZE(__FreeBSD__)\r
+#elif defined(__NetBSD__)\r
+#define BOOST_PLATFORM "NetBSD " BOOST_STRINGIZE(__NetBSD__)\r
+#elif defined(__OpenBSD__)\r
+#define BOOST_PLATFORM "OpenBSD " BOOST_STRINGIZE(__OpenBSD__)\r
+#elif defined(__DragonFly__)\r
+#define BOOST_PLATFORM "DragonFly " BOOST_STRINGIZE(__DragonFly__)\r
+#endif\r
+\r
+//\r
+// is this the correct version check?\r
+// FreeBSD has <nl_types.h> but does not\r
+// advertise the fact in <unistd.h>:\r
+//\r
+#if (defined(__FreeBSD__) && (__FreeBSD__ >= 3)) || defined(__DragonFly__)\r
+#  define BOOST_HAS_NL_TYPES_H\r
+#endif\r
+\r
+//\r
+// FreeBSD 3.x has pthreads support, but defines _POSIX_THREADS in <pthread.h>\r
+// and not in <unistd.h>\r
+//\r
+#if (defined(__FreeBSD__) && (__FreeBSD__ <= 3))\\r
+   || defined(__OpenBSD__) || defined(__DragonFly__) \r
+#  define BOOST_HAS_PTHREADS\r
+#endif\r
+\r
+//\r
+// No wide character support in the BSD header files:\r
+//\r
+#if defined(__NetBSD__)\r
+#define __NetBSD_GCC__ (__GNUC__         * 1000000 \\r
+                       + __GNUC_MINOR__ *    1000 \\r
+                       + __GNUC_PATCHLEVEL__)\r
+// XXX - the following is required until c++config.h\r
+//       defines _GLIBCXX_HAVE_SWPRINTF and friends\r
+//       or the preprocessor conditionals are removed\r
+//       from the cwchar header.\r
+#define _GLIBCXX_HAVE_SWPRINTF 1\r
+#endif\r
+\r
+#if !((defined(__FreeBSD__) && (__FreeBSD__ >= 5)) \\r
+      || (defined(__NetBSD_GCC__) && (__NetBSD_GCC__ >= 2095003)) || defined(__DragonFly__))\r
+#  define BOOST_NO_CWCHAR\r
+#endif\r
+//\r
+// The BSD <ctype.h> has macros only, no functions:\r
+//\r
+#if !defined(__OpenBSD__) || defined(__DragonFly__)\r
+#  define BOOST_NO_CTYPE_FUNCTIONS\r
+#endif\r
+\r
+//\r
+// thread API's not auto detected:\r
+//\r
+#define BOOST_HAS_SCHED_YIELD\r
+#define BOOST_HAS_NANOSLEEP\r
+#define BOOST_HAS_GETTIMEOFDAY\r
+#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#define BOOST_HAS_SIGACTION\r
+\r
+// boilerplate code:\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/cygwin.hpp b/src/external/boost/boost/config/platform/cygwin.hpp
new file mode 100644 (file)
index 0000000..c46f2e5
--- /dev/null
@@ -0,0 +1,58 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  cygwin specific config options:\r
+\r
+#define BOOST_PLATFORM "Cygwin"\r
+#define BOOST_HAS_DIRENT_H\r
+#define BOOST_HAS_LOG1P\r
+#define BOOST_HAS_EXPM1\r
+\r
+//\r
+// Threading API:\r
+// See if we have POSIX threads, if we do use them, otherwise\r
+// revert to native Win threads.\r
+#define BOOST_HAS_UNISTD_H\r
+#include <unistd.h>\r
+#if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS)\r
+#  define BOOST_HAS_PTHREADS\r
+#  define BOOST_HAS_SCHED_YIELD\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#  define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#  define BOOST_HAS_SIGACTION\r
+#else\r
+#  if !defined(BOOST_HAS_WINTHREADS)\r
+#     define BOOST_HAS_WINTHREADS\r
+#  endif\r
+#  define BOOST_HAS_FTIME\r
+#endif\r
+\r
+//\r
+// find out if we have a stdint.h, there should be a better way to do this:\r
+//\r
+#include <sys/types.h>\r
+#ifdef _STDINT_H\r
+#define BOOST_HAS_STDINT_H\r
+#endif\r
+\r
+/// Cygwin has no fenv.h\r
+#define BOOST_NO_FENV_H\r
+\r
+// boilerplate code:\r
+#include <boost/config/posix_features.hpp>\r
+\r
+//\r
+// Cygwin lies about XSI conformance, there is no nl_types.h:\r
+//\r
+#ifdef BOOST_HAS_NL_TYPES_H\r
+#  undef BOOST_HAS_NL_TYPES_H\r
+#endif\r
\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/hpux.hpp b/src/external/boost/boost/config/platform/hpux.hpp
new file mode 100644 (file)
index 0000000..8e79892
--- /dev/null
@@ -0,0 +1,87 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  (C) Copyright David Abrahams 2002. \r
+//  (C) Copyright Toon Knapen 2003. \r
+//  (C) Copyright Boris Gubenko 2006 - 2007.\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  hpux specific config options:\r
+\r
+#define BOOST_PLATFORM "HP-UX"\r
+\r
+// In principle, HP-UX has a nice <stdint.h> under the name <inttypes.h>\r
+// However, it has the following problem:\r
+// Use of UINT32_C(0) results in "0u l" for the preprocessed source\r
+// (verifyable with gcc 2.95.3)\r
+#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__HP_aCC)\r
+#  define BOOST_HAS_STDINT_H\r
+#endif\r
+\r
+#if !(defined(__HP_aCC) || !defined(_INCLUDE__STDC_A1_SOURCE))\r
+#  define BOOST_NO_SWPRINTF\r
+#endif\r
+#if defined(__HP_aCC) && !defined(_INCLUDE__STDC_A1_SOURCE)\r
+#  define BOOST_NO_CWCTYPE\r
+#endif\r
+\r
+#if defined(__GNUC__)\r
+#  if (__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3))\r
+      // GNU C on HP-UX does not support threads (checked up to gcc 3.3)\r
+#     define BOOST_DISABLE_THREADS\r
+#  elif !defined(BOOST_DISABLE_THREADS)\r
+      // threads supported from gcc-3.3 onwards:\r
+#     define BOOST_HAS_THREADS\r
+#     define BOOST_HAS_PTHREADS\r
+#  endif\r
+#elif defined(__HP_aCC) && !defined(BOOST_DISABLE_THREADS)\r
+#  define BOOST_HAS_PTHREADS\r
+#endif\r
+\r
+// boilerplate code:\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+// the following are always available:\r
+#ifndef BOOST_HAS_GETTIMEOFDAY\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#endif\r
+#ifndef BOOST_HAS_SCHED_YIELD\r
+#    define BOOST_HAS_SCHED_YIELD\r
+#endif\r
+#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#    define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#endif\r
+#ifndef BOOST_HAS_NL_TYPES_H\r
+#    define BOOST_HAS_NL_TYPES_H\r
+#endif\r
+#ifndef BOOST_HAS_NANOSLEEP\r
+#    define BOOST_HAS_NANOSLEEP\r
+#endif\r
+#ifndef BOOST_HAS_GETTIMEOFDAY\r
+#    define BOOST_HAS_GETTIMEOFDAY\r
+#endif\r
+#ifndef BOOST_HAS_DIRENT_H\r
+#    define BOOST_HAS_DIRENT_H\r
+#endif\r
+#ifndef BOOST_HAS_CLOCK_GETTIME\r
+#    define BOOST_HAS_CLOCK_GETTIME\r
+#endif\r
+#ifndef BOOST_HAS_SIGACTION\r
+#  define BOOST_HAS_SIGACTION\r
+#endif\r
+#ifndef BOOST_HAS_NRVO \r
+#  ifndef __parisc\r
+#    define BOOST_HAS_NRVO\r
+#  endif\r
+#endif\r
+#ifndef BOOST_HAS_LOG1P \r
+#  define BOOST_HAS_LOG1P\r
+#endif\r
+#ifndef BOOST_HAS_EXPM1\r
+#  define BOOST_HAS_EXPM1\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/platform/irix.hpp b/src/external/boost/boost/config/platform/irix.hpp
new file mode 100644 (file)
index 0000000..e0691a4
--- /dev/null
@@ -0,0 +1,31 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  SGI Irix specific config options:\r
+\r
+#define BOOST_PLATFORM "SGI Irix"\r
+\r
+#define BOOST_NO_SWPRINTF \r
+//\r
+// these are not auto detected by POSIX feature tests:\r
+//\r
+#define BOOST_HAS_GETTIMEOFDAY\r
+#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+\r
+#ifdef __GNUC__\r
+   // GNU C on IRIX does not support threads (checked up to gcc 3.3)\r
+#  define BOOST_DISABLE_THREADS\r
+#endif\r
+\r
+// boilerplate code:\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/linux.hpp b/src/external/boost/boost/config/platform/linux.hpp
new file mode 100644 (file)
index 0000000..b87db79
--- /dev/null
@@ -0,0 +1,98 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  linux specific config options:\r
+\r
+#define BOOST_PLATFORM "linux"\r
+\r
+// make sure we have __GLIBC_PREREQ if available at all\r
+#include <cstdlib>\r
+\r
+//\r
+// <stdint.h> added to glibc 2.1.1\r
+// We can only test for 2.1 though:\r
+//\r
+#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)))\r
+   // <stdint.h> defines int64_t unconditionally, but <sys/types.h> defines\r
+   // int64_t only if __GNUC__.  Thus, assume a fully usable <stdint.h>\r
+   // only when using GCC.\r
+#  if defined __GNUC__\r
+#    define BOOST_HAS_STDINT_H\r
+#  endif\r
+#endif\r
+\r
+#if defined(__LIBCOMO__)\r
+   //\r
+   // como on linux doesn't have std:: c functions:\r
+   // NOTE: versions of libcomo prior to beta28 have octal version numbering,\r
+   // e.g. version 25 is 21 (dec)\r
+   //\r
+#  if __LIBCOMO_VERSION__ <= 20\r
+#    define BOOST_NO_STDC_NAMESPACE\r
+#  endif\r
+\r
+#  if __LIBCOMO_VERSION__ <= 21\r
+#    define BOOST_NO_SWPRINTF\r
+#  endif\r
+\r
+#endif\r
+\r
+//\r
+// If glibc is past version 2 then we definitely have\r
+// gettimeofday, earlier versions may or may not have it:\r
+//\r
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#endif\r
+\r
+#ifdef __USE_POSIX199309\r
+#  define BOOST_HAS_NANOSLEEP\r
+#endif\r
+\r
+#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)\r
+// __GLIBC_PREREQ is available since 2.1.2\r
+\r
+   // swprintf is available since glibc 2.2.0\r
+#  if !__GLIBC_PREREQ(2,2) || (!defined(__USE_ISOC99) && !defined(__USE_UNIX98))\r
+#    define BOOST_NO_SWPRINTF\r
+#  endif\r
+#else\r
+#  define BOOST_NO_SWPRINTF\r
+#endif\r
+\r
+// boilerplate code:\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+#ifndef __GNUC__\r
+//\r
+// if the compiler is not gcc we still need to be able to parse\r
+// the GNU system headers, some of which (mainly <stdint.h>)\r
+// use GNU specific extensions:\r
+//\r
+#  ifndef __extension__\r
+#     define __extension__\r
+#  endif\r
+#  ifndef __const__\r
+#     define __const__ const\r
+#  endif\r
+#  ifndef __volatile__\r
+#     define __volatile__ volatile\r
+#  endif\r
+#  ifndef __signed__\r
+#     define __signed__ signed\r
+#  endif\r
+#  ifndef __typeof__\r
+#     define __typeof__ typeof\r
+#  endif\r
+#  ifndef __inline__\r
+#     define __inline__ inline\r
+#  endif\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/macos.hpp b/src/external/boost/boost/config/platform/macos.hpp
new file mode 100644 (file)
index 0000000..f21d6fc
--- /dev/null
@@ -0,0 +1,86 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Darin Adler 2001 - 2002. \r
+//  (C) Copyright Bill Kempf 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Mac OS specific config options:\r
+\r
+#define BOOST_PLATFORM "Mac OS"\r
+\r
+#if __MACH__ && !defined(_MSL_USING_MSL_C)\r
+\r
+// Using the Mac OS X system BSD-style C library.\r
+\r
+#  ifndef BOOST_HAS_UNISTD_H\r
+#    define BOOST_HAS_UNISTD_H\r
+#  endif\r
+//\r
+// Begin by including our boilerplate code for POSIX\r
+// feature detection, this is safe even when using\r
+// the MSL as Metrowerks supply their own <unistd.h>\r
+// to replace the platform-native BSD one. G++ users\r
+// should also always be able to do this on MaxOS X.\r
+//\r
+#  include <boost/config/posix_features.hpp>\r
+#  ifndef BOOST_HAS_STDINT_H\r
+#     define BOOST_HAS_STDINT_H\r
+#  endif\r
+\r
+//\r
+// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday,\r
+// of these only pthreads are advertised in <unistd.h>, so set the \r
+// other options explicitly:\r
+//\r
+#  define BOOST_HAS_SCHED_YIELD\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#  define BOOST_HAS_SIGACTION\r
+\r
+#  if (__GNUC__ < 3) && !defined( __APPLE_CC__)\r
+\r
+// GCC strange "ignore std" mode works better if you pretend everything\r
+// is in the std namespace, for the most part.\r
+\r
+#    define BOOST_NO_STDC_NAMESPACE\r
+#  endif\r
+\r
+#  if (__GNUC__ == 4)\r
+\r
+// Both gcc and intel require these.  \r
+#    define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#    define BOOST_HAS_NANOSLEEP\r
+\r
+#  endif\r
+\r
+#else\r
+\r
+// Using the MSL C library.\r
+\r
+// We will eventually support threads in non-Carbon builds, but we do\r
+// not support this yet.\r
+#  if ( defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON ) || ( defined(TARGET_CARBON) && TARGET_CARBON )\r
+\r
+#  if !defined(BOOST_HAS_PTHREADS)\r
+#    define BOOST_HAS_MPTASKS\r
+#  elif ( __dest_os == __mac_os_x )\r
+// We are doing a Carbon/Mach-O/MSL build which has pthreads, but only the\r
+// gettimeofday and no posix.\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#  endif\r
+\r
+// The MP task implementation of Boost Threads aims to replace MP-unsafe\r
+// parts of the MSL, so we turn on threads unconditionally.\r
+#    define BOOST_HAS_THREADS\r
+\r
+// The remote call manager depends on this.\r
+#    define BOOST_BIND_ENABLE_PASCAL\r
+\r
+#  endif\r
+\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/qnxnto.hpp b/src/external/boost/boost/config/platform/qnxnto.hpp
new file mode 100644 (file)
index 0000000..102f27c
--- /dev/null
@@ -0,0 +1,31 @@
+//  (C) Copyright Jim Douglas 2005. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  QNX specific config options:\r
+\r
+#define BOOST_PLATFORM "QNX"\r
+\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+// QNX claims XOpen version 5 compatibility, but doesn't have an nl_types.h\r
+// or log1p and expm1:\r
+#undef  BOOST_HAS_NL_TYPES_H\r
+#undef  BOOST_HAS_LOG1P\r
+#undef  BOOST_HAS_EXPM1\r
+\r
+#define BOOST_HAS_PTHREADS\r
+#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+\r
+#define BOOST_HAS_GETTIMEOFDAY\r
+#define BOOST_HAS_CLOCK_GETTIME\r
+#define BOOST_HAS_NANOSLEEP\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/solaris.hpp b/src/external/boost/boost/config/platform/solaris.hpp
new file mode 100644 (file)
index 0000000..af776bd
--- /dev/null
@@ -0,0 +1,28 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  sun specific config options:\r
+\r
+#define BOOST_PLATFORM "Sun Solaris"\r
+\r
+#define BOOST_HAS_GETTIMEOFDAY\r
+\r
+// boilerplate code:\r
+#define BOOST_HAS_UNISTD_H\r
+#include <boost/config/posix_features.hpp>\r
+\r
+//\r
+// pthreads don't actually work with gcc unless _PTHREADS is defined:\r
+//\r
+#if defined(__GNUC__) && defined(_POSIX_THREADS) && !defined(_PTHREADS)\r
+# undef BOOST_HAS_PTHREADS\r
+#endif\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/symbian.hpp b/src/external/boost/boost/config/platform/symbian.hpp
new file mode 100644 (file)
index 0000000..654f794
--- /dev/null
@@ -0,0 +1,94 @@
+//  (C) Copyright Yuriy Krasnoschek 2009. \r
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  symbian specific config options:\r
+\r
+\r
+#define BOOST_PLATFORM "Symbian"\r
+#define BOOST_SYMBIAN 1\r
+\r
+\r
+#if defined(__S60_3X__)\r
+// Open C / C++ plugin was introdused in this SDK, earlier versions don't have CRT / STL\r
+#  define BOOST_S60_3rd_EDITION_FP2_OR_LATER_SDK\r
+// make sure we have __GLIBC_PREREQ if available at all\r
+#  include <cstdlib>\r
+// boilerplate code:\r
+#  define BOOST_HAS_UNISTD_H\r
+#  include <boost/config/posix_features.hpp>\r
+// S60 SDK defines _POSIX_VERSION as POSIX.1\r
+#  ifndef BOOST_HAS_STDINT_H\r
+#    define BOOST_HAS_STDINT_H\r
+#  endif\r
+#  ifndef BOOST_HAS_GETTIMEOFDAY\r
+#    define BOOST_HAS_GETTIMEOFDAY\r
+#  endif\r
+#  ifndef BOOST_HAS_DIRENT_H\r
+#    define BOOST_HAS_DIRENT_H\r
+#  endif\r
+#  ifndef BOOST_HAS_SIGACTION\r
+#    define BOOST_HAS_SIGACTION\r
+#  endif\r
+#  ifndef BOOST_HAS_PTHREADS\r
+#    define BOOST_HAS_PTHREADS\r
+#  endif\r
+#  ifndef BOOST_HAS_NANOSLEEP\r
+#    define BOOST_HAS_NANOSLEEP\r
+#  endif\r
+#  ifndef BOOST_HAS_SCHED_YIELD\r
+#    define BOOST_HAS_SCHED_YIELD\r
+#  endif\r
+#  ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#    define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#  endif\r
+#  ifndef BOOST_HAS_LOG1P\r
+#    define BOOST_HAS_LOG1P\r
+#  endif\r
+#  ifndef BOOST_HAS_EXPM1\r
+#    define BOOST_HAS_EXPM1\r
+#  endif\r
+#  ifndef BOOST_POSIX_API\r
+#    define BOOST_POSIX_API\r
+#  endif\r
+// endianess support\r
+#  include <sys/endian.h>\r
+// Symbian SDK provides _BYTE_ORDER instead of __BYTE_ORDER\r
+#  ifndef __LITTLE_ENDIAN\r
+#    ifdef _LITTLE_ENDIAN\r
+#      define __LITTLE_ENDIAN _LITTLE_ENDIAN\r
+#    else\r
+#      define __LITTLE_ENDIAN 1234\r
+#    endif\r
+#  endif\r
+#  ifndef __BIG_ENDIAN\r
+#    ifdef _BIG_ENDIAN\r
+#      define __BIG_ENDIAN _BIG_ENDIAN\r
+#    else\r
+#      define __BIG_ENDIAN 4321\r
+#    endif\r
+#  endif\r
+#  ifndef __BYTE_ORDER\r
+#    define __BYTE_ORDER __LITTLE_ENDIAN // Symbian is LE\r
+#  endif\r
+// Known limitations\r
+#  define BOOST_ASIO_DISABLE_SERIAL_PORT\r
+#  define BOOST_DATE_TIME_NO_LOCALE\r
+#  define BOOST_NO_STD_WSTRING\r
+#  define BOOST_EXCEPTION_DISABLE\r
+#  define BOOST_NO_EXCEPTIONS\r
+\r
+#else // TODO: More platform support e.g. UIQ\r
+#  error "Unsuppoted Symbian SDK"\r
+#endif\r
+\r
+#if defined(__WINSCW__) && !defined(BOOST_DISABLE_WIN32)\r
+#  define BOOST_DISABLE_WIN32 // winscw defines WIN32 macro\r
+#endif\r
+\r
+\r
diff --git a/src/external/boost/boost/config/platform/vms.hpp b/src/external/boost/boost/config/platform/vms.hpp
new file mode 100644 (file)
index 0000000..3d51029
--- /dev/null
@@ -0,0 +1,25 @@
+//  (C) Copyright Artyom Beilis 2010.  \r
+//  Use, modification and distribution are subject to the  \r
+//  Boost Software License, Version 1.0. (See accompanying file  \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
+\r
+#ifndef BOOST_CONFIG_PLATFORM_VMS_HPP \r
+#define BOOST_CONFIG_PLATFORM_VMS_HPP \r
+\r
+#define BOOST_PLATFORM "OpenVMS" \r
+\r
+#undef  BOOST_HAS_STDINT_H \r
+#define BOOST_HAS_UNISTD_H \r
+#define BOOST_HAS_NL_TYPES_H \r
+#define BOOST_HAS_GETTIMEOFDAY \r
+#define BOOST_HAS_DIRENT_H \r
+#define BOOST_HAS_PTHREADS \r
+#define BOOST_HAS_NANOSLEEP \r
+#define BOOST_HAS_CLOCK_GETTIME \r
+#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \r
+#define BOOST_HAS_LOG1P \r
+#define BOOST_HAS_EXPM1 \r
+#define BOOST_HAS_THREADS \r
+#undef  BOOST_HAS_SCHED_YIELD \r
+\r
+#endif \r
diff --git a/src/external/boost/boost/config/platform/vxworks.hpp b/src/external/boost/boost/config/platform/vxworks.hpp
new file mode 100644 (file)
index 0000000..75b14ca
--- /dev/null
@@ -0,0 +1,31 @@
+//  (C) Copyright Dustin Spicuzza 2009. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  vxWorks specific config options:\r
+\r
+#define BOOST_PLATFORM "vxWorks"\r
+\r
+#define BOOST_NO_CWCHAR\r
+#define BOOST_NO_INTRINSIC_WCHAR_T\r
+\r
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)\r
+#define BOOST_NO_INT64_T\r
+#endif\r
+\r
+#define BOOST_HAS_UNISTD_H\r
+\r
+// these allow posix_features to work, since vxWorks doesn't\r
+// define them itself\r
+#define _POSIX_TIMERS 1\r
+#define _POSIX_THREADS 1\r
+\r
+// vxworks doesn't work with asio serial ports\r
+#define BOOST_ASIO_DISABLE_SERIAL_PORT\r
+\r
+// boilerplate code:\r
+#include <boost/config/posix_features.hpp>\r
\r
diff --git a/src/external/boost/boost/config/platform/win32.hpp b/src/external/boost/boost/config/platform/win32.hpp
new file mode 100644 (file)
index 0000000..93d1100
--- /dev/null
@@ -0,0 +1,69 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Bill Kempf 2001. \r
+//  (C) Copyright Aleksey Gurtovoy 2003. \r
+//  (C) Copyright Rene Rivera 2005.\r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Win32 specific config options:\r
+\r
+#define BOOST_PLATFORM "Win32"\r
+\r
+//  Get the information about the MinGW runtime, i.e. __MINGW32_*VERSION.\r
+#if defined(__MINGW32__)\r
+#  include <_mingw.h>\r
+#endif\r
+\r
+#if defined(__GNUC__) && !defined(BOOST_NO_SWPRINTF)\r
+#  define BOOST_NO_SWPRINTF\r
+#endif\r
+\r
+//  Default defines for BOOST_SYMBOL_EXPORT and BOOST_SYMBOL_IMPORT\r
+//  If a compiler doesn't support __declspec(dllexport)/__declspec(dllimport),\r
+//  its boost/config/compiler/ file must define BOOST_SYMBOL_EXPORT and\r
+//  BOOST_SYMBOL_IMPORT\r
+#ifndef BOOST_SYMBOL_EXPORT\r
+#  define BOOST_HAS_DECLSPEC\r
+#  define BOOST_SYMBOL_EXPORT __declspec(dllexport)\r
+#  define BOOST_SYMBOL_IMPORT __declspec(dllimport)\r
+#endif\r
+\r
+#if defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 2) || ((__MINGW32_MAJOR_VERSION == 2) && (__MINGW32_MINOR_VERSION >= 0)))\r
+#  define BOOST_HAS_STDINT_H\r
+#  define __STDC_LIMIT_MACROS\r
+#  define BOOST_HAS_DIRENT_H\r
+#  define BOOST_HAS_UNISTD_H\r
+#endif\r
+\r
+#if defined(__MINGW32__) && (__GNUC__ >= 4)\r
+#  define BOOST_HAS_EXPM1\r
+#  define BOOST_HAS_LOG1P\r
+#  define BOOST_HAS_GETTIMEOFDAY\r
+#endif\r
+//\r
+// Win32 will normally be using native Win32 threads,\r
+// but there is a pthread library avaliable as an option,\r
+// we used to disable this when BOOST_DISABLE_WIN32 was \r
+// defined but no longer - this should allow some\r
+// files to be compiled in strict mode - while maintaining\r
+// a consistent setting of BOOST_HAS_THREADS across\r
+// all translation units (needed for shared_ptr etc).\r
+//\r
+\r
+#ifdef _WIN32_WCE\r
+#  define BOOST_NO_ANSI_APIS\r
+#endif\r
+\r
+#ifndef BOOST_HAS_PTHREADS\r
+#  define BOOST_HAS_WINTHREADS\r
+#endif\r
+\r
+#ifndef BOOST_DISABLE_WIN32\r
+// WEK: Added\r
+#define BOOST_HAS_FTIME\r
+#define BOOST_WINDOWS 1\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/posix_features.hpp b/src/external/boost/boost/config/posix_features.hpp
new file mode 100644 (file)
index 0000000..bc3921c
--- /dev/null
@@ -0,0 +1,95 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+// All POSIX feature tests go in this file,\r
+// Note that we test _POSIX_C_SOURCE and _XOPEN_SOURCE as well\r
+// _POSIX_VERSION and _XOPEN_VERSION: on some systems POSIX API's\r
+// may be present but none-functional unless _POSIX_C_SOURCE and\r
+// _XOPEN_SOURCE have been defined to the right value (it's up\r
+// to the user to do this *before* including any header, although\r
+// in most cases the compiler will do this for you).\r
+\r
+#  if defined(BOOST_HAS_UNISTD_H)\r
+#     include <unistd.h>\r
+\r
+      // XOpen has <nl_types.h>, but is this the correct version check?\r
+#     if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 3)\r
+#        define BOOST_HAS_NL_TYPES_H\r
+#     endif\r
+\r
+      // POSIX version 6 requires <stdint.h>\r
+#     if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200100)\r
+#        define BOOST_HAS_STDINT_H\r
+#     endif\r
+\r
+      // POSIX version 2 requires <dirent.h>\r
+#     if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199009L)\r
+#        define BOOST_HAS_DIRENT_H\r
+#     endif\r
+\r
+      // POSIX version 3 requires <signal.h> to have sigaction:\r
+#     if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L)\r
+#        define BOOST_HAS_SIGACTION\r
+#     endif\r
+      // POSIX defines _POSIX_THREADS > 0 for pthread support,\r
+      // however some platforms define _POSIX_THREADS without\r
+      // a value, hence the (_POSIX_THREADS+0 >= 0) check.\r
+      // Strictly speaking this may catch platforms with a\r
+      // non-functioning stub <pthreads.h>, but such occurrences should\r
+      // occur very rarely if at all.\r
+#     if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_MPTASKS)\r
+#        define BOOST_HAS_PTHREADS\r
+#     endif\r
+\r
+      // BOOST_HAS_NANOSLEEP:\r
+      // This is predicated on _POSIX_TIMERS or _XOPEN_REALTIME:\r
+#     if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) \\r
+             || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0))\r
+#        define BOOST_HAS_NANOSLEEP\r
+#     endif\r
+\r
+      // BOOST_HAS_CLOCK_GETTIME:\r
+      // This is predicated on _POSIX_TIMERS (also on _XOPEN_REALTIME\r
+      // but at least one platform - linux - defines that flag without\r
+      // defining clock_gettime):\r
+#     if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0))\r
+#        define BOOST_HAS_CLOCK_GETTIME\r
+#     endif\r
+\r
+      // BOOST_HAS_SCHED_YIELD:\r
+      // This is predicated on _POSIX_PRIORITY_SCHEDULING or\r
+      // on _POSIX_THREAD_PRIORITY_SCHEDULING or on _XOPEN_REALTIME.\r
+#     if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING+0 > 0)\\r
+            || (defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING+0 > 0))\\r
+            || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0))\r
+#        define BOOST_HAS_SCHED_YIELD\r
+#     endif\r
+\r
+      // BOOST_HAS_GETTIMEOFDAY:\r
+      // BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE:\r
+      // These are predicated on _XOPEN_VERSION, and appears to be first released\r
+      // in issue 4, version 2 (_XOPEN_VERSION > 500).\r
+      // Likewise for the functions log1p and expm1.\r
+#     if defined(_XOPEN_VERSION) && (_XOPEN_VERSION+0 >= 500)\r
+#        define BOOST_HAS_GETTIMEOFDAY\r
+#        if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE+0 >= 500)\r
+#           define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#        endif\r
+#        ifndef BOOST_HAS_LOG1P\r
+#           define BOOST_HAS_LOG1P\r
+#        endif\r
+#        ifndef BOOST_HAS_EXPM1\r
+#           define BOOST_HAS_EXPM1\r
+#        endif\r
+#     endif\r
+\r
+#  endif\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/requires_threads.hpp b/src/external/boost/boost/config/requires_threads.hpp
new file mode 100644 (file)
index 0000000..b79723b
--- /dev/null
@@ -0,0 +1,92 @@
+//  (C) Copyright John Maddock 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_CONFIG_REQUIRES_THREADS_HPP\r
+#define BOOST_CONFIG_REQUIRES_THREADS_HPP\r
+\r
+#ifndef BOOST_CONFIG_HPP\r
+#  include <boost/config.hpp>\r
+#endif\r
+\r
+#if defined(BOOST_DISABLE_THREADS)\r
+\r
+//\r
+// special case to handle versions of gcc which don't currently support threads:\r
+//\r
+#if defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC_MINOR__ <= 3) || !defined(BOOST_STRICT_CONFIG))\r
+//\r
+// this is checked up to gcc 3.3:\r
+//\r
+#if defined(__sgi) || defined(__hpux)\r
+#  error "Multi-threaded programs are not supported by gcc on HPUX or Irix (last checked with gcc 3.3)"\r
+#endif\r
+\r
+#endif\r
+\r
+#  error "Threading support unavaliable: it has been explicitly disabled with BOOST_DISABLE_THREADS"\r
+\r
+#elif !defined(BOOST_HAS_THREADS)\r
+\r
+# if defined __COMO__\r
+//  Comeau C++\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_MT (Windows) or -D_REENTRANT (Unix)"\r
+\r
+#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)\r
+//  Intel\r
+#ifdef _WIN32\r
+#  error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd"\r
+#else\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -openmp"\r
+#endif\r
+\r
+# elif defined __GNUC__\r
+//  GNU C++:\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"\r
+\r
+#elif defined __sgi\r
+//  SGI MIPSpro C++\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_SGI_MP_SOURCE"\r
+\r
+#elif defined __DECCXX\r
+//  Compaq Tru64 Unix cxx\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread"\r
+\r
+#elif defined __BORLANDC__\r
+//  Borland\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -tWM"\r
+\r
+#elif defined  __MWERKS__\r
+//  Metrowerks CodeWarrior\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: either -runtime sm, -runtime smd, -runtime dm, or -runtime dmd"\r
+\r
+#elif defined  __SUNPRO_CC\r
+//  Sun Workshop Compiler C++\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt"\r
+\r
+#elif defined __HP_aCC\r
+//  HP aCC\r
+#   error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt"\r
+\r
+#elif defined(__IBMCPP__)\r
+//  IBM Visual Age\r
+#   error "Compiler threading support is not turned on. Please compile the code with the xlC_r compiler"\r
+\r
+#elif defined _MSC_VER\r
+//  Microsoft Visual C++\r
+//\r
+//  Must remain the last #elif since some other vendors (Metrowerks, for\r
+//  example) also #define _MSC_VER\r
+#  error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd"\r
+\r
+#else\r
+\r
+#  error "Compiler threading support is not turned on.  Please consult your compiler's documentation for the appropriate options to use"\r
+\r
+#endif // compilers\r
+\r
+#endif // BOOST_HAS_THREADS\r
+\r
+#endif // BOOST_CONFIG_REQUIRES_THREADS_HPP\r
diff --git a/src/external/boost/boost/config/select_compiler_config.hpp b/src/external/boost/boost/config/select_compiler_config.hpp
new file mode 100644 (file)
index 0000000..bb54900
--- /dev/null
@@ -0,0 +1,135 @@
+//  Boost compiler configuration selection header file\r
+\r
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Martin Wille 2003.\r
+//  (C) Copyright Guillaume Melquiond 2003.\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  (See accompanying file LICENSE_1_0.txt or copy at\r
+//   http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org/ for most recent version.\r
+\r
+\r
+// one identification macro for each of the\r
+// compilers we support:\r
+\r
+#   define BOOST_CXX_GCCXML     0\r
+#   define BOOST_CXX_NVCC       0\r
+#   define BOOST_CXX_COMO       0\r
+#   define BOOST_CXX_PATHSCALE  0\r
+#   define BOOST_CXX_CLANG      0\r
+#   define BOOST_CXX_DMC        0\r
+#   define BOOST_CXX_INTEL      0\r
+#   define BOOST_CXX_GNUC       0\r
+#   define BOOST_CXX_KCC        0\r
+#   define BOOST_CXX_SGI        0\r
+#   define BOOST_CXX_TRU64      0\r
+#   define BOOST_CXX_GHS        0\r
+#   define BOOST_CXX_BORLAND    0\r
+#   define BOOST_CXX_CW         0\r
+#   define BOOST_CXX_SUNPRO     0\r
+#   define BOOST_CXX_HPACC      0\r
+#   define BOOST_CXX_MPW        0\r
+#   define BOOST_CXX_IBMCPP     0\r
+#   define BOOST_CXX_MSVC       0\r
+#   define BOOST_CXX_PGI        0\r
+#   define BOOST_CXX_NVCC       0\r
+\r
+\r
+// locate which compiler we are using and define\r
+// BOOST_COMPILER_CONFIG as needed: \r
+\r
+#if defined(__GCCXML__)\r
+// GCC-XML emulates other compilers, it has to appear first here!\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc_xml.hpp"\r
+\r
+#elif defined __CUDACC__\r
+//  NVIDIA CUDA C++ compiler for GPU\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/nvcc.hpp"\r
+\r
+#elif defined __COMO__\r
+//  Comeau C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp"\r
+\r
+#elif defined(__PATHSCALE__) && (__PATHCC__ >= 4)\r
+// PathScale EKOPath compiler (has to come before clang and gcc)\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/pathscale.hpp"\r
+\r
+#elif defined __clang__\r
+//  Clang C++ emulates GCC, so it has to appear early.\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/clang.hpp"\r
+\r
+#elif defined __DMC__\r
+//  Digital Mars C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp"\r
+\r
+#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)\r
+//  Intel\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/intel.hpp"\r
+\r
+# elif defined __GNUC__\r
+//  GNU C++:\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp"\r
+\r
+#elif defined __KCC\r
+//  Kai C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/kai.hpp"\r
+\r
+#elif defined __sgi\r
+//  SGI MIPSpro C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/sgi_mipspro.hpp"\r
+\r
+#elif defined __DECCXX\r
+//  Compaq Tru64 Unix cxx\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/compaq_cxx.hpp"\r
+\r
+#elif defined __ghs\r
+//  Greenhills C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/greenhills.hpp"\r
+\r
+#elif defined __CODEGEARC__\r
+//  CodeGear - must be checked for before Borland\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/codegear.hpp"\r
+\r
+#elif defined __BORLANDC__\r
+//  Borland\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/borland.hpp"\r
+\r
+#elif defined  __MWERKS__\r
+//  Metrowerks CodeWarrior\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/metrowerks.hpp"\r
+\r
+#elif defined  __SUNPRO_CC\r
+//  Sun Workshop Compiler C++\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/sunpro_cc.hpp"\r
+\r
+#elif defined __HP_aCC\r
+//  HP aCC\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/hp_acc.hpp"\r
+\r
+#elif defined(__MRC__) || defined(__SC__)\r
+//  MPW MrCpp or SCpp\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp"\r
+\r
+#elif defined(__IBMCPP__)\r
+//  IBM Visual Age\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp"\r
+\r
+#elif defined(__PGI)\r
+//  Portland Group Inc.\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp"\r
+\r
+#elif defined _MSC_VER\r
+//  Microsoft Visual C++\r
+//\r
+//  Must remain the last #elif since some other vendors (Metrowerks, for\r
+//  example) also #define _MSC_VER\r
+#   define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp"\r
+\r
+#elif defined (BOOST_ASSERT_CONFIG)\r
+// this must come last - generate an error if we don't\r
+// recognise the compiler:\r
+#  error "Unknown compiler - please configure (http://www.boost.org/libs/config/config.htm#configuring) and report the results to the main boost mailing list (http://www.boost.org/more/mailing_lists.htm#main)"\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/config/select_platform_config.hpp b/src/external/boost/boost/config/select_platform_config.hpp
new file mode 100644 (file)
index 0000000..0052222
--- /dev/null
@@ -0,0 +1,101 @@
+//  Boost compiler configuration selection header file\r
+\r
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  (C) Copyright Jens Maurer 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+// locate which platform we are on and define BOOST_PLATFORM_CONFIG as needed.\r
+// Note that we define the headers to include using "header_name" not\r
+// <header_name> in order to prevent macro expansion within the header\r
+// name (for example "linux" is a macro on linux systems).\r
+\r
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) \r
+// linux, also other platforms (Hurd etc) that use GLIBC, should these really have their own config headers though?\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/linux.hpp"\r
+\r
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)\r
+// BSD:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/bsd.hpp"\r
+\r
+#elif defined(sun) || defined(__sun)\r
+// solaris:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/solaris.hpp"\r
+\r
+#elif defined(__sgi)\r
+// SGI Irix:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/irix.hpp"\r
+\r
+#elif defined(__hpux)\r
+// hp unix:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/hpux.hpp"\r
+\r
+#elif defined(__CYGWIN__)\r
+// cygwin is not win32:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/cygwin.hpp"\r
+\r
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)\r
+// win32:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp"\r
+\r
+#elif defined(__BEOS__)\r
+// BeOS\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/beos.hpp"\r
+\r
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)\r
+// MacOS\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp"\r
+\r
+#elif defined(__IBMCPP__) || defined(_AIX)\r
+// IBM\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp"\r
+\r
+#elif defined(__amigaos__)\r
+// AmigaOS\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/amigaos.hpp"\r
+\r
+#elif defined(__QNXNTO__)\r
+// QNX:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/qnxnto.hpp"\r
+\r
+#elif defined(__VXWORKS__)\r
+// vxWorks:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/vxworks.hpp"\r
+\r
+#elif defined(__SYMBIAN32__) \r
+// Symbian: \r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/symbian.hpp" \r
+\r
+#elif defined(__VMS) \r
+// VMS:\r
+#  define BOOST_PLATFORM_CONFIG "boost/config/platform/vms.hpp" \r
+#else\r
+\r
+#  if defined(unix) \\r
+      || defined(__unix) \\r
+      || defined(_XOPEN_SOURCE) \\r
+      || defined(_POSIX_SOURCE)\r
+\r
+   // generic unix platform:\r
+\r
+#  ifndef BOOST_HAS_UNISTD_H\r
+#     define BOOST_HAS_UNISTD_H\r
+#  endif\r
+\r
+#  include <boost/config/posix_features.hpp>\r
+\r
+#  endif\r
+\r
+#  if defined (BOOST_ASSERT_CONFIG)\r
+      // this must come last - generate an error if we don't\r
+      // recognise the platform:\r
+#     error "Unknown platform - please configure and report the results to boost.org"\r
+#  endif\r
+\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/select_stdlib_config.hpp b/src/external/boost/boost/config/select_stdlib_config.hpp
new file mode 100644 (file)
index 0000000..797bd7e
--- /dev/null
@@ -0,0 +1,81 @@
+//  Boost compiler configuration selection header file\r
+\r
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001 - 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+// locate which std lib we are using and define BOOST_STDLIB_CONFIG as needed:\r
+\r
+// First include <cstddef> to determine if some version of STLport is in use as the std lib\r
+// (do not rely on this header being included since users can short-circuit this header \r
+//  if they know whose std lib they are using.)\r
+#include <cstddef>\r
+\r
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)\r
+// STLPort library; this _must_ come first, otherwise since\r
+// STLport typically sits on top of some other library, we\r
+// can end up detecting that first rather than STLport:\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/stlport.hpp"\r
+\r
+#else\r
+\r
+// If our std lib was not some version of STLport, then include <utility> as it is about \r
+// the smallest of the std lib headers that includes real C++ stuff.  (Some std libs do not\r
+// include their C++-related macros in <cstddef> so this additional include makes sure\r
+// we get those definitions)\r
+// (again do not rely on this header being included since users can short-circuit this \r
+//  header if they know whose std lib they are using.)\r
+#include <boost/config/no_tr1/utility.hpp>\r
+\r
+#if defined(__LIBCOMO__)\r
+// Comeau STL:\r
+#define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcomo.hpp"\r
+\r
+#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)\r
+// Rogue Wave library:\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/roguewave.hpp"\r
+\r
+#elif defined(_LIBCPP_VERSION)\r
+// libc++\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcpp.hpp"\r
+\r
+#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)\r
+// GNU libstdc++ 3\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/libstdcpp3.hpp"\r
+\r
+#elif defined(__STL_CONFIG_H)\r
+// generic SGI STL\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/sgi.hpp"\r
+\r
+#elif defined(__MSL_CPP__)\r
+// MSL standard lib:\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp"\r
+\r
+#elif defined(__IBMCPP__)\r
+// take the default VACPP std lib\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp"\r
+\r
+#elif defined(MSIPL_COMPILE_H)\r
+// Modena C++ standard library\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/modena.hpp"\r
+\r
+#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)\r
+// Dinkumware Library (this has to appear after any possible replacement libraries):\r
+#  define BOOST_STDLIB_CONFIG "boost/config/stdlib/dinkumware.hpp"\r
+\r
+#elif defined (BOOST_ASSERT_CONFIG)\r
+// this must come last - generate an error if we don't\r
+// recognise the library:\r
+#  error "Unknown standard library - please configure and report the results to boost.org"\r
+\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/dinkumware.hpp b/src/external/boost/boost/config/stdlib/dinkumware.hpp
new file mode 100644 (file)
index 0000000..00684ad
--- /dev/null
@@ -0,0 +1,149 @@
+//  (C) Copyright John Maddock 2001 - 2003.\r
+//  (C) Copyright Jens Maurer 2001.\r
+//  (C) Copyright Peter Dimov 2001.\r
+//  (C) Copyright David Abrahams 2002.\r
+//  (C) Copyright Guillaume Melquiond 2003.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Dinkumware standard library config:\r
+\r
+#if !defined(_YVALS) && !defined(_CPPLIB_VER)\r
+#include <boost/config/no_tr1/utility.hpp>\r
+#if !defined(_YVALS) && !defined(_CPPLIB_VER)\r
+#error This is not the Dinkumware lib!\r
+#endif\r
+#endif\r
+\r
+\r
+#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 306)\r
+   // full dinkumware 3.06 and above\r
+   // fully conforming provided the compiler supports it:\r
+#  if !(defined(_GLOBAL_USING) && (_GLOBAL_USING+0 > 0)) && !defined(__BORLANDC__) && !defined(_STD) && !(defined(__ICC) && (__ICC >= 700))   // can be defined in yvals.h\r
+#     define BOOST_NO_STDC_NAMESPACE\r
+#  endif\r
+#  if !(defined(_HAS_MEMBER_TEMPLATES_REBIND) && (_HAS_MEMBER_TEMPLATES_REBIND+0 > 0)) && !(defined(_MSC_VER) && (_MSC_VER > 1300)) && defined(BOOST_MSVC)\r
+#     define BOOST_NO_STD_ALLOCATOR\r
+#  endif\r
+#  define BOOST_HAS_PARTIAL_STD_ALLOCATOR\r
+#  if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)\r
+      // if this lib version is set up for vc6 then there is no std::use_facet:\r
+#     define BOOST_NO_STD_USE_FACET\r
+#     define BOOST_HAS_TWO_ARG_USE_FACET\r
+      // C lib functions aren't in namespace std either:\r
+#     define BOOST_NO_STDC_NAMESPACE\r
+      // and nor is <exception>\r
+#     define BOOST_NO_EXCEPTION_STD_NAMESPACE\r
+#  endif\r
+// There's no numeric_limits<long long> support unless _LONGLONG is defined:\r
+#  if !defined(_LONGLONG) && (_CPPLIB_VER <= 310)\r
+#     define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#  endif\r
+// 3.06 appears to have (non-sgi versions of) <hash_set> & <hash_map>,\r
+// and no <slist> at all\r
+#else\r
+#  define BOOST_MSVC_STD_ITERATOR 1\r
+#  define BOOST_NO_STD_ITERATOR\r
+#  define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#  define BOOST_NO_STDC_NAMESPACE\r
+#  define BOOST_NO_STD_USE_FACET\r
+#  define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN\r
+#  define BOOST_HAS_MACRO_USE_FACET\r
+#  ifndef _CPPLIB_VER\r
+      // Updated Dinkum library defines this, and provides\r
+      // its own min and max definitions, as does MTA version.\r
+#     ifndef __MTA__ \r
+#        define BOOST_NO_STD_MIN_MAX\r
+#     endif\r
+#     define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#  endif\r
+#endif\r
+\r
+//\r
+// std extension namespace is stdext for vc7.1 and later, \r
+// the same applies to other compilers that sit on top\r
+// of vc7.1 (Intel and Comeau):\r
+//\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(__BORLANDC__)\r
+#  define BOOST_STD_EXTENSION_NAMESPACE stdext\r
+#endif\r
+\r
+\r
+#if (defined(_MSC_VER) && (_MSC_VER <= 1300) && !defined(__BORLANDC__)) || !defined(_CPPLIB_VER) || (_CPPLIB_VER < 306)\r
+   // if we're using a dinkum lib that's\r
+   // been configured for VC6/7 then there is\r
+   // no iterator traits (true even for icl)\r
+#  define BOOST_NO_STD_ITERATOR_TRAITS\r
+#endif\r
+\r
+#if defined(__ICL) && (__ICL < 800) && defined(_CPPLIB_VER) && (_CPPLIB_VER <= 310)\r
+// Intel C++ chokes over any non-trivial use of <locale>\r
+// this may be an overly restrictive define, but regex fails without it:\r
+#  define BOOST_NO_STD_LOCALE\r
+#endif\r
+\r
+#include <typeinfo>\r
+#if !_HAS_EXCEPTIONS\r
+#  define BOOST_NO_STD_TYPEINFO    \r
+#endif  \r
+\r
+//  C++0x headers implemented in 520 (as shipped by Microsoft)\r
+//\r
+#if !defined(_CPPLIB_VER) || _CPPLIB_VER < 520\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+#endif\r
+\r
+#if !defined(_HAS_TR1_IMPORTS) && !defined(BOOST_NO_0X_HDR_TUPLE)\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+\r
+#ifdef _CPPLIB_VER\r
+#  define BOOST_DINKUMWARE_STDLIB _CPPLIB_VER\r
+#else\r
+#  define BOOST_DINKUMWARE_STDLIB 1\r
+#endif\r
+\r
+#ifdef _CPPLIB_VER\r
+#  define BOOST_STDLIB "Dinkumware standard library version " BOOST_STRINGIZE(_CPPLIB_VER)\r
+#else\r
+#  define BOOST_STDLIB "Dinkumware standard library version 1.x"\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/libcomo.hpp b/src/external/boost/boost/config/stdlib/libcomo.hpp
new file mode 100644 (file)
index 0000000..8ed4cd8
--- /dev/null
@@ -0,0 +1,73 @@
+//  (C) Copyright John Maddock 2002 - 2003. \r
+//  (C) Copyright Jens Maurer 2002 - 2003. \r
+//  (C) Copyright Beman Dawes 2002 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Comeau STL:\r
+\r
+#if !defined(__LIBCOMO__)\r
+#  include <boost/config/no_tr1/utility.hpp>\r
+#  if !defined(__LIBCOMO__)\r
+#      error "This is not the Comeau STL!"\r
+#  endif\r
+#endif\r
+\r
+//\r
+// std::streambuf<wchar_t> is non-standard\r
+// NOTE: versions of libcomo prior to beta28 have octal version numbering,\r
+// e.g. version 25 is 21 (dec)\r
+#if __LIBCOMO_VERSION__ <= 22\r
+#  define BOOST_NO_STD_WSTREAMBUF\r
+#endif\r
+\r
+#if (__LIBCOMO_VERSION__ <= 31) && defined(_WIN32)\r
+#define BOOST_NO_SWPRINTF\r
+#endif\r
+\r
+#if __LIBCOMO_VERSION__ >= 31\r
+#  define BOOST_HAS_HASH\r
+#  define BOOST_HAS_SLIST\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+//\r
+// Intrinsic type_traits support.\r
+// The SGI STL has it's own __type_traits class, which\r
+// has intrinsic compiler support with SGI's compilers.\r
+// Whatever map SGI style type traits to boost equivalents:\r
+//\r
+#define BOOST_HAS_SGI_TYPE_TRAITS\r
+\r
+#define BOOST_STDLIB "Comeau standard library " BOOST_STRINGIZE(__LIBCOMO_VERSION__)\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/libcpp.hpp b/src/external/boost/boost/config/stdlib/libcpp.hpp
new file mode 100644 (file)
index 0000000..d6441aa
--- /dev/null
@@ -0,0 +1,34 @@
+//  (C) Copyright Christopher Jefferson 2011.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  config for libc++\r
+//  Might need more in here later.\r
+\r
+#if !defined(_LIBCPP_VERSION)\r
+#  include <ciso646>\r
+#  if !defined(_LIBCPP_VERSION)\r
+#      error "This is not libc++!"\r
+#  endif\r
+#endif\r
+\r
+#define BOOST_STDLIB "libc++ version " BOOST_STRINGIZE(_LIBCPP_VERSION)\r
+\r
+#define BOOST_HAS_THREADS\r
+\r
+#define BOOST_NO_0X_HDR_CONCEPTS\r
+#define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+\r
+#ifdef _LIBCPP_HAS_NO_VARIADICS\r
+#    define BOOST_NO_0X_HDR_TUPLE\r
+#endif\r
+\r
+// libc++ uses a non-standard messages_base\r
+#define BOOST_NO_STD_MESSAGES\r
+\r
+//  --- end ---\r
diff --git a/src/external/boost/boost/config/stdlib/libstdcpp3.hpp b/src/external/boost/boost/config/stdlib/libstdcpp3.hpp
new file mode 100644 (file)
index 0000000..79d9415
--- /dev/null
@@ -0,0 +1,145 @@
+//  (C) Copyright John Maddock 2001.\r
+//  (C) Copyright Jens Maurer 2001.\r
+//  Use, modification and distribution are subject to the\r
+//  Boost Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  config for libstdc++ v3\r
+//  not much to go in here:\r
+\r
+#define BOOST_GNU_STDLIB 1\r
+\r
+#ifdef __GLIBCXX__\r
+#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCXX__)\r
+#else\r
+#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCPP__)\r
+#endif\r
+\r
+#if !defined(_GLIBCPP_USE_WCHAR_T) && !defined(_GLIBCXX_USE_WCHAR_T)\r
+#  define BOOST_NO_CWCHAR\r
+#  define BOOST_NO_CWCTYPE\r
+#  define BOOST_NO_STD_WSTRING\r
+#  define BOOST_NO_STD_WSTREAMBUF\r
+#endif\r
+\r
+#if defined(__osf__) && !defined(_REENTRANT) \\r
+  && ( defined(_GLIBCXX_HAVE_GTHR_DEFAULT) || defined(_GLIBCPP_HAVE_GTHR_DEFAULT) )\r
+// GCC 3 on Tru64 forces the definition of _REENTRANT when any std lib header\r
+// file is included, therefore for consistency we define it here as well.\r
+#  define _REENTRANT\r
+#endif\r
+\r
+#ifdef __GLIBCXX__ // gcc 3.4 and greater:\r
+#  if defined(_GLIBCXX_HAVE_GTHR_DEFAULT) \\r
+        || defined(_GLIBCXX__PTHREADS)\r
+      //\r
+      // If the std lib has thread support turned on, then turn it on in Boost\r
+      // as well.  We do this because some gcc-3.4 std lib headers define _REENTANT\r
+      // while others do not...\r
+      //\r
+#     define BOOST_HAS_THREADS\r
+#  else\r
+#     define BOOST_DISABLE_THREADS\r
+#  endif\r
+#elif defined(__GLIBCPP__) \\r
+        && !defined(_GLIBCPP_HAVE_GTHR_DEFAULT) \\r
+        && !defined(_GLIBCPP__PTHREADS)\r
+   // disable thread support if the std lib was built single threaded:\r
+#  define BOOST_DISABLE_THREADS\r
+#endif\r
+\r
+#if (defined(linux) || defined(__linux) || defined(__linux__)) && defined(__arm__) && defined(_GLIBCPP_HAVE_GTHR_DEFAULT)\r
+// linux on arm apparently doesn't define _REENTRANT\r
+// so just turn on threading support whenever the std lib is thread safe:\r
+#  define BOOST_HAS_THREADS\r
+#endif\r
+\r
+#if !defined(_GLIBCPP_USE_LONG_LONG) \\r
+    && !defined(_GLIBCXX_USE_LONG_LONG)\\r
+    && defined(BOOST_HAS_LONG_LONG)\r
+// May have been set by compiler/*.hpp, but "long long" without library\r
+// support is useless.\r
+#  undef BOOST_HAS_LONG_LONG\r
+#endif\r
+\r
+// Apple doesn't seem to reliably defined a *unix* macro\r
+#if !defined(CYGWIN) && (  defined(__unix__)  \\r
+                        || defined(__unix)    \\r
+                        || defined(unix)      \\r
+                        || defined(__APPLE__) \\r
+                        || defined(__APPLE)   \\r
+                        || defined(APPLE))\r
+#  include <unistd.h>\r
+#endif\r
+\r
+#if defined(__GLIBCXX__) || (defined(__GLIBCPP__) && __GLIBCPP__>=20020514) // GCC >= 3.1.0\r
+#  define BOOST_STD_EXTENSION_NAMESPACE __gnu_cxx\r
+#  define BOOST_HAS_SLIST\r
+#  define BOOST_HAS_HASH\r
+#  define BOOST_SLIST_HEADER <ext/slist>\r
+# if !defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)\r
+#   define BOOST_HASH_SET_HEADER <ext/hash_set>\r
+#   define BOOST_HASH_MAP_HEADER <ext/hash_map>\r
+# else\r
+#   define BOOST_HASH_SET_HEADER <backward/hash_set>\r
+#   define BOOST_HASH_MAP_HEADER <backward/hash_map>\r
+# endif\r
+#endif\r
+\r
+//  stdlibc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly\r
+//  __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the stdlibc++\r
+//  developers. He also commented:\r
+//\r
+//       "I'm not sure how useful __GLIBCXX__ is for your purposes, for instance in\r
+//       GCC 4.2.4 it is set to 20080519 but in GCC 4.3.0 it is set to 20080305.\r
+//       Although 4.3.0 was released earlier than 4.2.4, it has better C++0x support\r
+//       than any release in the 4.2 series."\r
+//\r
+//  Another resource for understanding stdlibc++ features is:\r
+//  http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#manual.intro.status.standard.200x\r
+\r
+//  C++0x headers in GCC 4.3.0 and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_STD_UNORDERED  // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#endif\r
+\r
+//  C++0x headers in GCC 4.4.0 and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#endif\r
+\r
+//  C++0x features in GCC 4.5.0 and later\r
+//\r
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) || !defined(__GXX_EXPERIMENTAL_CXX0X__)\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+\r
+//  --- end ---\r
diff --git a/src/external/boost/boost/config/stdlib/modena.hpp b/src/external/boost/boost/config/stdlib/modena.hpp
new file mode 100644 (file)
index 0000000..0299a5b
--- /dev/null
@@ -0,0 +1,57 @@
+//  (C) Copyright Jens Maurer 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Modena C++ standard library (comes with KAI C++)\r
+\r
+#if !defined(MSIPL_COMPILE_H)\r
+#  include <boost/config/no_tr1/utility.hpp>\r
+#  if !defined(__MSIPL_COMPILE_H)\r
+#      error "This is not the Modena C++ library!"\r
+#  endif\r
+#endif\r
+\r
+#ifndef MSIPL_NL_TYPES\r
+#define BOOST_NO_STD_MESSAGES\r
+#endif\r
+\r
+#ifndef MSIPL_WCHART\r
+#define BOOST_NO_STD_WSTRING\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+#define BOOST_STDLIB "Modena C++ standard library"\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/msl.hpp b/src/external/boost/boost/config/stdlib/msl.hpp
new file mode 100644 (file)
index 0000000..89ae7db
--- /dev/null
@@ -0,0 +1,85 @@
+//  (C) Copyright John Maddock 2001. \r
+//  (C) Copyright Darin Adler 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Metrowerks standard library:\r
+\r
+#ifndef __MSL_CPP__\r
+#  include <boost/config/no_tr1/utility.hpp>\r
+#  ifndef __MSL_CPP__\r
+#     error This is not the MSL standard library!\r
+#  endif\r
+#endif\r
+\r
+#if __MSL_CPP__ >= 0x6000  // Pro 6\r
+#  define BOOST_HAS_HASH\r
+#  define BOOST_STD_EXTENSION_NAMESPACE Metrowerks\r
+#endif\r
+#define BOOST_HAS_SLIST\r
+\r
+#if __MSL_CPP__ < 0x6209\r
+#  define BOOST_NO_STD_MESSAGES\r
+#endif\r
+\r
+// check C lib version for <stdint.h>\r
+#include <cstddef>\r
+\r
+#if defined(__MSL__) && (__MSL__ >= 0x5000)\r
+#  define BOOST_HAS_STDINT_H\r
+#  if !defined(__PALMOS_TRAPS__)\r
+#    define BOOST_HAS_UNISTD_H\r
+#  endif\r
+   // boilerplate code:\r
+#  include <boost/config/posix_features.hpp>\r
+#endif\r
+\r
+#if defined(_MWMT) || _MSL_THREADSAFE\r
+#  define BOOST_HAS_THREADS\r
+#endif\r
+\r
+#ifdef _MSL_NO_EXPLICIT_FUNC_TEMPLATE_ARG\r
+#  define BOOST_NO_STD_USE_FACET\r
+#  define BOOST_HAS_TWO_ARG_USE_FACET\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__)\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/roguewave.hpp b/src/external/boost/boost/config/stdlib/roguewave.hpp
new file mode 100644 (file)
index 0000000..6ad6909
--- /dev/null
@@ -0,0 +1,185 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Jens Maurer 2001. \r
+//  (C) Copyright David Abrahams 2003. \r
+//  (C) Copyright Boris Gubenko 2007. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  Rogue Wave std lib:\r
+\r
+#define BOOST_RW_STDLIB 1 \r
+\r
+#if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)\r
+#  include <boost/config/no_tr1/utility.hpp>\r
+#  if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)\r
+#     error This is not the Rogue Wave standard library\r
+#  endif\r
+#endif\r
+//\r
+// figure out a consistent version number:\r
+//\r
+#ifndef _RWSTD_VER\r
+#  define BOOST_RWSTD_VER 0x010000\r
+#elif _RWSTD_VER < 0x010000\r
+#  define BOOST_RWSTD_VER (_RWSTD_VER << 8)\r
+#else\r
+#  define BOOST_RWSTD_VER _RWSTD_VER\r
+#endif\r
+\r
+#ifndef _RWSTD_VER\r
+#  define BOOST_STDLIB "Rogue Wave standard library version (Unknown version)"\r
+#elif _RWSTD_VER < 0x04010200\r
+ #  define BOOST_STDLIB "Rogue Wave standard library version " BOOST_STRINGIZE(_RWSTD_VER)\r
+#else\r
+#  ifdef _RWSTD_VER_STR\r
+#    define BOOST_STDLIB "Apache STDCXX standard library version " _RWSTD_VER_STR\r
+#  else\r
+#    define BOOST_STDLIB "Apache STDCXX standard library version " BOOST_STRINGIZE(_RWSTD_VER)\r
+#  endif\r
+#endif\r
+\r
+//\r
+// Prior to version 2.2.0 the primary template for std::numeric_limits\r
+// does not have compile time constants, even though specializations of that\r
+// template do:\r
+//\r
+#if BOOST_RWSTD_VER < 0x020200\r
+#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#endif\r
+\r
+// Sun CC 5.5 patch 113817-07 adds long long specialization, but does not change the\r
+// library version number (http://sunsolve6.sun.com/search/document.do?assetkey=1-21-113817):\r
+#if BOOST_RWSTD_VER <= 0x020101 && (!defined(__SUNPRO_CC) || (__SUNPRO_CC < 0x550))\r
+#  define BOOST_NO_LONG_LONG_NUMERIC_LIMITS\r
+# endif\r
+\r
+//\r
+// Borland version of numeric_limits lacks __int64 specialisation:\r
+//\r
+#ifdef __BORLANDC__\r
+#  define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#endif\r
+\r
+//\r
+// No std::iterator if it can't figure out default template args:\r
+//\r
+#if defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || defined(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || (BOOST_RWSTD_VER < 0x020000)\r
+#  define BOOST_NO_STD_ITERATOR\r
+#endif\r
+\r
+//\r
+// No iterator traits without partial specialization:\r
+//\r
+#if defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) || defined(RWSTD_NO_CLASS_PARTIAL_SPEC)\r
+#  define BOOST_NO_STD_ITERATOR_TRAITS\r
+#endif\r
+\r
+//\r
+// Prior to version 2.0, std::auto_ptr was buggy, and there were no\r
+// new-style iostreams, and no conformant std::allocator:\r
+//\r
+#if (BOOST_RWSTD_VER < 0x020000)\r
+#  define BOOST_NO_AUTO_PTR\r
+#  define BOOST_NO_STRINGSTREAM\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#  define BOOST_NO_STD_LOCALE\r
+#endif\r
+\r
+//\r
+// No template iterator constructors without member template support:\r
+//\r
+#if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(_RWSTD_NO_MEMBER_TEMPLATES)\r
+#  define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS\r
+#endif\r
+\r
+//\r
+// RW defines _RWSTD_ALLOCATOR if the allocator is conformant and in use\r
+// (the or _HPACC_ part is a hack - the library seems to define _RWSTD_ALLOCATOR\r
+// on HP aCC systems even though the allocator is in fact broken):\r
+//\r
+#if !defined(_RWSTD_ALLOCATOR) || (defined(__HP_aCC) && __HP_aCC <= 33100)\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+\r
+//\r
+// If we have a std::locale, we still may not have std::use_facet:\r
+//\r
+#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) && !defined(BOOST_NO_STD_LOCALE)\r
+#  define BOOST_NO_STD_USE_FACET\r
+#  define BOOST_HAS_TWO_ARG_USE_FACET\r
+#endif\r
+\r
+//\r
+// There's no std::distance prior to version 2, or without\r
+// partial specialization support:\r
+//\r
+#if (BOOST_RWSTD_VER < 0x020000) || defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)\r
+    #define BOOST_NO_STD_DISTANCE\r
+#endif\r
+\r
+//\r
+// Some versions of the rogue wave library don't have assignable\r
+// OutputIterators:\r
+//\r
+#if BOOST_RWSTD_VER < 0x020100\r
+#  define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN\r
+#endif\r
+\r
+//\r
+// Disable BOOST_HAS_LONG_LONG when the library has no support for it.\r
+//\r
+#if !defined(_RWSTD_LONG_LONG) && defined(BOOST_HAS_LONG_LONG)\r
+#  undef BOOST_HAS_LONG_LONG\r
+#endif\r
+\r
+//\r
+// check that on HP-UX, the proper RW library is used\r
+//\r
+#if defined(__HP_aCC) && !defined(_HP_NAMESPACE_STD)\r
+#  error "Boost requires Standard RW library. Please compile and link with -AA"\r
+#endif\r
+\r
+//\r
+// Define macros specific to RW V2.2 on HP-UX\r
+//\r
+#if defined(__HP_aCC) && (BOOST_RWSTD_VER == 0x02020100)\r
+#  ifndef __HP_TC1_MAKE_PAIR\r
+#    define __HP_TC1_MAKE_PAIR\r
+#  endif\r
+#  ifndef _HP_INSTANTIATE_STD2_VL\r
+#    define _HP_INSTANTIATE_STD2_VL\r
+#  endif\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#if _RWSTD_VER < 0x05000000\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#endif\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/sgi.hpp b/src/external/boost/boost/config/stdlib/sgi.hpp
new file mode 100644 (file)
index 0000000..f49f703
--- /dev/null
@@ -0,0 +1,149 @@
+//  (C) Copyright John Maddock 2001 - 2003. \r
+//  (C) Copyright Darin Adler 2001. \r
+//  (C) Copyright Jens Maurer 2001 - 2003. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  generic SGI STL:\r
+\r
+#if !defined(__STL_CONFIG_H)\r
+#  include <boost/config/no_tr1/utility.hpp>\r
+#  if !defined(__STL_CONFIG_H)\r
+#      error "This is not the SGI STL!"\r
+#  endif\r
+#endif\r
+\r
+//\r
+// No std::iterator traits without partial specialisation:\r
+//\r
+#if !defined(__STL_CLASS_PARTIAL_SPECIALIZATION)\r
+#  define BOOST_NO_STD_ITERATOR_TRAITS\r
+#endif\r
+\r
+//\r
+// No std::stringstream with gcc < 3\r
+//\r
+#if defined(__GNUC__) && (__GNUC__ < 3) && \\r
+     ((__GNUC_MINOR__ < 95) || (__GNUC_MINOR__ == 96)) && \\r
+     !defined(__STL_USE_NEW_IOSTREAMS) || \\r
+   defined(__APPLE_CC__)\r
+   // Note that we only set this for GNU C++ prior to 2.95 since the\r
+   // latest patches for that release do contain a minimal <sstream>\r
+   // If you are running a 2.95 release prior to 2.95.3 then this will need\r
+   // setting, but there is no way to detect that automatically (other\r
+   // than by running the configure script).\r
+   // Also, the unofficial GNU C++ 2.96 included in RedHat 7.1 doesn't\r
+   // have <sstream>.\r
+#  define BOOST_NO_STRINGSTREAM\r
+#endif\r
+\r
+// Apple doesn't seem to reliably defined a *unix* macro\r
+#if !defined(CYGWIN) && (  defined(__unix__)  \\r
+                        || defined(__unix)    \\r
+                        || defined(unix)      \\r
+                        || defined(__APPLE__) \\r
+                        || defined(__APPLE)   \\r
+                        || defined(APPLE))\r
+#  include <unistd.h>\r
+#endif\r
+\r
+\r
+//\r
+// Assume no std::locale without own iostreams (this may be an\r
+// incorrect assumption in some cases):\r
+//\r
+#if !defined(__SGI_STL_OWN_IOSTREAMS) && !defined(__STL_USE_NEW_IOSTREAMS)\r
+#  define BOOST_NO_STD_LOCALE\r
+#endif\r
+\r
+//\r
+// Original native SGI streams have non-standard std::messages facet:\r
+//\r
+#if defined(__sgi) && (_COMPILER_VERSION <= 650) && !defined(__SGI_STL_OWN_IOSTREAMS)\r
+#  define BOOST_NO_STD_LOCALE\r
+#endif\r
+\r
+//\r
+// SGI's new iostreams have missing "const" in messages<>::open\r
+//\r
+#if defined(__sgi) && (_COMPILER_VERSION <= 740) && defined(__STL_USE_NEW_IOSTREAMS)\r
+#  define BOOST_NO_STD_MESSAGES\r
+#endif\r
+\r
+//\r
+// No template iterator constructors, or std::allocator\r
+// without member templates:\r
+//\r
+#if !defined(__STL_MEMBER_TEMPLATES)\r
+#  define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+\r
+//\r
+// We always have SGI style hash_set, hash_map, and slist:\r
+//\r
+#define BOOST_HAS_HASH\r
+#define BOOST_HAS_SLIST\r
+\r
+//\r
+// If this is GNU libstdc++2, then no <limits> and no std::wstring:\r
+//\r
+#if (defined(__GNUC__) && (__GNUC__ < 3))\r
+#  include <string>\r
+#  if defined(__BASTRING__)\r
+#     define BOOST_NO_LIMITS\r
+// Note: <boost/limits.hpp> will provide compile-time constants\r
+#     undef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#     define BOOST_NO_STD_WSTRING\r
+#  endif\r
+#endif\r
+\r
+//\r
+// There is no standard iterator unless we have namespace support:\r
+//\r
+#if !defined(__STL_USE_NAMESPACES)\r
+#  define BOOST_NO_STD_ITERATOR\r
+#endif\r
+\r
+//\r
+// Intrinsic type_traits support.\r
+// The SGI STL has it's own __type_traits class, which\r
+// has intrinsic compiler support with SGI's compilers.\r
+// Whatever map SGI style type traits to boost equivalents:\r
+//\r
+#define BOOST_HAS_SGI_TYPE_TRAITS\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+#define BOOST_STDLIB "SGI standard library"\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/stlport.hpp b/src/external/boost/boost/config/stdlib/stlport.hpp
new file mode 100644 (file)
index 0000000..b205fcf
--- /dev/null
@@ -0,0 +1,248 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  (C) Copyright Darin Adler 2001. \r
+//  (C) Copyright Jens Maurer 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+//  STLPort standard library config:\r
+\r
+#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\r
+#  include <cstddef>\r
+#  if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)\r
+#      error "This is not STLPort!"\r
+#  endif\r
+#endif\r
+\r
+// Apple doesn't seem to reliably defined a *unix* macro\r
+#if !defined(CYGWIN) && (  defined(__unix__)  \\r
+                        || defined(__unix)    \\r
+                        || defined(unix)      \\r
+                        || defined(__APPLE__) \\r
+                        || defined(__APPLE)   \\r
+                        || defined(APPLE))\r
+#  include <unistd.h>\r
+#endif\r
+\r
+//\r
+// __STL_STATIC_CONST_INIT_BUG implies BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+// for versions prior to 4.1(beta)\r
+//\r
+#if (defined(__STL_STATIC_CONST_INIT_BUG) || defined(_STLP_STATIC_CONST_INIT_BUG)) && (__SGI_STL_PORT <= 0x400)\r
+#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#endif\r
+\r
+//\r
+// If STLport thinks that there is no partial specialisation, then there is no\r
+// std::iterator traits:\r
+//\r
+#if !(defined(_STLP_CLASS_PARTIAL_SPECIALIZATION) || defined(__STL_CLASS_PARTIAL_SPECIALIZATION))\r
+#  define BOOST_NO_STD_ITERATOR_TRAITS\r
+#endif\r
+\r
+//\r
+// No new style iostreams on GCC without STLport's iostreams enabled:\r
+//\r
+#if (defined(__GNUC__) && (__GNUC__ < 3)) && !(defined(__SGI_STL_OWN_IOSTREAMS) || defined(_STLP_OWN_IOSTREAMS))\r
+#  define BOOST_NO_STRINGSTREAM\r
+#endif\r
+\r
+//\r
+// No new iostreams implies no std::locale, and no std::stringstream:\r
+//\r
+#if defined(__STL_NO_IOSTREAMS) || defined(__STL_NO_NEW_IOSTREAMS) || defined(_STLP_NO_IOSTREAMS) || defined(_STLP_NO_NEW_IOSTREAMS)\r
+#  define BOOST_NO_STD_LOCALE\r
+#  define BOOST_NO_STRINGSTREAM\r
+#endif\r
+\r
+//\r
+// If the streams are not native, and we have a "using ::x" compiler bug\r
+// then the io stream facets are not available in namespace std::\r
+//\r
+#ifdef _STLPORT_VERSION\r
+#  if !(_STLPORT_VERSION >= 0x500) && !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__)\r
+#     define BOOST_NO_STD_LOCALE\r
+#  endif\r
+#else\r
+#  if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__)\r
+#     define BOOST_NO_STD_LOCALE\r
+#  endif\r
+#endif\r
+\r
+#if defined(_STLPORT_VERSION) && ((_STLPORT_VERSION < 0x500) || (_STLPORT_VERSION >= 0x520))\r
+#  define BOOST_NO_STD_UNORDERED\r
+#endif\r
+\r
+#if defined(_STLPORT_VERSION) && (_STLPORT_VERSION >= 0x520)\r
+#  define BOOST_HAS_TR1_UNORDERED_SET\r
+#  define BOOST_HAS_TR1_UNORDERED_MAP\r
+#endif\r
+//\r
+// Without member template support enabled, their are no template\r
+// iterate constructors, and no std::allocator:\r
+//\r
+#if !(defined(__STL_MEMBER_TEMPLATES) || defined(_STLP_MEMBER_TEMPLATES))\r
+#  define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+//\r
+// however we always have at least a partial allocator:\r
+//\r
+#define BOOST_HAS_PARTIAL_STD_ALLOCATOR\r
+\r
+#if !defined(_STLP_MEMBER_TEMPLATE_CLASSES) || defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+\r
+#if defined(_STLP_NO_MEMBER_TEMPLATE_KEYWORD) && defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+\r
+//\r
+// If STLport thinks there is no wchar_t at all, then we have to disable\r
+// the support for the relevant specilazations of std:: templates.\r
+//\r
+#if !defined(_STLP_HAS_WCHAR_T) && !defined(_STLP_WCHAR_T_IS_USHORT)\r
+#  ifndef  BOOST_NO_STD_WSTRING\r
+#     define BOOST_NO_STD_WSTRING\r
+#  endif\r
+#  ifndef  BOOST_NO_STD_WSTREAMBUF\r
+#     define BOOST_NO_STD_WSTREAMBUF\r
+#  endif\r
+#endif\r
+\r
+//\r
+// We always have SGI style hash_set, hash_map, and slist:\r
+//\r
+#ifndef _STLP_NO_EXTENSIONS\r
+#define BOOST_HAS_HASH\r
+#define BOOST_HAS_SLIST\r
+#endif\r
+\r
+//\r
+// STLport does a good job of importing names into namespace std::,\r
+// but doesn't always get them all, define BOOST_NO_STDC_NAMESPACE, since our\r
+// workaround does not conflict with STLports:\r
+//\r
+//\r
+// Harold Howe says:\r
+// Borland switched to STLport in BCB6. Defining BOOST_NO_STDC_NAMESPACE with\r
+// BCB6 does cause problems. If we detect C++ Builder, then don't define \r
+// BOOST_NO_STDC_NAMESPACE\r
+//\r
+#if !defined(__BORLANDC__) && !defined(__DMC__)\r
+//\r
+// If STLport is using it's own namespace, and the real names are in\r
+// the global namespace, then we duplicate STLport's using declarations\r
+// (by defining BOOST_NO_STDC_NAMESPACE), we do this because STLport doesn't\r
+// necessarily import all the names we need into namespace std::\r
+// \r
+#  if (defined(__STL_IMPORT_VENDOR_CSTD) \\r
+         || defined(__STL_USE_OWN_NAMESPACE) \\r
+         || defined(_STLP_IMPORT_VENDOR_CSTD) \\r
+         || defined(_STLP_USE_OWN_NAMESPACE)) \\r
+      && (defined(__STL_VENDOR_GLOBAL_CSTD) || defined (_STLP_VENDOR_GLOBAL_CSTD))\r
+#     define BOOST_NO_STDC_NAMESPACE\r
+#     define BOOST_NO_EXCEPTION_STD_NAMESPACE\r
+#  endif\r
+#elif defined(__BORLANDC__) && __BORLANDC__ < 0x560\r
+// STLport doesn't import std::abs correctly:\r
+#include <stdlib.h>\r
+namespace std { using ::abs; }\r
+// and strcmp/strcpy don't get imported either ('cos they are macros)\r
+#include <string.h>\r
+#ifdef strcpy\r
+#  undef strcpy\r
+#endif\r
+#ifdef strcmp\r
+#  undef strcmp\r
+#endif\r
+#ifdef _STLP_VENDOR_CSTD\r
+namespace std{ using _STLP_VENDOR_CSTD::strcmp; using _STLP_VENDOR_CSTD::strcpy; }\r
+#endif\r
+#endif\r
+\r
+//\r
+// std::use_facet may be non-standard, uses a class instead:\r
+//\r
+#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) || defined(_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS)\r
+#  define BOOST_NO_STD_USE_FACET\r
+#  define BOOST_HAS_STLP_USE_FACET\r
+#endif\r
+\r
+//\r
+// If STLport thinks there are no wide functions, <cwchar> etc. is not working; but\r
+// only if BOOST_NO_STDC_NAMESPACE is not defined (if it is then we do the import \r
+// into std:: ourselves).\r
+//\r
+#if defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE)\r
+#  define BOOST_NO_CWCHAR\r
+#  define BOOST_NO_CWCTYPE\r
+#endif\r
+\r
+//\r
+// If STLport for some reason was configured so that it thinks that wchar_t\r
+// is not an intrinsic type, then we have to disable the support for it as\r
+// well (we would be missing required specializations otherwise).\r
+//\r
+#if !defined( _STLP_HAS_WCHAR_T) || defined(_STLP_WCHAR_T_IS_USHORT)\r
+#  undef  BOOST_NO_INTRINSIC_WCHAR_T\r
+#  define BOOST_NO_INTRINSIC_WCHAR_T\r
+#endif\r
+\r
+//\r
+// Borland ships a version of STLport with C++ Builder 6 that lacks\r
+// hashtables and the like:\r
+//\r
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x560)\r
+#  undef BOOST_HAS_HASH\r
+#endif\r
+\r
+//\r
+// gcc-2.95.3/STLPort does not like the using declarations we use to get ADL with std::min/max\r
+//\r
+#if defined(__GNUC__) && (__GNUC__ < 3)\r
+#  include <algorithm> // for std::min and std::max\r
+#  define BOOST_USING_STD_MIN() ((void)0)\r
+#  define BOOST_USING_STD_MAX() ((void)0)\r
+namespace boost { using std::min; using std::max; }\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT)\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/stdlib/vacpp.hpp b/src/external/boost/boost/config/stdlib/vacpp.hpp
new file mode 100644 (file)
index 0000000..bacec1a
--- /dev/null
@@ -0,0 +1,55 @@
+//  (C) Copyright John Maddock 2001 - 2002. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org for most recent version.\r
+\r
+#if __IBMCPP__ <= 501\r
+#  define BOOST_NO_STD_ALLOCATOR\r
+#endif\r
+\r
+#define BOOST_HAS_MACRO_USE_FACET\r
+#define BOOST_NO_STD_MESSAGES\r
+\r
+// Apple doesn't seem to reliably defined a *unix* macro\r
+#if !defined(CYGWIN) && (  defined(__unix__)  \\r
+                        || defined(__unix)    \\r
+                        || defined(unix)      \\r
+                        || defined(__APPLE__) \\r
+                        || defined(__APPLE)   \\r
+                        || defined(APPLE))\r
+#  include <unistd.h>\r
+#endif\r
+\r
+//  C++0x headers not yet implemented\r
+//\r
+#  define BOOST_NO_0X_HDR_ARRAY\r
+#  define BOOST_NO_0X_HDR_CHRONO\r
+#  define BOOST_NO_0X_HDR_CODECVT\r
+#  define BOOST_NO_0X_HDR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_CONDITION_VARIABLE\r
+#  define BOOST_NO_0X_HDR_CONTAINER_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_FORWARD_LIST\r
+#  define BOOST_NO_0X_HDR_FUTURE\r
+#  define BOOST_NO_0X_HDR_INITIALIZER_LIST\r
+#  define BOOST_NO_0X_HDR_ITERATOR_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MEMORY_CONCEPTS\r
+#  define BOOST_NO_0X_HDR_MUTEX\r
+#  define BOOST_NO_0X_HDR_RANDOM\r
+#  define BOOST_NO_0X_HDR_RATIO\r
+#  define BOOST_NO_0X_HDR_REGEX\r
+#  define BOOST_NO_0X_HDR_SYSTEM_ERROR\r
+#  define BOOST_NO_0X_HDR_THREAD\r
+#  define BOOST_NO_0X_HDR_TUPLE\r
+#  define BOOST_NO_0X_HDR_TYPE_TRAITS\r
+#  define BOOST_NO_0X_HDR_TYPEINDEX\r
+#  define BOOST_NO_STD_UNORDERED        // deprecated; see following\r
+#  define BOOST_NO_0X_HDR_UNORDERED_MAP\r
+#  define BOOST_NO_0X_HDR_UNORDERED_SET\r
+#  define BOOST_NO_NUMERIC_LIMITS_LOWEST\r
+\r
+#define BOOST_STDLIB "Visual Age default standard library"\r
+\r
+\r
+\r
diff --git a/src/external/boost/boost/config/suffix.hpp b/src/external/boost/boost/config/suffix.hpp
new file mode 100644 (file)
index 0000000..e836635
--- /dev/null
@@ -0,0 +1,668 @@
+//  Boost config.hpp configuration header file  ------------------------------//\r
+\r
+//  Copyright (c) 2001-2003 John Maddock\r
+//  Copyright (c) 2001 Darin Adler\r
+//  Copyright (c) 2001 Peter Dimov\r
+//  Copyright (c) 2002 Bill Kempf \r
+//  Copyright (c) 2002 Jens Maurer\r
+//  Copyright (c) 2002-2003 David Abrahams\r
+//  Copyright (c) 2003 Gennaro Prota\r
+//  Copyright (c) 2003 Eric Friedman\r
+//  Copyright (c) 2010 Eric Jourdanneau, Joel Falcou\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org/ for most recent version.\r
+\r
+//  Boost config.hpp policy and rationale documentation has been moved to\r
+//  http://www.boost.org/libs/config/\r
+//\r
+//  This file is intended to be stable, and relatively unchanging.\r
+//  It should contain boilerplate code only - no compiler specific\r
+//  code unless it is unavoidable - no changes unless unavoidable.\r
+\r
+#ifndef BOOST_CONFIG_SUFFIX_HPP\r
+#define BOOST_CONFIG_SUFFIX_HPP\r
+\r
+#if defined(__GNUC__) && (__GNUC__ >= 4)\r
+//\r
+// Some GCC-4.x versions issue warnings even when __extension__ is used,\r
+// so use this as a workaround:\r
+//\r
+#pragma GCC system_header\r
+#endif\r
+\r
+//\r
+// ensure that visibility macros are always defined, thus symplifying use\r
+//\r
+#ifndef BOOST_SYMBOL_EXPORT\r
+# define BOOST_SYMBOL_EXPORT\r
+#endif\r
+#ifndef BOOST_SYMBOL_IMPORT\r
+# define BOOST_SYMBOL_IMPORT\r
+#endif\r
+#ifndef BOOST_SYMBOL_VISIBLE\r
+# define BOOST_SYMBOL_VISIBLE\r
+#endif\r
+\r
+//\r
+// look for long long by looking for the appropriate macros in <limits.h>.\r
+// Note that we use limits.h rather than climits for maximal portability,\r
+// remember that since these just declare a bunch of macros, there should be\r
+// no namespace issues from this.\r
+//\r
+#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG)                                              \\r
+   && !defined(BOOST_MSVC) && !defined(__BORLANDC__)\r
+# include <limits.h>\r
+# if (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX))\r
+#   define BOOST_HAS_LONG_LONG\r
+# else\r
+#   define BOOST_NO_LONG_LONG\r
+# endif\r
+#endif\r
+\r
+// GCC 3.x will clean up all of those nasty macro definitions that\r
+// BOOST_NO_CTYPE_FUNCTIONS is intended to help work around, so undefine\r
+// it under GCC 3.x.\r
+#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(BOOST_NO_CTYPE_FUNCTIONS)\r
+#  undef BOOST_NO_CTYPE_FUNCTIONS\r
+#endif\r
+\r
+//\r
+// Assume any extensions are in namespace std:: unless stated otherwise:\r
+//\r
+#  ifndef BOOST_STD_EXTENSION_NAMESPACE\r
+#    define BOOST_STD_EXTENSION_NAMESPACE std\r
+#  endif\r
+\r
+//\r
+// If cv-qualified specializations are not allowed, then neither are cv-void ones:\r
+//\r
+#  if defined(BOOST_NO_CV_SPECIALIZATIONS) \\r
+      && !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)\r
+#     define BOOST_NO_CV_VOID_SPECIALIZATIONS\r
+#  endif\r
+\r
+//\r
+// If there is no numeric_limits template, then it can't have any compile time\r
+// constants either!\r
+//\r
+#  if defined(BOOST_NO_LIMITS) \\r
+      && !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)\r
+#     define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
+#     define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#     define BOOST_NO_LONG_LONG_NUMERIC_LIMITS\r
+#  endif\r
+\r
+//\r
+// if there is no long long then there is no specialisation\r
+// for numeric_limits<long long> either:\r
+//\r
+#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS)\r
+#  define BOOST_NO_LONG_LONG_NUMERIC_LIMITS\r
+#endif\r
+\r
+//\r
+// Normalize BOOST_NO_STATIC_ASSERT and (depricated) BOOST_HAS_STATIC_ASSERT:\r
+//\r
+#if !defined(BOOST_NO_STATIC_ASSERT) && !defined(BOOST_HAS_STATIC_ASSERT)\r
+#  define BOOST_HAS_STATIC_ASSERT\r
+#endif\r
+\r
+//\r
+// if there is no __int64 then there is no specialisation\r
+// for numeric_limits<__int64> either:\r
+//\r
+#if !defined(BOOST_HAS_MS_INT64) && !defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS)\r
+#  define BOOST_NO_MS_INT64_NUMERIC_LIMITS\r
+#endif\r
+\r
+//\r
+// if member templates are supported then so is the\r
+// VC6 subset of member templates:\r
+//\r
+#  if !defined(BOOST_NO_MEMBER_TEMPLATES) \\r
+       && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)\r
+#     define BOOST_MSVC6_MEMBER_TEMPLATES\r
+#  endif\r
+\r
+//\r
+// Without partial specialization, can't test for partial specialisation bugs:\r
+//\r
+#  if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \\r
+      && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG)\r
+#     define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG\r
+#  endif\r
+\r
+//\r
+// Without partial specialization, we can't have array-type partial specialisations:\r
+//\r
+#  if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \\r
+      && !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)\r
+#     define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS\r
+#  endif\r
+\r
+//\r
+// Without partial specialization, std::iterator_traits can't work:\r
+//\r
+#  if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \\r
+      && !defined(BOOST_NO_STD_ITERATOR_TRAITS)\r
+#     define BOOST_NO_STD_ITERATOR_TRAITS\r
+#  endif\r
+\r
+//\r
+// Without partial specialization, partial \r
+// specialization with default args won't work either:\r
+//\r
+#  if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \\r
+      && !defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS)\r
+#     define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS\r
+#  endif\r
+\r
+//\r
+// Without member template support, we can't have template constructors\r
+// in the standard library either:\r
+//\r
+#  if defined(BOOST_NO_MEMBER_TEMPLATES) \\r
+      && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \\r
+      && !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\r
+#     define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS\r
+#  endif\r
+\r
+//\r
+// Without member template support, we can't have a conforming\r
+// std::allocator template either:\r
+//\r
+#  if defined(BOOST_NO_MEMBER_TEMPLATES) \\r
+      && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \\r
+      && !defined(BOOST_NO_STD_ALLOCATOR)\r
+#     define BOOST_NO_STD_ALLOCATOR\r
+#  endif\r
+\r
+//\r
+// without ADL support then using declarations will break ADL as well:\r
+//\r
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)\r
+#  define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL\r
+#endif\r
+\r
+//\r
+// Without typeid support we have no dynamic RTTI either:\r
+//\r
+#if defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)\r
+#  define BOOST_NO_RTTI\r
+#endif\r
+\r
+//\r
+// If we have a standard allocator, then we have a partial one as well:\r
+//\r
+#if !defined(BOOST_NO_STD_ALLOCATOR)\r
+#  define BOOST_HAS_PARTIAL_STD_ALLOCATOR\r
+#endif\r
+\r
+//\r
+// We can't have a working std::use_facet if there is no std::locale:\r
+//\r
+#  if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_USE_FACET)\r
+#     define BOOST_NO_STD_USE_FACET\r
+#  endif\r
+\r
+//\r
+// We can't have a std::messages facet if there is no std::locale:\r
+//\r
+#  if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_MESSAGES)\r
+#     define BOOST_NO_STD_MESSAGES\r
+#  endif\r
+\r
+//\r
+// We can't have a working std::wstreambuf if there is no std::locale:\r
+//\r
+#  if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_WSTREAMBUF)\r
+#     define BOOST_NO_STD_WSTREAMBUF\r
+#  endif\r
+\r
+//\r
+// We can't have a <cwctype> if there is no <cwchar>:\r
+//\r
+#  if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_CWCTYPE)\r
+#     define BOOST_NO_CWCTYPE\r
+#  endif\r
+\r
+//\r
+// We can't have a swprintf if there is no <cwchar>:\r
+//\r
+#  if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF)\r
+#     define BOOST_NO_SWPRINTF\r
+#  endif\r
+\r
+//\r
+// If Win32 support is turned off, then we must turn off\r
+// threading support also, unless there is some other\r
+// thread API enabled:\r
+//\r
+#if defined(BOOST_DISABLE_WIN32) && defined(_WIN32) \\r
+   && !defined(BOOST_DISABLE_THREADS) && !defined(BOOST_HAS_PTHREADS)\r
+#  define BOOST_DISABLE_THREADS\r
+#endif\r
+\r
+//\r
+// Turn on threading support if the compiler thinks that it's in\r
+// multithreaded mode.  We put this here because there are only a\r
+// limited number of macros that identify this (if there's any missing\r
+// from here then add to the appropriate compiler section):\r
+//\r
+#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \\r
+    || defined(_PTHREADS) || defined(__APPLE__) || defined(__DragonFly__)) \\r
+    && !defined(BOOST_HAS_THREADS)\r
+#  define BOOST_HAS_THREADS\r
+#endif\r
+\r
+//\r
+// Turn threading support off if BOOST_DISABLE_THREADS is defined:\r
+//\r
+#if defined(BOOST_DISABLE_THREADS) && defined(BOOST_HAS_THREADS)\r
+#  undef BOOST_HAS_THREADS\r
+#endif\r
+\r
+//\r
+// Turn threading support off if we don't recognise the threading API:\r
+//\r
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_HAS_PTHREADS)\\r
+      && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_BETHREADS)\\r
+      && !defined(BOOST_HAS_MPTASKS)\r
+#  undef BOOST_HAS_THREADS\r
+#endif\r
+\r
+//\r
+// Turn threading detail macros off if we don't (want to) use threading\r
+//\r
+#ifndef BOOST_HAS_THREADS\r
+#  undef BOOST_HAS_PTHREADS\r
+#  undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE\r
+#  undef BOOST_HAS_PTHREAD_YIELD\r
+#  undef BOOST_HAS_PTHREAD_DELAY_NP\r
+#  undef BOOST_HAS_WINTHREADS\r
+#  undef BOOST_HAS_BETHREADS\r
+#  undef BOOST_HAS_MPTASKS\r
+#endif\r
+\r
+//\r
+// If the compiler claims to be C99 conformant, then it had better\r
+// have a <stdint.h>:\r
+//\r
+#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)\r
+#     define BOOST_HAS_STDINT_H\r
+#     ifndef BOOST_HAS_LOG1P\r
+#        define BOOST_HAS_LOG1P\r
+#     endif\r
+#     ifndef BOOST_HAS_EXPM1\r
+#        define BOOST_HAS_EXPM1\r
+#     endif\r
+#  endif\r
+\r
+//\r
+// Define BOOST_NO_SLIST and BOOST_NO_HASH if required.\r
+// Note that this is for backwards compatibility only.\r
+//\r
+#  if !defined(BOOST_HAS_SLIST) && !defined(BOOST_NO_SLIST)\r
+#     define BOOST_NO_SLIST\r
+#  endif\r
+\r
+#  if !defined(BOOST_HAS_HASH) && !defined(BOOST_NO_HASH)\r
+#     define BOOST_NO_HASH\r
+#  endif\r
+\r
+//\r
+// Set BOOST_SLIST_HEADER if not set already:\r
+//\r
+#if defined(BOOST_HAS_SLIST) && !defined(BOOST_SLIST_HEADER)\r
+#  define BOOST_SLIST_HEADER <slist>\r
+#endif\r
+\r
+//\r
+// Set BOOST_HASH_SET_HEADER if not set already:\r
+//\r
+#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_SET_HEADER)\r
+#  define BOOST_HASH_SET_HEADER <hash_set>\r
+#endif\r
+\r
+//\r
+// Set BOOST_HASH_MAP_HEADER if not set already:\r
+//\r
+#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_MAP_HEADER)\r
+#  define BOOST_HASH_MAP_HEADER <hash_map>\r
+#endif\r
+\r
+//\r
+// Set BOOST_NO_INITIALIZER_LISTS if there is no library support.\r
+//\r
+\r
+#if defined(BOOST_NO_0X_HDR_INITIALIZER_LIST) && !defined(BOOST_NO_INITIALIZER_LISTS)\r
+#  define BOOST_NO_INITIALIZER_LISTS\r
+#endif\r
+\r
+//\r
+// Set BOOST_HAS_RVALUE_REFS when BOOST_NO_RVALUE_REFERENCES is not defined\r
+//\r
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_HAS_RVALUE_REFS)\r
+#define BOOST_HAS_RVALUE_REFS\r
+#endif\r
+\r
+//\r
+// Set BOOST_HAS_VARIADIC_TMPL when BOOST_NO_VARIADIC_TEMPLATES is not defined\r
+//\r
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES) && !defined(BOOST_HAS_VARIADIC_TMPL)\r
+#define BOOST_HAS_VARIADIC_TMPL\r
+#endif\r
+\r
+//  BOOST_HAS_ABI_HEADERS\r
+//  This macro gets set if we have headers that fix the ABI,\r
+//  and prevent ODR violations when linking to external libraries:\r
+#if defined(BOOST_ABI_PREFIX) && defined(BOOST_ABI_SUFFIX) && !defined(BOOST_HAS_ABI_HEADERS)\r
+#  define BOOST_HAS_ABI_HEADERS\r
+#endif\r
+\r
+#if defined(BOOST_HAS_ABI_HEADERS) && defined(BOOST_DISABLE_ABI_HEADERS)\r
+#  undef BOOST_HAS_ABI_HEADERS\r
+#endif\r
+\r
+//  BOOST_NO_STDC_NAMESPACE workaround  --------------------------------------//\r
+//  Because std::size_t usage is so common, even in boost headers which do not\r
+//  otherwise use the C library, the <cstddef> workaround is included here so\r
+//  that ugly workaround code need not appear in many other boost headers.\r
+//  NOTE WELL: This is a workaround for non-conforming compilers; <cstddef>\r
+//  must still be #included in the usual places so that <cstddef> inclusion\r
+//  works as expected with standard conforming compilers.  The resulting\r
+//  double inclusion of <cstddef> is harmless.\r
+\r
+# ifdef BOOST_NO_STDC_NAMESPACE\r
+#   include <cstddef>\r
+    namespace std { using ::ptrdiff_t; using ::size_t; }\r
+# endif\r
+\r
+//  Workaround for the unfortunate min/max macros defined by some platform headers\r
+\r
+#define BOOST_PREVENT_MACRO_SUBSTITUTION\r
+\r
+#ifndef BOOST_USING_STD_MIN\r
+#  define BOOST_USING_STD_MIN() using std::min\r
+#endif\r
+\r
+#ifndef BOOST_USING_STD_MAX\r
+#  define BOOST_USING_STD_MAX() using std::max\r
+#endif\r
+\r
+//  BOOST_NO_STD_MIN_MAX workaround  -----------------------------------------//\r
+\r
+#  ifdef BOOST_NO_STD_MIN_MAX\r
+\r
+namespace std {\r
+  template <class _Tp>\r
+  inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {\r
+    return __b < __a ? __b : __a;\r
+  }\r
+  template <class _Tp>\r
+  inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {\r
+    return  __a < __b ? __b : __a;\r
+  }\r
+}\r
+\r
+#  endif\r
+\r
+// BOOST_STATIC_CONSTANT workaround --------------------------------------- //\r
+// On compilers which don't allow in-class initialization of static integral\r
+// constant members, we must use enums as a workaround if we want the constants\r
+// to be available at compile-time. This macro gives us a convenient way to\r
+// declare such constants.\r
+\r
+#  ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION\r
+#       define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment }\r
+#  else\r
+#     define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment\r
+#  endif\r
+\r
+// BOOST_USE_FACET / HAS_FACET workaround ----------------------------------//\r
+// When the standard library does not have a conforming std::use_facet there\r
+// are various workarounds available, but they differ from library to library.\r
+// The same problem occurs with has_facet.\r
+// These macros provide a consistent way to access a locale's facets.\r
+// Usage:\r
+//    replace\r
+//       std::use_facet<Type>(loc);\r
+//    with\r
+//       BOOST_USE_FACET(Type, loc);\r
+//    Note do not add a std:: prefix to the front of BOOST_USE_FACET!\r
+//  Use for BOOST_HAS_FACET is analogous.\r
+\r
+#if defined(BOOST_NO_STD_USE_FACET)\r
+#  ifdef BOOST_HAS_TWO_ARG_USE_FACET\r
+#     define BOOST_USE_FACET(Type, loc) std::use_facet(loc, static_cast<Type*>(0))\r
+#     define BOOST_HAS_FACET(Type, loc) std::has_facet(loc, static_cast<Type*>(0))\r
+#  elif defined(BOOST_HAS_MACRO_USE_FACET)\r
+#     define BOOST_USE_FACET(Type, loc) std::_USE(loc, Type)\r
+#     define BOOST_HAS_FACET(Type, loc) std::_HAS(loc, Type)\r
+#  elif defined(BOOST_HAS_STLP_USE_FACET)\r
+#     define BOOST_USE_FACET(Type, loc) (*std::_Use_facet<Type >(loc))\r
+#     define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc)\r
+#  endif\r
+#else\r
+#  define BOOST_USE_FACET(Type, loc) std::use_facet< Type >(loc)\r
+#  define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc)\r
+#endif\r
+\r
+// BOOST_NESTED_TEMPLATE workaround ------------------------------------------//\r
+// Member templates are supported by some compilers even though they can't use\r
+// the A::template member<U> syntax, as a workaround replace:\r
+//\r
+// typedef typename A::template rebind<U> binder;\r
+//\r
+// with:\r
+//\r
+// typedef typename A::BOOST_NESTED_TEMPLATE rebind<U> binder;\r
+\r
+#ifndef BOOST_NO_MEMBER_TEMPLATE_KEYWORD\r
+#  define BOOST_NESTED_TEMPLATE template\r
+#else\r
+#  define BOOST_NESTED_TEMPLATE\r
+#endif\r
+\r
+// BOOST_UNREACHABLE_RETURN(x) workaround -------------------------------------//\r
+// Normally evaluates to nothing, unless BOOST_NO_UNREACHABLE_RETURN_DETECTION\r
+// is defined, in which case it evaluates to return x; Use when you have a return\r
+// statement that can never be reached.\r
+\r
+#ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION\r
+#  define BOOST_UNREACHABLE_RETURN(x) return x;\r
+#else\r
+#  define BOOST_UNREACHABLE_RETURN(x)\r
+#endif\r
+\r
+// BOOST_DEDUCED_TYPENAME workaround ------------------------------------------//\r
+//\r
+// Some compilers don't support the use of `typename' for dependent\r
+// types in deduced contexts, e.g.\r
+//\r
+//     template <class T> void f(T, typename T::type);\r
+//                                  ^^^^^^^^\r
+// Replace these declarations with:\r
+//\r
+//     template <class T> void f(T, BOOST_DEDUCED_TYPENAME T::type);\r
+\r
+#ifndef BOOST_NO_DEDUCED_TYPENAME\r
+#  define BOOST_DEDUCED_TYPENAME typename\r
+#else\r
+#  define BOOST_DEDUCED_TYPENAME\r
+#endif\r
+\r
+#ifndef BOOST_NO_TYPENAME_WITH_CTOR\r
+#  define BOOST_CTOR_TYPENAME typename\r
+#else\r
+#  define BOOST_CTOR_TYPENAME\r
+#endif\r
+\r
+// long long workaround ------------------------------------------//\r
+// On gcc (and maybe other compilers?) long long is alway supported\r
+// but it's use may generate either warnings (with -ansi), or errors\r
+// (with -pedantic -ansi) unless it's use is prefixed by __extension__\r
+//\r
+#if defined(BOOST_HAS_LONG_LONG)\r
+namespace boost{\r
+#  ifdef __GNUC__\r
+   __extension__ typedef long long long_long_type;\r
+   __extension__ typedef unsigned long long ulong_long_type;\r
+#  else\r
+   typedef long long long_long_type;\r
+   typedef unsigned long long ulong_long_type;\r
+#  endif\r
+}\r
+#endif\r
+\r
+// BOOST_[APPEND_]EXPLICIT_TEMPLATE_[NON_]TYPE macros --------------------------//\r
+//\r
+// Some compilers have problems with function templates whose template\r
+// parameters don't appear in the function parameter list (basically\r
+// they just link one instantiation of the template in the final\r
+// executable). These macros provide a uniform way to cope with the\r
+// problem with no effects on the calling syntax.\r
+\r
+// Example:\r
+//\r
+//  #include <iostream>\r
+//  #include <ostream>\r
+//  #include <typeinfo>\r
+//\r
+//  template <int n>\r
+//  void f() { std::cout << n << ' '; }\r
+//\r
+//  template <typename T>\r
+//  void g() { std::cout << typeid(T).name() << ' '; }\r
+//\r
+//  int main() {\r
+//    f<1>();\r
+//    f<2>();\r
+//\r
+//    g<int>();\r
+//    g<double>();\r
+//  }\r
+//\r
+// With VC++ 6.0 the output is:\r
+//\r
+//   2 2 double double\r
+//\r
+// To fix it, write\r
+//\r
+//   template <int n>\r
+//   void f(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, n)) { ... }\r
+//\r
+//   template <typename T>\r
+//   void g(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) { ... }\r
+//\r
+\r
+\r
+#if defined BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+\r
+#  include "boost/type.hpp"\r
+#  include "boost/non_type.hpp"\r
+\r
+#  define BOOST_EXPLICIT_TEMPLATE_TYPE(t)              boost::type<t>* = 0\r
+#  define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t)         boost::type<t>*\r
+#  define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v)       boost::non_type<t, v>* = 0\r
+#  define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)  boost::non_type<t, v>*\r
+\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)        \\r
+             , BOOST_EXPLICIT_TEMPLATE_TYPE(t)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t)   \\r
+             , BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) \\r
+             , BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)    \\r
+             , BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)\r
+\r
+#else\r
+\r
+// no workaround needed: expand to nothing\r
+\r
+#  define BOOST_EXPLICIT_TEMPLATE_TYPE(t)\r
+#  define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t)\r
+#  define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v)\r
+#  define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)\r
+\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v)\r
+#  define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)\r
+\r
+\r
+#endif // defined BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS\r
+\r
+// When BOOST_NO_STD_TYPEINFO is defined, we can just import\r
+// the global definition into std namespace:\r
+#ifdef BOOST_NO_STD_TYPEINFO\r
+#include <typeinfo>\r
+namespace std{ using ::type_info; }\r
+#endif\r
+\r
+// ---------------------------------------------------------------------------//\r
+\r
+//\r
+// Helper macro BOOST_STRINGIZE:\r
+// Converts the parameter X to a string after macro replacement\r
+// on X has been performed.\r
+//\r
+#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)\r
+#define BOOST_DO_STRINGIZE(X) #X\r
+\r
+//\r
+// Helper macro BOOST_JOIN:\r
+// The following piece of macro magic joins the two\r
+// arguments together, even when one of the arguments is\r
+// itself a macro (see 16.3.1 in C++ standard).  The key\r
+// is that macro expansion of macro arguments does not\r
+// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN.\r
+//\r
+#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )\r
+#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)\r
+#define BOOST_DO_JOIN2( X, Y ) X##Y\r
+\r
+//\r
+// Set some default values for compiler/library/platform names.\r
+// These are for debugging config setup only:\r
+//\r
+#  ifndef BOOST_COMPILER\r
+#     define BOOST_COMPILER "Unknown ISO C++ Compiler"\r
+#  endif\r
+#  ifndef BOOST_STDLIB\r
+#     define BOOST_STDLIB "Unknown ISO standard library"\r
+#  endif\r
+#  ifndef BOOST_PLATFORM\r
+#     if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) \\r
+         || defined(_POSIX_SOURCE)\r
+#        define BOOST_PLATFORM "Generic Unix"\r
+#     else\r
+#        define BOOST_PLATFORM "Unknown"\r
+#     endif\r
+#  endif\r
+\r
+//\r
+// Set some default values GPU support\r
+//\r
+#  ifndef BOOST_GPU_ENABLED\r
+#  define BOOST_GPU_ENABLED \r
+#  endif\r
+\r
+//\r
+// constexpr workarounds\r
+// \r
+#if defined(BOOST_NO_CONSTEXPR)\r
+#define BOOST_CONSTEXPR\r
+#define BOOST_CONSTEXPR_OR_CONST const\r
+#else\r
+#define BOOST_CONSTEXPR constexpr\r
+#define BOOST_CONSTEXPR_OR_CONST constexpr\r
+#endif\r
+\r
+#define BOOST_STATIC_CONSTEXPR  static BOOST_CONSTEXPR_OR_CONST\r
+\r
+#endif\r
+\r
diff --git a/src/external/boost/boost/config/user.hpp b/src/external/boost/boost/config/user.hpp
new file mode 100644 (file)
index 0000000..3b998d1
--- /dev/null
@@ -0,0 +1,124 @@
+//  boost/config/user.hpp  ---------------------------------------------------//\r
+\r
+//  (C) Copyright John Maddock 2001. \r
+//  Use, modification and distribution are subject to the \r
+//  Boost Software License, Version 1.0. (See accompanying file \r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  Do not check in modified versions of this file,\r
+//  This file may be customized by the end user, but not by boost.\r
+\r
+//\r
+//  Use this file to define a site and compiler specific\r
+//  configuration policy:\r
+//\r
+\r
+// define this to locate a compiler config file:\r
+// #define BOOST_COMPILER_CONFIG <myheader>\r
+\r
+// define this to locate a stdlib config file:\r
+// #define BOOST_STDLIB_CONFIG   <myheader>\r
+\r
+// define this to locate a platform config file:\r
+// #define BOOST_PLATFORM_CONFIG <myheader>\r
+\r
+// define this to disable compiler config,\r
+// use if your compiler config has nothing to set:\r
+// #define BOOST_NO_COMPILER_CONFIG\r
+\r
+// define this to disable stdlib config,\r
+// use if your stdlib config has nothing to set:\r
+// #define BOOST_NO_STDLIB_CONFIG\r
+\r
+// define this to disable platform config,\r
+// use if your platform config has nothing to set:\r
+// #define BOOST_NO_PLATFORM_CONFIG\r
+\r
+// define this to disable all config options,\r
+// excluding the user config.  Use if your\r
+// setup is fully ISO compliant, and has no\r
+// useful extensions, or for autoconf generated\r
+// setups:\r
+// #define BOOST_NO_CONFIG\r
+\r
+// define this to make the config "optimistic"\r
+// about unknown compiler versions.  Normally\r
+// unknown compiler versions are assumed to have\r
+// all the defects of the last known version, however\r
+// setting this flag, causes the config to assume\r
+// that unknown compiler versions are fully conformant\r
+// with the standard:\r
+// #define BOOST_STRICT_CONFIG\r
+\r
+// define this to cause the config to halt compilation\r
+// with an #error if it encounters anything unknown --\r
+// either an unknown compiler version or an unknown\r
+// compiler/platform/library:\r
+// #define BOOST_ASSERT_CONFIG\r
+\r
+\r
+// define if you want to disable threading support, even\r
+// when available:\r
+// #define BOOST_DISABLE_THREADS\r
+\r
+// define when you want to disable Win32 specific features\r
+// even when available:\r
+// #define BOOST_DISABLE_WIN32\r
+\r
+// BOOST_DISABLE_ABI_HEADERS: Stops boost headers from including any \r
+// prefix/suffix headers that normally control things like struct \r
+// packing and alignment. \r
+// #define BOOST_DISABLE_ABI_HEADERS\r
+\r
+// BOOST_ABI_PREFIX: A prefix header to include in place of whatever\r
+// boost.config would normally select, any replacement should set up \r
+// struct packing and alignment options as required. \r
+// #define BOOST_ABI_PREFIX my-header-name\r
+\r
+// BOOST_ABI_SUFFIX: A suffix header to include in place of whatever \r
+// boost.config would normally select, any replacement should undo \r
+// the effects of the prefix header. \r
+// #define BOOST_ABI_SUFFIX my-header-name\r
+\r
+// BOOST_ALL_DYN_LINK: Forces all libraries that have separate source, \r
+// to be linked as dll's rather than static libraries on Microsoft Windows \r
+// (this macro is used to turn on __declspec(dllimport) modifiers, so that \r
+// the compiler knows which symbols to look for in a dll rather than in a \r
+// static library).  Note that there may be some libraries that can only \r
+// be statically linked (Boost.Test for example) and others which may only \r
+// be dynamically linked (Boost.Threads for example), in these cases this \r
+// macro has no effect.\r
+// #define BOOST_ALL_DYN_LINK\r
\r
+// BOOST_WHATEVER_DYN_LINK: Forces library "whatever" to be linked as a dll \r
+// rather than a static library on Microsoft Windows: replace the WHATEVER \r
+// part of the macro name with the name of the library that you want to \r
+// dynamically link to, for example use BOOST_DATE_TIME_DYN_LINK or \r
+// BOOST_REGEX_DYN_LINK etc (this macro is used to turn on __declspec(dllimport) \r
+// modifiers, so that the compiler knows which symbols to look for in a dll \r
+// rather than in a static library).  \r
+// Note that there may be some libraries that can only be statically linked \r
+// (Boost.Test for example) and others which may only be dynamically linked \r
+// (Boost.Threads for example), in these cases this macro is unsupported.\r
+// #define BOOST_WHATEVER_DYN_LINK\r
\r
+// BOOST_ALL_NO_LIB: Tells the config system not to automatically select \r
+// which libraries to link against.  \r
+// Normally if a compiler supports #pragma lib, then the correct library \r
+// build variant will be automatically selected and linked against, \r
+// simply by the act of including one of that library's headers.  \r
+// This macro turns that feature off.\r
+// #define BOOST_ALL_NO_LIB\r
\r
+// BOOST_WHATEVER_NO_LIB: Tells the config system not to automatically \r
+// select which library to link against for library "whatever", \r
+// replace WHATEVER in the macro name with the name of the library; \r
+// for example BOOST_DATE_TIME_NO_LIB or BOOST_REGEX_NO_LIB.  \r
+// Normally if a compiler supports #pragma lib, then the correct library \r
+// build variant will be automatically selected and linked against, simply \r
+// by the act of including one of that library's headers.  This macro turns \r
+// that feature off.\r
+// #define BOOST_WHATEVER_NO_LIB\r
\r
+\r
+\r
diff --git a/src/external/boost/boost/config/warning_disable.hpp b/src/external/boost/boost/config/warning_disable.hpp
new file mode 100644 (file)
index 0000000..8fd46ff
--- /dev/null
@@ -0,0 +1,47 @@
+//  Copyright John Maddock 2008\r
+//  Use, modification, and distribution is subject to the Boost Software\r
+//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  This file exists to turn off some overly-pedantic warning emitted\r
+//  by certain compilers.  You should include this header only in:\r
+//\r
+//  * A test case, before any other headers, or,\r
+//  * A library source file before any other headers.\r
+//\r
+//  IT SHOULD NOT BE INCLUDED BY ANY BOOST HEADER.\r
+//\r
+//  YOU SHOULD NOT INCLUDE IT IF YOU CAN REASONABLY FIX THE WARNING.\r
+//\r
+//  The only warnings disabled here are those that are:\r
+//\r
+//  * Quite unreasonably pedantic.\r
+//  * Generally only emitted by a single compiler.\r
+//  * Can't easily be fixed: for example if the vendors own std lib \r
+//    code emits these warnings!\r
+//\r
+//  Note that THIS HEADER MUST NOT INCLUDE ANY OTHER HEADERS:\r
+//  not even std library ones!  Doing so may turn the warning\r
+//  off too late to be of any use.  For example the VC++ C4996\r
+//  warning can be omitted from <iosfwd> if that header is included\r
+//  before or by this one :-(\r
+//\r
+\r
+#ifndef BOOST_CONFIG_WARNING_DISABLE_HPP\r
+#define BOOST_CONFIG_WARNING_DISABLE_HPP\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) \r
+   // Error 'function': was declared deprecated\r
+   // http://msdn2.microsoft.com/en-us/library/ttcz0bys(VS.80).aspx\r
+   // This error is emitted when you use some perfectly conforming\r
+   // std lib functions in a perfectly correct way, and also by\r
+   // some of Microsoft's own std lib code !\r
+#  pragma warning(disable:4996)\r
+#endif\r
+#if defined(__INTEL_COMPILER) || defined(__ICL)\r
+   // As above: gives warning when a "deprecated"\r
+   // std library function is encountered.\r
+#  pragma warning(disable:1786)\r
+#endif\r
+\r
+#endif // BOOST_CONFIG_WARNING_DISABLE_HPP\r
diff --git a/src/external/boost/boost/current_function.hpp b/src/external/boost/boost/current_function.hpp
new file mode 100644 (file)
index 0000000..3714e9e
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED\r
+#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/current_function.hpp - BOOST_CURRENT_FUNCTION\r
+//\r
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  http://www.boost.org/libs/utility/current_function.html\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void current_function_helper()\r
+{\r
+\r
+#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))\r
+\r
+# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__\r
+\r
+#elif defined(__DMC__) && (__DMC__ >= 0x810)\r
+\r
+# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__\r
+\r
+#elif defined(__FUNCSIG__)\r
+\r
+# define BOOST_CURRENT_FUNCTION __FUNCSIG__\r
+\r
+#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))\r
+\r
+# define BOOST_CURRENT_FUNCTION __FUNCTION__\r
+\r
+#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)\r
+\r
+# define BOOST_CURRENT_FUNCTION __FUNC__\r
+\r
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)\r
+\r
+# define BOOST_CURRENT_FUNCTION __func__\r
+\r
+#else\r
+\r
+# define BOOST_CURRENT_FUNCTION "(unknown)"\r
+\r
+#endif\r
+\r
+}\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/detail/interlocked.hpp b/src/external/boost/boost/detail/interlocked.hpp
new file mode 100644 (file)
index 0000000..e3f5086
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED\r
+#define BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/interlocked.hpp\r
+//\r
+//  Copyright 2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/config.hpp>\r
+\r
+#if defined( BOOST_USE_WINDOWS_H )\r
+\r
+# include <windows.h>\r
+\r
+# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement\r
+# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER InterlockedCompareExchangePointer\r
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER InterlockedExchangePointer\r
+\r
+#elif defined(_WIN32_WCE)\r
+\r
+// under Windows CE we still have old-style Interlocked* functions\r
+\r
+extern "C" long __cdecl InterlockedIncrement( long* );\r
+extern "C" long __cdecl InterlockedDecrement( long* );\r
+extern "C" long __cdecl InterlockedCompareExchange( long*, long, long );\r
+extern "C" long __cdecl InterlockedExchange( long*, long );\r
+extern "C" long __cdecl InterlockedExchangeAdd( long*, long );\r
+\r
+# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement\r
+# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd\r
+\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \\r
+    ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest),(long)(exchange),(long)(compare)))\r
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \\r
+    ((void*)BOOST_INTERLOCKED_EXCHANGE((long*)(dest),(long)(exchange)))\r
+\r
+#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN )\r
+\r
+#if defined( __CLRCALL_PURE_OR_CDECL )\r
+\r
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedIncrement( long volatile * );\r
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedDecrement( long volatile * );\r
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( long volatile *, long, long );\r
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchange( long volatile *, long );\r
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( long volatile *, long );\r
+\r
+#else\r
+\r
+extern "C" long __cdecl _InterlockedIncrement( long volatile * );\r
+extern "C" long __cdecl _InterlockedDecrement( long volatile * );\r
+extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );\r
+extern "C" long __cdecl _InterlockedExchange( long volatile *, long );\r
+extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );\r
+\r
+#endif\r
+\r
+# pragma intrinsic( _InterlockedIncrement )\r
+# pragma intrinsic( _InterlockedDecrement )\r
+# pragma intrinsic( _InterlockedCompareExchange )\r
+# pragma intrinsic( _InterlockedExchange )\r
+# pragma intrinsic( _InterlockedExchangeAdd )\r
+\r
+# if defined(_M_IA64) || defined(_M_AMD64)\r
+\r
+extern "C" void* __cdecl _InterlockedCompareExchangePointer( void* volatile *, void*, void* );\r
+extern "C" void* __cdecl _InterlockedExchangePointer( void* volatile *, void* );\r
+\r
+#  pragma intrinsic( _InterlockedCompareExchangePointer )\r
+#  pragma intrinsic( _InterlockedExchangePointer )\r
+\r
+#  define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER _InterlockedCompareExchangePointer\r
+#  define BOOST_INTERLOCKED_EXCHANGE_POINTER _InterlockedExchangePointer\r
+\r
+# else\r
+\r
+#  define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \\r
+    ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare)))\r
+#  define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \\r
+    ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange)))\r
+\r
+# endif\r
+\r
+# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement\r
+# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE _InterlockedExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd\r
+\r
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * );\r
+extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * );\r
+extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long );\r
+extern "C" __declspec(dllimport) long __stdcall InterlockedExchange( long volatile *, long );\r
+extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd( long volatile *, long );\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+# define BOOST_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement\r
+# define BOOST_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange\r
+# define BOOST_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd\r
+\r
+# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \\r
+    ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare)))\r
+# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \\r
+    ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange)))\r
+\r
+#else\r
+\r
+# error "Interlocked intrinsics not available"\r
+\r
+#endif\r
+\r
+#endif // #ifndef BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/detail/lightweight_mutex.hpp b/src/external/boost/boost/detail/lightweight_mutex.hpp
new file mode 100644 (file)
index 0000000..79cd0b2
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
+#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/lightweight_mutex.hpp - lightweight mutex\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+//\r
+\r
+#include <boost/smart_ptr/detail/lightweight_mutex.hpp>\r
+\r
+#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/detail/sp_typeinfo.hpp b/src/external/boost/boost/detail/sp_typeinfo.hpp
new file mode 100644 (file)
index 0000000..50da7aa
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED\r
+#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//  detail/sp_typeinfo.hpp\r
+//\r
+//  Copyright 2007 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#include <boost/config.hpp>\r
+\r
+#if defined( BOOST_NO_TYPEID )\r
+\r
+#include <boost/current_function.hpp>\r
+#include <functional>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class sp_typeinfo\r
+{\r
+private:\r
+\r
+    sp_typeinfo( sp_typeinfo const& );\r
+    sp_typeinfo& operator=( sp_typeinfo const& );\r
+\r
+    char const * name_;\r
+\r
+public:\r
+\r
+    explicit sp_typeinfo( char const * name ): name_( name )\r
+    {\r
+    }\r
+\r
+    bool operator==( sp_typeinfo const& rhs ) const\r
+    {\r
+        return this == &rhs;\r
+    }\r
+\r
+    bool operator!=( sp_typeinfo const& rhs ) const\r
+    {\r
+        return this != &rhs;\r
+    }\r
+\r
+    bool before( sp_typeinfo const& rhs ) const\r
+    {\r
+        return std::less< sp_typeinfo const* >()( this, &rhs );\r
+    }\r
+\r
+    char const* name() const\r
+    {\r
+        return name_;\r
+    }\r
+};\r
+\r
+template<class T> struct sp_typeid_\r
+{\r
+    static sp_typeinfo ti_;\r
+\r
+    static char const * name()\r
+    {\r
+        return BOOST_CURRENT_FUNCTION;\r
+    }\r
+};\r
+\r
+#if defined(__SUNPRO_CC)\r
+// see #4199, the Sun Studio compiler gets confused about static initialization \r
+// constructor arguments. But an assignment works just fine. \r
+template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();\r
+#else\r
+template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());\r
+#endif\r
+\r
+template<class T> struct sp_typeid_< T & >: sp_typeid_< T >\r
+{\r
+};\r
+\r
+template<class T> struct sp_typeid_< T const >: sp_typeid_< T >\r
+{\r
+};\r
+\r
+template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >\r
+{\r
+};\r
+\r
+template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >\r
+{\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)\r
+\r
+#else\r
+\r
+#include <typeinfo>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#if defined( BOOST_NO_STD_TYPEINFO )\r
+\r
+typedef ::type_info sp_typeinfo;\r
+\r
+#else\r
+\r
+typedef std::type_info sp_typeinfo;\r
+\r
+#endif\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#define BOOST_SP_TYPEID(T) typeid(T)\r
+\r
+#endif\r
+\r
+#endif  // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/detail/workaround.hpp b/src/external/boost/boost/detail/workaround.hpp
new file mode 100644 (file)
index 0000000..92cf7c1
--- /dev/null
@@ -0,0 +1,267 @@
+// Copyright David Abrahams 2002.\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+#ifndef WORKAROUND_DWA2002126_HPP\r
+# define WORKAROUND_DWA2002126_HPP\r
+\r
+// Compiler/library version workaround macro\r
+//\r
+// Usage:\r
+//\r
+//     #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)\r
+//        // workaround for eVC4 and VC6\r
+//        ... // workaround code here\r
+//     #endif\r
+//\r
+// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the\r
+// first argument must be undefined or expand to a numeric\r
+// value. The above expands to:\r
+//\r
+//     (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300\r
+//\r
+// When used for workarounds that apply to the latest known version \r
+// and all earlier versions of a compiler, the following convention \r
+// should be observed:\r
+//\r
+//     #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301))\r
+//\r
+// The version number in this case corresponds to the last version in\r
+// which the workaround was known to have been required. When\r
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro\r
+// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates\r
+// the workaround for any version of the compiler. When\r
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or\r
+// error will be issued if the compiler version exceeds the argument\r
+// to BOOST_TESTED_AT().  This can be used to locate workarounds which\r
+// may be obsoleted by newer versions.\r
+\r
+# ifndef BOOST_STRICT_CONFIG\r
+\r
+#include <boost/config.hpp>\r
+\r
+#ifndef __BORLANDC__\r
+#define __BORLANDC___WORKAROUND_GUARD 1\r
+#else\r
+#define __BORLANDC___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __CODEGEARC__\r
+#define __CODEGEARC___WORKAROUND_GUARD 1\r
+#else\r
+#define __CODEGEARC___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _MSC_VER\r
+#define _MSC_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define _MSC_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _MSC_FULL_VER\r
+#define _MSC_FULL_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define _MSC_FULL_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_MSVC\r
+#define BOOST_MSVC_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_MSVC_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_MSVC_FULL_VER\r
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __GNUC__\r
+#define __GNUC___WORKAROUND_GUARD 1\r
+#else\r
+#define __GNUC___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __GNUC_MINOR__\r
+#define __GNUC_MINOR___WORKAROUND_GUARD 1\r
+#else\r
+#define __GNUC_MINOR___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __GNUC_PATCHLEVEL__\r
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1\r
+#else\r
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __IBMCPP__\r
+#define __IBMCPP___WORKAROUND_GUARD 1\r
+#else\r
+#define __IBMCPP___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __SUNPRO_CC\r
+#define __SUNPRO_CC_WORKAROUND_GUARD 1\r
+#else\r
+#define __SUNPRO_CC_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __DECCXX_VER\r
+#define __DECCXX_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define __DECCXX_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __MWERKS__\r
+#define __MWERKS___WORKAROUND_GUARD 1\r
+#else\r
+#define __MWERKS___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __EDG__\r
+#define __EDG___WORKAROUND_GUARD 1\r
+#else\r
+#define __EDG___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __EDG_VERSION__\r
+#define __EDG_VERSION___WORKAROUND_GUARD 1\r
+#else\r
+#define __EDG_VERSION___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __HP_aCC\r
+#define __HP_aCC_WORKAROUND_GUARD 1\r
+#else\r
+#define __HP_aCC_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __hpxstd98\r
+#define __hpxstd98_WORKAROUND_GUARD 1\r
+#else\r
+#define __hpxstd98_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _CRAYC\r
+#define _CRAYC_WORKAROUND_GUARD 1\r
+#else\r
+#define _CRAYC_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __DMC__\r
+#define __DMC___WORKAROUND_GUARD 1\r
+#else\r
+#define __DMC___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef MPW_CPLUS\r
+#define MPW_CPLUS_WORKAROUND_GUARD 1\r
+#else\r
+#define MPW_CPLUS_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __COMO__\r
+#define __COMO___WORKAROUND_GUARD 1\r
+#else\r
+#define __COMO___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __COMO_VERSION__\r
+#define __COMO_VERSION___WORKAROUND_GUARD 1\r
+#else\r
+#define __COMO_VERSION___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __INTEL_COMPILER\r
+#define __INTEL_COMPILER_WORKAROUND_GUARD 1\r
+#else\r
+#define __INTEL_COMPILER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __ICL\r
+#define __ICL_WORKAROUND_GUARD 1\r
+#else\r
+#define __ICL_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _COMPILER_VERSION\r
+#define _COMPILER_VERSION_WORKAROUND_GUARD 1\r
+#else\r
+#define _COMPILER_VERSION_WORKAROUND_GUARD 0\r
+#endif\r
+\r
+#ifndef _RWSTD_VER\r
+#define _RWSTD_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define _RWSTD_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_RWSTD_VER\r
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __GLIBCPP__\r
+#define __GLIBCPP___WORKAROUND_GUARD 1\r
+#else\r
+#define __GLIBCPP___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC\r
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1\r
+#else\r
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __SGI_STL_PORT\r
+#define __SGI_STL_PORT_WORKAROUND_GUARD 1\r
+#else\r
+#define __SGI_STL_PORT_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _STLPORT_VERSION\r
+#define _STLPORT_VERSION_WORKAROUND_GUARD 1\r
+#else\r
+#define _STLPORT_VERSION_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef __LIBCOMO_VERSION__\r
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 1\r
+#else\r
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef _CPPLIB_VER\r
+#define _CPPLIB_VER_WORKAROUND_GUARD 1\r
+#else\r
+#define _CPPLIB_VER_WORKAROUND_GUARD 0\r
+#endif\r
+\r
+#ifndef BOOST_INTEL_CXX_VERSION\r
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_INTEL_WIN\r
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_DINKUMWARE_STDLIB\r
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0\r
+#endif\r
+#ifndef BOOST_INTEL\r
+#define BOOST_INTEL_WORKAROUND_GUARD 1\r
+#else\r
+#define BOOST_INTEL_WORKAROUND_GUARD 0\r
+#endif\r
+// Always define to zero, if it's used it'll be defined my MPL:\r
+#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0\r
+\r
+#  define BOOST_WORKAROUND(symbol, test)                \\r
+         ((symbol ## _WORKAROUND_GUARD + 0 == 0) &&     \\r
+         (symbol != 0) && (1 % (( (symbol test) ) + 1)))\r
+//                              ^ ^           ^ ^\r
+// The extra level of parenthesis nesting above, along with the\r
+// BOOST_OPEN_PAREN indirection below, is required to satisfy the\r
+// broken preprocessor in MWCW 8.3 and earlier.\r
+//\r
+// The basic mechanism works as follows:\r
+//      (symbol test) + 1        =>   if (symbol test) then 2 else 1\r
+//      1 % ((symbol test) + 1)  =>   if (symbol test) then 1 else 0\r
+//\r
+// The complication with % is for cooperation with BOOST_TESTED_AT().\r
+// When "test" is BOOST_TESTED_AT(x) and\r
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined,\r
+//\r
+//      symbol test              =>   if (symbol <= x) then 1 else -1\r
+//      (symbol test) + 1        =>   if (symbol <= x) then 2 else 0\r
+//      1 % ((symbol test) + 1)  =>   if (symbol <= x) then 1 else divide-by-zero\r
+//\r
+\r
+#  ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS\r
+#   define BOOST_OPEN_PAREN (\r
+#   define BOOST_TESTED_AT(value)  > value) ?(-1): BOOST_OPEN_PAREN 1\r
+#  else\r
+#   define BOOST_TESTED_AT(value) != ((value)-(value))\r
+#  endif\r
+\r
+# else\r
+\r
+#  define BOOST_WORKAROUND(symbol, test) 0\r
+\r
+# endif \r
+\r
+#endif // WORKAROUND_DWA2002126_HPP\r
diff --git a/src/external/boost/boost/exception/all.hpp b/src/external/boost/boost/exception/all.hpp
new file mode 100644 (file)
index 0000000..b2fb63a
--- /dev/null
@@ -0,0 +1,36 @@
+//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_316FDA946C0D11DEA9CBAE5255D89593\r
+#define UUID_316FDA946C0D11DEA9CBAE5255D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/exception/diagnostic_information.hpp>\r
+#include <boost/exception/error_info.hpp>\r
+#include <boost/exception/exception.hpp>\r
+#include <boost/exception/get_error_info.hpp>\r
+#include <boost/exception/info.hpp>\r
+//GMX_REMOVED: #include <boost/exception/info_tuple.hpp>\r
+#include <boost/exception/errinfo_api_function.hpp>\r
+#include <boost/exception/errinfo_at_line.hpp>\r
+#include <boost/exception/errinfo_errno.hpp>\r
+#include <boost/exception/errinfo_file_handle.hpp>\r
+#include <boost/exception/errinfo_file_name.hpp>\r
+#include <boost/exception/errinfo_file_open_mode.hpp>\r
+#include <boost/exception/errinfo_type_info_name.hpp>\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+#include <boost/exception/errinfo_nested_exception.hpp>\r
+#include <boost/exception_ptr.hpp>\r
+#endif\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/current_exception_cast.hpp b/src/external/boost/boost/exception/current_exception_cast.hpp
new file mode 100644 (file)
index 0000000..bc7f97a
--- /dev/null
@@ -0,0 +1,43 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_7E83C166200811DE885E826156D89593\r
+#define UUID_7E83C166200811DE885E826156D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class E>\r
+    inline\r
+    E *\r
+    current_exception_cast()\r
+        {\r
+        try\r
+            {\r
+            throw;\r
+            }\r
+        catch(\r
+        E & e )\r
+            {\r
+            return &e;\r
+            }\r
+        catch(\r
+        ...)\r
+            {\r
+            return 0;\r
+            }\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/attribute_noreturn.hpp b/src/external/boost/boost/exception/detail/attribute_noreturn.hpp
new file mode 100644 (file)
index 0000000..f397790
--- /dev/null
@@ -0,0 +1,17 @@
+//Copyright (c) 2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_61531AB0680611DEADD5846855D89593\r
+#define UUID_61531AB0680611DEADD5846855D89593\r
+\r
+#if defined(_MSC_VER)\r
+#define BOOST_ATTRIBUTE_NORETURN __declspec(noreturn)\r
+#elif defined(__GNUC__)\r
+#define BOOST_ATTRIBUTE_NORETURN __attribute__((noreturn))\r
+#else\r
+#define BOOST_ATTRIBUTE_NORETURN\r
+#endif\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/error_info_impl.hpp b/src/external/boost/boost/exception/detail/error_info_impl.hpp
new file mode 100644 (file)
index 0000000..f4fe8ba
--- /dev/null
@@ -0,0 +1,75 @@
+//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_CE6983AC753411DDA764247956D89593\r
+#define UUID_CE6983AC753411DDA764247956D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <string>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        class\r
+        error_info_base\r
+            {\r
+            public:\r
+\r
+            virtual std::string tag_typeid_name() const = 0;\r
+            virtual std::string value_as_string() const = 0;\r
+\r
+            protected:\r
+\r
+            ~error_info_base() throw()\r
+                {\r
+                }\r
+            };\r
+        }\r
+\r
+    template <class Tag,class T>\r
+    class\r
+    error_info:\r
+        public exception_detail::error_info_base\r
+        {\r
+        public:\r
+\r
+        typedef T value_type;\r
+\r
+        error_info( value_type const & value );\r
+        ~error_info() throw();\r
+\r
+        value_type const &\r
+        value() const\r
+            {\r
+            return value_;\r
+            }\r
+\r
+        value_type &\r
+        value()\r
+            {\r
+            return value_;\r
+            }\r
+\r
+        private:\r
+\r
+        std::string tag_typeid_name() const;\r
+        std::string value_as_string() const;\r
+\r
+        value_type value_;\r
+        };\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/exception_ptr.hpp b/src/external/boost/boost/exception/detail/exception_ptr.hpp
new file mode 100644 (file)
index 0000000..29974b2
--- /dev/null
@@ -0,0 +1,431 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_618474C2DE1511DEB74A388C56D89593\r
+#define UUID_618474C2DE1511DEB74A388C56D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/config.hpp>\r
+#ifdef BOOST_NO_EXCEPTIONS\r
+#error This header requires exception handling to be enabled.\r
+#endif\r
+#include <boost/exception/exception.hpp>\r
+#include <boost/exception/info.hpp>\r
+#include <boost/exception/diagnostic_information.hpp>\r
+#include <boost/exception/detail/type_info.hpp>\r
+#include <boost/shared_ptr.hpp>\r
+#include <stdexcept>\r
+#include <new>\r
+#include <ios>\r
+\r
+namespace\r
+boost\r
+    {\r
+    typedef shared_ptr<exception_detail::clone_base const> exception_ptr;\r
+\r
+    exception_ptr current_exception();\r
+\r
+    template <class T>\r
+    inline\r
+    exception_ptr\r
+    copy_exception( T const & e )\r
+        {\r
+        try\r
+            {\r
+            throw enable_current_exception(e);\r
+            }\r
+        catch(\r
+        ... )\r
+            {\r
+            return current_exception();\r
+            }\r
+        }\r
+\r
+#ifndef BOOST_NO_RTTI\r
+    typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type;\r
+\r
+    inline\r
+    std::string\r
+    to_string( original_exception_type const & x )\r
+        {\r
+        return x.value()->name();\r
+        }\r
+#endif\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        struct\r
+        bad_alloc_:\r
+            boost::exception,\r
+            std::bad_alloc\r
+                {\r
+                };\r
+\r
+        template <int Dummy>\r
+        exception_ptr\r
+        get_bad_alloc()\r
+            {\r
+            bad_alloc_ ba;\r
+            exception_detail::clone_impl<bad_alloc_> c(ba);\r
+            c <<\r
+                throw_function(BOOST_CURRENT_FUNCTION) <<\r
+                throw_file(__FILE__) <<\r
+                throw_line(__LINE__);\r
+            static exception_ptr ep(new exception_detail::clone_impl<bad_alloc_>(c));\r
+            return ep;\r
+            }\r
+\r
+        template <int Dummy>\r
+        struct\r
+        exception_ptr_bad_alloc\r
+            {\r
+            static exception_ptr const e;\r
+            };\r
+\r
+        template <int Dummy>\r
+        exception_ptr const\r
+        exception_ptr_bad_alloc<Dummy>::\r
+        e = get_bad_alloc<Dummy>();\r
+        }\r
+\r
+    class\r
+    unknown_exception:\r
+        public boost::exception,\r
+        public std::exception\r
+        {\r
+        public:\r
+\r
+        unknown_exception()\r
+            {\r
+            }\r
+\r
+        explicit\r
+        unknown_exception( std::exception const & e )\r
+            {\r
+            add_original_type(e);\r
+            }\r
+\r
+        explicit\r
+        unknown_exception( boost::exception const & e ):\r
+            boost::exception(e)\r
+            {\r
+            add_original_type(e);\r
+            }\r
+\r
+        ~unknown_exception() throw()\r
+            {\r
+            }\r
+\r
+        private:\r
+\r
+        template <class E>\r
+        void\r
+        add_original_type( E const & e )\r
+            {\r
+#ifndef BOOST_NO_RTTI\r
+            (*this) << original_exception_type(&typeid(e));\r
+#endif\r
+            }\r
+        };\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class T>\r
+        class\r
+        current_exception_std_exception_wrapper:\r
+            public T,\r
+            public boost::exception\r
+            {\r
+            public:\r
+\r
+            explicit\r
+            current_exception_std_exception_wrapper( T const & e1 ):\r
+                T(e1)\r
+                {\r
+                add_original_type(e1);\r
+                }\r
+\r
+            current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ):\r
+                T(e1),\r
+                boost::exception(e2)\r
+                {\r
+                add_original_type(e1);\r
+                }\r
+\r
+            ~current_exception_std_exception_wrapper() throw()\r
+                {\r
+                }\r
+\r
+            private:\r
+\r
+            template <class E>\r
+            void\r
+            add_original_type( E const & e )\r
+                {\r
+#ifndef BOOST_NO_RTTI\r
+                (*this) << original_exception_type(&typeid(e));\r
+#endif\r
+                }\r
+            };\r
+\r
+#ifdef BOOST_NO_RTTI\r
+        template <class T>\r
+        boost::exception const *\r
+        get_boost_exception( T const * )\r
+            {\r
+            try\r
+                {\r
+                throw;\r
+                }\r
+            catch(\r
+            boost::exception & x )\r
+                {\r
+                return &x;\r
+                }\r
+            catch(...)\r
+                {\r
+                return 0;\r
+                }\r
+            }\r
+#else\r
+        template <class T>\r
+        boost::exception const *\r
+        get_boost_exception( T const * x )\r
+            {\r
+            return dynamic_cast<boost::exception const *>(x);\r
+            }\r
+#endif\r
+\r
+        template <class T>\r
+        inline\r
+        exception_ptr\r
+        current_exception_std_exception( T const & e1 )\r
+            {\r
+            if( boost::exception const * e2 = get_boost_exception(&e1) )\r
+                return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1,*e2));\r
+            else\r
+                return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1));\r
+            }\r
+\r
+        inline\r
+        exception_ptr\r
+        current_exception_unknown_exception()\r
+            {\r
+            return boost::copy_exception(unknown_exception());\r
+            }\r
+\r
+        inline\r
+        exception_ptr\r
+        current_exception_unknown_boost_exception( boost::exception const & e )\r
+            {\r
+            return boost::copy_exception(unknown_exception(e));\r
+            }\r
+\r
+        inline\r
+        exception_ptr\r
+        current_exception_unknown_std_exception( std::exception const & e )\r
+            {\r
+            if( boost::exception const * be = get_boost_exception(&e) )\r
+                return current_exception_unknown_boost_exception(*be);\r
+            else\r
+                return boost::copy_exception(unknown_exception(e));\r
+            }\r
+\r
+        inline\r
+        exception_ptr\r
+        current_exception_impl()\r
+            {\r
+            try\r
+                {\r
+                throw;\r
+                }\r
+            catch(\r
+            exception_detail::clone_base & e )\r
+                {\r
+                return exception_ptr(e.clone());\r
+                }\r
+            catch(\r
+            std::domain_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::invalid_argument & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::length_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::out_of_range & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::logic_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::range_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::overflow_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::underflow_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::ios_base::failure & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::runtime_error & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::bad_alloc & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+#ifndef BOOST_NO_TYPEID\r
+            catch(\r
+            std::bad_cast & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::bad_typeid & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+#endif\r
+            catch(\r
+            std::bad_exception & e )\r
+                {\r
+                return exception_detail::current_exception_std_exception(e);\r
+                }\r
+            catch(\r
+            std::exception & e )\r
+                {\r
+                return exception_detail::current_exception_unknown_std_exception(e);\r
+                }\r
+            catch(\r
+            boost::exception & e )\r
+                {\r
+                return exception_detail::current_exception_unknown_boost_exception(e);\r
+                }\r
+            catch(\r
+            ... )\r
+                {\r
+                return exception_detail::current_exception_unknown_exception();\r
+                }\r
+            }\r
+        }\r
+\r
+    inline\r
+    exception_ptr\r
+    current_exception()\r
+        {\r
+        exception_ptr ret;\r
+        BOOST_ASSERT(!ret);\r
+        try\r
+            {\r
+            ret=exception_detail::current_exception_impl();\r
+            }\r
+        catch(\r
+        std::bad_alloc & )\r
+            {\r
+            ret=exception_detail::exception_ptr_bad_alloc<42>::e;\r
+            }\r
+        catch(\r
+        ... )\r
+            {\r
+            try\r
+                {\r
+                ret=exception_detail::current_exception_std_exception(std::bad_exception());\r
+                }\r
+            catch(\r
+            std::bad_alloc & )\r
+                {\r
+                ret=exception_detail::exception_ptr_bad_alloc<42>::e;\r
+                }\r
+            catch(\r
+            ... )\r
+                {\r
+                BOOST_ASSERT(0);\r
+                }\r
+            }\r
+        BOOST_ASSERT(ret);\r
+        return ret;\r
+        }\r
+\r
+    inline\r
+    void\r
+    rethrow_exception( exception_ptr const & p )\r
+        {\r
+        BOOST_ASSERT(p);\r
+        p->rethrow();\r
+        }\r
+\r
+    inline\r
+    std::string\r
+    diagnostic_information( exception_ptr const & p )\r
+        {\r
+        if( p )\r
+            try\r
+                {\r
+                rethrow_exception(p);\r
+                }\r
+            catch(\r
+            ... )\r
+                {\r
+                return current_exception_diagnostic_information();\r
+                }\r
+        return "<empty>";\r
+        }\r
+\r
+    inline\r
+    std::string\r
+    to_string( exception_ptr const & p )\r
+        {\r
+        std::string s='\n'+diagnostic_information(p);\r
+        std::string padding("  ");\r
+        std::string r;\r
+        bool f=false;\r
+        for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i )\r
+            {\r
+            if( f )\r
+                r+=padding;\r
+            char c=*i;\r
+            r+=c;\r
+            f=(c=='\n');\r
+            }\r
+        return r;\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/is_output_streamable.hpp b/src/external/boost/boost/exception/detail/is_output_streamable.hpp
new file mode 100644 (file)
index 0000000..99d6c3e
--- /dev/null
@@ -0,0 +1,60 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_898984B4076411DD973EDFA055D89593\r
+#define UUID_898984B4076411DD973EDFA055D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <ostream>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    to_string_detail\r
+        {\r
+        struct\r
+        partial_ordering_helper1\r
+            {\r
+            template <class CharT,class Traits>\r
+            partial_ordering_helper1( std::basic_ostream<CharT,Traits> & );\r
+            };\r
+\r
+        struct\r
+        partial_ordering_helper2\r
+            {\r
+            template <class T>\r
+            partial_ordering_helper2( T const & );\r
+            };\r
+\r
+        char operator<<( partial_ordering_helper1, partial_ordering_helper2 );\r
+\r
+        template <class T,class CharT,class Traits>\r
+        struct\r
+        is_output_streamable_impl\r
+            {\r
+            static std::basic_ostream<CharT,Traits> & f();\r
+            static T const & g();\r
+            enum e { value=1!=(sizeof(f()<<g())) };\r
+            };\r
+        }\r
+\r
+    template <class T, class CharT=char, class Traits=std::char_traits<CharT> >\r
+    struct\r
+    is_output_streamable\r
+        {\r
+        enum e { value=to_string_detail::is_output_streamable_impl<T,CharT,Traits>::value };\r
+        };\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/object_hex_dump.hpp b/src/external/boost/boost/exception/detail/object_hex_dump.hpp
new file mode 100644 (file)
index 0000000..da0ba9e
--- /dev/null
@@ -0,0 +1,50 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_6F463AC838DF11DDA3E6909F56D89593\r
+#define UUID_6F463AC838DF11DDA3E6909F56D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/exception/detail/type_info.hpp>\r
+#include <iomanip>\r
+#include <ios>\r
+#include <string>\r
+#include <sstream>\r
+#include <cstdlib>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class T>\r
+        inline\r
+        std::string\r
+        object_hex_dump( T const & x, std::size_t max_size=16 )\r
+            {\r
+            std::ostringstream s;\r
+            s << "type: " << type_name<T>() << ", size: " << sizeof(T) << ", dump: ";\r
+            std::size_t n=sizeof(T)>max_size?max_size:sizeof(T);\r
+            s.fill('0');\r
+            s.width(2);\r
+            unsigned char const * b=reinterpret_cast<unsigned char const *>(&x);\r
+            s << std::setw(2) << std::hex << (unsigned int)*b;\r
+            for( unsigned char const * e=b+n; ++b!=e; )\r
+                s << " " << std::setw(2) << std::hex << (unsigned int)*b;\r
+            return s.str();\r
+            }\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/detail/type_info.hpp b/src/external/boost/boost/exception/detail/type_info.hpp
new file mode 100644 (file)
index 0000000..ebc3a9f
--- /dev/null
@@ -0,0 +1,83 @@
+//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_C3E1741C754311DDB2834CCA55D89593\r
+#define UUID_C3E1741C754311DDB2834CCA55D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <boost/current_function.hpp>\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_TYPEID\r
+//GMX_REMOVED #include <boost/units/detail/utility.hpp> -- doesn't support not having set BOOST_NO_TYPEID\r
+#endif\r
+#include <string>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class T>\r
+    inline\r
+    std::string\r
+    tag_type_name()\r
+        {\r
+#ifdef BOOST_NO_TYPEID\r
+        return BOOST_CURRENT_FUNCTION;\r
+#else\r
+        return units::detail::demangle(typeid(T*).name());\r
+#endif\r
+        }\r
+\r
+    template <class T>\r
+    inline\r
+    std::string\r
+    type_name()\r
+        {\r
+#ifdef BOOST_NO_TYPEID\r
+        return BOOST_CURRENT_FUNCTION;\r
+#else\r
+        return units::detail::demangle(typeid(T).name());\r
+#endif\r
+        }\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        struct\r
+        type_info_\r
+            {\r
+            detail::sp_typeinfo const & type_;\r
+\r
+            explicit\r
+            type_info_( detail::sp_typeinfo const & type ):\r
+                type_(type)\r
+                {\r
+                }\r
+\r
+            friend\r
+            bool\r
+            operator<( type_info_ const & a, type_info_ const & b )\r
+                {\r
+                return 0!=(a.type_.before(b.type_));\r
+                }\r
+            };\r
+        }\r
+    }\r
+\r
+#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T))\r
+\r
+#ifndef BOOST_NO_RTTI\r
+#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x))\r
+#endif\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/diagnostic_information.hpp b/src/external/boost/boost/exception/diagnostic_information.hpp
new file mode 100644 (file)
index 0000000..3c39e7d
--- /dev/null
@@ -0,0 +1,184 @@
+//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_0552D49838DD11DD90146B8956D89593\r
+#define UUID_0552D49838DD11DD90146B8956D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/exception/get_error_info.hpp>\r
+#include <boost/utility/enable_if.hpp>\r
+#ifndef BOOST_NO_RTTI\r
+#error GMX_REMOVED: #include <boost/units/detail/utility.hpp>  -- doesn't suport not having set NO_RTTI\r
+#endif\r
+#include <exception>\r
+#include <sstream>\r
+#include <string>\r
+\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+#include <boost/exception/current_exception_cast.hpp>\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        std::string diagnostic_information_impl( boost::exception const *, std::exception const *, bool );\r
+        }\r
+\r
+    inline\r
+    std::string\r
+    current_exception_diagnostic_information()\r
+        {\r
+        boost::exception const * be=current_exception_cast<boost::exception const>();\r
+        std::exception const * se=current_exception_cast<std::exception const>();\r
+        if( be || se )\r
+            return exception_detail::diagnostic_information_impl(be,se,true);\r
+        else\r
+            return "No diagnostic information available.";\r
+        }\r
+    }\r
+#endif\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        inline\r
+        exception const *\r
+        get_boost_exception( exception const * e )\r
+            {\r
+            return e;\r
+            }\r
+\r
+        inline\r
+        exception const *\r
+        get_boost_exception( ... )\r
+            {\r
+            return 0;\r
+            }\r
+\r
+        inline\r
+        std::exception const *\r
+        get_std_exception( std::exception const * e )\r
+            {\r
+            return e;\r
+            }\r
+\r
+        inline\r
+        std::exception const *\r
+        get_std_exception( ... )\r
+            {\r
+            return 0;\r
+            }\r
+\r
+        inline\r
+        char const *\r
+        get_diagnostic_information( exception const & x, char const * header )\r
+            {\r
+            if( error_info_container * c=x.data_.get() )\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+                try\r
+                    {\r
+#endif\r
+                    return c->diagnostic_information(header);\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+                    }\r
+                catch(...)\r
+                    {\r
+                    }\r
+#endif\r
+            return 0;\r
+            }\r
+\r
+        inline\r
+        std::string\r
+        diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what )\r
+            {\r
+            if( !be && !se )\r
+                return "Unknown exception.";\r
+#ifndef BOOST_NO_RTTI\r
+            if( !be )\r
+                be=dynamic_cast<boost::exception const *>(se);\r
+            if( !se )\r
+                se=dynamic_cast<std::exception const *>(be);\r
+#endif\r
+            char const * wh=0;\r
+            if( with_what && se )\r
+                {\r
+                wh=se->what();\r
+                if( be && exception_detail::get_diagnostic_information(*be,0)==wh )\r
+                    return wh;\r
+                }\r
+            std::ostringstream tmp;\r
+            if( be )\r
+                {\r
+                if( char const * const * f=get_error_info<throw_file>(*be) )\r
+                    {\r
+                    tmp << *f;\r
+                    if( int const * l=get_error_info<throw_line>(*be) )\r
+                        tmp << '(' << *l << "): ";\r
+                    }\r
+                tmp << "Throw in function ";\r
+                if( char const * const * fn=get_error_info<throw_function>(*be) )\r
+                    tmp << *fn;\r
+                else\r
+                    tmp << "(unknown)";\r
+                tmp << '\n';\r
+                }\r
+#ifndef BOOST_NO_RTTI\r
+            tmp << std::string("Dynamic exception type: ") <<\r
+                units::detail::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_.name()) << '\n';\r
+#endif\r
+            if( with_what && se )\r
+                tmp << "std::exception::what: " << wh << '\n';\r
+            if( be )\r
+                if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) )\r
+                    if( *s )\r
+                        return s;\r
+            return tmp.str();\r
+            }\r
+        }\r
+\r
+    template <class T>\r
+    std::string\r
+    diagnostic_information( T const & e )\r
+        {\r
+        return exception_detail::diagnostic_information_impl(exception_detail::get_boost_exception(&e),exception_detail::get_std_exception(&e),true);\r
+        }\r
+\r
+    inline\r
+    char const *\r
+    diagnostic_information_what( exception const & e ) throw()\r
+        {\r
+        char const * w=0;\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+        try\r
+            {\r
+#endif\r
+            (void) exception_detail::diagnostic_information_impl(&e,0,false);\r
+            return exception_detail::get_diagnostic_information(e,0);\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+            }\r
+        catch(\r
+        ... )\r
+            {\r
+            }\r
+#endif\r
+        return w;\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_api_function.hpp b/src/external/boost/boost/exception/errinfo_api_function.hpp
new file mode 100644 (file)
index 0000000..7b6a9fe
--- /dev/null
@@ -0,0 +1,22 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_DDFBB4546C1211DEA4659E9055D89593\r
+#define UUID_DDFBB4546C1211DEA4659E9055D89593\r
+\r
+#include "boost/exception/error_info.hpp"\r
+\r
+namespace\r
+boost\r
+    {\r
+    //Usage hint:\r
+    //if( api_function(....)!=0 )\r
+    //    BOOST_THROW_EXCEPTION(\r
+    //        failure() <<\r
+    //        errinfo_api_function("api_function") );\r
+    typedef error_info<struct errinfo_api_function_,char const *> errinfo_api_function;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_at_line.hpp b/src/external/boost/boost/exception/errinfo_at_line.hpp
new file mode 100644 (file)
index 0000000..cc422ce
--- /dev/null
@@ -0,0 +1,18 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_E7255CE26C1211DE85800C9155D89593\r
+#define UUID_E7255CE26C1211DE85800C9155D89593\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class Tag,class T> class error_info;\r
+\r
+    //Use with parsing errors exceptions, for example in a XML file parser.\r
+    typedef error_info<struct errinfo_at_line_,int> errinfo_at_line;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_errno.hpp b/src/external/boost/boost/exception/errinfo_errno.hpp
new file mode 100644 (file)
index 0000000..c1e6c97
--- /dev/null
@@ -0,0 +1,44 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_F0EE17BE6C1211DE87FF459155D89593\r
+#define UUID_F0EE17BE6C1211DE87FF459155D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include "boost/exception/info.hpp"\r
+#include <errno.h>\r
+#include <string.h>\r
+\r
+namespace\r
+boost\r
+    {\r
+    typedef error_info<struct errinfo_errno_,int> errinfo_errno;\r
+\r
+    //Usage hint:\r
+    //if( c_function(....)!=0 )\r
+    //    BOOST_THROW_EXCEPTION(\r
+    //        failure() <<\r
+    //        errinfo_errno(errno) <<\r
+    //        errinfo_api_function("c_function") );\r
+    inline\r
+    std::string\r
+    to_string( errinfo_errno const & e )\r
+        {\r
+        std::ostringstream tmp;\r
+        int v=e.value();\r
+        tmp << v << ", \"" << strerror(v) << "\"";\r
+        return tmp.str();\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_file_handle.hpp b/src/external/boost/boost/exception/errinfo_file_handle.hpp
new file mode 100644 (file)
index 0000000..5b9673d
--- /dev/null
@@ -0,0 +1,20 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_F79E6EE26C1211DEB26E929155D89593\r
+#define UUID_F79E6EE26C1211DEB26E929155D89593\r
+\r
+#include <stdio.h>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class> class weak_ptr;\r
+    template <class Tag,class T> class error_info;\r
+\r
+    typedef error_info<struct errinfo_file_handle_,weak_ptr<FILE> > errinfo_file_handle;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_file_name.hpp b/src/external/boost/boost/exception/errinfo_file_name.hpp
new file mode 100644 (file)
index 0000000..c6f1c9e
--- /dev/null
@@ -0,0 +1,26 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_FEE5120A6C1211DE94E8BC9155D89593\r
+#define UUID_FEE5120A6C1211DE94E8BC9155D89593\r
+\r
+#include <string>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class Tag,class T> class error_info;\r
+\r
+    //Usage hint:\r
+    //FILE * f=fopen(name,mode);\r
+    //if( !f )\r
+    //    BOOST_THROW_EXCEPTION(\r
+    //        file_open_error() <<\r
+    //        errinfo_file_name(name) <<\r
+    //        errinfo_file_open_mode(mode) );\r
+    typedef error_info<struct errinfo_file_name_,std::string> errinfo_file_name;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_file_open_mode.hpp b/src/external/boost/boost/exception/errinfo_file_open_mode.hpp
new file mode 100644 (file)
index 0000000..c1bbaa1
--- /dev/null
@@ -0,0 +1,26 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_056F1F266C1311DE8E74299255D89593\r
+#define UUID_056F1F266C1311DE8E74299255D89593\r
+\r
+#include <string>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class Tag,class T> class error_info;\r
+\r
+    //Usage hint:\r
+    //FILE * f=fopen(name,mode);\r
+    //if( !f )\r
+    //    BOOST_THROW_EXCEPTION(\r
+    //        file_open_error() <<\r
+    //        errinfo_file_name(name) <<\r
+    //        errinfo_file_open_mode(mode) );\r
+    typedef error_info<struct errinfo_file_open_mode_,std::string> errinfo_file_open_mode;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_nested_exception.hpp b/src/external/boost/boost/exception/errinfo_nested_exception.hpp
new file mode 100644 (file)
index 0000000..072e47e
--- /dev/null
@@ -0,0 +1,19 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_45CC9A82B77511DEB330FC4956D89593\r
+#define UUID_45CC9A82B77511DEB330FC4956D89593\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace exception_detail { class clone_base; };\r
+    template <class Tag,class T> class error_info;\r
+    template <class T> class shared_ptr;\r
+    typedef shared_ptr<exception_detail::clone_base const> exception_ptr;\r
+    typedef error_info<struct errinfo_nested_exception_,exception_ptr> errinfo_nested_exception;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/errinfo_type_info_name.hpp b/src/external/boost/boost/exception/errinfo_type_info_name.hpp
new file mode 100644 (file)
index 0000000..dbd9abf
--- /dev/null
@@ -0,0 +1,23 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_0E11109E6C1311DEB7EA649255D89593\r
+#define UUID_0E11109E6C1311DEB7EA649255D89593\r
+\r
+#include <string>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class Tag,class T> class error_info;\r
+\r
+    //Usage hint:\r
+    //BOOST_THROW_EXCEPTION(\r
+    //    bad_type() <<\r
+    //    errinfo_type_info_name(typeid(x).name()) );\r
+    typedef error_info<struct errinfo_type_info_name_,std::string> errinfo_type_info_name;\r
+    }\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/exception/error_info.hpp b/src/external/boost/boost/exception/error_info.hpp
new file mode 100644 (file)
index 0000000..8f22b0b
--- /dev/null
@@ -0,0 +1,6 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+namespace boost { template <class Tag,class T> class error_info; }\r
diff --git a/src/external/boost/boost/exception/exception.hpp b/src/external/boost/boost/exception/exception.hpp
new file mode 100644 (file)
index 0000000..76970ac
--- /dev/null
@@ -0,0 +1,436 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_274DA366004E11DCB1DDFE2E56D89593\r
+#define UUID_274DA366004E11DCB1DDFE2E56D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class T>\r
+        class\r
+        refcount_ptr\r
+            {\r
+            public:\r
+\r
+            refcount_ptr():\r
+                px_(0)\r
+                {\r
+                }\r
+\r
+            ~refcount_ptr()\r
+                {\r
+                release();\r
+                }\r
+\r
+            refcount_ptr( refcount_ptr const & x ):\r
+                px_(x.px_)\r
+                {\r
+                add_ref();\r
+                }\r
+\r
+            refcount_ptr &\r
+            operator=( refcount_ptr const & x )\r
+                {\r
+                adopt(x.px_);\r
+                return *this;\r
+                }\r
+\r
+            void\r
+            adopt( T * px )\r
+                {\r
+                release();\r
+                px_=px;\r
+                add_ref();\r
+                }\r
+\r
+            T *\r
+            get() const\r
+                {\r
+                return px_;\r
+                }\r
+\r
+            private:\r
+\r
+            T * px_;\r
+\r
+            void\r
+            add_ref()\r
+                {\r
+                if( px_ )\r
+                    px_->add_ref();\r
+                }\r
+\r
+            void\r
+            release()\r
+                {\r
+                if( px_ && px_->release() )\r
+                    px_=0;\r
+                }\r
+            };\r
+        }\r
+\r
+    ////////////////////////////////////////////////////////////////////////\r
+\r
+    template <class Tag,class T>\r
+    class error_info;\r
+\r
+    typedef error_info<struct throw_function_,char const *> throw_function;\r
+    typedef error_info<struct throw_file_,char const *> throw_file;\r
+    typedef error_info<struct throw_line_,int> throw_line;\r
+\r
+    template <>\r
+    class\r
+    error_info<throw_function_,char const *>\r
+        {\r
+        public:\r
+        typedef char const * value_type;\r
+        value_type v_;\r
+        explicit\r
+        error_info( value_type v ):\r
+            v_(v)\r
+            {\r
+            }\r
+        };\r
+\r
+    template <>\r
+    class\r
+    error_info<throw_file_,char const *>\r
+        {\r
+        public:\r
+        typedef char const * value_type;\r
+        value_type v_;\r
+        explicit\r
+        error_info( value_type v ):\r
+            v_(v)\r
+            {\r
+            }\r
+        };\r
+\r
+    template <>\r
+    class\r
+    error_info<throw_line_,int>\r
+        {\r
+        public:\r
+        typedef int value_type;\r
+        value_type v_;\r
+        explicit\r
+        error_info( value_type v ):\r
+            v_(v)\r
+            {\r
+            }\r
+        };\r
+\r
+    class exception;\r
+\r
+    template <class T>\r
+    class shared_ptr;\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        class error_info_base;\r
+        struct type_info_;\r
+\r
+        struct\r
+        error_info_container\r
+            {\r
+            virtual char const * diagnostic_information( char const * ) const = 0;\r
+            virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0;\r
+            virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0;\r
+            virtual void add_ref() const = 0;\r
+            virtual bool release() const = 0;\r
+            virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0;\r
+\r
+            protected:\r
+\r
+            ~error_info_container() throw()\r
+                {\r
+                }\r
+            };\r
+\r
+        template <class>\r
+        struct get_info;\r
+\r
+        template <>\r
+        struct get_info<throw_function>;\r
+\r
+        template <>\r
+        struct get_info<throw_file>;\r
+\r
+        template <>\r
+        struct get_info<throw_line>;\r
+\r
+        char const * get_diagnostic_information( exception const &, char const * );\r
+\r
+        void copy_boost_exception( exception *, exception const * );\r
+\r
+        template <class E,class Tag,class T>\r
+        E const & set_info( E const &, error_info<Tag,T> const & );\r
+\r
+        template <class E>\r
+        E const & set_info( E const &, throw_function const & );\r
+\r
+        template <class E>\r
+        E const & set_info( E const &, throw_file const & );\r
+\r
+        template <class E>\r
+        E const & set_info( E const &, throw_line const & );\r
+        }\r
+\r
+    class\r
+    exception\r
+        {\r
+        protected:\r
+\r
+        exception():\r
+            throw_function_(0),\r
+            throw_file_(0),\r
+            throw_line_(-1)\r
+            {\r
+            }\r
+\r
+#ifdef __HP_aCC\r
+        //On HP aCC, this protected copy constructor prevents throwing boost::exception.\r
+        //On all other platforms, the same effect is achieved by the pure virtual destructor.\r
+        exception( exception const & x ) throw():\r
+            data_(x.data_),\r
+            throw_function_(x.throw_function_),\r
+            throw_file_(x.throw_file_),\r
+            throw_line_(x.throw_line_)\r
+            {\r
+            }\r
+#endif\r
+\r
+        virtual ~exception() throw()\r
+#ifndef __HP_aCC\r
+            = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.\r
+#endif\r
+            ;\r
+\r
+#if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310)\r
+        public:\r
+#else\r
+        private:\r
+\r
+        template <class E>\r
+        friend E const & exception_detail::set_info( E const &, throw_function const & );\r
+\r
+        template <class E>\r
+        friend E const & exception_detail::set_info( E const &, throw_file const & );\r
+\r
+        template <class E>\r
+        friend E const & exception_detail::set_info( E const &, throw_line const & );\r
+\r
+        template <class E,class Tag,class T>\r
+        friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & );\r
+\r
+        friend char const * exception_detail::get_diagnostic_information( exception const &, char const * );\r
+\r
+        template <class>\r
+        friend struct exception_detail::get_info;\r
+        friend struct exception_detail::get_info<throw_function>;\r
+        friend struct exception_detail::get_info<throw_file>;\r
+        friend struct exception_detail::get_info<throw_line>;\r
+        friend void exception_detail::copy_boost_exception( exception *, exception const * );\r
+#endif\r
+        mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;\r
+        mutable char const * throw_function_;\r
+        mutable char const * throw_file_;\r
+        mutable int throw_line_;\r
+        };\r
+\r
+    inline\r
+    exception::\r
+    ~exception() throw()\r
+        {\r
+        }\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class E>\r
+        E const &\r
+        set_info( E const & x, throw_function const & y )\r
+            {\r
+            x.throw_function_=y.v_;\r
+            return x;\r
+            }\r
+\r
+        template <class E>\r
+        E const &\r
+        set_info( E const & x, throw_file const & y )\r
+            {\r
+            x.throw_file_=y.v_;\r
+            return x;\r
+            }\r
+\r
+        template <class E>\r
+        E const &\r
+        set_info( E const & x, throw_line const & y )\r
+            {\r
+            x.throw_line_=y.v_;\r
+            return x;\r
+            }\r
+        }\r
+\r
+    ////////////////////////////////////////////////////////////////////////\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class T>\r
+        struct\r
+        error_info_injector:\r
+            public T,\r
+            public exception\r
+            {\r
+            explicit\r
+            error_info_injector( T const & x ):\r
+                T(x)\r
+                {\r
+                }\r
+\r
+            ~error_info_injector() throw()\r
+                {\r
+                }\r
+            };\r
+\r
+        struct large_size { char c[256]; };\r
+        large_size dispatch_boost_exception( exception const * );\r
+\r
+        struct small_size { };\r
+        small_size dispatch_boost_exception( void const * );\r
+\r
+        template <class,int>\r
+        struct enable_error_info_helper;\r
+\r
+        template <class T>\r
+        struct\r
+        enable_error_info_helper<T,sizeof(large_size)>\r
+            {\r
+            typedef T type;\r
+            };\r
+\r
+        template <class T>\r
+        struct\r
+        enable_error_info_helper<T,sizeof(small_size)>\r
+            {\r
+            typedef error_info_injector<T> type;\r
+            };\r
+\r
+        template <class T>\r
+        struct\r
+        enable_error_info_return_type\r
+            {\r
+            typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception((T*)0))>::type type;\r
+            };\r
+        }\r
+\r
+    template <class T>\r
+    inline\r
+    typename\r
+    exception_detail::enable_error_info_return_type<T>::type\r
+    enable_error_info( T const & x )\r
+        {\r
+        typedef typename exception_detail::enable_error_info_return_type<T>::type rt;\r
+        return rt(x);\r
+        }\r
+\r
+    ////////////////////////////////////////////////////////////////////////\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        class\r
+        clone_base\r
+            {\r
+            public:\r
+\r
+            virtual clone_base const * clone() const = 0;\r
+            virtual void rethrow() const = 0;\r
+\r
+            virtual\r
+            ~clone_base() throw()\r
+                {\r
+                }\r
+            };\r
+\r
+        inline\r
+        void\r
+        copy_boost_exception( exception * a, exception const * b )\r
+            {\r
+            refcount_ptr<error_info_container> data;\r
+            if( error_info_container * d=b->data_.get() )\r
+                data = d->clone();\r
+            a->throw_file_ = b->throw_file_;\r
+            a->throw_line_ = b->throw_line_;\r
+            a->throw_function_ = b->throw_function_;\r
+            a->data_ = data;\r
+            }\r
+\r
+        inline\r
+        void\r
+        copy_boost_exception( void *, void const * )\r
+            {\r
+            }\r
+\r
+        template <class T>\r
+        class\r
+        clone_impl:\r
+            public T,\r
+            public clone_base\r
+            {\r
+            public:\r
+\r
+            explicit\r
+            clone_impl( T const & x ):\r
+                T(x)\r
+                {\r
+                copy_boost_exception(this,&x);\r
+                }\r
+\r
+            ~clone_impl() throw()\r
+                {\r
+                }\r
+\r
+            private:\r
+\r
+            clone_base const *\r
+            clone() const\r
+                {\r
+                return new clone_impl(*this);\r
+                }\r
+\r
+            void\r
+            rethrow() const\r
+                {\r
+                throw*this;\r
+                }\r
+            };\r
+        }\r
+\r
+    template <class T>\r
+    inline\r
+    exception_detail::clone_impl<T>\r
+    enable_current_exception( T const & x )\r
+        {\r
+        return exception_detail::clone_impl<T>(x);\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/get_error_info.hpp b/src/external/boost/boost/exception/get_error_info.hpp
new file mode 100644 (file)
index 0000000..c3cf137
--- /dev/null
@@ -0,0 +1,130 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_1A590226753311DD9E4CCF6156D89593\r
+#define UUID_1A590226753311DD9E4CCF6156D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/exception/exception.hpp>\r
+#include <boost/exception/detail/error_info_impl.hpp>\r
+#include <boost/exception/detail/type_info.hpp>\r
+#include <boost/shared_ptr.hpp>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <class ErrorInfo>\r
+        struct\r
+        get_info\r
+            {\r
+            static\r
+            typename ErrorInfo::value_type *\r
+            get( exception const & x )\r
+                {\r
+                if( exception_detail::error_info_container * c=x.data_.get() )\r
+                    if( shared_ptr<exception_detail::error_info_base> eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) )\r
+                        {\r
+#ifndef BOOST_NO_RTTI\r
+                        BOOST_ASSERT( 0!=dynamic_cast<ErrorInfo *>(eib.get()) );\r
+#endif\r
+                        ErrorInfo * w = static_cast<ErrorInfo *>(eib.get());\r
+                        return &w->value();\r
+                        }\r
+                return 0;\r
+                }\r
+            };\r
+\r
+        template <>\r
+        struct\r
+        get_info<throw_function>\r
+            {\r
+            static\r
+            char const * *\r
+            get( exception const & x )\r
+                {\r
+                return x.throw_function_ ? &x.throw_function_ : 0;\r
+                }\r
+            };\r
+\r
+        template <>\r
+        struct\r
+        get_info<throw_file>\r
+            {\r
+            static\r
+            char const * *\r
+            get( exception const & x )\r
+                {\r
+                return x.throw_file_ ? &x.throw_file_ : 0;\r
+                }\r
+            };\r
+\r
+        template <>\r
+        struct\r
+        get_info<throw_line>\r
+            {\r
+            static\r
+            int *\r
+            get( exception const & x )\r
+                {\r
+                return x.throw_line_!=-1 ? &x.throw_line_ : 0;\r
+                }\r
+            };\r
+\r
+        template <class T,class R>\r
+        struct\r
+        get_error_info_return_type\r
+            {\r
+            typedef R * type;\r
+            };\r
+\r
+        template <class T,class R>\r
+        struct\r
+        get_error_info_return_type<T const,R>\r
+            {\r
+            typedef R const * type;\r
+            };\r
+        }\r
+\r
+#ifdef BOOST_NO_RTTI\r
+    template <class ErrorInfo>\r
+    inline\r
+    typename ErrorInfo::value_type const *\r
+    get_error_info( boost::exception const & x )\r
+        {\r
+        return exception_detail::get_info<ErrorInfo>::get(x);\r
+        }\r
+    template <class ErrorInfo>\r
+    inline\r
+    typename ErrorInfo::value_type *\r
+    get_error_info( boost::exception & x )\r
+        {\r
+        return exception_detail::get_info<ErrorInfo>::get(x);\r
+        }\r
+#else\r
+    template <class ErrorInfo,class E>\r
+    inline\r
+    typename exception_detail::get_error_info_return_type<E,typename ErrorInfo::value_type>::type\r
+    get_error_info( E & some_exception )\r
+        {\r
+        if( exception const * x = dynamic_cast<exception const *>(&some_exception) )\r
+            return exception_detail::get_info<ErrorInfo>::get(*x);\r
+        else\r
+            return 0;\r
+        }\r
+#endif\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/info.hpp b/src/external/boost/boost/exception/info.hpp
new file mode 100644 (file)
index 0000000..ecbf84b
--- /dev/null
@@ -0,0 +1,200 @@
+//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593\r
+#define UUID_8D22C4CA9CC811DCAA9133D256D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/exception/exception.hpp>\r
+#include <boost/exception/to_string_stub.hpp>\r
+#include <boost/exception/detail/error_info_impl.hpp>\r
+#include <boost/shared_ptr.hpp>\r
+#include <boost/config.hpp>\r
+#include <map>\r
+\r
+namespace\r
+boost\r
+    {\r
+    template <class Tag,class T>\r
+    inline\r
+    typename enable_if<has_to_string<T>,std::string>::type\r
+    to_string( error_info<Tag,T> const & x )\r
+        {\r
+        return to_string(x.value());\r
+        }\r
+\r
+    template <class Tag,class T>\r
+    inline\r
+    error_info<Tag,T>::\r
+    error_info( value_type const & value ):\r
+        value_(value)\r
+        {\r
+        }\r
+\r
+    template <class Tag,class T>\r
+    inline\r
+    error_info<Tag,T>::\r
+    ~error_info() throw()\r
+        {\r
+        }\r
+\r
+    template <class Tag,class T>\r
+    inline\r
+    std::string\r
+    error_info<Tag,T>::\r
+    tag_typeid_name() const\r
+        {\r
+        return tag_type_name<Tag>();\r
+        }\r
+\r
+    template <class Tag,class T>\r
+    inline\r
+    std::string\r
+    error_info<Tag,T>::\r
+    value_as_string() const\r
+        {\r
+        return to_string_stub(*this);\r
+        }\r
+\r
+    namespace\r
+    exception_detail\r
+        {\r
+        class\r
+        error_info_container_impl:\r
+            public error_info_container\r
+            {\r
+            public:\r
+\r
+            error_info_container_impl():\r
+                count_(0)\r
+                {\r
+                }\r
+\r
+            ~error_info_container_impl() throw()\r
+                {\r
+                }\r
+\r
+            void\r
+            set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ )\r
+                {\r
+                BOOST_ASSERT(x);\r
+                info_[typeid_] = x;\r
+                diagnostic_info_str_.clear();\r
+                }\r
+\r
+            shared_ptr<error_info_base>\r
+            get( type_info_ const & ti ) const\r
+                {\r
+                error_info_map::const_iterator i=info_.find(ti);\r
+                if( info_.end()!=i )\r
+                    {\r
+                    shared_ptr<error_info_base> const & p = i->second;\r
+#ifndef BOOST_NO_RTTI\r
+                    BOOST_ASSERT( BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==ti.type_ );\r
+#endif\r
+                    return p;\r
+                    }\r
+                return shared_ptr<error_info_base>();\r
+                }\r
+\r
+            char const *\r
+            diagnostic_information( char const * header ) const\r
+                {\r
+                if( header )\r
+                    {\r
+                    BOOST_ASSERT(*header!=0);\r
+                    std::ostringstream tmp;\r
+                    tmp << header;\r
+                    for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )\r
+                        {\r
+                        error_info_base const & x = *i->second;\r
+                        tmp << '[' << x.tag_typeid_name() << "] = " << x.value_as_string() << '\n';\r
+                        }\r
+                    tmp.str().swap(diagnostic_info_str_);\r
+                    }\r
+                return diagnostic_info_str_.c_str();\r
+                }\r
+\r
+            private:\r
+\r
+            friend class boost::exception;\r
+\r
+            typedef std::map< type_info_, shared_ptr<error_info_base> > error_info_map;\r
+            error_info_map info_;\r
+            mutable std::string diagnostic_info_str_;\r
+            mutable int count_;\r
+\r
+            error_info_container_impl( error_info_container_impl const & );\r
+            error_info_container_impl & operator=( error_info_container const & );\r
+\r
+            void\r
+            add_ref() const\r
+                {\r
+                ++count_;\r
+                }\r
+\r
+            bool\r
+            release() const\r
+                {\r
+                if( --count_ )\r
+                    return false;\r
+                else\r
+                    {\r
+                    delete this;\r
+                    return true;\r
+                    }\r
+                }\r
+\r
+            refcount_ptr<error_info_container>\r
+            clone() const\r
+                {\r
+                refcount_ptr<error_info_container> p;\r
+                error_info_container_impl * c=new error_info_container_impl;\r
+                p.adopt(c);\r
+                c->info_ = info_;\r
+                return p;\r
+                }\r
+            };\r
+\r
+        template <class E,class Tag,class T>\r
+        inline\r
+        E const &\r
+        set_info( E const & x, error_info<Tag,T> const & v )\r
+            {\r
+            typedef error_info<Tag,T> error_info_tag_t;\r
+            shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) );\r
+            exception_detail::error_info_container * c=x.data_.get();\r
+            if( !c )\r
+                x.data_.adopt(c=new exception_detail::error_info_container_impl);\r
+            c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));\r
+            return x;\r
+            }\r
+\r
+        template <class T>\r
+        struct\r
+        derives_boost_exception\r
+            {\r
+            enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) };\r
+            };\r
+        }\r
+\r
+    template <class E,class Tag,class T>\r
+    inline\r
+    typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type\r
+    operator<<( E const & x, error_info<Tag,T> const & v )\r
+        {\r
+        return exception_detail::set_info(x,v);\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/to_string.hpp b/src/external/boost/boost/exception/to_string.hpp
new file mode 100644 (file)
index 0000000..483aed9
--- /dev/null
@@ -0,0 +1,83 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_7E48761AD92811DC9011477D56D89593\r
+#define UUID_7E48761AD92811DC9011477D56D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/utility/enable_if.hpp>\r
+#include <boost/exception/detail/is_output_streamable.hpp>\r
+#include <sstream>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    to_string_detail\r
+        {\r
+        template <class T>\r
+        typename disable_if<is_output_streamable<T>,char>::type to_string( T const & );\r
+\r
+        template <class,bool IsOutputStreamable>\r
+        struct has_to_string_impl;\r
+\r
+        template <class T>\r
+        struct\r
+        has_to_string_impl<T,true>\r
+            {\r
+            enum e { value=1 };\r
+            };\r
+\r
+        template <class T>\r
+        struct\r
+        has_to_string_impl<T,false>\r
+            {\r
+            static T const & f();\r
+            enum e { value=1!=sizeof(to_string(f())) };\r
+            };\r
+        }\r
+\r
+    template <class T>\r
+    inline\r
+    typename enable_if<is_output_streamable<T>,std::string>::type\r
+    to_string( T const & x )\r
+        {\r
+        std::ostringstream out;\r
+        out << x;\r
+        return out.str();\r
+        }\r
+\r
+    template <class T>\r
+    struct\r
+    has_to_string\r
+        {\r
+        enum e { value=to_string_detail::has_to_string_impl<T,is_output_streamable<T>::value>::value };\r
+        };\r
+\r
+    template <class T,class U>\r
+    inline\r
+    std::string\r
+    to_string( std::pair<T,U> const & x )\r
+        {\r
+        return std::string("(") + to_string(x.first) + ',' + to_string(x.second) + ')';\r
+        }\r
+\r
+    inline\r
+    std::string\r
+    to_string( std::exception const & x )\r
+        {\r
+        return x.what();\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception/to_string_stub.hpp b/src/external/boost/boost/exception/to_string_stub.hpp
new file mode 100644 (file)
index 0000000..0f8eb99
--- /dev/null
@@ -0,0 +1,109 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_E788439ED9F011DCB181F25B55D89593\r
+#define UUID_E788439ED9F011DCB181F25B55D89593\r
+#if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma GCC system_header\r
+#endif\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(push,1)\r
+#endif\r
+\r
+#include <boost/exception/to_string.hpp>\r
+#include <boost/exception/detail/object_hex_dump.hpp>\r
+#include <boost/assert.hpp>\r
+\r
+namespace\r
+boost\r
+    {\r
+    namespace\r
+    exception_detail\r
+        {\r
+        template <bool ToStringAvailable>\r
+        struct\r
+        to_string_dispatcher\r
+            {\r
+            template <class T,class Stub>\r
+            static\r
+            std::string\r
+            convert( T const & x, Stub )\r
+                {\r
+                return to_string(x);\r
+                }\r
+            };\r
+\r
+        template <>\r
+        struct\r
+        to_string_dispatcher<false>\r
+            {\r
+            template <class T,class Stub>\r
+            static\r
+            std::string\r
+            convert( T const & x, Stub s )\r
+                {\r
+                return s(x);\r
+                }\r
+\r
+            template <class T>\r
+            static\r
+            std::string\r
+            convert( T const & x, std::string s )\r
+                {\r
+                return s;\r
+                }\r
+\r
+            template <class T>\r
+            static\r
+            std::string\r
+            convert( T const & x, char const * s )\r
+                {\r
+                BOOST_ASSERT(s!=0);\r
+                return s;\r
+                }\r
+            };\r
+\r
+        namespace\r
+        to_string_dispatch\r
+            {\r
+            template <class T,class Stub>\r
+            inline\r
+            std::string\r
+            dispatch( T const & x, Stub s )\r
+                {\r
+                return to_string_dispatcher<has_to_string<T>::value>::convert(x,s);\r
+                }\r
+            }\r
+\r
+        template <class T>\r
+        inline\r
+        std::string\r
+        string_stub_dump( T const & x )\r
+            {\r
+            return "[ " + exception_detail::object_hex_dump(x) + " ]";\r
+            }\r
+        }\r
+\r
+    template <class T>\r
+    inline\r
+    std::string\r
+    to_string_stub( T const & x )\r
+        {\r
+        return exception_detail::to_string_dispatch::dispatch(x,&exception_detail::string_stub_dump<T>);\r
+        }\r
+\r
+    template <class T,class Stub>\r
+    inline\r
+    std::string\r
+    to_string_stub( T const & x, Stub s )\r
+        {\r
+        return exception_detail::to_string_dispatch::dispatch(x,s);\r
+        }\r
+    }\r
+\r
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)\r
+#pragma warning(pop)\r
+#endif\r
+#endif\r
diff --git a/src/external/boost/boost/exception_ptr.hpp b/src/external/boost/boost/exception_ptr.hpp
new file mode 100644 (file)
index 0000000..9900b58
--- /dev/null
@@ -0,0 +1,11 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+\r
+//Distributed under the Boost Software License, Version 1.0. (See accompanying\r
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593\r
+#define UUID_FA5836A2CADA11DC8CD47C8555D89593\r
+\r
+#include <boost/exception/detail/exception_ptr.hpp>\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/memory_order.hpp b/src/external/boost/boost/memory_order.hpp
new file mode 100644 (file)
index 0000000..1c8bdc6
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED\r
+#define BOOST_MEMORY_ORDER_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//  boost/memory_order.hpp\r
+//\r
+//  Defines enum boost::memory_order per the C++0x working draft\r
+//\r
+//  Copyright (c) 2008, 2009 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+namespace boost\r
+{\r
+\r
+//\r
+// Enum values are chosen so that code that needs to insert\r
+// a trailing fence for acquire semantics can use a single\r
+// test such as:\r
+//\r
+// if( mo & memory_order_acquire ) { ...fence... }\r
+//\r
+// For leading fences one can use:\r
+//\r
+// if( mo & memory_order_release ) { ...fence... }\r
+//\r
+// Architectures such as Alpha that need a fence on consume\r
+// can use:\r
+//\r
+// if( mo & ( memory_order_acquire | memory_order_consume ) ) { ...fence... }\r
+//\r
+\r
+enum memory_order\r
+{\r
+    memory_order_relaxed = 0,\r
+    memory_order_acquire = 1,\r
+    memory_order_release = 2,\r
+    memory_order_acq_rel = 3, // acquire | release\r
+    memory_order_seq_cst = 7, // acq_rel | 4\r
+    memory_order_consume = 8\r
+};\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/non_type.hpp b/src/external/boost/boost/non_type.hpp
new file mode 100644 (file)
index 0000000..7a4651a
--- /dev/null
@@ -0,0 +1,27 @@
+// -------------------------------------\r
+//\r
+//           (C) Copyright Gennaro Prota 2003.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0.\r
+//    (See accompanying file LICENSE_1_0.txt or copy at\r
+//          http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+// ------------------------------------------------------\r
+\r
+#ifndef BOOST_NON_TYPE_HPP_GP_20030417\r
+#define BOOST_NON_TYPE_HPP_GP_20030417\r
+\r
+\r
+namespace boost {\r
+\r
+  // Just a simple "envelope" for non-type template parameters. Useful\r
+  // to work around some MSVC deficiencies.\r
+\r
+ template <typename T, T n>\r
+ struct non_type { };\r
+\r
+\r
+}\r
+\r
+\r
+#endif // include guard\r
diff --git a/src/external/boost/boost/shared_ptr.hpp b/src/external/boost/boost/shared_ptr.hpp
new file mode 100644 (file)
index 0000000..832ddac
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED\r
+#define BOOST_SHARED_PTR_HPP_INCLUDED\r
+\r
+//\r
+//  shared_ptr.hpp\r
+//\r
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.\r
+//  Copyright (c) 2001-2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.\r
+//\r
+\r
+#include <boost/smart_ptr/shared_ptr.hpp>\r
+\r
+#endif  // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/bad_weak_ptr.hpp b/src/external/boost/boost/smart_ptr/bad_weak_ptr.hpp
new file mode 100644 (file)
index 0000000..72fff35
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/smart_ptr/bad_weak_ptr.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <exception>\r
+\r
+#ifdef __BORLANDC__\r
+# pragma warn -8026     // Functions with excep. spec. are not expanded inline\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+// The standard library that comes with Borland C++ 5.5.1, 5.6.4\r
+// defines std::exception and its members as having C calling\r
+// convention (-pc). When the definition of bad_weak_ptr\r
+// is compiled with -ps, the compiler issues an error.\r
+// Hence, the temporary #pragma option -pc below.\r
+\r
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564\r
+# pragma option push -pc\r
+#endif\r
+\r
+class bad_weak_ptr: public std::exception\r
+{\r
+public:\r
+\r
+    virtual char const * what() const throw()\r
+    {\r
+        return "tr1::bad_weak_ptr";\r
+    }\r
+};\r
+\r
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564\r
+# pragma option pop\r
+#endif\r
+\r
+} // namespace boost\r
+\r
+#ifdef __BORLANDC__\r
+# pragma warn .8026     // Functions with excep. spec. are not expanded inline\r
+#endif\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count.hpp
new file mode 100644 (file)
index 0000000..f856137
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/atomic_count.hpp - thread/SMP safe reference counter\r
+//\r
+//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  typedef <implementation-defined> boost::detail::atomic_count;\r
+//\r
+//  atomic_count a(n);\r
+//\r
+//    (n is convertible to long)\r
+//\r
+//    Effects: Constructs an atomic_count with an initial value of n\r
+//\r
+//  a;\r
+//\r
+//    Returns: (long) the current value of a\r
+//\r
+//  ++a;\r
+//\r
+//    Effects: Atomically increments the value of a\r
+//    Returns: (long) the new value of a\r
+//\r
+//  --a;\r
+//\r
+//    Effects: Atomically decrements the value of a\r
+//    Returns: (long) the new value of a\r
+//\r
+//    Important note: when --a returns zero, it must act as a\r
+//      read memory barrier (RMB); i.e. the calling thread must\r
+//      have a synchronized view of the memory\r
+//\r
+//    On Intel IA-32 (x86) memory is always synchronized, so this\r
+//      is not a problem.\r
+//\r
+//    On many architectures the atomic instructions already act as\r
+//      a memory barrier.\r
+//\r
+//    This property is necessary for proper reference counting, since\r
+//      a thread can update the contents of a shared object, then\r
+//      release its reference, and another thread may immediately\r
+//      release the last reference causing object destruction.\r
+//\r
+//    The destructor needs to have a synchronized view of the\r
+//      object to perform proper cleanup.\r
+//\r
+//    Original example by Alexander Terekhov:\r
+//\r
+//    Given:\r
+//\r
+//    - a mutable shared object OBJ;\r
+//    - two threads THREAD1 and THREAD2 each holding \r
+//      a private smart_ptr object pointing to that OBJ.\r
+//\r
+//    t1: THREAD1 updates OBJ (thread-safe via some synchronization)\r
+//      and a few cycles later (after "unlock") destroys smart_ptr;\r
+//\r
+//    t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization \r
+//      with respect to shared mutable object OBJ; OBJ destructors\r
+//      are called driven by smart_ptr interface...\r
+//\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>\r
+\r
+#ifndef BOOST_HAS_THREADS\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+typedef long atomic_count;\r
+\r
+}\r
+\r
+}\r
+\r
+#elif defined(BOOST_AC_USE_PTHREADS)\r
+#  include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>\r
+\r
+#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )\r
+#  include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>\r
+\r
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\r
+#  include <boost/smart_ptr/detail/atomic_count_win32.hpp>\r
+\r
+#elif defined( BOOST_SP_HAS_SYNC )\r
+#  include <boost/smart_ptr/detail/atomic_count_sync.hpp>\r
+\r
+#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)\r
+#  include <boost/smart_ptr/detail/atomic_count_gcc.hpp>\r
+\r
+#elif defined(BOOST_HAS_PTHREADS)\r
+\r
+#  define BOOST_AC_USE_PTHREADS\r
+#  include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>\r
+\r
+#else\r
+\r
+// Use #define BOOST_DISABLE_THREADS to avoid the error\r
+#error Unrecognized threading platform\r
+\r
+#endif\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count_gcc.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count_gcc.hpp
new file mode 100644 (file)
index 0000000..0c10d88
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED\r
+\r
+//\r
+//  boost/detail/atomic_count_gcc.hpp\r
+//\r
+//  atomic_count for GNU libstdc++ v3\r
+//\r
+//  http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html\r
+//\r
+//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.\r
+//  Copyright (c) 2002 Lars Gullik Bj�nnes <larsbj@lyx.org>\r
+//  Copyright 2003-2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402\r
+# include <ext/atomicity.h> \r
+#else \r
+# include <bits/atomicity.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#if defined(__GLIBCXX__) // g++ 3.4+\r
+\r
+using __gnu_cxx::__atomic_add;\r
+using __gnu_cxx::__exchange_and_add;\r
+\r
+#endif\r
+\r
+class atomic_count\r
+{\r
+public:\r
+\r
+    explicit atomic_count( long v ) : value_( v ) {}\r
+\r
+    long operator++()\r
+    {\r
+        return __exchange_and_add( &value_, +1 ) + 1;\r
+    }\r
+\r
+    long operator--()\r
+    {\r
+        return __exchange_and_add( &value_, -1 ) - 1;\r
+    }\r
+\r
+    operator long() const\r
+    {\r
+        return __exchange_and_add( &value_, 0 );\r
+    }\r
+\r
+private:\r
+\r
+    atomic_count(atomic_count const &);\r
+    atomic_count & operator=(atomic_count const &);\r
+\r
+    mutable _Atomic_word value_;\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
new file mode 100644 (file)
index 0000000..388498b
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED\r
+\r
+//\r
+//  boost/detail/atomic_count_gcc_x86.hpp\r
+//\r
+//  atomic_count for g++ on 486+/AMD64\r
+//\r
+//  Copyright 2007 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class atomic_count\r
+{\r
+public:\r
+\r
+    explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {}\r
+\r
+    long operator++()\r
+    {\r
+        return atomic_exchange_and_add( &value_, +1 ) + 1;\r
+    }\r
+\r
+    long operator--()\r
+    {\r
+        return atomic_exchange_and_add( &value_, -1 ) - 1;\r
+    }\r
+\r
+    operator long() const\r
+    {\r
+        return atomic_exchange_and_add( &value_, 0 );\r
+    }\r
+\r
+private:\r
+\r
+    atomic_count(atomic_count const &);\r
+    atomic_count & operator=(atomic_count const &);\r
+\r
+    mutable int value_;\r
+\r
+private:\r
+\r
+    static int atomic_exchange_and_add( int * pw, int dv )\r
+    {\r
+        // int r = *pw;\r
+        // *pw += dv;\r
+        // return r;\r
+\r
+        int r;\r
+\r
+        __asm__ __volatile__\r
+        (\r
+            "lock\n\t"\r
+            "xadd %1, %0":\r
+            "+m"( *pw ), "=r"( r ): // outputs (%0, %1)\r
+            "1"( dv ): // inputs (%2 == %1)\r
+            "memory", "cc" // clobbers\r
+        );\r
+\r
+        return r;\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count_pthreads.hpp
new file mode 100644 (file)
index 0000000..5e89faa
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED\r
+\r
+//\r
+//  boost/detail/atomic_count_pthreads.hpp\r
+//\r
+//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <pthread.h>\r
+\r
+//\r
+//  The generic pthread_mutex-based implementation sometimes leads to\r
+//    inefficiencies. Example: a class with two atomic_count members\r
+//    can get away with a single mutex.\r
+//\r
+//  Users can detect this situation by checking BOOST_AC_USE_PTHREADS.\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class atomic_count\r
+{\r
+private:\r
+\r
+    class scoped_lock\r
+    {\r
+    public:\r
+\r
+        scoped_lock(pthread_mutex_t & m): m_(m)\r
+        {\r
+            pthread_mutex_lock(&m_);\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            pthread_mutex_unlock(&m_);\r
+        }\r
+\r
+    private:\r
+\r
+        pthread_mutex_t & m_;\r
+    };\r
+\r
+public:\r
+\r
+    explicit atomic_count(long v): value_(v)\r
+    {\r
+        pthread_mutex_init(&mutex_, 0);\r
+    }\r
+\r
+    ~atomic_count()\r
+    {\r
+        pthread_mutex_destroy(&mutex_);\r
+    }\r
+\r
+    long operator++()\r
+    {\r
+        scoped_lock lock(mutex_);\r
+        return ++value_;\r
+    }\r
+\r
+    long operator--()\r
+    {\r
+        scoped_lock lock(mutex_);\r
+        return --value_;\r
+    }\r
+\r
+    operator long() const\r
+    {\r
+        scoped_lock lock(mutex_);\r
+        return value_;\r
+    }\r
+\r
+private:\r
+\r
+    atomic_count(atomic_count const &);\r
+    atomic_count & operator=(atomic_count const &);\r
+\r
+    mutable pthread_mutex_t mutex_;\r
+    long value_;\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count_sync.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count_sync.hpp
new file mode 100644 (file)
index 0000000..521dbe8
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED\r
+\r
+//\r
+//  boost/detail/atomic_count_sync.hpp\r
+//\r
+//  atomic_count for g++ 4.1+\r
+//\r
+//  http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html\r
+//\r
+//  Copyright 2007 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )\r
+# include <ia64intrin.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class atomic_count\r
+{\r
+public:\r
+\r
+    explicit atomic_count( long v ) : value_( v ) {}\r
+\r
+    long operator++()\r
+    {\r
+        return __sync_add_and_fetch( &value_, 1 );\r
+    }\r
+\r
+    long operator--()\r
+    {\r
+        return __sync_add_and_fetch( &value_, -1 );\r
+    }\r
+\r
+    operator long() const\r
+    {\r
+        return __sync_fetch_and_add( &value_, 0 );\r
+    }\r
+\r
+private:\r
+\r
+    atomic_count(atomic_count const &);\r
+    atomic_count & operator=(atomic_count const &);\r
+\r
+    mutable long value_;\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/atomic_count_win32.hpp b/src/external/boost/boost/smart_ptr/detail/atomic_count_win32.hpp
new file mode 100644 (file)
index 0000000..70edce9
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/atomic_count_win32.hpp\r
+//\r
+//  Copyright (c) 2001-2005 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/detail/interlocked.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class atomic_count\r
+{\r
+public:\r
+\r
+    explicit atomic_count( long v ): value_( v )\r
+    {\r
+    }\r
+\r
+    long operator++()\r
+    {\r
+        return BOOST_INTERLOCKED_INCREMENT( &value_ );\r
+    }\r
+\r
+    long operator--()\r
+    {\r
+        return BOOST_INTERLOCKED_DECREMENT( &value_ );\r
+    }\r
+\r
+    operator long() const\r
+    {\r
+        return static_cast<long const volatile &>( value_ );\r
+    }\r
+\r
+private:\r
+\r
+    atomic_count( atomic_count const & );\r
+    atomic_count & operator=( atomic_count const & );\r
+\r
+    long value_;\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/lightweight_mutex.hpp b/src/external/boost/boost/smart_ptr/detail/lightweight_mutex.hpp
new file mode 100644 (file)
index 0000000..f6c159e
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/lightweight_mutex.hpp - lightweight mutex\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  typedef <unspecified> boost::detail::lightweight_mutex;\r
+//\r
+//  boost::detail::lightweight_mutex is a header-only implementation of\r
+//  a subset of the Mutex concept requirements:\r
+//\r
+//  http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex\r
+//\r
+//  It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.\r
+//\r
+\r
+#include <boost/config.hpp>\r
+\r
+#if !defined(BOOST_HAS_THREADS)\r
+#  include <boost/smart_ptr/detail/lwm_nop.hpp>\r
+#elif defined(BOOST_HAS_PTHREADS)\r
+#  include <boost/smart_ptr/detail/lwm_pthreads.hpp>\r
+#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\r
+#  include <boost/smart_ptr/detail/lwm_win32_cs.hpp>\r
+#else\r
+// Use #define BOOST_DISABLE_THREADS to avoid the error\r
+#  error Unrecognized threading platform\r
+#endif\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/lwm_nop.hpp b/src/external/boost/boost/smart_ptr/detail/lwm_nop.hpp
new file mode 100644 (file)
index 0000000..cc1e97f
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/lwm_nop.hpp\r
+//\r
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class lightweight_mutex\r
+{\r
+public:\r
+\r
+    typedef lightweight_mutex scoped_lock;\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/lwm_pthreads.hpp b/src/external/boost/boost/smart_ptr/detail/lwm_pthreads.hpp
new file mode 100644 (file)
index 0000000..6a2b70b
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/lwm_pthreads.hpp\r
+//\r
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/assert.hpp>\r
+#include <pthread.h>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class lightweight_mutex\r
+{\r
+private:\r
+\r
+    pthread_mutex_t m_;\r
+\r
+    lightweight_mutex(lightweight_mutex const &);\r
+    lightweight_mutex & operator=(lightweight_mutex const &);\r
+\r
+public:\r
+\r
+    lightweight_mutex()\r
+    {\r
+\r
+// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init\r
+\r
+#if defined(__hpux) && defined(_DECTHREADS_)\r
+        BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );\r
+#else\r
+        BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );\r
+#endif\r
+    }\r
+\r
+    ~lightweight_mutex()\r
+    {\r
+        BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );\r
+    }\r
+\r
+    class scoped_lock;\r
+    friend class scoped_lock;\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        pthread_mutex_t & m_;\r
+\r
+        scoped_lock(scoped_lock const &);\r
+        scoped_lock & operator=(scoped_lock const &);\r
+\r
+    public:\r
+\r
+        scoped_lock(lightweight_mutex & m): m_(m.m_)\r
+        {\r
+            BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/lwm_win32_cs.hpp b/src/external/boost/boost/smart_ptr/detail/lwm_win32_cs.hpp
new file mode 100644 (file)
index 0000000..f2cbb9a
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/lwm_win32_cs.hpp\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#ifdef BOOST_USE_WINDOWS_H\r
+#  include <windows.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#ifndef BOOST_USE_WINDOWS_H\r
+\r
+struct critical_section\r
+{\r
+    struct critical_section_debug * DebugInfo;\r
+    long LockCount;\r
+    long RecursionCount;\r
+    void * OwningThread;\r
+    void * LockSemaphore;\r
+#if defined(_WIN64)\r
+    unsigned __int64 SpinCount;\r
+#else\r
+    unsigned long SpinCount;\r
+#endif\r
+};\r
+\r
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);\r
+extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);\r
+extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);\r
+extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);\r
+\r
+#else\r
+\r
+typedef ::CRITICAL_SECTION critical_section;\r
+\r
+#endif // #ifndef BOOST_USE_WINDOWS_H\r
+\r
+class lightweight_mutex\r
+{\r
+private:\r
+\r
+    critical_section cs_;\r
+\r
+    lightweight_mutex(lightweight_mutex const &);\r
+    lightweight_mutex & operator=(lightweight_mutex const &);\r
+\r
+public:\r
+\r
+    lightweight_mutex()\r
+    {\r
+        InitializeCriticalSection(&cs_);\r
+    }\r
+\r
+    ~lightweight_mutex()\r
+    {\r
+        DeleteCriticalSection(&cs_);\r
+    }\r
+\r
+    class scoped_lock;\r
+    friend class scoped_lock;\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        lightweight_mutex & m_;\r
+\r
+        scoped_lock(scoped_lock const &);\r
+        scoped_lock & operator=(scoped_lock const &);\r
+\r
+    public:\r
+\r
+        explicit scoped_lock(lightweight_mutex & m): m_(m)\r
+        {\r
+            EnterCriticalSection(&m_.cs_);\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            LeaveCriticalSection(&m_.cs_);\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/operator_bool.hpp b/src/external/boost/boost/smart_ptr/detail/operator_bool.hpp
new file mode 100644 (file)
index 0000000..a4bc752
--- /dev/null
@@ -0,0 +1,56 @@
+//  This header intentionally has no include guards.\r
+//\r
+//  Copyright (c) 2001-2009 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+\r
+#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)\r
+\r
+    operator bool () const\r
+    {\r
+        return px != 0;\r
+    }\r
+\r
+#elif defined( _MANAGED )\r
+\r
+    static void unspecified_bool( this_type*** )\r
+    {\r
+    }\r
+\r
+    typedef void (*unspecified_bool_type)( this_type*** );\r
+\r
+    operator unspecified_bool_type() const // never throws\r
+    {\r
+        return px == 0? 0: unspecified_bool;\r
+    }\r
+\r
+#elif \\r
+    ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \\r
+    ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \\r
+    ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )\r
+\r
+    typedef T * (this_type::*unspecified_bool_type)() const;\r
+\r
+    operator unspecified_bool_type() const // never throws\r
+    {\r
+        return px == 0? 0: &this_type::get;\r
+    }\r
+\r
+#else\r
+\r
+    typedef T * this_type::*unspecified_bool_type;\r
+\r
+    operator unspecified_bool_type() const // never throws\r
+    {\r
+        return px == 0? 0: &this_type::px;\r
+    }\r
+\r
+#endif\r
+\r
+    // operator! is redundant, but some compilers need it\r
+    bool operator! () const // never throws\r
+    {\r
+        return px == 0;\r
+    }\r
diff --git a/src/external/boost/boost/smart_ptr/detail/shared_count.hpp b/src/external/boost/boost/smart_ptr/detail/shared_count.hpp
new file mode 100644 (file)
index 0000000..ce1beb0
--- /dev/null
@@ -0,0 +1,444 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/shared_count.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#ifdef __BORLANDC__\r
+# pragma warn -8027     // Functions containing try are not expanded inline\r
+#endif\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/checked_delete.hpp>\r
+#include <boost/throw_exception.hpp>\r
+#include <boost/smart_ptr/bad_weak_ptr.hpp>\r
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>\r
+#include <boost/smart_ptr/detail/sp_counted_impl.hpp>\r
+#include <boost/detail/workaround.hpp>\r
+// In order to avoid circular dependencies with Boost.TR1\r
+// we make sure that our include of <memory> doesn't try to\r
+// pull in the TR1 headers: that's why we use this header \r
+// rather than including <memory> directly:\r
+#include <boost/config/no_tr1/memory.hpp>  // std::auto_ptr\r
+#include <functional>       // std::less\r
+#include <new>              // std::bad_alloc\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+\r
+int const shared_count_id = 0x2C35F101;\r
+int const   weak_count_id = 0x298C38A4;\r
+\r
+#endif\r
+\r
+struct sp_nothrow_tag {};\r
+\r
+class weak_count;\r
+\r
+class shared_count\r
+{\r
+private:\r
+\r
+    sp_counted_base * pi_;\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+    int id_;\r
+#endif\r
+\r
+    friend class weak_count;\r
+\r
+public:\r
+\r
+    shared_count(): pi_(0) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+    }\r
+\r
+    template<class Y> explicit shared_count( Y * p ): pi_( 0 )\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+\r
+        try\r
+        {\r
+            pi_ = new sp_counted_impl_p<Y>( p );\r
+        }\r
+        catch(...)\r
+        {\r
+            boost::checked_delete( p );\r
+            throw;\r
+        }\r
+\r
+#else\r
+\r
+        pi_ = new sp_counted_impl_p<Y>( p );\r
+\r
+        if( pi_ == 0 )\r
+        {\r
+            boost::checked_delete( p );\r
+            boost::throw_exception( std::bad_alloc() );\r
+        }\r
+\r
+#endif\r
+    }\r
+\r
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )\r
+    template<class Y, class D> shared_count( Y * p, D d ): pi_(0)\r
+#else\r
+    template<class P, class D> shared_count( P p, D d ): pi_(0)\r
+#endif\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )\r
+        typedef Y* P;\r
+#endif\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+\r
+        try\r
+        {\r
+            pi_ = new sp_counted_impl_pd<P, D>(p, d);\r
+        }\r
+        catch(...)\r
+        {\r
+            d(p); // delete p\r
+            throw;\r
+        }\r
+\r
+#else\r
+\r
+        pi_ = new sp_counted_impl_pd<P, D>(p, d);\r
+\r
+        if(pi_ == 0)\r
+        {\r
+            d(p); // delete p\r
+            boost::throw_exception(std::bad_alloc());\r
+        }\r
+\r
+#endif\r
+    }\r
+\r
+    template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+        typedef sp_counted_impl_pda<P, D, A> impl_type;\r
+        typedef typename A::template rebind< impl_type >::other A2;\r
+\r
+        A2 a2( a );\r
+\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+\r
+        try\r
+        {\r
+            pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );\r
+            new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );\r
+        }\r
+        catch(...)\r
+        {\r
+            d( p );\r
+\r
+            if( pi_ != 0 )\r
+            {\r
+                a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );\r
+            }\r
+\r
+            throw;\r
+        }\r
+\r
+#else\r
+\r
+        pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );\r
+\r
+        if( pi_ != 0 )\r
+        {\r
+            new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );\r
+        }\r
+        else\r
+        {\r
+            d( p );\r
+            boost::throw_exception( std::bad_alloc() );\r
+        }\r
+\r
+#endif\r
+    }\r
+\r
+#ifndef BOOST_NO_AUTO_PTR\r
+\r
+    // auto_ptr<Y> is special cased to provide the strong guarantee\r
+\r
+    template<class Y>\r
+    explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+#ifdef BOOST_NO_EXCEPTIONS\r
+\r
+        if( pi_ == 0 )\r
+        {\r
+            boost::throw_exception(std::bad_alloc());\r
+        }\r
+\r
+#endif\r
+\r
+        r.release();\r
+    }\r
+\r
+#endif \r
+\r
+    ~shared_count() // nothrow\r
+    {\r
+        if( pi_ != 0 ) pi_->release();\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        id_ = 0;\r
+#endif\r
+    }\r
+\r
+    shared_count(shared_count const & r): pi_(r.pi_) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+        if( pi_ != 0 ) pi_->add_ref_copy();\r
+    }\r
+\r
+#if defined( BOOST_HAS_RVALUE_REFS )\r
+\r
+    shared_count(shared_count && r): pi_(r.pi_) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+    {\r
+        r.pi_ = 0;\r
+    }\r
+\r
+#endif\r
+\r
+    explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0\r
+    shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0\r
+\r
+    shared_count & operator= (shared_count const & r) // nothrow\r
+    {\r
+        sp_counted_base * tmp = r.pi_;\r
+\r
+        if( tmp != pi_ )\r
+        {\r
+            if( tmp != 0 ) tmp->add_ref_copy();\r
+            if( pi_ != 0 ) pi_->release();\r
+            pi_ = tmp;\r
+        }\r
+\r
+        return *this;\r
+    }\r
+\r
+    void swap(shared_count & r) // nothrow\r
+    {\r
+        sp_counted_base * tmp = r.pi_;\r
+        r.pi_ = pi_;\r
+        pi_ = tmp;\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return pi_ != 0? pi_->use_count(): 0;\r
+    }\r
+\r
+    bool unique() const // nothrow\r
+    {\r
+        return use_count() == 1;\r
+    }\r
+\r
+    bool empty() const // nothrow\r
+    {\r
+        return pi_ == 0;\r
+    }\r
+\r
+    friend inline bool operator==(shared_count const & a, shared_count const & b)\r
+    {\r
+        return a.pi_ == b.pi_;\r
+    }\r
+\r
+    friend inline bool operator<(shared_count const & a, shared_count const & b)\r
+    {\r
+        return std::less<sp_counted_base *>()( a.pi_, b.pi_ );\r
+    }\r
+\r
+    void * get_deleter( sp_typeinfo const & ti ) const\r
+    {\r
+        return pi_? pi_->get_deleter( ti ): 0;\r
+    }\r
+};\r
+\r
+\r
+class weak_count\r
+{\r
+private:\r
+\r
+    sp_counted_base * pi_;\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+    int id_;\r
+#endif\r
+\r
+    friend class shared_count;\r
+\r
+public:\r
+\r
+    weak_count(): pi_(0) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(weak_count_id)\r
+#endif\r
+    {\r
+    }\r
+\r
+    weak_count(shared_count const & r): pi_(r.pi_) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(weak_count_id)\r
+#endif\r
+    {\r
+        if(pi_ != 0) pi_->weak_add_ref();\r
+    }\r
+\r
+    weak_count(weak_count const & r): pi_(r.pi_) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(weak_count_id)\r
+#endif\r
+    {\r
+        if(pi_ != 0) pi_->weak_add_ref();\r
+    }\r
+\r
+// Move support\r
+\r
+#if defined( BOOST_HAS_RVALUE_REFS )\r
+\r
+    weak_count(weak_count && r): pi_(r.pi_) // nothrow\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(weak_count_id)\r
+#endif\r
+    {\r
+        r.pi_ = 0;\r
+    }\r
+\r
+#endif\r
+\r
+    ~weak_count() // nothrow\r
+    {\r
+        if(pi_ != 0) pi_->weak_release();\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        id_ = 0;\r
+#endif\r
+    }\r
+\r
+    weak_count & operator= (shared_count const & r) // nothrow\r
+    {\r
+        sp_counted_base * tmp = r.pi_;\r
+\r
+        if( tmp != pi_ )\r
+        {\r
+            if(tmp != 0) tmp->weak_add_ref();\r
+            if(pi_ != 0) pi_->weak_release();\r
+            pi_ = tmp;\r
+        }\r
+\r
+        return *this;\r
+    }\r
+\r
+    weak_count & operator= (weak_count const & r) // nothrow\r
+    {\r
+        sp_counted_base * tmp = r.pi_;\r
+\r
+        if( tmp != pi_ )\r
+        {\r
+            if(tmp != 0) tmp->weak_add_ref();\r
+            if(pi_ != 0) pi_->weak_release();\r
+            pi_ = tmp;\r
+        }\r
+\r
+        return *this;\r
+    }\r
+\r
+    void swap(weak_count & r) // nothrow\r
+    {\r
+        sp_counted_base * tmp = r.pi_;\r
+        r.pi_ = pi_;\r
+        pi_ = tmp;\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return pi_ != 0? pi_->use_count(): 0;\r
+    }\r
+\r
+    bool empty() const // nothrow\r
+    {\r
+        return pi_ == 0;\r
+    }\r
+\r
+    friend inline bool operator==(weak_count const & a, weak_count const & b)\r
+    {\r
+        return a.pi_ == b.pi_;\r
+    }\r
+\r
+    friend inline bool operator<(weak_count const & a, weak_count const & b)\r
+    {\r
+        return std::less<sp_counted_base *>()(a.pi_, b.pi_);\r
+    }\r
+};\r
+\r
+inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+{\r
+    if( pi_ == 0 || !pi_->add_ref_lock() )\r
+    {\r
+        boost::throw_exception( boost::bad_weak_ptr() );\r
+    }\r
+}\r
+\r
+inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        , id_(shared_count_id)\r
+#endif\r
+{\r
+    if( pi_ != 0 && !pi_->add_ref_lock() )\r
+    {\r
+        pi_ = 0;\r
+    }\r
+}\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#ifdef __BORLANDC__\r
+# pragma warn .8027     // Functions containing try are not expanded inline\r
+#endif\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/shared_ptr_nmt.hpp b/src/external/boost/boost/smart_ptr/detail/shared_ptr_nmt.hpp
new file mode 100644 (file)
index 0000000..2921f41
--- /dev/null
@@ -0,0 +1,182 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED\r
+\r
+//\r
+//  detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates\r
+//\r
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.\r
+//  Copyright (c) 2001, 2002 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.\r
+//\r
+\r
+#include <boost/assert.hpp>\r
+#include <boost/checked_delete.hpp>\r
+#include <boost/throw_exception.hpp>\r
+#include <boost/smart_ptr/detail/atomic_count.hpp>\r
+\r
+#ifndef BOOST_NO_AUTO_PTR\r
+# include <memory>          // for std::auto_ptr\r
+#endif\r
+\r
+#include <algorithm>        // for std::swap\r
+#include <functional>       // for std::less\r
+#include <new>              // for std::bad_alloc\r
+\r
+namespace boost\r
+{\r
+\r
+template<class T> class shared_ptr\r
+{\r
+private:\r
+\r
+    typedef detail::atomic_count count_type;\r
+\r
+public:\r
+\r
+    typedef T element_type;\r
+    typedef T value_type;\r
+\r
+    explicit shared_ptr(T * p = 0): px(p)\r
+    {\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+\r
+        try  // prevent leak if new throws\r
+        {\r
+            pn = new count_type(1);\r
+        }\r
+        catch(...)\r
+        {\r
+            boost::checked_delete(p);\r
+            throw;\r
+        }\r
+\r
+#else\r
+\r
+        pn = new count_type(1);\r
+\r
+        if(pn == 0)\r
+        {\r
+            boost::checked_delete(p);\r
+            boost::throw_exception(std::bad_alloc());\r
+        }\r
+\r
+#endif\r
+    }\r
+\r
+    ~shared_ptr()\r
+    {\r
+        if(--*pn == 0)\r
+        {\r
+            boost::checked_delete(px);\r
+            delete pn;\r
+        }\r
+    }\r
+\r
+    shared_ptr(shared_ptr const & r): px(r.px)  // never throws\r
+    {\r
+        pn = r.pn;\r
+        ++*pn;\r
+    }\r
+\r
+    shared_ptr & operator=(shared_ptr const & r)\r
+    {\r
+        shared_ptr(r).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+#ifndef BOOST_NO_AUTO_PTR\r
+\r
+    explicit shared_ptr(std::auto_ptr<T> & r)\r
+    { \r
+        pn = new count_type(1); // may throw\r
+        px = r.release(); // fix: moved here to stop leak if new throws\r
+    } \r
+\r
+    shared_ptr & operator=(std::auto_ptr<T> & r)\r
+    {\r
+        shared_ptr(r).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+#endif\r
+\r
+    void reset(T * p = 0)\r
+    {\r
+        BOOST_ASSERT(p == 0 || p != px);\r
+        shared_ptr(p).swap(*this);\r
+    }\r
+\r
+    T & operator*() const  // never throws\r
+    {\r
+        BOOST_ASSERT(px != 0);\r
+        return *px;\r
+    }\r
+\r
+    T * operator->() const  // never throws\r
+    {\r
+        BOOST_ASSERT(px != 0);\r
+        return px;\r
+    }\r
+\r
+    T * get() const  // never throws\r
+    {\r
+        return px;\r
+    }\r
+\r
+    long use_count() const  // never throws\r
+    {\r
+        return *pn;\r
+    }\r
+\r
+    bool unique() const  // never throws\r
+    {\r
+        return *pn == 1;\r
+    }\r
+    \r
+    void swap(shared_ptr<T> & other)  // never throws\r
+    {\r
+        std::swap(px, other.px);\r
+        std::swap(pn, other.pn);\r
+    }\r
+\r
+private:\r
+\r
+    T * px;            // contained pointer\r
+    count_type * pn;   // ptr to reference counter\r
+};\r
+\r
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)\r
+{\r
+    return std::less<T*>()(a.get(), b.get());\r
+}\r
+\r
+template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)\r
+{\r
+    a.swap(b);\r
+}\r
+\r
+// get_pointer() enables boost::mem_fn to recognize shared_ptr\r
+\r
+template<class T> inline T * get_pointer(shared_ptr<T> const & p)\r
+{\r
+    return p.get();\r
+}\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_convertible.hpp b/src/external/boost/boost/smart_ptr/detail/sp_convertible.hpp
new file mode 100644 (file)
index 0000000..6270b79
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//  detail/sp_convertible.hpp\r
+//\r
+//  Copyright 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+\r
+#include <boost/config.hpp>\r
+\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE )\r
+# define BOOST_SP_NO_SP_CONVERTIBLE\r
+#endif\r
+\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 )\r
+# define BOOST_SP_NO_SP_CONVERTIBLE\r
+#endif\r
+\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )\r
+# define BOOST_SP_NO_SP_CONVERTIBLE\r
+#endif\r
+\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template< class Y, class T > struct sp_convertible\r
+{\r
+    typedef char (&yes) [1];\r
+    typedef char (&no)  [2];\r
+\r
+    static yes f( T* );\r
+    static no  f( ... );\r
+\r
+    enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) };\r
+};\r
+\r
+struct sp_empty\r
+{\r
+};\r
+\r
+template< bool > struct sp_enable_if_convertible_impl;\r
+\r
+template<> struct sp_enable_if_convertible_impl<true>\r
+{\r
+    typedef sp_empty type;\r
+};\r
+\r
+template<> struct sp_enable_if_convertible_impl<false>\r
+{\r
+};\r
+\r
+template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >\r
+{\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE )\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base.hpp
new file mode 100644 (file)
index 0000000..7302560
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base.hpp\r
+//\r
+//  Copyright 2005, 2006 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>\r
+\r
+#if defined( BOOST_SP_DISABLE_THREADS )\r
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>\r
+\r
+#elif defined( BOOST_SP_USE_SPINLOCK )\r
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>\r
+\r
+#elif defined( BOOST_SP_USE_PTHREADS )\r
+# include <boost/smart_ptr/detail/sp_counted_base_pt.hpp>\r
+\r
+#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )\r
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>\r
+\r
+#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )\r
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>\r
+\r
+#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER )\r
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>\r
+\r
+#elif defined(__HP_aCC) && defined(__ia64)\r
+# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>\r
+\r
+#elif defined( __MWERKS__ ) && defined( __POWERPC__ )\r
+# include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp>\r
+\r
+#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) )\r
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>\r
+\r
+#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) )\r
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>\r
+\r
+#elif defined( BOOST_SP_HAS_SYNC )\r
+# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>\r
+\r
+#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )\r
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>\r
+\r
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)\r
+# include <boost/smart_ptr/detail/sp_counted_base_w32.hpp>\r
+\r
+#elif !defined( BOOST_HAS_THREADS )\r
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>\r
+\r
+#else\r
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>\r
+\r
+#endif\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
new file mode 100644 (file)
index 0000000..1fe2326
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r
+\r
+//\r
+//  detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64\r
+//\r
+//  Copyright 2007 Baruch Zilber\r
+//  Copyright 2007 Boris Gubenko\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <machine/sys/inline.h>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    // ++*pw;\r
+\r
+    _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE);\r
+} \r
+\r
+inline int atomic_decrement( int * pw )\r
+{\r
+    // return --*pw;\r
+\r
+    int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE));\r
+    if (1 == r)\r
+    {\r
+        _Asm_mf();\r
+    }\r
+    \r
+    return r - 1;\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    // if( *pw != 0 ) ++*pw;\r
+    // return *pw;\r
+\r
+    int v = *pw;\r
+    \r
+    for (;;)\r
+    {\r
+        if (0 == v)\r
+        {\r
+            return 0;\r
+        }\r
+        \r
+        _Asm_mov_to_ar(_AREG_CCV,\r
+                       v,\r
+                       (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE));\r
+        int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE));\r
+        if (r == v)\r
+        {\r
+            return r + 1;\r
+        }\r
+        \r
+        v = r;\r
+    }\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
new file mode 100644 (file)
index 0000000..01c0c45
--- /dev/null
@@ -0,0 +1,170 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+//  Thanks to Ben Hitchings for the #weak + (#shared != 0)\r
+//  formulation\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void atomic_increment( register long * pw )\r
+{\r
+    register int a;\r
+\r
+    asm\r
+    {\r
+loop:\r
+\r
+    lwarx   a, 0, pw\r
+    addi    a, a, 1\r
+    stwcx.  a, 0, pw\r
+    bne-    loop\r
+    }\r
+}\r
+\r
+inline long atomic_decrement( register long * pw )\r
+{\r
+    register int a;\r
+\r
+    asm\r
+    {\r
+    sync\r
+\r
+loop:\r
+\r
+    lwarx   a, 0, pw\r
+    addi    a, a, -1\r
+    stwcx.  a, 0, pw\r
+    bne-    loop\r
+\r
+    isync\r
+    }\r
+\r
+    return a;\r
+}\r
+\r
+inline long atomic_conditional_increment( register long * pw )\r
+{\r
+    register int a;\r
+\r
+    asm\r
+    {\r
+loop:\r
+\r
+    lwarx   a, 0, pw\r
+    cmpwi   a, 0\r
+    beq     store\r
+\r
+    addi    a, a, 1\r
+\r
+store:\r
+\r
+    stwcx.  a, 0, pw\r
+    bne-    loop\r
+    }\r
+\r
+    return a;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    long use_count_;        // #shared\r
+    long weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<long const volatile &>( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
new file mode 100644 (file)
index 0000000..c7f37d8
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED\r
+\r
+//\r
+//  detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2006 Peter Dimov\r
+//  Copyright 2005 Ben Hutchings\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    // ++*pw;\r
+\r
+    int tmp;\r
+\r
+    // No barrier is required here but fetchadd always has an acquire or\r
+    // release barrier associated with it.  We choose release as it should be\r
+    // cheaper.\r
+    __asm__ ("fetchadd4.rel %0=%1,1" :\r
+         "=r"(tmp), "=m"(*pw) :\r
+         "m"( *pw ));\r
+}\r
+\r
+inline int atomic_decrement( int * pw )\r
+{\r
+    // return --*pw;\r
+\r
+    int rv;\r
+\r
+    __asm__ ("     fetchadd4.rel %0=%1,-1 ;; \n"\r
+             "     cmp.eq        p7,p0=1,%0 ;; \n"\r
+             "(p7) ld4.acq       %0=%1    " :\r
+             "=&r"(rv), "=m"(*pw) :\r
+             "m"( *pw ) :\r
+             "p7");\r
+\r
+    return rv;\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    // if( *pw != 0 ) ++*pw;\r
+    // return *pw;\r
+\r
+    int rv, tmp, tmp2;\r
+\r
+    __asm__ ("0:   ld4          %0=%3           ;; \n"\r
+         "     cmp.eq       p7,p0=0,%0        ;; \n"\r
+         "(p7) br.cond.spnt 1f                \n"\r
+         "     mov          ar.ccv=%0         \n"\r
+         "     add          %1=1,%0           ;; \n"\r
+         "     cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n"\r
+         "     cmp.ne       p7,p0=%0,%2       ;; \n"\r
+         "(p7) br.cond.spnt 0b                \n"\r
+         "     mov          %0=%1             ;; \n"\r
+         "1:" : \r
+         "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :\r
+         "m"( *pw ) :\r
+         "ar.ccv", "p7");\r
+\r
+    return rv;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
new file mode 100644 (file)
index 0000000..addc009
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED\r
+#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS\r
+//\r
+//  Copyright (c) 2009, Spirent Communications, Inc.\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    // ++*pw;\r
+\r
+    int tmp;\r
+\r
+    __asm__ __volatile__\r
+    (\r
+        "0:\n\t"\r
+        "ll %0, %1\n\t"\r
+        "addiu %0, 1\n\t"\r
+        "sc %0, %1\n\t"\r
+        "beqz %0, 0b":\r
+        "=&r"( tmp ), "=m"( *pw ):\r
+        "m"( *pw )\r
+    );\r
+}\r
+\r
+inline int atomic_decrement( int * pw )\r
+{\r
+    // return --*pw;\r
+\r
+    int rv, tmp;\r
+\r
+    __asm__ __volatile__\r
+    (\r
+        "0:\n\t"\r
+        "ll %1, %2\n\t"\r
+        "addiu %0, %1, -1\n\t"\r
+        "sc %0, %2\n\t"\r
+        "beqz %0, 0b\n\t"\r
+        "addiu %0, %1, -1":\r
+        "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):\r
+        "m"( *pw ):\r
+        "memory"\r
+    );\r
+\r
+    return rv;\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    // if( *pw != 0 ) ++*pw;\r
+    // return *pw;\r
+\r
+    int rv, tmp;\r
+\r
+    __asm__ __volatile__\r
+    (\r
+        "0:\n\t"\r
+        "ll %0, %2\n\t"\r
+        "beqz %0, 1f\n\t"\r
+        "addiu %1, %0, 1\n\t"\r
+        "sc %1, %2\n\t"\r
+        "beqz %1, 0b\n\t"\r
+        "addiu %0, %0, 1\n\t"\r
+        "1:":\r
+        "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):\r
+        "m"( *pw ):\r
+        "memory"\r
+    );\r
+\r
+    return rv;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<int const volatile &>( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
new file mode 100644 (file)
index 0000000..1fa8bf6
--- /dev/null
@@ -0,0 +1,181 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+//  Thanks to Ben Hitchings for the #weak + (#shared != 0)\r
+//  formulation\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    // ++*pw;\r
+\r
+    int tmp;\r
+\r
+    __asm__\r
+    (\r
+        "0:\n\t"\r
+        "lwarx %1, 0, %2\n\t"\r
+        "addi %1, %1, 1\n\t"\r
+        "stwcx. %1, 0, %2\n\t"\r
+        "bne- 0b":\r
+\r
+        "=m"( *pw ), "=&b"( tmp ):\r
+        "r"( pw ), "m"( *pw ):\r
+        "cc"\r
+    );\r
+}\r
+\r
+inline int atomic_decrement( int * pw )\r
+{\r
+    // return --*pw;\r
+\r
+    int rv;\r
+\r
+    __asm__ __volatile__\r
+    (\r
+        "sync\n\t"\r
+        "0:\n\t"\r
+        "lwarx %1, 0, %2\n\t"\r
+        "addi %1, %1, -1\n\t"\r
+        "stwcx. %1, 0, %2\n\t"\r
+        "bne- 0b\n\t"\r
+        "isync":\r
+\r
+        "=m"( *pw ), "=&b"( rv ):\r
+        "r"( pw ), "m"( *pw ):\r
+        "memory", "cc"\r
+    );\r
+\r
+    return rv;\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    // if( *pw != 0 ) ++*pw;\r
+    // return *pw;\r
+\r
+    int rv;\r
+\r
+    __asm__\r
+    (\r
+        "0:\n\t"\r
+        "lwarx %1, 0, %2\n\t"\r
+        "cmpwi %1, 0\n\t"\r
+        "beq 1f\n\t"\r
+        "addi %1, %1, 1\n\t"\r
+        "1:\n\t"\r
+        "stwcx. %1, 0, %2\n\t"\r
+        "bne- 0b":\r
+\r
+        "=m"( *pw ), "=&b"( rv ):\r
+        "r"( pw ), "m"( *pw ):\r
+        "cc"\r
+    );\r
+\r
+    return rv;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<int const volatile &>( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
new file mode 100644 (file)
index 0000000..d9fbafa
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//  detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+\r
+//\r
+//  Copyright (c) 2006 Piotr Wyderski\r
+//  Copyright (c) 2006 Tomas Puverle\r
+//  Copyright (c) 2006 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+//\r
+//  Thanks to Michael van der Westhuizen\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <inttypes.h> // int32_t\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ )\r
+{\r
+    __asm__ __volatile__( "cas [%1], %2, %0"\r
+                        : "+r" (swap_)\r
+                        : "r" (dest_), "r" (compare_)\r
+                        : "memory" );\r
+\r
+    return swap_;\r
+}\r
+\r
+inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv )\r
+{\r
+    // long r = *pw;\r
+    // *pw += dv;\r
+    // return r;\r
+\r
+    for( ;; )\r
+    {\r
+        int32_t r = *pw;\r
+\r
+        if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )\r
+        {\r
+            return r;\r
+        }\r
+    }\r
+}\r
+\r
+inline void atomic_increment( int32_t * pw )\r
+{\r
+    atomic_fetch_and_add( pw, 1 );\r
+}\r
+\r
+inline int32_t atomic_decrement( int32_t * pw )\r
+{\r
+    return atomic_fetch_and_add( pw, -1 );\r
+}\r
+\r
+inline int32_t atomic_conditional_increment( int32_t * pw )\r
+{\r
+    // long r = *pw;\r
+    // if( r != 0 ) ++*pw;\r
+    // return r;\r
+\r
+    for( ;; )\r
+    {\r
+        int32_t r = *pw;\r
+\r
+        if( r == 0 )\r
+        {\r
+            return r;\r
+        }\r
+\r
+        if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )\r
+        {\r
+            return r;\r
+        }\r
+    }    \r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int32_t use_count_;        // #shared\r
+    int32_t weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 1 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 1 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return const_cast< int32_t const volatile & >( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
new file mode 100644 (file)
index 0000000..d357d31
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+//  Thanks to Ben Hitchings for the #weak + (#shared != 0)\r
+//  formulation\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline int atomic_exchange_and_add( int * pw, int dv )\r
+{\r
+    // int r = *pw;\r
+    // *pw += dv;\r
+    // return r;\r
+\r
+    int r;\r
+\r
+    __asm__ __volatile__\r
+    (\r
+        "lock\n\t"\r
+        "xadd %1, %0":\r
+        "=m"( *pw ), "=r"( r ): // outputs (%0, %1)\r
+        "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)\r
+        "memory", "cc" // clobbers\r
+    );\r
+\r
+    return r;\r
+}\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    //atomic_exchange_and_add( pw, 1 );\r
+\r
+    __asm__\r
+    (\r
+        "lock\n\t"\r
+        "incl %0":\r
+        "=m"( *pw ): // output (%0)\r
+        "m"( *pw ): // input (%1)\r
+        "cc" // clobbers\r
+    );\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    // int rv = *pw;\r
+    // if( rv != 0 ) ++*pw;\r
+    // return rv;\r
+\r
+    int rv, tmp;\r
+\r
+    __asm__\r
+    (\r
+        "movl %0, %%eax\n\t"\r
+        "0:\n\t"\r
+        "test %%eax, %%eax\n\t"\r
+        "je 1f\n\t"\r
+        "movl %%eax, %2\n\t"\r
+        "incl %2\n\t"\r
+        "lock\n\t"\r
+        "cmpxchgl %2, %0\n\t"\r
+        "jne 0b\n\t"\r
+        "1:":\r
+        "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)\r
+        "m"( *pw ): // input (%3)\r
+        "cc" // clobbers\r
+    );\r
+\r
+    return rv;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<int const volatile &>( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_nt.hpp
new file mode 100644 (file)
index 0000000..612e1d8
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_nt.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    long use_count_;        // #shared\r
+    long weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        ++use_count_;\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        if( use_count_ == 0 ) return false;\r
+        ++use_count_;\r
+        return true;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( --use_count_ == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        ++weak_count_;\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( --weak_count_ == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return use_count_;\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_pt.hpp
new file mode 100644 (file)
index 0000000..3469764
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_pt.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <pthread.h>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    long use_count_;        // #shared\r
+    long weak_count_;       // #weak + (#shared != 0)\r
+\r
+    mutable pthread_mutex_t m_;\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init\r
+\r
+#if defined(__hpux) && defined(_DECTHREADS_)\r
+        pthread_mutex_init( &m_, pthread_mutexattr_default );\r
+#else\r
+        pthread_mutex_init( &m_, 0 );\r
+#endif\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+        pthread_mutex_destroy( &m_ );\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        ++use_count_;\r
+        pthread_mutex_unlock( &m_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        bool r = use_count_ == 0? false: ( ++use_count_, true );\r
+        pthread_mutex_unlock( &m_ );\r
+        return r;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        long new_use_count = --use_count_;\r
+        pthread_mutex_unlock( &m_ );\r
+\r
+        if( new_use_count == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        ++weak_count_;\r
+        pthread_mutex_unlock( &m_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        long new_weak_count = --weak_count_;\r
+        pthread_mutex_unlock( &m_ );\r
+\r
+        if( new_weak_count == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        pthread_mutex_lock( &m_ );\r
+        long r = use_count_;\r
+        pthread_mutex_unlock( &m_ );\r
+\r
+        return r;\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_spin.hpp
new file mode 100644 (file)
index 0000000..09feb63
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline int atomic_exchange_and_add( int * pw, int dv )\r
+{\r
+    spinlock_pool<1>::scoped_lock lock( pw );\r
+\r
+    int r = *pw;\r
+    *pw += dv;\r
+    return r;\r
+}\r
+\r
+inline void atomic_increment( int * pw )\r
+{\r
+    spinlock_pool<1>::scoped_lock lock( pw );\r
+    ++*pw;\r
+}\r
+\r
+inline int atomic_conditional_increment( int * pw )\r
+{\r
+    spinlock_pool<1>::scoped_lock lock( pw );\r
+\r
+    int rv = *pw;\r
+    if( rv != 0 ) ++*pw;\r
+    return rv;\r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    int use_count_;        // #shared\r
+    int weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        spinlock_pool<1>::scoped_lock lock( &use_count_ );\r
+        return use_count_;\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_sync.hpp
new file mode 100644 (file)
index 0000000..5a074c0
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//  detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics\r
+//\r
+//  Copyright (c) 2007 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+#include <limits.h>\r
+\r
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )\r
+# include <ia64intrin.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#if INT_MAX >= 2147483647\r
+\r
+typedef int sp_int32_t;\r
+\r
+#else\r
+\r
+typedef long sp_int32_t;\r
+\r
+#endif\r
+\r
+inline void atomic_increment( sp_int32_t * pw )\r
+{\r
+    __sync_fetch_and_add( pw, 1 );\r
+}\r
+\r
+inline sp_int32_t atomic_decrement( sp_int32_t * pw )\r
+{\r
+    return __sync_fetch_and_add( pw, -1 );\r
+}\r
+\r
+inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )\r
+{\r
+    // long r = *pw;\r
+    // if( r != 0 ) ++*pw;\r
+    // return r;\r
+\r
+    sp_int32_t r = *pw;\r
+\r
+    for( ;; )\r
+    {\r
+        if( r == 0 )\r
+        {\r
+            return r;\r
+        }\r
+\r
+        sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 );\r
+\r
+        if( r2 == r )\r
+        {\r
+            return r;\r
+        }\r
+        else\r
+        {\r
+            r = r2;\r
+        }\r
+    }    \r
+}\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    sp_int32_t use_count_;        // #shared\r
+    sp_int32_t weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        atomic_increment( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        return atomic_conditional_increment( &use_count_ ) != 0;\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( atomic_decrement( &use_count_ ) == 1 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        atomic_increment( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( atomic_decrement( &weak_count_ ) == 1 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return const_cast< sp_int32_t const volatile & >( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_base_w32.hpp
new file mode 100644 (file)
index 0000000..84ac67b
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_base_w32.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//\r
+//  Lock-free algorithm by Alexander Terekhov\r
+//\r
+//  Thanks to Ben Hitchings for the #weak + (#shared != 0)\r
+//  formulation\r
+//\r
+\r
+#include <boost/detail/interlocked.hpp>\r
+#include <boost/detail/workaround.hpp>\r
+#include <boost/detail/sp_typeinfo.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class sp_counted_base\r
+{\r
+private:\r
+\r
+    sp_counted_base( sp_counted_base const & );\r
+    sp_counted_base & operator= ( sp_counted_base const & );\r
+\r
+    long use_count_;        // #shared\r
+    long weak_count_;       // #weak + (#shared != 0)\r
+\r
+public:\r
+\r
+    sp_counted_base(): use_count_( 1 ), weak_count_( 1 )\r
+    {\r
+    }\r
+\r
+    virtual ~sp_counted_base() // nothrow\r
+    {\r
+    }\r
+\r
+    // dispose() is called when use_count_ drops to zero, to release\r
+    // the resources managed by *this.\r
+\r
+    virtual void dispose() = 0; // nothrow\r
+\r
+    // destroy() is called when weak_count_ drops to zero.\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        delete this;\r
+    }\r
+\r
+    virtual void * get_deleter( sp_typeinfo const & ti ) = 0;\r
+\r
+    void add_ref_copy()\r
+    {\r
+        BOOST_INTERLOCKED_INCREMENT( &use_count_ );\r
+    }\r
+\r
+    bool add_ref_lock() // true on success\r
+    {\r
+        for( ;; )\r
+        {\r
+            long tmp = static_cast< long const volatile& >( use_count_ );\r
+            if( tmp == 0 ) return false;\r
+\r
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )\r
+\r
+            // work around a code generation bug\r
+\r
+            long tmp2 = tmp + 1;\r
+            if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;\r
+\r
+#else\r
+\r
+            if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;\r
+\r
+#endif\r
+        }\r
+    }\r
+\r
+    void release() // nothrow\r
+    {\r
+        if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )\r
+        {\r
+            dispose();\r
+            weak_release();\r
+        }\r
+    }\r
+\r
+    void weak_add_ref() // nothrow\r
+    {\r
+        BOOST_INTERLOCKED_INCREMENT( &weak_count_ );\r
+    }\r
+\r
+    void weak_release() // nothrow\r
+    {\r
+        if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )\r
+        {\r
+            destroy();\r
+        }\r
+    }\r
+\r
+    long use_count() const // nothrow\r
+    {\r
+        return static_cast<long const volatile &>( use_count_ );\r
+    }\r
+};\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_counted_impl.hpp b/src/external/boost/boost/smart_ptr/detail/sp_counted_impl.hpp
new file mode 100644 (file)
index 0000000..b32eafa
--- /dev/null
@@ -0,0 +1,231 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  detail/sp_counted_impl.hpp\r
+//\r
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.\r
+//  Copyright 2004-2005 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/config.hpp>\r
+\r
+#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)\r
+# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.\r
+#endif\r
+\r
+#include <boost/checked_delete.hpp>\r
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>\r
+\r
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)\r
+#error GMX_REMOVED: #include <boost/smart_ptr/detail/quick_allocator.hpp>\r
+#endif\r
+\r
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)\r
+#include <memory>           // std::allocator\r
+#endif\r
+\r
+#include <cstddef>          // std::size_t\r
+\r
+namespace boost\r
+{\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+\r
+void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );\r
+void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );\r
+\r
+#endif\r
+\r
+namespace detail\r
+{\r
+\r
+template<class X> class sp_counted_impl_p: public sp_counted_base\r
+{\r
+private:\r
+\r
+    X * px_;\r
+\r
+    sp_counted_impl_p( sp_counted_impl_p const & );\r
+    sp_counted_impl_p & operator= ( sp_counted_impl_p const & );\r
+\r
+    typedef sp_counted_impl_p<X> this_type;\r
+\r
+public:\r
+\r
+    explicit sp_counted_impl_p( X * px ): px_( px )\r
+    {\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        boost::sp_scalar_constructor_hook( px, sizeof(X), this );\r
+#endif\r
+    }\r
+\r
+    virtual void dispose() // nothrow\r
+    {\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+        boost::sp_scalar_destructor_hook( px_, sizeof(X), this );\r
+#endif\r
+        boost::checked_delete( px_ );\r
+    }\r
+\r
+    virtual void * get_deleter( detail::sp_typeinfo const & )\r
+    {\r
+        return 0;\r
+    }\r
+\r
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)\r
+\r
+    void * operator new( std::size_t )\r
+    {\r
+        return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );\r
+    }\r
+\r
+    void operator delete( void * p )\r
+    {\r
+        std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );\r
+    }\r
+\r
+#endif\r
+\r
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)\r
+\r
+    void * operator new( std::size_t )\r
+    {\r
+        return quick_allocator<this_type>::alloc();\r
+    }\r
+\r
+    void operator delete( void * p )\r
+    {\r
+        quick_allocator<this_type>::dealloc( p );\r
+    }\r
+\r
+#endif\r
+};\r
+\r
+//\r
+// Borland's Codeguard trips up over the -Vx- option here:\r
+//\r
+#ifdef __CODEGUARD__\r
+# pragma option push -Vx-\r
+#endif\r
+\r
+template<class P, class D> class sp_counted_impl_pd: public sp_counted_base\r
+{\r
+private:\r
+\r
+    P ptr; // copy constructor must not throw\r
+    D del; // copy constructor must not throw\r
+\r
+    sp_counted_impl_pd( sp_counted_impl_pd const & );\r
+    sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );\r
+\r
+    typedef sp_counted_impl_pd<P, D> this_type;\r
+\r
+public:\r
+\r
+    // pre: d(p) must not throw\r
+\r
+    sp_counted_impl_pd( P p, D d ): ptr(p), del(d)\r
+    {\r
+    }\r
+\r
+    virtual void dispose() // nothrow\r
+    {\r
+        del( ptr );\r
+    }\r
+\r
+    virtual void * get_deleter( detail::sp_typeinfo const & ti )\r
+    {\r
+        return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;\r
+    }\r
+\r
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)\r
+\r
+    void * operator new( std::size_t )\r
+    {\r
+        return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );\r
+    }\r
+\r
+    void operator delete( void * p )\r
+    {\r
+        std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );\r
+    }\r
+\r
+#endif\r
+\r
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)\r
+\r
+    void * operator new( std::size_t )\r
+    {\r
+        return quick_allocator<this_type>::alloc();\r
+    }\r
+\r
+    void operator delete( void * p )\r
+    {\r
+        quick_allocator<this_type>::dealloc( p );\r
+    }\r
+\r
+#endif\r
+};\r
+\r
+template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base\r
+{\r
+private:\r
+\r
+    P p_; // copy constructor must not throw\r
+    D d_; // copy constructor must not throw\r
+    A a_; // copy constructor must not throw\r
+\r
+    sp_counted_impl_pda( sp_counted_impl_pda const & );\r
+    sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );\r
+\r
+    typedef sp_counted_impl_pda<P, D, A> this_type;\r
+\r
+public:\r
+\r
+    // pre: d( p ) must not throw\r
+\r
+    sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a )\r
+    {\r
+    }\r
+\r
+    virtual void dispose() // nothrow\r
+    {\r
+        d_( p_ );\r
+    }\r
+\r
+    virtual void destroy() // nothrow\r
+    {\r
+        typedef typename A::template rebind< this_type >::other A2;\r
+\r
+        A2 a2( a_ );\r
+\r
+        this->~this_type();\r
+        a2.deallocate( this, 1 );\r
+    }\r
+\r
+    virtual void * get_deleter( detail::sp_typeinfo const & ti )\r
+    {\r
+        return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;\r
+    }\r
+};\r
+\r
+#ifdef __CODEGUARD__\r
+# pragma option pop\r
+#endif\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/sp_has_sync.hpp b/src/external/boost/boost/smart_ptr/detail/sp_has_sync.hpp
new file mode 100644 (file)
index 0000000..e423fa0
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/smart_ptr/detail/sp_has_sync.hpp\r
+//\r
+//  Copyright (c) 2008, 2009 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics\r
+//  are available.\r
+//\r
+\r
+#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )\r
+\r
+#define BOOST_SP_HAS_SYNC\r
+\r
+#if defined( __arm__ )  || defined( __armel__ )\r
+#undef BOOST_SP_HAS_SYNC\r
+#endif\r
+\r
+#if defined( __hppa ) || defined( __hppa__ )\r
+#undef BOOST_SP_HAS_SYNC\r
+#endif\r
+\r
+#if defined( __m68k__ )\r
+#undef BOOST_SP_HAS_SYNC\r
+#endif\r
+\r
+#if defined( __sparc__ )\r
+#undef BOOST_SP_HAS_SYNC\r
+#endif\r
+\r
+#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1100 )\r
+#undef BOOST_SP_HAS_SYNC\r
+#endif\r
+\r
+#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock.hpp
new file mode 100644 (file)
index 0000000..e4653f7
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/spinlock.hpp\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  struct spinlock\r
+//  {\r
+//      void lock();\r
+//      bool try_lock();\r
+//      void unlock();\r
+//\r
+//      class scoped_lock;\r
+//  };\r
+//\r
+//  #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>\r
+//\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>\r
+\r
+#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )\r
+#  include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>\r
+\r
+#elif defined( BOOST_SP_HAS_SYNC )\r
+#  include <boost/smart_ptr/detail/spinlock_sync.hpp>\r
+\r
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)\r
+#  include <boost/smart_ptr/detail/spinlock_w32.hpp>\r
+\r
+#elif defined(BOOST_HAS_PTHREADS)\r
+#  include <boost/smart_ptr/detail/spinlock_pt.hpp>\r
+\r
+#elif !defined(BOOST_HAS_THREADS)\r
+#  include <boost/smart_ptr/detail/spinlock_nt.hpp>\r
+\r
+#else\r
+#  error Unrecognized threading platform\r
+#endif\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
new file mode 100644 (file)
index 0000000..7d7c786
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED\r
+\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/smart_ptr/detail/yield_k.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class spinlock\r
+{\r
+public:\r
+\r
+    int v_;\r
+\r
+public:\r
+\r
+    bool try_lock()\r
+    {\r
+        int r;\r
+\r
+        __asm__ __volatile__(\r
+            "swp %0, %1, [%2]":\r
+            "=&r"( r ): // outputs\r
+            "r"( 1 ), "r"( &v_ ): // inputs\r
+            "memory", "cc" );\r
+\r
+        return r == 0;\r
+    }\r
+\r
+    void lock()\r
+    {\r
+        for( unsigned k = 0; !try_lock(); ++k )\r
+        {\r
+            boost::detail::yield( k );\r
+        }\r
+    }\r
+\r
+    void unlock()\r
+    {\r
+        __asm__ __volatile__( "" ::: "memory" );\r
+        *const_cast< int volatile* >( &v_ ) = 0;\r
+    }\r
+\r
+public:\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( spinlock & sp ): sp_( sp )\r
+        {\r
+            sp.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#define BOOST_DETAIL_SPINLOCK_INIT {0}\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_nt.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_nt.hpp
new file mode 100644 (file)
index 0000000..920d67e
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/assert.hpp>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class spinlock\r
+{\r
+public:\r
+\r
+    bool locked_;\r
+\r
+public:\r
+\r
+    inline bool try_lock()\r
+    {\r
+        if( locked_ )\r
+        {\r
+            return false;\r
+        }\r
+        else\r
+        {\r
+            locked_ = true;\r
+            return true;\r
+        }\r
+    }\r
+\r
+    inline void lock()\r
+    {\r
+        BOOST_ASSERT( !locked_ );\r
+        locked_ = true;\r
+    }\r
+\r
+    inline void unlock()\r
+    {\r
+        BOOST_ASSERT( locked_ );\r
+        locked_ = false;\r
+    }\r
+\r
+public:\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( spinlock & sp ): sp_( sp )\r
+        {\r
+            sp.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#define BOOST_DETAIL_SPINLOCK_INIT { false }\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_pool.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_pool.hpp
new file mode 100644 (file)
index 0000000..8a62a90
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/detail/spinlock_pool.hpp\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  spinlock_pool<0> is reserved for atomic<>, when/if it arrives\r
+//  spinlock_pool<1> is reserved for shared_ptr reference counts\r
+//  spinlock_pool<2> is reserved for shared_ptr atomic access\r
+//\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/smart_ptr/detail/spinlock.hpp>\r
+#include <cstddef>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template< int I > class spinlock_pool\r
+{\r
+private:\r
+\r
+    static spinlock pool_[ 41 ];\r
+\r
+public:\r
+\r
+    static spinlock & spinlock_for( void const * pv )\r
+    {\r
+        std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;\r
+        return pool_[ i ];\r
+    }\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )\r
+        {\r
+            sp_.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] =\r
+{\r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, \r
+    BOOST_DETAIL_SPINLOCK_INIT\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_pt.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_pt.hpp
new file mode 100644 (file)
index 0000000..f55e61f
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <pthread.h>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class spinlock\r
+{\r
+public:\r
+\r
+    pthread_mutex_t v_;\r
+\r
+public:\r
+\r
+    bool try_lock()\r
+    {\r
+        return pthread_mutex_trylock( &v_ ) == 0;\r
+    }\r
+\r
+    void lock()\r
+    {\r
+        pthread_mutex_lock( &v_ );\r
+    }\r
+\r
+    void unlock()\r
+    {\r
+        pthread_mutex_unlock( &v_ );\r
+    }\r
+\r
+public:\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( spinlock & sp ): sp_( sp )\r
+        {\r
+            sp.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER }\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_sync.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_sync.hpp
new file mode 100644 (file)
index 0000000..f948306
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/smart_ptr/detail/yield_k.hpp>\r
+\r
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )\r
+# include <ia64intrin.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class spinlock\r
+{\r
+public:\r
+\r
+    int v_;\r
+\r
+public:\r
+\r
+    bool try_lock()\r
+    {\r
+        int r = __sync_lock_test_and_set( &v_, 1 );\r
+        return r == 0;\r
+    }\r
+\r
+    void lock()\r
+    {\r
+        for( unsigned k = 0; !try_lock(); ++k )\r
+        {\r
+            boost::detail::yield( k );\r
+        }\r
+    }\r
+\r
+    void unlock()\r
+    {\r
+        __sync_lock_release( &v_ );\r
+    }\r
+\r
+public:\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( spinlock & sp ): sp_( sp )\r
+        {\r
+            sp.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#define BOOST_DETAIL_SPINLOCK_INIT {0}\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/spinlock_w32.hpp b/src/external/boost/boost/smart_ptr/detail/spinlock_w32.hpp
new file mode 100644 (file)
index 0000000..8caa33c
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#include <boost/detail/interlocked.hpp>\r
+#include <boost/smart_ptr/detail/yield_k.hpp>\r
+\r
+// BOOST_COMPILER_FENCE\r
+\r
+#if defined(__INTEL_COMPILER)\r
+\r
+#define BOOST_COMPILER_FENCE __memory_barrier();\r
+\r
+#elif defined( _MSC_VER ) && _MSC_VER >= 1310\r
+\r
+extern "C" void _ReadWriteBarrier();\r
+#pragma intrinsic( _ReadWriteBarrier )\r
+\r
+#define BOOST_COMPILER_FENCE _ReadWriteBarrier();\r
+\r
+#elif defined(__GNUC__)\r
+\r
+#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" );\r
+\r
+#else\r
+\r
+#define BOOST_COMPILER_FENCE\r
+\r
+#endif\r
+\r
+//\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+class spinlock\r
+{\r
+public:\r
+\r
+    long v_;\r
+\r
+public:\r
+\r
+    bool try_lock()\r
+    {\r
+        long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 );\r
+\r
+        BOOST_COMPILER_FENCE\r
+\r
+        return r == 0;\r
+    }\r
+\r
+    void lock()\r
+    {\r
+        for( unsigned k = 0; !try_lock(); ++k )\r
+        {\r
+            boost::detail::yield( k );\r
+        }\r
+    }\r
+\r
+    void unlock()\r
+    {\r
+        BOOST_COMPILER_FENCE\r
+        *const_cast< long volatile* >( &v_ ) = 0;\r
+    }\r
+\r
+public:\r
+\r
+    class scoped_lock\r
+    {\r
+    private:\r
+\r
+        spinlock & sp_;\r
+\r
+        scoped_lock( scoped_lock const & );\r
+        scoped_lock & operator=( scoped_lock const & );\r
+\r
+    public:\r
+\r
+        explicit scoped_lock( spinlock & sp ): sp_( sp )\r
+        {\r
+            sp.lock();\r
+        }\r
+\r
+        ~scoped_lock()\r
+        {\r
+            sp_.unlock();\r
+        }\r
+    };\r
+};\r
+\r
+} // namespace detail\r
+} // namespace boost\r
+\r
+#define BOOST_DETAIL_SPINLOCK_INIT {0}\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/detail/yield_k.hpp b/src/external/boost/boost/smart_ptr/detail/yield_k.hpp
new file mode 100644 (file)
index 0000000..4f174bb
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  yield_k.hpp\r
+//\r
+//  Copyright (c) 2008 Peter Dimov\r
+//\r
+//  void yield( unsigned k );\r
+//\r
+//  Typical use:\r
+//\r
+//  for( unsigned k = 0; !try_lock(); ++k ) yield( k );\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0.\r
+//  See accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt\r
+//\r
+\r
+#include <boost/config.hpp>\r
+\r
+// BOOST_SMT_PAUSE\r
+\r
+#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )\r
+\r
+extern "C" void _mm_pause();\r
+#pragma intrinsic( _mm_pause )\r
+\r
+#define BOOST_SMT_PAUSE _mm_pause();\r
+\r
+#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )\r
+\r
+#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );\r
+\r
+#endif\r
+\r
+//\r
+\r
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )\r
+\r
+#if defined( BOOST_USE_WINDOWS_H )\r
+# include <windows.h>\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+#if !defined( BOOST_USE_WINDOWS_H )\r
+  extern "C" void __stdcall Sleep( unsigned long ms );\r
+#endif\r
+\r
+inline void yield( unsigned k )\r
+{\r
+    if( k < 4 )\r
+    {\r
+    }\r
+#if defined( BOOST_SMT_PAUSE )\r
+    else if( k < 16 )\r
+    {\r
+        BOOST_SMT_PAUSE\r
+    }\r
+#endif\r
+    else if( k < 32 )\r
+    {\r
+        Sleep( 0 );\r
+    }\r
+    else\r
+    {\r
+        Sleep( 1 );\r
+    }\r
+}\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#elif defined( BOOST_HAS_PTHREADS )\r
+\r
+#include <sched.h>\r
+#include <time.h>\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void yield( unsigned k )\r
+{\r
+    if( k < 4 )\r
+    {\r
+    }\r
+#if defined( BOOST_SMT_PAUSE )\r
+    else if( k < 16 )\r
+    {\r
+        BOOST_SMT_PAUSE\r
+    }\r
+#endif\r
+    else if( k < 32 || k & 1 )\r
+    {\r
+        sched_yield();\r
+    }\r
+    else\r
+    {\r
+        // g++ -Wextra warns on {} or {0}\r
+        struct timespec rqtp = { 0, 0 };\r
+\r
+        // POSIX says that timespec has tv_sec and tv_nsec\r
+        // But it doesn't guarantee order or placement\r
+\r
+        rqtp.tv_sec = 0;\r
+        rqtp.tv_nsec = 1000;\r
+\r
+        nanosleep( &rqtp, 0 );\r
+    }\r
+}\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#else\r
+\r
+namespace boost\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+inline void yield( unsigned )\r
+{\r
+}\r
+\r
+} // namespace detail\r
+\r
+} // namespace boost\r
+\r
+#endif\r
+\r
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/smart_ptr/shared_ptr.hpp b/src/external/boost/boost/smart_ptr/shared_ptr.hpp
new file mode 100644 (file)
index 0000000..78d367a
--- /dev/null
@@ -0,0 +1,701 @@
+#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED\r
+#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED\r
+\r
+//\r
+//  shared_ptr.hpp\r
+//\r
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.\r
+//  Copyright (c) 2001-2008 Peter Dimov\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.\r
+//\r
+\r
+#include <boost/config.hpp>   // for broken compiler workarounds\r
+\r
+#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)\r
+#include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>\r
+#else\r
+\r
+// In order to avoid circular dependencies with Boost.TR1\r
+// we make sure that our include of <memory> doesn't try to\r
+// pull in the TR1 headers: that's why we use this header \r
+// rather than including <memory> directly:\r
+#include <boost/config/no_tr1/memory.hpp>  // std::auto_ptr\r
+\r
+#include <boost/assert.hpp>\r
+#include <boost/checked_delete.hpp>\r
+#include <boost/throw_exception.hpp>\r
+#include <boost/smart_ptr/detail/shared_count.hpp>\r
+#include <boost/detail/workaround.hpp>\r
+#include <boost/smart_ptr/detail/sp_convertible.hpp>\r
+\r
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)\r
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>\r
+#include <boost/memory_order.hpp>\r
+#endif\r
+\r
+#include <algorithm>            // for std::swap\r
+#include <functional>           // for std::less\r
+#include <typeinfo>             // for std::bad_cast\r
+\r
+#if !defined(BOOST_NO_IOSTREAM)\r
+#if !defined(BOOST_NO_IOSFWD)\r
+#include <iosfwd>               // for std::basic_ostream\r
+#else\r
+#include <ostream>\r
+#endif\r
+#endif\r
+\r
+#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash\r
+# pragma warning(push)\r
+# pragma warning(disable:4284) // odd return type for operator->\r
+#endif\r
+\r
+namespace boost\r
+{\r
+\r
+template<class T> class shared_ptr;\r
+template<class T> class weak_ptr;\r
+template<class T> class enable_shared_from_this;\r
+template<class T> class enable_shared_from_this2;\r
+\r
+namespace detail\r
+{\r
+\r
+struct static_cast_tag {};\r
+struct const_cast_tag {};\r
+struct dynamic_cast_tag {};\r
+struct polymorphic_cast_tag {};\r
+\r
+template<class T> struct shared_ptr_traits\r
+{\r
+    typedef T & reference;\r
+};\r
+\r
+template<> struct shared_ptr_traits<void>\r
+{\r
+    typedef void reference;\r
+};\r
+\r
+#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)\r
+\r
+template<> struct shared_ptr_traits<void const>\r
+{\r
+    typedef void reference;\r
+};\r
+\r
+template<> struct shared_ptr_traits<void volatile>\r
+{\r
+    typedef void reference;\r
+};\r
+\r
+template<> struct shared_ptr_traits<void const volatile>\r
+{\r
+    typedef void reference;\r
+};\r
+\r
+#endif\r
+\r
+// enable_shared_from_this support\r
+\r
+template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )\r
+{\r
+    if( pe != 0 )\r
+    {\r
+        pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );\r
+    }\r
+}\r
+\r
+template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe )\r
+{\r
+    if( pe != 0 )\r
+    {\r
+        pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );\r
+    }\r
+}\r
+\r
+#ifdef _MANAGED\r
+\r
+// Avoid C4793, ... causes native code generation\r
+\r
+struct sp_any_pointer\r
+{\r
+    template<class T> sp_any_pointer( T* ) {}\r
+};\r
+\r
+inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )\r
+{\r
+}\r
+\r
+#else // _MANAGED\r
+\r
+inline void sp_enable_shared_from_this( ... )\r
+{\r
+}\r
+\r
+#endif // _MANAGED\r
+\r
+#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )\r
+\r
+// rvalue auto_ptr support based on a technique by Dave Abrahams\r
+\r
+template< class T, class R > struct sp_enable_if_auto_ptr\r
+{\r
+};\r
+\r
+template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >\r
+{\r
+    typedef R type;\r
+}; \r
+\r
+#endif\r
+\r
+} // namespace detail\r
+\r
+\r
+//\r
+//  shared_ptr\r
+//\r
+//  An enhanced relative of scoped_ptr with reference counted copy semantics.\r
+//  The object pointed to is deleted when the last shared_ptr pointing to it\r
+//  is destroyed or reset.\r
+//\r
+\r
+template<class T> class shared_ptr\r
+{\r
+private:\r
+\r
+    // Borland 5.5.1 specific workaround\r
+    typedef shared_ptr<T> this_type;\r
+\r
+public:\r
+\r
+    typedef T element_type;\r
+    typedef T value_type;\r
+    typedef T * pointer;\r
+    typedef typename boost::detail::shared_ptr_traits<T>::reference reference;\r
+\r
+    shared_ptr(): px(0), pn() // never throws in 1.30+\r
+    {\r
+    }\r
+\r
+    template<class Y>\r
+    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete\r
+    {\r
+        boost::detail::sp_enable_shared_from_this( this, p, p );\r
+    }\r
+\r
+    //\r
+    // Requirements: D's copy constructor must not throw\r
+    //\r
+    // shared_ptr will release p by calling d(p)\r
+    //\r
+\r
+    template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)\r
+    {\r
+        boost::detail::sp_enable_shared_from_this( this, p, p );\r
+    }\r
+\r
+    // As above, but with allocator. A's copy constructor shall not throw.\r
+\r
+    template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )\r
+    {\r
+        boost::detail::sp_enable_shared_from_this( this, p, p );\r
+    }\r
+\r
+//  generated copy constructor, destructor are fine\r
+\r
+    template<class Y>\r
+    explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw\r
+    {\r
+        // it is now safe to copy r.px, as pn(r.pn) did not throw\r
+        px = r.px;\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws\r
+    {\r
+        if( !pn.empty() )\r
+        {\r
+            px = r.px;\r
+        }\r
+    }\r
+\r
+    template<class Y>\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )\r
+\r
+    shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )\r
+\r
+#else\r
+\r
+    shared_ptr( shared_ptr<Y> const & r )\r
+\r
+#endif\r
+    : px( r.px ), pn( r.pn ) // never throws\r
+    {\r
+    }\r
+\r
+    // aliasing\r
+    template< class Y >\r
+    shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws\r
+    {\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)\r
+    {\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)\r
+    {\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)\r
+    {\r
+        if(px == 0) // need to allocate new counter -- the cast failed\r
+        {\r
+            pn = boost::detail::shared_count();\r
+        }\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)\r
+    {\r
+        if(px == 0)\r
+        {\r
+            boost::throw_exception(std::bad_cast());\r
+        }\r
+    }\r
+\r
+#ifndef BOOST_NO_AUTO_PTR\r
+\r
+    template<class Y>\r
+    explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()\r
+    {\r
+        Y * tmp = r.get();\r
+        pn = boost::detail::shared_count(r);\r
+        boost::detail::sp_enable_shared_from_this( this, tmp, tmp );\r
+    }\r
+\r
+#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )\r
+\r
+    template<class Ap>\r
+    explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()\r
+    {\r
+        typename Ap::element_type * tmp = r.get();\r
+        pn = boost::detail::shared_count( r );\r
+        boost::detail::sp_enable_shared_from_this( this, tmp, tmp );\r
+    }\r
+\r
+\r
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+\r
+#endif // BOOST_NO_AUTO_PTR\r
+\r
+    // assignment\r
+\r
+    shared_ptr & operator=( shared_ptr const & r ) // never throws\r
+    {\r
+        this_type(r).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)\r
+\r
+    template<class Y>\r
+    shared_ptr & operator=(shared_ptr<Y> const & r) // never throws\r
+    {\r
+        this_type(r).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+#endif\r
+\r
+#ifndef BOOST_NO_AUTO_PTR\r
+\r
+    template<class Y>\r
+    shared_ptr & operator=( std::auto_ptr<Y> & r )\r
+    {\r
+        this_type(r).swap(*this);\r
+        return *this;\r
+    }\r
+\r
+#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )\r
+\r
+    template<class Ap>\r
+    typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )\r
+    {\r
+        this_type( r ).swap( *this );\r
+        return *this;\r
+    }\r
+\r
+\r
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION\r
+\r
+#endif // BOOST_NO_AUTO_PTR\r
+\r
+// Move support\r
+\r
+#if defined( BOOST_HAS_RVALUE_REFS )\r
+\r
+    shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws\r
+    {\r
+        pn.swap( r.pn );\r
+        r.px = 0;\r
+    }\r
+\r
+    template<class Y>\r
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )\r
+\r
+    shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )\r
+\r
+#else\r
+\r
+    shared_ptr( shared_ptr<Y> && r )\r
+\r
+#endif\r
+    : px( r.px ), pn() // never throws\r
+    {\r
+        pn.swap( r.pn );\r
+        r.px = 0;\r
+    }\r
+\r
+    shared_ptr & operator=( shared_ptr && r ) // never throws\r
+    {\r
+        this_type( static_cast< shared_ptr && >( r ) ).swap( *this );\r
+        return *this;\r
+    }\r
+\r
+    template<class Y>\r
+    shared_ptr & operator=( shared_ptr<Y> && r ) // never throws\r
+    {\r
+        this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );\r
+        return *this;\r
+    }\r
+\r
+#endif\r
+\r
+    void reset() // never throws in 1.30+\r
+    {\r
+        this_type().swap(*this);\r
+    }\r
+\r
+    template<class Y> void reset(Y * p) // Y must be complete\r
+    {\r
+        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors\r
+        this_type(p).swap(*this);\r
+    }\r
+\r
+    template<class Y, class D> void reset( Y * p, D d )\r
+    {\r
+        this_type( p, d ).swap( *this );\r
+    }\r
+\r
+    template<class Y, class D, class A> void reset( Y * p, D d, A a )\r
+    {\r
+        this_type( p, d, a ).swap( *this );\r
+    }\r
+\r
+    template<class Y> void reset( shared_ptr<Y> const & r, T * p )\r
+    {\r
+        this_type( r, p ).swap( *this );\r
+    }\r
+\r
+    reference operator* () const // never throws\r
+    {\r
+        BOOST_ASSERT(px != 0);\r
+        return *px;\r
+    }\r
+\r
+    T * operator-> () const // never throws\r
+    {\r
+        BOOST_ASSERT(px != 0);\r
+        return px;\r
+    }\r
+\r
+    T * get() const // never throws\r
+    {\r
+        return px;\r
+    }\r
+\r
+// implicit conversion to "bool"\r
+#include <boost/smart_ptr/detail/operator_bool.hpp>\r
+\r
+    bool unique() const // never throws\r
+    {\r
+        return pn.unique();\r
+    }\r
+\r
+    long use_count() const // never throws\r
+    {\r
+        return pn.use_count();\r
+    }\r
+\r
+    void swap(shared_ptr<T> & other) // never throws\r
+    {\r
+        std::swap(px, other.px);\r
+        pn.swap(other.pn);\r
+    }\r
+\r
+    template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const\r
+    {\r
+        return pn < rhs.pn;\r
+    }\r
+\r
+    void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const\r
+    {\r
+        return pn.get_deleter( ti );\r
+    }\r
+\r
+    bool _internal_equiv( shared_ptr const & r ) const\r
+    {\r
+        return px == r.px && pn == r.pn;\r
+    }\r
+\r
+// Tasteless as this may seem, making all members public allows member templates\r
+// to work in the absence of member template friends. (Matthew Langston)\r
+\r
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS\r
+\r
+private:\r
+\r
+    template<class Y> friend class shared_ptr;\r
+    template<class Y> friend class weak_ptr;\r
+\r
+\r
+#endif\r
+\r
+    T * px;                     // contained pointer\r
+    boost::detail::shared_count pn;    // reference counter\r
+\r
+};  // shared_ptr\r
+\r
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)\r
+{\r
+    return a.get() == b.get();\r
+}\r
+\r
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96\r
+\r
+// Resolve the ambiguity between our op!= and the one in rel_ops\r
+\r
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)\r
+{\r
+    return a.get() != b.get();\r
+}\r
+\r
+#endif\r
+\r
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)\r
+{\r
+    return a._internal_less(b);\r
+}\r
+\r
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)\r
+{\r
+    a.swap(b);\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::static_cast_tag());\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::const_cast_tag());\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());\r
+}\r
+\r
+// shared_*_cast names are deprecated. Use *_pointer_cast instead.\r
+\r
+template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::static_cast_tag());\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)\r
+{\r
+    return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());\r
+}\r
+\r
+template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)\r
+{\r
+    BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());\r
+    return shared_static_cast<T>(r);\r
+}\r
+\r
+// get_pointer() enables boost::mem_fn to recognize shared_ptr\r
+\r
+template<class T> inline T * get_pointer(shared_ptr<T> const & p)\r
+{\r
+    return p.get();\r
+}\r
+\r
+// operator<<\r
+\r
+#if !defined(BOOST_NO_IOSTREAM)\r
+\r
+#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )\r
+\r
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)\r
+{\r
+    os << p.get();\r
+    return os;\r
+}\r
+\r
+#else\r
+\r
+// in STLport's no-iostreams mode no iostream symbols can be used\r
+#ifndef _STLP_NO_IOSTREAMS\r
+\r
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)\r
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL\r
+using std::basic_ostream;\r
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)\r
+# else\r
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)\r
+# endif\r
+{\r
+    os << p.get();\r
+    return os;\r
+}\r
+\r
+#endif // _STLP_NO_IOSTREAMS\r
+\r
+#endif // __GNUC__ < 3\r
+\r
+#endif // !defined(BOOST_NO_IOSTREAM)\r
+\r
+// get_deleter\r
+\r
+#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \\r
+    ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \\r
+    ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )\r
+\r
+// g++ 2.9x doesn't allow static_cast<X const *>(void *)\r
+// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it\r
+\r
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)\r
+{\r
+    void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));\r
+    return const_cast<D *>(static_cast<D const *>(q));\r
+}\r
+\r
+#else\r
+\r
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)\r
+{\r
+    return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));\r
+}\r
+\r
+#endif\r
+\r
+// atomic access\r
+\r
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)\r
+\r
+template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )\r
+{\r
+    return false;\r
+}\r
+\r
+template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )\r
+{\r
+    boost::detail::spinlock_pool<2>::scoped_lock lock( p );\r
+    return *p;\r
+}\r
+\r
+template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )\r
+{\r
+    return atomic_load( p );\r
+}\r
+\r
+template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )\r
+{\r
+    boost::detail::spinlock_pool<2>::scoped_lock lock( p );\r
+    p->swap( r );\r
+}\r
+\r
+template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )\r
+{\r
+    atomic_store( p, r ); // std::move( r )\r
+}\r
+\r
+template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )\r
+{\r
+    boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );\r
+\r
+    sp.lock();\r
+    p->swap( r );\r
+    sp.unlock();\r
+\r
+    return r; // return std::move( r )\r
+}\r
+\r
+template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )\r
+{\r
+    return atomic_exchange( p, r ); // std::move( r )\r
+}\r
+\r
+template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )\r
+{\r
+    boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );\r
+\r
+    sp.lock();\r
+\r
+    if( p->_internal_equiv( *v ) )\r
+    {\r
+        p->swap( w );\r
+\r
+        sp.unlock();\r
+\r
+        return true;\r
+    }\r
+    else\r
+    {\r
+        shared_ptr<T> tmp( *p );\r
+\r
+        sp.unlock();\r
+\r
+        tmp.swap( *v );\r
+        return false;\r
+    }\r
+}\r
+\r
+template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )\r
+{\r
+    return atomic_compare_exchange( p, v, w ); // std::move( w )\r
+}\r
+\r
+#endif\r
+\r
+} // namespace boost\r
+\r
+#ifdef BOOST_MSVC\r
+# pragma warning(pop)\r
+#endif\r
+\r
+#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)\r
+\r
+#endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/throw_exception.hpp b/src/external/boost/boost/throw_exception.hpp
new file mode 100644 (file)
index 0000000..4073b7b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED\r
+#define BOOST_THROW_EXCEPTION_HPP_INCLUDED\r
+\r
+// MS compatible compilers support #pragma once\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+//\r
+//  boost/throw_exception.hpp\r
+//\r
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.\r
+//  Copyright (c) 2008-2009 Emil Dotchevski and Reverge Studios, Inc.\r
+//\r
+//  Distributed under the Boost Software License, Version 1.0. (See\r
+//  accompanying file LICENSE_1_0.txt or copy at\r
+//  http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+//  http://www.boost.org/libs/utility/throw_exception.html\r
+//\r
+\r
+#include <boost/exception/detail/attribute_noreturn.hpp>\r
+#include <boost/detail/workaround.hpp>\r
+#include <boost/config.hpp>\r
+#include <exception>\r
+\r
+#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x593) )\r
+# define BOOST_EXCEPTION_DISABLE\r
+#endif\r
+\r
+#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1310 )\r
+# define BOOST_EXCEPTION_DISABLE\r
+#endif\r
+\r
+#if !defined( BOOST_EXCEPTION_DISABLE )\r
+# include <boost/exception/exception.hpp>\r
+# include <boost/current_function.hpp>\r
+# define BOOST_THROW_EXCEPTION(x) ::boost::exception_detail::throw_exception_(x,BOOST_CURRENT_FUNCTION,__FILE__,__LINE__)\r
+#else\r
+# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)\r
+#endif\r
+\r
+namespace boost\r
+{\r
+#ifdef BOOST_NO_EXCEPTIONS\r
+\r
+void throw_exception( std::exception const & e ); // user defined\r
+\r
+#else\r
+\r
+inline void throw_exception_assert_compatibility( std::exception const & ) { }\r
+\r
+template<class E> BOOST_ATTRIBUTE_NORETURN inline void throw_exception( E const & e )\r
+{\r
+    //All boost exceptions are required to derive from std::exception,\r
+    //to ensure compatibility with BOOST_NO_EXCEPTIONS.\r
+    throw_exception_assert_compatibility(e);\r
+\r
+#ifndef BOOST_EXCEPTION_DISABLE\r
+    throw enable_current_exception(enable_error_info(e));\r
+#else\r
+    throw e;\r
+#endif\r
+}\r
+\r
+#endif\r
+\r
+#if !defined( BOOST_EXCEPTION_DISABLE )\r
+    namespace\r
+    exception_detail\r
+    {\r
+        template <class E>\r
+        BOOST_ATTRIBUTE_NORETURN\r
+        void\r
+        throw_exception_( E const & x, char const * current_function, char const * file, int line )\r
+        {\r
+            boost::throw_exception(\r
+                set_info(\r
+                    set_info(\r
+                        set_info(\r
+                            boost::enable_error_info(x),\r
+                            throw_function(current_function)),\r
+                        throw_file(file)),\r
+                    throw_line(line)));\r
+        }\r
+    }\r
+#endif\r
+} // namespace boost\r
+\r
+#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED\r
diff --git a/src/external/boost/boost/type.hpp b/src/external/boost/boost/type.hpp
new file mode 100644 (file)
index 0000000..4a1f750
--- /dev/null
@@ -0,0 +1,18 @@
+// (C) Copyright David Abrahams 2001.\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_TYPE_DWA20010120_HPP\r
+# define BOOST_TYPE_DWA20010120_HPP\r
+\r
+namespace boost {\r
+\r
+  // Just a simple "type envelope". Useful in various contexts, mostly to work\r
+  // around some MSVC deficiencies.\r
+  template <class T>\r
+  struct type {};\r
+\r
+}\r
+\r
+#endif // BOOST_TYPE_DWA20010120_HPP\r
diff --git a/src/external/boost/boost/utility/enable_if.hpp b/src/external/boost/boost/utility/enable_if.hpp
new file mode 100644 (file)
index 0000000..d89eb9f
--- /dev/null
@@ -0,0 +1,119 @@
+// Boost enable_if library\r
+\r
+// Copyright 2003 (c) The Trustees of Indiana University.\r
+\r
+// Use, modification, and distribution is subject to the Boost Software\r
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//    Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)\r
+//             Jeremiah Willcock (jewillco at osl.iu.edu)\r
+//             Andrew Lumsdaine (lums at osl.iu.edu)\r
+\r
+\r
+#ifndef BOOST_UTILITY_ENABLE_IF_HPP\r
+#define BOOST_UTILITY_ENABLE_IF_HPP\r
+\r
+#include "boost/config.hpp"\r
+\r
+// Even the definition of enable_if causes problems on some compilers,\r
+// so it's macroed out for all compilers that do not support SFINAE\r
+\r
+#ifndef BOOST_NO_SFINAE\r
+\r
+namespace boost\r
+{\r
\r
+  template <bool B, class T = void>\r
+  struct enable_if_c {\r
+    typedef T type;\r
+  };\r
+\r
+  template <class T>\r
+  struct enable_if_c<false, T> {};\r
+\r
+  template <class Cond, class T = void> \r
+  struct enable_if : public enable_if_c<Cond::value, T> {};\r
+\r
+  template <bool B, class T>\r
+  struct lazy_enable_if_c {\r
+    typedef typename T::type type;\r
+  };\r
+\r
+  template <class T>\r
+  struct lazy_enable_if_c<false, T> {};\r
+\r
+  template <class Cond, class T> \r
+  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};\r
+\r
+\r
+  template <bool B, class T = void>\r
+  struct disable_if_c {\r
+    typedef T type;\r
+  };\r
+\r
+  template <class T>\r
+  struct disable_if_c<true, T> {};\r
+\r
+  template <class Cond, class T = void> \r
+  struct disable_if : public disable_if_c<Cond::value, T> {};\r
+\r
+  template <bool B, class T>\r
+  struct lazy_disable_if_c {\r
+    typedef typename T::type type;\r
+  };\r
+\r
+  template <class T>\r
+  struct lazy_disable_if_c<true, T> {};\r
+\r
+  template <class Cond, class T> \r
+  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};\r
+\r
+} // namespace boost\r
+\r
+#else\r
+\r
+namespace boost {\r
+\r
+  namespace detail { typedef void enable_if_default_T; }\r
+\r
+  template <typename T>\r
+  struct enable_if_does_not_work_on_this_compiler;\r
+\r
+  template <bool B, class T = detail::enable_if_default_T>\r
+  struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <bool B, class T = detail::enable_if_default_T> \r
+  struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <bool B, class T = detail::enable_if_default_T> \r
+  struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <bool B, class T = detail::enable_if_default_T> \r
+  struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <class Cond, class T = detail::enable_if_default_T> \r
+  struct enable_if : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <class Cond, class T = detail::enable_if_default_T> \r
+  struct disable_if : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <class Cond, class T = detail::enable_if_default_T> \r
+  struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+  template <class Cond, class T = detail::enable_if_default_T> \r
+  struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>\r
+  { };\r
+\r
+} // namespace boost\r
+\r
+#endif // BOOST_NO_SFINAE\r
+\r
+#endif\r
diff --git a/src/external/boost/boost/version.hpp b/src/external/boost/boost/version.hpp
new file mode 100644 (file)
index 0000000..e66379c
--- /dev/null
@@ -0,0 +1,35 @@
+//  Boost version.hpp configuration header file  ------------------------------//\r
+\r
+//  (C) Copyright John maddock 1999. Distributed under the Boost\r
+//  Software License, Version 1.0. (See accompanying file\r
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+//  See http://www.boost.org/libs/config for documentation\r
+\r
+#ifndef BOOST_VERSION_HPP\r
+#define BOOST_VERSION_HPP\r
+\r
+//\r
+//  Caution, this is the only boost header that is guarenteed\r
+//  to change with every boost release, including this header\r
+//  will cause a recompile every time a new boost version is\r
+//  released.\r
+//\r
+//  BOOST_VERSION % 100 is the patch level\r
+//  BOOST_VERSION / 100 % 1000 is the minor version\r
+//  BOOST_VERSION / 100000 is the major version\r
+\r
+#define BOOST_VERSION 104601\r
+\r
+//\r
+//  BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION\r
+//  but as a *string* in the form "x_y[_z]" where x is the major version\r
+//  number, y is the minor version number, and z is the patch level if not 0.\r
+//  This is used by <config/auto_link.hpp> to select which library version to link to.\r
+\r
+#define BOOST_LIB_VERSION "1_46_1"\r
+\r
+#endif\r
+\r
+\r
+\r
diff --git a/src/external/boost/libs/smart_ptr/src/sp_collector.cpp b/src/external/boost/libs/smart_ptr/src/sp_collector.cpp
new file mode 100644 (file)
index 0000000..cebc7bf
--- /dev/null
@@ -0,0 +1,270 @@
+//\r
+//  sp_collector.cpp\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+\r
+#include <boost/assert.hpp>\r
+#include <boost/shared_ptr.hpp>\r
+#include <boost/detail/lightweight_mutex.hpp>\r
+#include <cstdlib>\r
+#include <map>\r
+#include <deque>\r
+#include <iostream>\r
+\r
+typedef std::map< void const *, std::pair<void *, size_t> > map_type;\r
+\r
+static map_type & get_map()\r
+{\r
+    static map_type m;\r
+    return m;\r
+}\r
+\r
+typedef boost::detail::lightweight_mutex mutex_type;\r
+\r
+static mutex_type & get_mutex()\r
+{\r
+    static mutex_type m;\r
+    return m;\r
+}\r
+\r
+static void * init_mutex_before_main = &get_mutex();\r
+\r
+namespace\r
+{\r
+    class X;\r
+\r
+    struct count_layout\r
+    {\r
+        boost::detail::sp_counted_base * pi;\r
+        int id;\r
+    };\r
+\r
+    struct shared_ptr_layout\r
+    {\r
+        X * px;\r
+        count_layout pn;\r
+    };\r
+}\r
+\r
+// assume 4 byte alignment for pointers when scanning\r
+size_t const pointer_align = 4;\r
+\r
+typedef std::map<void const *, long> map2_type;\r
+\r
+static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2)\r
+{\r
+    unsigned char const * p = static_cast<unsigned char const *>(area);\r
+\r
+    for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)\r
+    {\r
+        shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);\r
+\r
+        if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0)\r
+        {\r
+            ++m2[q->pn.pi];\r
+        }\r
+    }\r
+}\r
+\r
+typedef std::deque<void const *> open_type;\r
+\r
+static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open)\r
+{\r
+    unsigned char const * p = static_cast<unsigned char const *>(area);\r
+\r
+    for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)\r
+    {\r
+        shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);\r
+\r
+        if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0)\r
+        {\r
+            open.push_back(q->pn.pi);\r
+            m2.erase(q->pn.pi);\r
+        }\r
+    }\r
+}\r
+\r
+static void find_unreachable_objects_impl(map_type const & m, map2_type & m2)\r
+{\r
+    // scan objects for shared_ptr members, compute internal counts\r
+\r
+    {\r
+        std::cout << "... " << m.size() << " objects in m.\n";\r
+\r
+        for(map_type::const_iterator i = m.begin(); i != m.end(); ++i)\r
+        {\r
+            boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);\r
+\r
+            BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map\r
+\r
+            m2[ i->first ];\r
+\r
+            scan_and_count(i->second.first, i->second.second, m, m2);\r
+        }\r
+\r
+        std::cout << "... " << m2.size() << " objects in m2.\n";\r
+    }\r
+\r
+    // mark reachable objects\r
+\r
+    {\r
+        open_type open;\r
+\r
+        for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i)\r
+        {\r
+            boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);\r
+            if(p->use_count() != i->second) open.push_back(p);\r
+        }\r
+\r
+        std::cout << "... " << open.size() << " objects in open.\n";\r
+\r
+        for(open_type::iterator j = open.begin(); j != open.end(); ++j)\r
+        {\r
+            m2.erase(*j);\r
+        }\r
+\r
+        while(!open.empty())\r
+        {\r
+            void const * p = open.front();\r
+            open.pop_front();\r
+\r
+            map_type::const_iterator i = m.find(p);\r
+            BOOST_ASSERT(i != m.end());\r
+\r
+            scan_and_mark(i->second.first, i->second.second, m2, open);\r
+        }\r
+    }\r
+\r
+    // m2 now contains the unreachable objects\r
+}\r
+\r
+std::size_t find_unreachable_objects(bool report)\r
+{\r
+    map2_type m2;\r
+\r
+#ifdef BOOST_HAS_THREADS\r
+\r
+    // This will work without the #ifdef, but some compilers warn\r
+    // that lock is not referenced\r
+\r
+    mutex_type::scoped_lock lock(get_mutex());\r
+\r
+#endif\r
+\r
+    map_type const & m = get_map();\r
+\r
+    find_unreachable_objects_impl(m, m2);\r
+\r
+    if(report)\r
+    {\r
+        for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)\r
+        {\r
+            map_type::const_iterator i = m.find(j->first);\r
+            BOOST_ASSERT(i != m.end());\r
+            std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n";\r
+        }\r
+    }\r
+\r
+    return m2.size();\r
+}\r
+\r
+typedef std::deque< boost::shared_ptr<X> > free_list_type;\r
+\r
+static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free)\r
+{\r
+    unsigned char * p = static_cast<unsigned char *>(area);\r
+\r
+    for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)\r
+    {\r
+        shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p);\r
+\r
+        if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0)\r
+        {\r
+            boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);\r
+            free.push_back(*ppx);\r
+            ppx->reset();\r
+        }\r
+    }\r
+}\r
+\r
+void free_unreachable_objects()\r
+{\r
+    free_list_type free;\r
+\r
+    {\r
+        map2_type m2;\r
+\r
+#ifdef BOOST_HAS_THREADS\r
+\r
+        mutex_type::scoped_lock lock(get_mutex());\r
+\r
+#endif\r
+\r
+        map_type const & m = get_map();\r
+\r
+        find_unreachable_objects_impl(m, m2);\r
+\r
+        for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)\r
+        {\r
+            map_type::const_iterator i = m.find(j->first);\r
+            BOOST_ASSERT(i != m.end());\r
+            scan_and_free(i->second.first, i->second.second, m2, free);\r
+        }\r
+    }\r
+\r
+    std::cout << "... about to free " << free.size() << " objects.\n";\r
+}\r
+\r
+// debug hooks\r
+\r
+namespace boost\r
+{\r
+\r
+void sp_scalar_constructor_hook(void *)\r
+{\r
+}\r
+\r
+void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn)\r
+{\r
+#ifdef BOOST_HAS_THREADS\r
+\r
+    mutex_type::scoped_lock lock(get_mutex());\r
+\r
+#endif\r
+\r
+    get_map()[pn] = std::make_pair(px, size);\r
+}\r
+\r
+void sp_scalar_destructor_hook(void *)\r
+{\r
+}\r
+\r
+void sp_scalar_destructor_hook(void *, std::size_t, void * pn)\r
+{\r
+#ifdef BOOST_HAS_THREADS\r
+\r
+    mutex_type::scoped_lock lock(get_mutex());\r
+\r
+#endif\r
+\r
+    get_map().erase(pn);\r
+}\r
+\r
+void sp_array_constructor_hook(void *)\r
+{\r
+}\r
+\r
+void sp_array_destructor_hook(void *)\r
+{\r
+}\r
+\r
+} // namespace boost\r
+\r
+#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
diff --git a/src/external/boost/libs/smart_ptr/src/sp_debug_hooks.cpp b/src/external/boost/libs/smart_ptr/src/sp_debug_hooks.cpp
new file mode 100644 (file)
index 0000000..5fff673
--- /dev/null
@@ -0,0 +1,243 @@
+//\r
+//  sp_debug_hooks.cpp\r
+//\r
+//  Copyright (c) 2002, 2003 Peter Dimov\r
+//\r
+// Distributed under the Boost Software License, Version 1.0. (See\r
+// accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+//\r
+\r
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
+\r
+#include <boost/assert.hpp>\r
+#include <new>\r
+#include <cstdlib>\r
+\r
+int const m = 2; // m * sizeof(int) must be aligned appropriately\r
+\r
+// magic values to mark heap blocks with\r
+\r
+int const allocated_scalar  = 0x1234560C;\r
+int const allocated_array   = 0x1234560A;\r
+int const adopted_scalar    = 0x0567890C;\r
+int const adopted_array     = 0x0567890A;\r
+int const deleted           = 0x498769DE;\r
+\r
+using namespace std; // for compilers where things aren't in std\r
+\r
+// operator new\r
+\r
+static new_handler get_new_handler()\r
+{\r
+    new_handler p = set_new_handler(0);\r
+    set_new_handler(p);\r
+    return p;\r
+}\r
+\r
+static void * allocate(size_t n, int mark)\r
+{\r
+    int * pm;\r
+\r
+    for(;;)\r
+    {\r
+        pm = static_cast<int*>(malloc(n + m * sizeof(int)));\r
+\r
+        if(pm != 0) break;\r
+\r
+        if(new_handler pnh = get_new_handler())\r
+        {\r
+            pnh();\r
+        }\r
+        else\r
+        {\r
+            return 0;\r
+        }\r
+    }\r
+\r
+    *pm = mark;\r
+\r
+    return pm + m;\r
+}\r
+\r
+void * operator new(size_t n) throw(bad_alloc)\r
+{\r
+    void * p = allocate(n, allocated_scalar);\r
+\r
+#if !defined(BOOST_NO_EXCEPTIONS)\r
+\r
+    if(p == 0) throw bad_alloc();\r
+\r
+#endif\r
+\r
+    return p;\r
+}\r
+\r
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)\r
+\r
+void * operator new(size_t n, nothrow_t const &) throw()\r
+{\r
+    return allocate(n, allocated_scalar);\r
+}\r
+\r
+#endif\r
+\r
+void * operator new[](size_t n) throw(bad_alloc)\r
+{\r
+    void * p = allocate(n, allocated_array);\r
+\r
+#if !defined(BOOST_NO_EXCEPTIONS)\r
+\r
+    if(p == 0) throw bad_alloc();\r
+\r
+#endif\r
+\r
+    return p;\r
+}\r
+\r
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)\r
+\r
+void * operator new[](size_t n, nothrow_t const &) throw()\r
+{\r
+    return allocate(n, allocated_array);\r
+}\r
+\r
+#endif\r
+\r
+// debug hooks\r
+\r
+namespace boost\r
+{\r
+\r
+void sp_scalar_constructor_hook(void * p)\r
+{\r
+    if(p == 0) return;\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm != adopted_scalar);    // second smart pointer to the same address\r
+    BOOST_ASSERT(*pm != allocated_array);   // allocated with new[]\r
+    BOOST_ASSERT(*pm == allocated_scalar);  // not allocated with new\r
+\r
+    *pm = adopted_scalar;\r
+}\r
+\r
+void sp_scalar_constructor_hook(void * px, std::size_t, void *)\r
+{\r
+    sp_scalar_constructor_hook(px);\r
+}\r
+\r
+void sp_scalar_destructor_hook(void * p)\r
+{\r
+    if(p == 0) return;\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm == adopted_scalar);    // attempt to destroy nonmanaged block\r
+\r
+    *pm = allocated_scalar;\r
+}\r
+\r
+void sp_scalar_destructor_hook(void * px, std::size_t, void *)\r
+{\r
+    sp_scalar_destructor_hook(px);\r
+}\r
+\r
+// It is not possible to handle the array hooks in a portable manner.\r
+// The implementation typically reserves a bit of storage for the number\r
+// of objects in the array, and the argument of the array hook isn't\r
+// equal to the return value of operator new[].\r
+\r
+void sp_array_constructor_hook(void * /* p */)\r
+{\r
+/*\r
+    if(p == 0) return;\r
+\r
+    // adjust p depending on the implementation\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm != adopted_array);     // second smart array pointer to the same address\r
+    BOOST_ASSERT(*pm != allocated_scalar);  // allocated with new\r
+    BOOST_ASSERT(*pm == allocated_array);   // not allocated with new[]\r
+\r
+    *pm = adopted_array;\r
+*/\r
+}\r
+\r
+void sp_array_destructor_hook(void * /* p */)\r
+{\r
+/*\r
+    if(p == 0) return;\r
+\r
+    // adjust p depending on the implementation\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block\r
+\r
+    *pm = allocated_array;\r
+*/\r
+}\r
+\r
+} // namespace boost\r
+\r
+// operator delete\r
+\r
+void operator delete(void * p) throw()\r
+{\r
+    if(p == 0) return;\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm != deleted);           // double delete\r
+    BOOST_ASSERT(*pm != adopted_scalar);    // delete p.get();\r
+    BOOST_ASSERT(*pm != allocated_array);   // allocated with new[]\r
+    BOOST_ASSERT(*pm == allocated_scalar);  // not allocated with new\r
+\r
+    *pm = deleted;\r
+\r
+    free(pm);\r
+}\r
+\r
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)\r
+\r
+void operator delete(void * p, nothrow_t const &) throw()\r
+{\r
+    ::operator delete(p);\r
+}\r
+\r
+#endif\r
+\r
+void operator delete[](void * p) throw()\r
+{\r
+    if(p == 0) return;\r
+\r
+    int * pm = static_cast<int*>(p);\r
+    pm -= m;\r
+\r
+    BOOST_ASSERT(*pm != deleted);           // double delete\r
+    BOOST_ASSERT(*pm != adopted_scalar);    // delete p.get();\r
+    BOOST_ASSERT(*pm != allocated_scalar);  // allocated with new\r
+    BOOST_ASSERT(*pm == allocated_array);   // not allocated with new[]\r
+\r
+    *pm = deleted;\r
+\r
+    free(pm);\r
+}\r
+\r
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)\r
+\r
+void operator delete[](void * p, nothrow_t const &) throw()\r
+{\r
+    ::operator delete[](p);\r
+}\r
+\r
+#endif\r
+\r
+#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)\r
diff --git a/src/external/gmock-1.6.0/CMakeLists.txt b/src/external/gmock-1.6.0/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fd43eaa
--- /dev/null
@@ -0,0 +1,32 @@
+find_package(Pthreads)
+
+if (PTHREADS_FOUND)
+    set(GMOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+    set(GTEST_DIR ${GMOCK_DIR}/gtest)
+    set(GTEST_SOURCES ${GTEST_DIR}/src/gtest-all.cc)
+    set(GMOCK_SOURCES ${GMOCK_DIR}/src/gmock-all.cc)
+
+    set(GTEST_INCLUDE_DIRS ${GTEST_DIR}/include)
+    set(GMOCK_INCLUDE_DIRS ${GMOCK_DIR}/include ${GTEST_INCLUDE_DIRS})
+    if (GMX_USE_GMOCK)
+        set(GMX_USE_GTEST ON)
+        include_directories(${GTEST_INCLUDE_DIRS})
+        include_directories(${GTEST_DIR})
+        include_directories(${GMOCK_INCLUDE_DIRS})
+        include_directories(${GMOCK_DIR})
+        add_library(gmock STATIC ${GMOCK_SOURCES} ${GTEST_SOURCES})
+        set(GMOCK_LIBRARIES gmock ${PTHREADS_LIBRARIES} PARENT_SCOPE)
+    endif (GMX_USE_GMOCK)
+    if (GMX_USE_GTEST)
+        include_directories(${GTEST_INCLUDE_DIRS})
+        include_directories(${GTEST_DIR})
+        add_library(gtest STATIC ${GTEST_SOURCES})
+        set(GTEST_LIBRARIES gtest ${PTHREADS_LIBRARIES} PARENT_SCOPE)
+    endif (GMX_USE_GTEST)
+    set(GMX_USE_GTEST ${GMX_USE_GTEST} PARENT_SCOPE)
+    set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} PARENT_SCOPE)
+    set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIRS} PARENT_SCOPE)
+else (PTHREADS_FOUND)
+    set(GMX_USE_GTEST OFF PARENT_SCOPE)
+    set(GMX_USE_GMOCK OFF PARENT_SCOPE)
+endif (PTHREADS_FOUND)
diff --git a/src/external/gmock-1.6.0/COPYING b/src/external/gmock-1.6.0/COPYING
new file mode 100644 (file)
index 0000000..1941a11
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/external/gmock-1.6.0/README b/src/external/gmock-1.6.0/README
new file mode 100644 (file)
index 0000000..aa3283d
--- /dev/null
@@ -0,0 +1,354 @@
+Google C++ Mocking Framework
+============================
+
+http://code.google.com/p/googlemock/
+
+Overview
+--------
+
+Google's framework for writing and using C++ mock classes on a variety
+of platforms (Linux, Mac OS X, Windows, Windows CE, Symbian, etc).
+Inspired by jMock, EasyMock, and Hamcrest, and designed with C++'s
+specifics in mind, it can help you derive better designs of your
+system and write better tests.
+
+Google Mock:
+
+- provides a declarative syntax for defining mocks,
+- can easily define partial (hybrid) mocks, which are a cross of real
+  and mock objects,
+- handles functions of arbitrary types and overloaded functions,
+- comes with a rich set of matchers for validating function arguments,
+- uses an intuitive syntax for controlling the behavior of a mock,
+- does automatic verification of expectations (no record-and-replay
+  needed),
+- allows arbitrary (partial) ordering constraints on
+  function calls to be expressed,
+- lets a user extend it by defining new matchers and actions.
+- does not use exceptions, and
+- is easy to learn and use.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+Please note that code under scripts/generator/ is from the cppclean
+project (http://code.google.com/p/cppclean/) and under the Apache
+License, which is different from Google Mock's license.
+
+Requirements for End Users
+--------------------------
+
+Google Mock is implemented on top of the Google Test C++ testing
+framework (http://code.google.com/p/googletest/), and includes the
+latter as part of the SVN repositary and distribution package.  You
+must use the bundled version of Google Test when using Google Mock, or
+you may get compiler/linker errors.
+
+You can also easily configure Google Mock to work with another testing
+framework of your choice; although it will still need Google Test as
+an internal dependency.  Please read
+http://code.google.com/p/googlemock/wiki/ForDummies#Using_Google_Mock_with_Any_Testing_Framework
+for how to do it.
+
+Google Mock depends on advanced C++ features and thus requires a more
+modern compiler.  The following are needed to use Google Mock:
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Mock from a source
+package (as described below):
+
+  * GNU-compatible Make or "gmake"
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * C++98-standard-compliant compiler (e.g. GCC 3.4 or newer)
+
+### Windows Requirements ###
+
+  * Microsoft Visual C++ 8.0 SP1 or newer
+
+### Mac OS X Requirements ###
+
+  * Mac OS X 10.4 Tiger or newer
+  * Developer Tools Installed
+
+Requirements for Contributors
+-----------------------------
+
+We welcome patches.  If you plan to contribute a patch, you need to
+build Google Mock and its own tests from an SVN checkout (described
+below), which has further requirements:
+
+  * Automake version 1.9 or newer
+  * Autoconf version 2.59 or newer
+  * Libtool / Libtoolize
+  * Python version 2.3 or newer (for running some of the tests and
+    re-generating certain source files from templates)
+
+Getting the Source
+------------------
+
+There are two primary ways of getting Google Mock's source code: you
+can download a stable source release in your preferred archive format,
+or directly check out the source from our Subversion (SVN) repositary.
+The SVN checkout requires a few extra steps and some extra software
+packages on your system, but lets you track development and make
+patches much more easily, so we highly encourage it.
+
+### Source Package ###
+
+Google Mock is released in versioned source packages which can be
+downloaded from the download page [1].  Several different archive
+formats are provided, but the only difference is the tools needed to
+extract their contents, and the size of the resulting file.  Download
+whichever you are most comfortable with.
+
+  [1] http://code.google.com/p/googlemock/downloads/list
+
+Once downloaded expand the archive using whichever tools you prefer
+for that type.  This will always result in a new directory with the
+name "gmock-X.Y.Z" which contains all of the source code.  Here are
+some examples on Linux:
+
+  tar -xvzf gmock-X.Y.Z.tar.gz
+  tar -xvjf gmock-X.Y.Z.tar.bz2
+  unzip gmock-X.Y.Z.zip
+
+### SVN Checkout ###
+
+To check out the main branch (also known as the "trunk") of Google
+Mock, run the following Subversion command:
+
+  svn checkout http://googlemock.googlecode.com/svn/trunk/ gmock-svn
+
+If you are using a *nix system and plan to use the GNU Autotools build
+system to build Google Mock (described below), you'll need to
+configure it now.  Otherwise you are done with getting the source
+files.
+
+To prepare the Autotools build system, enter the target directory of
+the checkout command you used ('gmock-svn') and proceed with the
+following command:
+
+  autoreconf -fvi
+
+Once you have completed this step, you are ready to build the library.
+Note that you should only need to complete this step once.  The
+subsequent 'make' invocations will automatically re-generate the bits
+of the build system that need to be changed.
+
+If your system uses older versions of the autotools, the above command
+will fail.  You may need to explicitly specify a version to use.  For
+instance, if you have both GNU Automake 1.4 and 1.9 installed and
+'automake' would invoke the 1.4, use instead:
+
+  AUTOMAKE=automake-1.9 ACLOCAL=aclocal-1.9 autoreconf -fvi
+
+Make sure you're using the same version of automake and aclocal.
+
+Setting up the Build
+--------------------
+
+To build Google Mock and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+### Generic Build Instructions ###
+
+This section shows how you can integrate Google Mock into your
+existing build system.
+
+Suppose you put Google Mock in directory ${GMOCK_DIR} and Google Test
+in ${GTEST_DIR} (the latter is ${GMOCK_DIR}/gtest by default).  To
+build Google Mock, create a library build target (or a project as
+called by Visual Studio and Xcode) to compile
+
+  ${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc
+
+with
+
+  ${GTEST_DIR}/include, ${GTEST_DIR}, ${GMOCK_DIR}/include, and ${GMOCK_DIR}
+
+in the header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
+      -I${GMOCK_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
+      -I${GMOCK_DIR} -c ${GMOCK_DIR}/src/gmock-all.cc
+  ar -rv libgmock.a gtest-all.o gmock-all.o
+
+Next, you should compile your test source file with
+${GTEST_DIR}/include and ${GMOCK_DIR}/include in the header search
+path, and link it with gmock and any other necessary libraries:
+
+  g++ -I${GTEST_DIR}/include -I${GMOCK_DIR}/include \
+      path/to/your_test.cc libgmock.a -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Mock on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Mock's own tests.  Instead, it just builds the Google Mock library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+  cd ${GMOCK_DIR}/make
+  make
+  ./gmock_test
+
+If you see errors, try to tweak the contents of make/Makefile to make
+them go away.  There are instructions in make/Makefile on how to do
+it.
+
+### Windows ###
+
+The msvc/2005 directory contains VC++ 2005 projects and the msvc/2010
+directory contains VC++ 2010 projects for building Google Mock and
+selected tests.
+
+Change to the appropriate directory and run "msbuild gmock.sln" to
+build the library and tests (or open the gmock.sln in the MSVC IDE).
+If you want to create your own project to use with Google Mock, you'll
+have to configure it to use the gmock_config propety sheet.  For that:
+
+ * Open the Property Manager window (View | Other Windows | Property Manager)
+ * Right-click on your project and select "Add Existing Property Sheet..."
+ * Navigate to gmock_config.vsprops or gmock_config.props and select it.
+ * In Project Properties | Configuration Properties | General | Additional
+   Include Directories, type <path to Google Mock>/include.
+
+Tweaking Google Mock
+--------------------
+
+Google Mock can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Mock by
+defining control macros on the compiler command line.  Generally,
+these macros are named like GTEST_XYZ and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file ${GTEST_DIR}/include/gtest/internal/gtest-port.h.
+
+### Choosing a TR1 Tuple Library ###
+
+Google Mock uses the C++ Technical Report 1 (TR1) tuple library
+heavily.  Unfortunately TR1 tuple is not yet widely available with all
+compilers.  The good news is that Google Test 1.4.0+ implements a
+subset of TR1 tuple that's enough for Google Mock's need.  Google Mock
+will automatically use that implementation when the compiler doesn't
+provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+and Google Mock use.  However, if your project already uses TR1 tuple,
+you need to tell Google Test and Google Mock to use the same TR1 tuple
+library the rest of your project uses, or the two tuple
+implementations will clash.  To do that, add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test, Google Mock, and
+your tests.  If you want to force Google Test and Google Mock to use
+their own tuple library, just add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you want to use Boost's TR1 tuple library with Google Mock, please
+refer to the Boost website (http://www.boost.org/) for how to obtain
+it and set it up.
+
+### Tweaking Google Test ###
+
+Most of Google Test's control macros apply to Google Mock as well.
+Please see file ${GTEST_DIR}/README for how to tweak them.
+
+Upgrading from an Earlier Version
+---------------------------------
+
+We strive to keep Google Mock releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits.  This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Mock.
+
+### Upgrading from 1.1.0 or Earlier ###
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library.  See the instructions in section "Choosing a TR1 Tuple
+Library".
+
+### Upgrading from 1.4.0 or Earlier ###
+
+On platforms where the pthread library is available, Google Test and
+Google Mock use it in order to be thread-safe.  For this to work, you
+may need to tweak your compiler and/or linker flags.  Please see the
+"Multi-threaded Tests" section in file ${GTEST_DIR}/README for what
+you may need to do.
+
+If you have custom matchers defined using MatcherInterface or
+MakePolymorphicMatcher(), you'll need to update their definitions to
+use the new matcher API [2].  Matchers defined using MATCHER() or
+MATCHER_P*() aren't affected.
+
+  [2] http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers,
+      http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers
+
+Developing Google Mock
+----------------------
+
+This section discusses how to make your own changes to Google Mock.
+
+### Testing Google Mock Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you'll need Autotools.  First, make sure you have followed
+the instructions in section "SVN Checkout" to configure Google Mock.
+Then, create a build output directory and enter it.  Next,
+
+  ${GMOCK_DIR}/configure  # Standard GNU configure script, --help for more info
+
+Once you have successfully configured Google Mock, the build steps are
+standard for GNU-style OSS packages.
+
+  make        # Standard makefile following GNU conventions
+  make check  # Builds and runs all tests - all should pass.
+
+Note that when building your project against Google Mock, you are building
+against Google Test as well.  There is no need to configure Google Test
+separately.
+
+### Regenerating Source Files ###
+
+Some of Google Mock's source files are generated from templates (not
+in the C++ sense) using a script.  A template file is named FOO.pump,
+where FOO is the name of the file it will generate.  For example, the
+file include/gmock/gmock-generated-actions.h.pump is used to generate
+gmock-generated-actions.h in the same directory.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them.  In that case, you should modify the
+corresponding .pump files instead and run the 'pump' script (for Pump
+is Useful for Meta Programming) to regenerate them.  You can find
+pump.py in the ${GTEST_DIR}/scripts/ directory.  Read the Pump manual
+[3] for how to use it.
+
+  [3] http://code.google.com/p/googletest/wiki/PumpManual.
+
+### Contributing a Patch ###
+
+We welcome patches.  Please read the Google Mock developer's guide [4]
+for how you can contribute.  In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+  [4] http://code.google.com/p/googlemock/wiki/DevGuide
+
+Happy testing!
diff --git a/src/external/gmock-1.6.0/README.Gromacs b/src/external/gmock-1.6.0/README.Gromacs
new file mode 100644 (file)
index 0000000..41877e4
--- /dev/null
@@ -0,0 +1,15 @@
+This directory contains source code for Google C++ Testing and Mocking
+Frameworks.
+
+The code has been copied verbatim from the source distribution for GMock 1.6.0
+by copying the following files/directories recursively, excluding *.pump files:
+gmock-1.6.0/COPYING
+gmock-1.6.0/README
+gmock-1.6.0/include/
+gmock-1.6.0/src/
+gmock-1.6.0/gtest/COPYING
+gmock-1.6.0/gtest/include/
+gmock-1.6.0/gtest/src/
+
+The file CMakeLists.txt in this directory is part of the Gromacs build system
+and has been written from scratch.
diff --git a/src/external/gmock-1.6.0/gtest/COPYING b/src/external/gmock-1.6.0/gtest/COPYING
new file mode 100644 (file)
index 0000000..1941a11
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-death-test.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-death-test.h
new file mode 100644 (file)
index 0000000..a27883f
--- /dev/null
@@ -0,0 +1,283 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//         << "Failed to die on request " << i);
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-message.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-message.h
new file mode 100644 (file)
index 0000000..9b7142f
--- /dev/null
@@ -0,0 +1,230 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  // We allocate the stringstream separately because otherwise each use of
+  // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+  // stack frame leading to huge stack frames in some cases; gcc does not reuse
+  // the stack space.
+  Message() : ss_(new ::std::stringstream) {
+    // By default, we want there to be enough precision when printing
+    // a double to a Message.
+    *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+  }
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    ::GTestStreamToHelper(ss_.get(), val);
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+  Message& operator <<(wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as a String.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::String GetString() const {
+    return internal::StringStreamToString(ss_.get());
+  }
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
+    ::GTestStreamToHelper(ss_.get(), value);
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-param-test.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-param-test.h
new file mode 100644 (file)
index 0000000..6407cfd
--- /dev/null
@@ -0,0 +1,1421 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple(bool, bool)> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-printers.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-printers.h
new file mode 100644 (file)
index 0000000..9cbab3f
--- /dev/null
@@ -0,0 +1,796 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan@google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin,
+                                    size_t len,
+                                    ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalPrint(value, os);
+}
+inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
+  if (str == NULL) {
+    *os << "NULL";
+  } else {
+    UniversalPrint(string(str), os);
+  }
+}
+inline void UniversalTersePrint(char* str, ::std::ostream* os) {
+  UniversalTersePrint(static_cast<const char*>(str), os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  UniversalPrinter<T>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    *os << ", ";
+    UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+        ::Print(::std::tr1::get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+        Print(::std::tr1::get<0>(t), os);
+  }
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+      PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrint(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-spi.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-spi.h
new file mode 100644 (file)
index 0000000..b226e55
--- /dev/null
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-test-part.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-test-part.h
new file mode 100644 (file)
index 0000000..8aeea14
--- /dev/null
@@ -0,0 +1,176 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const { return file_name_.c_str(); }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static internal::String ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // NULL if the source file is unknown.
+  internal::String file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  internal::String summary_;  // The test failure summary.
+  internal::String message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest-typed-test.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest-typed-test.h
new file mode 100644 (file)
index 0000000..fe1e83b
--- /dev/null
@@ -0,0 +1,259 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest.h
new file mode 100644 (file)
index 0000000..cd01c7b
--- /dev/null
@@ -0,0 +1,2155 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared in gtest-internal.h but defined here, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  explicit AssertionResult(bool success) : success_(success) {}
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl@google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+
+  GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { ... }
+//     virtual void TearDown() { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test.  Only the last value for a given
+  // key is remembered.
+  // These are public static so they can be called from utility functions
+  // that are not members of the test fixture.
+  // The arguments are const char* instead strings, as Google Test is used
+  // on platforms where string doesn't compile.
+  //
+  // Note that a driving consideration for these RecordProperty methods
+  // was to produce xml output suited to the Greenspan charting utility,
+  // which at present will only chart values that fit in a 32-bit int. It
+  // is the user's responsibility to restrict their values to 32-bit ints
+  // if they intend them to be used with Greenspan.
+  static void RecordProperty(const char* key, const char* value);
+  static void RecordProperty(const char* key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  // Uses a GTestFlagSaver to save and restore all Google Test flags.
+  const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+  // Often a user mis-spells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if a user declares void Setup() in his test
+  //   fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if a user calls it from his test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const char* a_key, const char* a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const char* new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  internal::String key_;
+  // The value supplied by the user.
+  internal::String value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.
+  void RecordProperty(const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if this test should run, that is if the test is not disabled
+  // (or it is disabled but the also_run_disabled_tests flag has been specified)
+  // and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name, const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const char* test_case_name, const char* name,
+           const char* a_type_param,
+           const char* a_value_param,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  internal::String name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const;
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const;
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry();
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const internal::String& message,
+                         const internal::String& os_stack_trace);
+
+  // Adds a TestProperty to the current TestResult object. If the result already
+  // contains a property with the same key, the value will be updated.
+  void RecordPropertyForCurrentTest(const char* key, const char* value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const internal::String& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace();
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char*, and print it as a C string when it is compared against an
+// std::string object, for example.
+//
+// The default implementation ignores the type of the other operand.
+// Some specialized versions are used to handle formatting wide or
+// narrow C strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+String FormatForComparisonFailureMessage(const T1& value,
+                                         const T2& /* other_operand */) {
+  // C++Builder compiles this incorrectly if the namespace isn't explicitly
+  // given.
+  return ::testing::PrintToString(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4389)  // Temporarily disables warning on
+                               // signed/unsigned mismatch.
+#endif
+
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)          // Restores the warning state.
+#endif
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, < );
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, > );
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char*        const file;
+    int                const line;
+    String             const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const { return *parameter_; }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+//
+// Examples:
+//
+//   EXPECT_TRUE(server.StatusIsOK());
+//   ASSERT_FALSE(server.HasPendingRequest(port))
+//       << "There are still pending requests " << "on port " << port;
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C String Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+// Use this macro in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+
+#define RUN_ALL_TESTS()\
+  (::testing::UnitTest::GetInstance()->Run())
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest_pred_impl.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest_pred_impl.h
new file mode 100644 (file)
index 0000000..3805f85
--- /dev/null
@@ -0,0 +1,358 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/gtest_prod.h b/src/external/gmock-1.6.0/gtest/include/gtest/gtest_prod.h
new file mode 100644 (file)
index 0000000..da80ddc
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-death-test-internal.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644 (file)
index 0000000..1d9f83b
--- /dev/null
@@ -0,0 +1,308 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const String& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static String last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const String& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  String file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  String file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-filepath.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-filepath.h
new file mode 100644 (file)
index 0000000..b36b3cf
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const char* pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  explicit FilePath(const String& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  String ToString() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is NULL or "".
+  bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  String pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-internal.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-internal.h
new file mode 100644 (file)
index 0000000..7aa1197
--- /dev/null
@@ -0,0 +1,1226 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#include <ctype.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+// Google Test defines the testing::Message class to allow construction of
+// test messages via the << operator.  The idea is that anything
+// streamable to std::ostream can be streamed to a testing::Message.
+// This allows a user to use his own types in Google Test assertions by
+// overloading the << operator.
+//
+// util/gtl/stl_logging-inl.h overloads << for STL containers.  These
+// overloads cannot be defined in the std namespace, as that will be
+// undefined behavior.  Therefore, they are defined in the global
+// namespace instead.
+//
+// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+// overloads are visible in either the std namespace or the global
+// namespace, but not other namespaces, including the testing
+// namespace which Google Test's Message class is in.
+//
+// To allow STL containers (and other types that has a << operator
+// defined in the global namespace) to be used in Google Test assertions,
+// testing::Message must access the custom << operator from the global
+// namespace.  Hence this helper function.
+//
+// Note: Jeffrey Yasskin suggested an alternative fix by "using
+// ::operator<<;" in the definition of Message's operator<<.  That fix
+// doesn't require a helper function, but unfortunately doesn't
+// compile with MSVC.
+template <typename T>
+inline void GTestStreamToHelper(std::ostream* os, const T& val) {
+  *os << val;
+}
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ String AppendUserMessage(const String& gtest_msg,
+                                    const Message& user_msg);
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference.  If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error.  Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
+#else
+# define GTEST_CREF_WORKAROUND_
+#endif
+
+// When this operand is a const char* or char*, if the other operand
+// is a ::std::string or ::string, we print this operand as a C string
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
+
+// This internal macro is used to avoid duplicated code.
+#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
+inline String FormatForComparisonFailureMessage(\
+    operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}\
+inline String FormatForComparisonFailureMessage(\
+    const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}
+
+GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
+#if GTEST_HAS_STD_WSTRING
+GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_STRING
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#undef GTEST_FORMAT_IMPL_
+
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object.  In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType)                       \
+  template <typename T>                                             \
+  String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+                                           const T&) { \
+    return PrintToString(static_cast<const void*>(p));              \
+  }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const String& expected_value,
+                                     const String& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ String GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not  a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    defined_test_names_.insert(test_name);
+    return true;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  bool registered_;
+  ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline String GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? String(str) : String(str, comma - str);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names, int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
+                       case_name, index).c_str(),
+        GetPrefixUntilComma(test_names).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/, int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names) {
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
+                                                  int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static From MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4244)  // Temporarily disables warning 4244.
+
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop)           // Restores the warning state.
+#elif defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif  // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array.
+  NativeArray(const Element* array, size_t count, RelationToSource relation) {
+    Init(array, count, relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    static_cast<void>(StaticAssertTypeEqHelper<Element,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t a_size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[a_size];
+      CopyArray(array, a_size, copy);
+      array_ = copy;
+    }
+    size_ = a_size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-linked_ptr.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644 (file)
index 0000000..57147b4
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  // L < g_linked_ptr_mutex
+  void join(linked_ptr_internal const* ptr) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) p = p->next_;
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  // L < g_linked_ptr_mutex
+  bool depart() {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) p = p->next_;
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util-generated.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644 (file)
index 0000000..2582675
--- /dev/null
@@ -0,0 +1,4822 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_,
+        v23_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_,
+        v35_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_,
+        v47_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_, v50_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9, T10> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9, T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-param-util.h
new file mode 100644 (file)
index 0000000..0ef9718
--- /dev/null
@@ -0,0 +1,619 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = value_ + step_;
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = i + step)
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+  explicit ParameterizedTestCaseInfo(const char* name)
+      : test_case_name_(name) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               const char* /* file */,
+                               int /* line */) {
+    instantiations_.push_back(::std::make_pair(instantiation_name, func));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->first;
+        ParamGenerator<ParamType> generator((*gen_it->second)());
+
+        Message test_case_name_stream;
+        if ( !instantiation_name.empty() )
+          test_case_name_stream << instantiation_name << "/";
+        test_case_name_stream << test_info->test_case_base_name;
+
+        int i = 0;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+          test_name_stream << test_info->test_base_name << "/" << i;
+          MakeAndRegisterTestInfo(
+              test_case_name_stream.GetString().c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Keeps pairs of <Instantiation name, Sequence generator creation function>
+  // received from INSTANTIATE_TEST_CASE_P macros.
+  typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+      InstantiationContainer;
+
+  const string test_case_name_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      const char* file,
+      int line) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name,  file, line);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-port.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-port.h
new file mode 100644 (file)
index 0000000..157b47f
--- /dev/null
@@ -0,0 +1,1775 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior.  If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                  - synchronization primitives.
+//   GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+//                         synchronization primitives have real implementations
+//                         and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_FLAG()       - references a flag.
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetArgvs()         - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif  // ANDROID
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#endif  // __CYGWIN__
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl@google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+#  include <strings.h>  // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+// The user didn't tell us not to do it, so we assume it's OK.
+# define GTEST_HAS_TR1_TUPLE 1
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, GCC 4.0.0+ and MSVC
+// 2010 are the only mainstream compilers that come with a TR1 tuple
+// implementation.  NVIDIA's CUDA NVCC compiler pretends to be GCC by
+// defining __GNUC__ and friends, but cannot compile GCC's tuple
+// implementation.  MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
+// Feature Pack download, which we cannot assume the user has.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
+    || _MSC_VER >= 1600
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+#  include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  define GTEST_HAS_CLONE 1
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector>  // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+class String;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                         content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(bool(expr))> \
+      msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of a string, as Google Test may be used
+  // where string is not available.  We also do not use Google Test's own
+  // String type here, in order to simplify dependencies between the
+  // files.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ String GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ String GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+extern ::std::vector<String> g_argvs;
+
+// GTEST_HAS_DEATH_TEST implies we have ::std::string.
+const ::std::vector<String>& GetArgvs();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds.  This function is only for
+// testing Google Test's own constructs.  Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {}
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() { notified_ = true; }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    while(!notified_) {
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  volatile bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void (*UserThreadFunc)(T);
+
+  ThreadWithParam(
+      UserThreadFunc func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  const UserThreadFunc func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the end
+//                            // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes.  Do not use MutexBase directly.  Instead, write
+// the following to define a static mutex:
+//
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // We don't protect writing to owner_ here, as it's the caller's
+    // responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    owner_ = 0;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(owner_ == pthread_self())
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  pthread_t owner_;  // The thread holding the mutex; 0 means no one holds it.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    owner_ = 0;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms.  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits.  Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies.  It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : key_(CreateKey()),
+                  default_() {}
+  explicit ThreadLocal(const T& value) : key_(CreateKey()),
+                                         default_(value) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = new ValueHolder(default_);
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  const T default_;  // The default value for each thread.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else  // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif  // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // We are on Windows CE, which has no environment variables.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-string.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-string.h
new file mode 100644 (file)
index 0000000..dc3a07b
--- /dev/null
@@ -0,0 +1,350 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include "gtest/internal/gtest-port.h"
+
+#include <string>
+
+namespace testing {
+namespace internal {
+
+// String - a UTF-8 string class.
+//
+// For historic reasons, we don't use std::string.
+//
+// TODO(wan@google.com): replace this class with std::string or
+// implement it in terms of the latter.
+//
+// Note that String can represent both NULL and the empty string,
+// while std::string cannot represent NULL.
+//
+// NULL and the empty string are considered different.  NULL is less
+// than anything (including the empty string) except itself.
+//
+// This class only provides minimum functionality necessary for
+// implementing Google Test.  We do not intend to implement a full-fledged
+// string class here.
+//
+// Since the purpose of this class is to provide a substitute for
+// std::string on platforms where it cannot be used, we define a copy
+// constructor and assignment operators such that we don't need
+// conditional compilation in a lot of places.
+//
+// In order to make the representation efficient, the d'tor of String
+// is not virtual.  Therefore DO NOT INHERIT FROM String.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Returns the input enclosed in double quotes if it's not NULL;
+  // otherwise returns "(null)".  For example, "\"Hello\"" is returned
+  // for input "Hello".
+  //
+  // This is useful for printing a C string in the syntax of a literal.
+  //
+  // Known issue: escape sequences are not handled yet.
+  static String ShowCStringQuoted(const char* c_str);
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static String ShowWideCString(const wchar_t* wide_c_str);
+
+  // Similar to ShowWideCString(), except that this function encloses
+  // the converted string in double quotes.
+  static String ShowWideCStringQuoted(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Formats a list of arguments to a String, using the same format
+  // spec string as for printf.
+  //
+  // We do not use the StringPrintf class as it is not universally
+  // available.
+  //
+  // The result is limited to 4096 characters (including the tailing
+  // 0).  If 4096 characters are not enough to format the input,
+  // "<buffer exceeded>" is returned.
+  static String Format(const char* format, ...);
+
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  String() : c_str_(NULL), length_(0) {}
+
+  // Constructs a String by cloning a 0-terminated C string.
+  String(const char* a_c_str) {  // NOLINT
+    if (a_c_str == NULL) {
+      c_str_ = NULL;
+      length_ = 0;
+    } else {
+      ConstructNonNull(a_c_str, strlen(a_c_str));
+    }
+  }
+
+  // Constructs a String by copying a given number of chars from a
+  // buffer.  E.g. String("hello", 3) creates the string "hel",
+  // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
+  // and String(NULL, 1) results in access violation.
+  String(const char* buffer, size_t a_length) {
+    ConstructNonNull(buffer, a_length);
+  }
+
+  // The copy c'tor creates a new copy of the string.  The two
+  // String objects do not share content.
+  String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
+
+  // D'tor.  String is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~String() { delete[] c_str_; }
+
+  // Allows a String to be implicitly converted to an ::std::string or
+  // ::string, and vice versa.  Converting a String containing a NULL
+  // pointer to ::std::string or ::string is undefined behavior.
+  // Converting a ::std::string or ::string containing an embedded NUL
+  // character to a String will result in the prefix up to the first
+  // NUL character.
+  String(const ::std::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::std::string() const { return ::std::string(c_str(), length()); }
+
+#if GTEST_HAS_GLOBAL_STRING
+  String(const ::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::string() const { return ::string(c_str(), length()); }
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  // Returns true iff this is an empty string (i.e. "").
+  bool empty() const { return (c_str() != NULL) && (length() == 0); }
+
+  // Compares this with another String.
+  // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+  // if this is greater than rhs.
+  int Compare(const String& rhs) const;
+
+  // Returns true iff this String equals the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
+
+  // Returns true iff this String is less than the given String.  A
+  // NULL string is considered less than "".
+  bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
+
+  // Returns true iff this String doesn't equal the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
+
+  // Returns true iff this String ends with the given suffix.  *Any*
+  // String is considered to end with a NULL or empty suffix.
+  bool EndsWith(const char* suffix) const;
+
+  // Returns true iff this String ends with the given suffix, not considering
+  // case. Any String is considered to end with a NULL or empty suffix.
+  bool EndsWithCaseInsensitive(const char* suffix) const;
+
+  // Returns the length of the encapsulated string, or 0 if the
+  // string is NULL.
+  size_t length() const { return length_; }
+
+  // Gets the 0-terminated C string this String object represents.
+  // The String object still owns the string.  Therefore the caller
+  // should NOT delete the return value.
+  const char* c_str() const { return c_str_; }
+
+  // Assigns a C string to this object.  Self-assignment works.
+  const String& operator=(const char* a_c_str) {
+    return *this = String(a_c_str);
+  }
+
+  // Assigns a String object to this object.  Self-assignment works.
+  const String& operator=(const String& rhs) {
+    if (this != &rhs) {
+      delete[] c_str_;
+      if (rhs.c_str() == NULL) {
+        c_str_ = NULL;
+        length_ = 0;
+      } else {
+        ConstructNonNull(rhs.c_str(), rhs.length());
+      }
+    }
+
+    return *this;
+  }
+
+ private:
+  // Constructs a non-NULL String from the given content.  This
+  // function can only be called when c_str_ has not been allocated.
+  // ConstructNonNull(NULL, 0) results in an empty string ("").
+  // ConstructNonNull(NULL, non_zero) is undefined behavior.
+  void ConstructNonNull(const char* buffer, size_t a_length) {
+    char* const str = new char[a_length + 1];
+    memcpy(str, buffer, a_length);
+    str[a_length] = '\0';
+    c_str_ = str;
+    length_ = a_length;
+  }
+
+  const char* c_str_;
+  size_t length_;
+};  // class String
+
+// Streams a String to an ostream.  Each '\0' character in the String
+// is replaced with "\\0".
+inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
+  if (str.c_str() == NULL) {
+    os << "(null)";
+  } else {
+    const char* const c_str = str.c_str();
+    for (size_t i = 0; i != str.length(); i++) {
+      if (c_str[i] == '\0') {
+        os << "\\0";
+      } else {
+        os << c_str[i];
+      }
+    }
+  }
+  return os;
+}
+
+// Gets the content of the stringstream's buffer as a String.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-tuple.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-tuple.h
new file mode 100644 (file)
index 0000000..d1af50e
--- /dev/null
@@ -0,0 +1,968 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T)>::value,
+      tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-type-util.h b/src/external/gmock-1.6.0/gtest/include/gtest/internal/gtest-type-util.h
new file mode 100644 (file)
index 0000000..b7b01b0
--- /dev/null
@@ -0,0 +1,3330 @@
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# ifdef __GLIBCXX__
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // __GLIBCXX__
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+String GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if defined(__GLIBCXX__) || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   ifdef __GLIBCXX__
+  using abi::__cxa_demangle;
+#   endif // __GLIBCXX__
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const String name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // __GLIBCXX__ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList { typedef Types1<T> type; };
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-all.cc b/src/external/gmock-1.6.0/gtest/src/gtest-all.cc
new file mode 100644 (file)
index 0000000..0a9cee5
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-death-test.cc b/src/external/gmock-1.6.0/gtest/src/gtest-death-test.cc
new file mode 100644 (file)
index 0000000..8b2e413
--- /dev/null
@@ -0,0 +1,1234 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "colons.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static String ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static String DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const String& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s != -1", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+String GetLastErrnoDescription() {
+    return String(errno == 0 ? "" : posix::StrError(errno));
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const String& message) {
+  last_death_test_message_ = message;
+}
+
+String DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const String error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const String filter_flag = String::Format("--%s%s=%s.%s",
+                                            GTEST_FLAG_PREFIX_, kFilterFlag,
+                                            info->test_case_name(),
+                                            info->name());
+  const String internal_flag = String::Format(
+    "--%s%s=%s|%d|%d|%u|%Iu|%Iu",
+      GTEST_FLAG_PREFIX_,
+      kInternalRunDeathTestFlag,
+      file_, line_,
+      death_test_index,
+      static_cast<unsigned int>(::GetCurrentProcessId()),
+      // size_t has the same with as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      reinterpret_cast<size_t>(write_handle),
+      reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  String command_line = String::Format("%s %s \"%s\"",
+                                       ::GetCommandLineA(),
+                                       filter_flag.c_str(),
+                                       internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
+                                  original_dir,
+                                  GetLastErrnoDescription().c_str()));
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
+                                args->argv[0],
+                                original_dir,
+                                GetLastErrnoDescription().c_str()));
+  return EXIT_FAILURE;
+}
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
+bool StackLowerThanAddress(const void* ptr) {
+  int dummy;
+  return &dummy < ptr;
+}
+
+bool StackGrowsDown() {
+  int dummy;
+  return StackLowerThanAddress(&dummy);
+}
+
+// A threadsafe implementation of fork(2) for threadsafe-style death tests
+// that uses clone(2).  It dies with an error message if anything goes
+// wrong.
+static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+    void* const stack_top =
+        static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#  else
+  const bool use_fork = true;
+#  endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const String filter_flag =
+      String::Format("--%s%s=%s.%s",
+                     GTEST_FLAG_PREFIX_, kFilterFlag,
+                     info->test_case_name(), info->name());
+  const String internal_flag =
+      String::Format("--%s%s=%s|%d|%d|%d",
+                     GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
+                     file_, line_, death_test_index, pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvs());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(String::Format(
+          "Death test count (%d) somehow exceeded expected maximum (%d)",
+          death_test_index, flag->index()));
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(String::Format(
+        "Unknown death test style \"%s\" encountered",
+        GTEST_FLAG(death_test_style).c_str()));
+    return false;
+  }
+
+  return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+                        ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort(String::Format("Unable to open parent process %u",
+                                  parent_process_id));
+  }
+
+  // TODO(vladl@google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the pipe handle %Iu from the parent process %u",
+        write_handle_as_size_t, parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the event handle %Iu from the parent process %u",
+        event_handle_as_size_t, parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort(String::Format(
+        "Unable to convert pipe handle %Iu to a file descriptor",
+        write_handle_as_size_t));
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-filepath.cc b/src/external/gmock-1.6.0/gtest/src/gtest-filepath.cc
new file mode 100644 (file)
index 0000000..91b2571
--- /dev/null
@@ -0,0 +1,380 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  String dot_extension(String::Format(".%s", extension));
+  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
+    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(String(last_sep + 1)) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  String dir;
+  if (last_sep) {
+    dir = String(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  String file;
+  if (number == 0) {
+    file = String::Format("%s.%s", base_name.c_str(), extension);
+  } else {
+    file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
+                                 relative_path.c_str()));
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan@google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-internal-inl.h b/src/external/gmock-1.6.0/gtest/src/gtest-internal-inl.h
new file mode 100644 (file)
index 0000000..65a2101
--- /dev/null
@@ -0,0 +1,1038 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h"  // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  String color_;
+  String death_test_style_;
+  bool death_test_use_fork_;
+  String filter_;
+  String internal_run_death_test_;
+  bool list_tests_;
+  String output_;
+  bool print_time_;
+  bool pretty_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  String stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const char* key)
+      : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return String(test_property.key()).Compare(key_) == 0;
+  }
+
+ private:
+  String key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static String GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static String GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const String &test_case_name,
+                                const String &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const String& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as a String.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual String CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() : caller_frame_(NULL) {}
+  virtual String CurrentStackTrace(int max_depth, int skip_count);
+  virtual void UponLeavingGTest();
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  Mutex mutex_;  // protects all internal state
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to CurrentStackTrace() from within the user code.
+  void* caller_frame_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  String message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as a String.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  String CurrentOsStackTraceExceptTop(int skip_count);
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ String GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+  AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+  explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+  ~AutoHandle() { Reset(); }
+
+  HANDLE Get() const { return handle_; }
+  void Reset() { Reset(INVALID_HANDLE_VALUE); }
+  void Reset(HANDLE handle) {
+    if (handle != handle_) {
+      if (handle_ != INVALID_HANDLE_VALUE)
+        ::CloseHandle(handle_);
+      handle_ = handle;
+    }
+  }
+
+ private:
+  HANDLE handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif  // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl@google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const TestProperty& property) {
+    test_result->RecordProperty(property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-port.cc b/src/external/gmock-1.6.0/gtest/src/gtest-port.cc
new file mode 100644 (file)
index 0000000..b860d48
--- /dev/null
@@ -0,0 +1,746 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+String FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan@google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0) {
+    return String::Format("%s:", file_name).c_str();
+  }
+#ifdef _MSC_VER
+  return String::Format("%s(%d):", file_name, line).c_str();
+#else
+  return String::Format("%s:%d:", file_name, line).c_str();
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0)
+    return file_name;
+  else
+    return String::Format("%s:%d", file_name, line).c_str();
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif  // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the
+    // current directory, so we create the temporary file in the /tmp
+    // directory instead.
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  String GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const String content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  // Reads the entire content of a file as a String.
+  static String ReadEntireFile(FILE* file);
+
+  // Returns the size (in bytes) of a file.
+  static size_t GetFileSize(FILE* file);
+
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+String CapturedStream::ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const String content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+String GetCapturedStream(CapturedStream** captured_stream) {
+  const String content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
+
+// Stops capturing stderr and returns the captured string.
+String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<String> g_argvs;
+
+// Returns the command line as a vector of strings.
+const ::std::vector<String>& GetArgvs() { return g_argvs; }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static String FlagToEnvVar(const char* flag) {
+  const String full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-printers.cc b/src/external/gmock-1.6.0/gtest/src/gtest-printers.cc
new file mode 100644 (file)
index 0000000..ed63c7b
--- /dev/null
@@ -0,0 +1,356 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+#if GTEST_OS_WINDOWS_MOBILE  // Windows CE does not define _snprintf_s.
+# define snprintf _snprintf
+#elif _MSC_VER >= 1400  // VC 8.0 and later deprecate snprintf and _snprintf.
+# define snprintf _snprintf_s
+#elif _MSC_VER
+# define snprintf _snprintf
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
+  return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << String::Format("%d", c).c_str();
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << String::Format(", 0x%X",
+                          static_cast<UnsignedChar>(c)).c_str();
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.
+// The array starts at *begin, the length is len, it may include '\0' characters
+// and may not be null-terminated.
+static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
+  *os << "\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const char cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" \"";
+    }
+    is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  PrintCharsAsStringTo(begin, len, os);
+}
+
+// Prints the given array of wide characters to the ostream.
+// The array starts at *begin, the length is len, it may include L'\0'
+// characters and may not be null-terminated.
+static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
+                                     ostream* os) {
+  *os << "L\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const wchar_t cur = begin[index];
+    if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" L\"";
+    }
+    is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintWideCharsAsStringTo(s, wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-test-part.cc b/src/external/gmock-1.6.0/gtest/src/gtest-test-part.cc
new file mode 100644 (file)
index 0000000..5ddc67c
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+internal::String TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? internal::String(message) :
+      internal::String(message, stack_trace - message);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest-typed-test.cc b/src/external/gmock-1.6.0/gtest/src/gtest-typed-test.cc
new file mode 100644 (file)
index 0000000..a5cc88f
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+  registered_ = true;
+
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
+  Message errors;
+  ::std::set<String> tests;
+  for (const char* names = registered_tests; names != NULL;
+       names = SkipComma(names)) {
+    const String name = GetPrefixUntilComma(names);
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (DefinedTestIter it = defined_test_names_.begin();
+         it != defined_test_names_.end();
+         ++it) {
+      if (name == *it) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (DefinedTestIter it = defined_test_names_.begin();
+       it != defined_test_names_.end();
+       ++it) {
+    if (tests.count(*it) == 0) {
+      errors << "You forgot to list test " << *it << ".\n";
+    }
+  }
+
+  const String& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest.cc b/src/external/gmock-1.6.0/gtest/src/gtest.cc
new file mode 100644 (file)
index 0000000..904d9d7
--- /dev/null
@@ -0,0 +1,4898 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to xterm, xterm-color, xterm-256color, linux or cygwin.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", kUniversalFilter),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test.  g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called.  We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+String g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(g_executable_path));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+String UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      String(gtest_output_flag) :
+      String(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+String UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return String(internal::FilePath::ConcatPaths(
+               internal::FilePath(
+                   UnitTest::GetInstance()->original_working_dir()),
+               internal::FilePath(kDefaultOutputFile)).ToString() );
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan@google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.ToString();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.ToString();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// TODO(keithray): move String function implementations to gtest-string.cc.
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
+                                        const String &test_name) {
+  const String& full_name = String::Format("%s.%s",
+                                           test_case_name.c_str(),
+                                           test_name.c_str());
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  String positive;
+  String negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = String("");
+  } else {
+    positive = String(p, dash - p);  // Everything up to the dash
+    negative = String(dash+1);       // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const String expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  (void)skip_count;
+  return String("");
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton@google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+# ifdef _MSC_VER
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton@google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4996)  // Temporarily disables warning 4996.
+  _ftime64(&now);
+#  pragma warning(pop)           // Restores the warning state.
+# else
+
+  _ftime64(&now);
+
+# endif  // _MSC_VER
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String
+
+// Returns the input enclosed in double quotes if it's not NULL;
+// otherwise returns "(null)".  For example, "\"Hello\"" is returned
+// for input "Hello".
+//
+// This is useful for printing a C string in the syntax of a literal.
+//
+// Known issue: escape sequences are not handled yet.
+String String::ShowCStringQuoted(const char* c_str) {
+  return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
+}
+
+// Copies at most length characters from str into a newly-allocated
+// piece of memory of size length+1.  The memory is allocated with new[].
+// A terminating null byte is written to the memory, and a pointer to it
+// is returned.  If str is NULL, NULL is returned.
+static char* CloneString(const char* str, size_t length) {
+  if (str == NULL) {
+    return NULL;
+  } else {
+    char* const clone = new char[length + 1];
+    posix::StrNCpy(clone, str, length);
+    clone[length] = '\0';
+    return clone;
+  }
+}
+
+// Clones a 0-terminated C string, allocating memory using new.  The
+// caller is responsible for deleting[] the return value.  Returns the
+// cloned string, or NULL if the input is NULL.
+const char * String::CloneCString(const char* c_str) {
+  return (c_str == NULL) ?
+                    NULL : CloneString(c_str, strlen(c_str));
+}
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  // TODO(wan): consider allowing a testing::String object to
+  // contain '\0'.  This will make it behave more like std::string,
+  // and will allow ToUtf8String() to return the correct encoding
+  // for '\0' s.t. we can get rid of the conditional here (and in
+  // several other places).
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+}  // namespace internal
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const String& expected_value,
+                          const String& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
+                                      const char* expression_text,
+                                      const char* actual_predicate_value,
+                                      const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;  // String::Format can't exceed this length.
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing cr-lf)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const String error_hex(String::Format("0x%08X ", hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+char* CodePointToUtf8(UInt32 code_point, char* str) {
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else if (code_point <= kMaxCodePoint4) {
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  } else {
+    // The longest string String::Format can produce when invoked
+    // with these parameters is 28 character long (not including
+    // the terminating nul character). We are asking for 32 character
+    // buffer just in case. This is also enough for strncpy to
+    // null-terminate the destination string.
+    posix::StrNCpy(
+        str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32);
+    str[31] = '\0';  // Makes sure no change in the format to strncpy leaves
+                     // the result unterminated.
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+String WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    char buffer[32];  // CodePointToUtf8 requires a buffer this big.
+    stream << CodePointToUtf8(unicode_code_point, buffer);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to a String using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+String String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
+}
+
+// Similar to ShowWideCString(), except that this function encloses
+// the converted string in double quotes.
+String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String::Format("L\"%s\"",
+                        String::ShowWideCString(wide_c_str).c_str());
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowWideCStringQuoted(expected),
+                   String::ShowWideCStringQuoted(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << String::ShowWideCStringQuoted(s1)
+                            << " vs " << String::ShowWideCStringQuoted(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Compares this with another String.
+// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+// if this is greater than rhs.
+int String::Compare(const String & rhs) const {
+  const char* const lhs_c_str = c_str();
+  const char* const rhs_c_str = rhs.c_str();
+
+  if (lhs_c_str == NULL) {
+    return rhs_c_str == NULL ? 0 : -1;  // NULL < anything except NULL
+  } else if (rhs_c_str == NULL) {
+    return 1;
+  }
+
+  const size_t shorter_str_len =
+      length() <= rhs.length() ? length() : rhs.length();
+  for (size_t i = 0; i != shorter_str_len; i++) {
+    if (lhs_c_str[i] < rhs_c_str[i]) {
+      return -1;
+    } else if (lhs_c_str[i] > rhs_c_str[i]) {
+      return 1;
+    }
+  }
+  return (length() < rhs.length()) ? -1 :
+      (length() > rhs.length()) ? 1 : 0;
+}
+
+// Returns true iff this String ends with the given suffix.  *Any*
+// String is considered to end with a NULL or empty suffix.
+bool String::EndsWith(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Returns true iff this String ends with the given suffix, ignoring case.
+// Any String is considered to end with a NULL or empty suffix.
+bool String::EndsWithCaseInsensitive(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Formats a list of arguments to a String, using the same format
+// spec string as for printf.
+//
+// We do not use the StringPrintf class as it is not universally
+// available.
+//
+// The result is limited to 4096 characters (including the tailing 0).
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
+String String::Format(const char * format, ...) {
+  va_list args;
+  va_start(args, format);
+
+  char buffer[4096];
+  const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
+  // MSVC 8 deprecates vsnprintf(), so we want to suppress warning
+  // 4996 (deprecated function) there.
+#ifdef _MSC_VER  // We are using MSVC.
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996.
+
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+
+# pragma warning(pop)           // Restores the warning state.
+#else  // We are not using MSVC.
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+#endif  // _MSC_VER
+  va_end(args);
+
+  // vsnprintf()'s behavior is not portable.  When the buffer is not
+  // big enough, it returns a negative value in MSVC, and returns the
+  // needed buffer size on Linux.  When there is an output error, it
+  // always returns a negative value.  For simplicity, we lump the two
+  // error cases together.
+  if (size < 0 || size >= kBufferSize) {
+    return String("<formatting error or buffer exceeded>");
+  } else {
+    return String(buffer, size);
+  }
+}
+
+// Converts the buffer in a stringstream to a String, converting NUL
+// bytes to "\\0" along the way.
+String StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  // We need to use a helper stringstream to do this transformation
+  // because String doesn't support push_back().
+  ::std::stringstream helper;
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      helper << "\\0";  // Replaces NUL with "\\0";
+    } else {
+      helper.put(*ch);
+    }
+  }
+
+  return String(helper.str().c_str());
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+String AppendUserMessage(const String& gtest_msg,
+                         const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const String user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  Message msg;
+  msg << gtest_msg << "\n" << user_msg_string;
+
+  return msg.GetString();
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const TestProperty& test_property) {
+  if (!ValidateTestProperty(test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// Adds a failure if the key is a reserved attribute of Google Test
+// testcase tags.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
+  internal::String key(test_property.key());
+  if (key == "name" || key == "status" || key == "time" || key == "classname") {
+    ADD_FAILURE()
+        << "Reserved key used in RecordProperty(): "
+        << key
+        << " ('name', 'status', 'time', and 'classname' are reserved by "
+        << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+    : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+  delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, const char* value) {
+  UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      String());  // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // The user mixed TEST and TEST_F in this test case - we'll tell
+      // him/her how to fix it.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // The user defined two fixture classes with the same name in
+      // two namespaces - we'll tell him/her how to fix it.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+                                                   const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new internal::String(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+                                                  const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled).  We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time.  Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure)
+      : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    internal::String* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const GoogleTestFailureException&) {  // NOLINT
+      // This exception doesn't originate in code under test. It makes no
+      // sense to report it as a test failure.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
+TestInfo::TestInfo(const char* a_test_case_name,
+                   const char* a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               const char* file, int line) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true iff the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && internal::String(test_info->name()).Compare(name_) == 0;
+  }
+
+ private:
+  internal::String name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static internal::String FormatCountableNoun(int count,
+                                            const char * singular_form,
+                                            const char * plural_form) {
+  return internal::String::Format("%d %s", count,
+                                  count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static internal::String FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static internal::String FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+// Prints a TestPartResult to a String.
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const internal::String& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+namespace internal {
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  const bool use_color = false;
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("TypeParam = %s", type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("GetParam() = %s", value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+
+  internal::String test_case_name_;
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!internal::String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case_name_.c_str());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where TypeParam = %s\n", test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case_name_.c_str(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static String EscapeXml(const char* str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static string RemoveInvalidXmlCharacters(const string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static String EscapeXmlAttribute(const char* str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(FILE* out, const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the String is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static String TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const String output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  PrintXmlUnitTest(xmlout, unit_test);
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
+  Message m;
+
+  if (str != NULL) {
+    for (const char* src = str; *src; ++src) {
+      switch (*src) {
+        case '<':
+          m << "&lt;";
+          break;
+        case '>':
+          m << "&gt;";
+          break;
+        case '&':
+          m << "&amp;";
+          break;
+        case '\'':
+          if (is_attribute)
+            m << "&apos;";
+          else
+            m << '\'';
+          break;
+        case '"':
+          if (is_attribute)
+            m << "&quot;";
+          else
+            m << '"';
+          break;
+        default:
+          if (IsValidXmlCharacter(*src)) {
+            if (is_attribute && IsNormalizableWhitespace(*src))
+              m << String::Format("&#x%02X;", unsigned(*src));
+            else
+              m << *src;
+          }
+          break;
+      }
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+  string output;
+  output.reserve(str.size());
+  for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << ms/1000.0;
+  return ss.str();
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  *stream << "    <testcase name=\""
+          << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+  if (test_info.value_param() != NULL) {
+    *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+            << "\"";
+  }
+  if (test_info.type_param() != NULL) {
+    *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+            << "\"";
+  }
+
+  *stream << " status=\""
+          << (test_info.should_run() ? "run" : "notrun")
+          << "\" time=\""
+          << FormatTimeInMillisAsSeconds(result.elapsed_time())
+          << "\" classname=\"" << EscapeXmlAttribute(test_case_name).c_str()
+          << "\"" << TestPropertiesAsXmlAttributes(result).c_str();
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1)
+        *stream << ">\n";
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(part.summary()).c_str()
+              << "\" type=\"\">";
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string message = location + "\n" + part.message();
+      OutputXmlCDataSection(stream,
+                            RemoveInvalidXmlCharacters(message).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
+                                                const TestCase& test_case) {
+  fprintf(out,
+          "  <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" "
+          "disabled=\"%d\" ",
+          EscapeXmlAttribute(test_case.name()).c_str(),
+          test_case.total_test_count(),
+          test_case.failed_test_count(),
+          test_case.disabled_test_count());
+  fprintf(out,
+          "errors=\"0\" time=\"%s\">\n",
+          FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    ::std::stringstream stream;
+    OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
+    fprintf(out, "%s", StringStreamToString(&stream).c_str());
+  }
+  fprintf(out, "  </testsuite>\n");
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
+                                                const UnitTest& unit_test) {
+  fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+  fprintf(out,
+          "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
+          "errors=\"0\" time=\"%s\" ",
+          unit_test.total_test_count(),
+          unit_test.failed_test_count(),
+          unit_test.disabled_test_count(),
+          FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
+  if (GTEST_FLAG(shuffle)) {
+    fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
+  }
+  fprintf(out, "name=\"AllTests\">\n");
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+    PrintXmlTestCase(out, *unit_test.GetTestCase(i));
+  fprintf(out, "</testsuites>\n");
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : sockfd_(-1), host_name_(host), port_num_(port) {
+    MakeConnection();
+    Send("gtest_streaming_protocol_version=1.0\n");
+  }
+
+  virtual ~StreamingListener() {
+    if (sockfd_ != -1)
+      CloseConnection();
+  }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    Send("event=TestProgramStart\n");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    Send(String::Format("event=TestProgramEnd&passed=%d\n",
+                        unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    Send(String::Format("event=TestIterationStart&iteration=%d\n",
+                        iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+                        unit_test.Passed(),
+                        StreamableToString(unit_test.elapsed_time()).c_str()));
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+                        test_case.Passed(),
+                        StreamableToString(test_case.elapsed_time()).c_str()));
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    Send(String::Format(
+        "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+        (test_info.result())->Passed(),
+        StreamableToString((test_info.result())->elapsed_time()).c_str()));
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+                        UrlEncode(file_name).c_str(),
+                        test_part_result.line_number()));
+    Send(UrlEncode(test_part_result.message()) + "\n");
+  }
+
+ private:
+  // Creates a client socket and connects to the server.
+  void MakeConnection();
+
+  // Closes the socket.
+  void CloseConnection() {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "CloseConnection() can be called only when there is a connection.";
+
+    close(sockfd_);
+    sockfd_ = -1;
+  }
+
+  // Sends a string to the socket.
+  void Send(const string& message) {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "Send() can be called only when there is a connection.";
+
+    const int len = static_cast<int>(message.length());
+    if (write(sockfd_, message.c_str(), len) != len) {
+      GTEST_LOG_(WARNING)
+          << "stream_result_to: failed to stream to "
+          << host_name_ << ":" << port_num_;
+    }
+  }
+
+  int sockfd_;   // socket file descriptor
+  const string host_name_;
+  const string port_num_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+// L < UnitTest::mutex_
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+// L < UnitTest::mutex_
+ScopedTrace::~ScopedTrace() {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as a String.  Parameters:
+//
+//   max_depth  - the maximum number of stack frames to be included
+//                in the trace.
+//   skip_count - the number of top frames to be skipped; doesn't count
+//                against max_depth.
+//
+// L < mutex_
+// We use "L < mutex_" to denote that the function may acquire mutex_.
+String OsStackTraceGetter::CurrentStackTrace(int, int) {
+  return String("");
+}
+
+// L < mutex_
+void OsStackTraceGetter::UponLeavingGTest() {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest * UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+// L < mutex_
+void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
+                                 const char* file_name,
+                                 int line_number,
+                                 const internal::String& message,
+                                 const internal::String& os_stack_trace) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Creates and adds a property to the current TestResult. If a property matching
+// the supplied value already exists, updates its value instead.
+void UnitTest::RecordPropertyForCurrentTest(const char* key,
+                                            const char* value) {
+  const TestProperty test_property(key, value);
+  impl_->current_test_result()->RecordProperty(test_property);
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestCase* UnitTest::current_test_case() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestInfo* UnitTest::current_test_info() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+// L < mutex_
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry() {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+// L < mutex_
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+// L < mutex_
+void UnitTest::PopGTestTrace() {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push)                    // Saves the current warning state.
+# pragma warning(disable:4355)            // Temporarily disables warning 4355
+                                         // (using this in initializer).
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop)                     // Restores the warning state again.
+#else
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+#endif  // _MSC_VER
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      internal_run_death_test_flag_(NULL),
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const String& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const String& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  String name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const String &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const String test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.\n", test_case->name());
+        }
+        printf("  %s\n", test_info->name());
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                       int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag);
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", String(str, p - str).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto@D.\n"
+"  -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const String arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    // Do we see a Google Test flag?
+    if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                      &GTEST_FLAG(also_run_disabled_tests)) ||
+        ParseBoolFlag(arg, kBreakOnFailureFlag,
+                      &GTEST_FLAG(break_on_failure)) ||
+        ParseBoolFlag(arg, kCatchExceptionsFlag,
+                      &GTEST_FLAG(catch_exceptions)) ||
+        ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+        ParseStringFlag(arg, kDeathTestStyleFlag,
+                        &GTEST_FLAG(death_test_style)) ||
+        ParseBoolFlag(arg, kDeathTestUseFork,
+                      &GTEST_FLAG(death_test_use_fork)) ||
+        ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+        ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                        &GTEST_FLAG(internal_run_death_test)) ||
+        ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+        ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+        ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+        ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+        ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+        ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+        ParseInt32Flag(arg, kStackTraceDepthFlag,
+                       &GTEST_FLAG(stack_trace_depth)) ||
+        ParseStringFlag(arg, kStreamResultToFlag,
+                        &GTEST_FLAG(stream_result_to)) ||
+        ParseBoolFlag(arg, kThrowOnFailureFlag,
+                      &GTEST_FLAG(throw_on_failure))
+        ) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  g_init_gtest_count++;
+
+  // We don't want to run the initialization code twice.
+  if (g_init_gtest_count != 1) return;
+
+  if (*argc <= 0) return;
+
+  internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/gtest/src/gtest_main.cc b/src/external/gmock-1.6.0/gtest/src/gtest_main.cc
new file mode 100644 (file)
index 0000000..a09bbe0
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+  std::cout << "Running main() from gtest_main.cc\n";
+
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-actions.h b/src/external/gmock-1.6.0/include/gmock/gmock-actions.h
new file mode 100644 (file)
index 0000000..d6a3e14
--- /dev/null
@@ -0,0 +1,1076 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+
+#include <algorithm>
+#include <string>
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+// To implement an action Foo, define:
+//   1. a class FooAction that implements the ActionInterface interface, and
+//   2. a factory function that creates an Action object from a
+//      const FooAction*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Action objects can now be copied like plain values.
+
+namespace internal {
+
+template <typename F1, typename F2>
+class ActionAdaptor;
+
+// BuiltInDefaultValue<T>::Get() returns the "built-in" default
+// value for type T, which is NULL when T is a pointer type, 0 when T
+// is a numeric type, false when T is bool, or "" when T is string or
+// std::string.  For any other type T, this value is undefined and the
+// function will abort the process.
+template <typename T>
+class BuiltInDefaultValue {
+ public:
+  // This function returns true iff type T has a built-in default value.
+  static bool Exists() { return false; }
+  static T Get() {
+    Assert(false, __FILE__, __LINE__,
+           "Default action undefined for the function return type.");
+    return internal::Invalid<T>();
+    // The above statement will never be reached, but is required in
+    // order for this function to compile.
+  }
+};
+
+// This partial specialization says that we use the same built-in
+// default value for T and const T.
+template <typename T>
+class BuiltInDefaultValue<const T> {
+ public:
+  static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
+  static T Get() { return BuiltInDefaultValue<T>::Get(); }
+};
+
+// This partial specialization defines the default values for pointer
+// types.
+template <typename T>
+class BuiltInDefaultValue<T*> {
+ public:
+  static bool Exists() { return true; }
+  static T* Get() { return NULL; }
+};
+
+// The following specializations define the default values for
+// specific types we care about.
+#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \
+  template <> \
+  class BuiltInDefaultValue<type> { \
+   public: \
+    static bool Exists() { return true; } \
+    static type Get() { return value; } \
+  }
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, );  // NOLINT
+#if GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, "");
+#endif  // GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
+
+// There's no need for a default action for signed wchar_t, as that
+// type is the same as wchar_t for gcc, and invalid for MSVC.
+//
+// There's also no need for a default action for unsigned wchar_t, as
+// that type is the same as unsigned int for gcc, and invalid for
+// MSVC.
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U);  // NOLINT
+#endif
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0);
+
+#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_
+
+}  // namespace internal
+
+// When an unexpected function call is encountered, Google Mock will
+// let it return a default value if the user has specified one for its
+// return type, or if the return type has a built-in default value;
+// otherwise Google Mock won't know what value to return and will have
+// to abort the process.
+//
+// The DefaultValue<T> class allows a user to specify the
+// default value for a type T that is both copyable and publicly
+// destructible (i.e. anything that can be used as a function return
+// type).  The usage is:
+//
+//   // Sets the default value for type T to be foo.
+//   DefaultValue<T>::Set(foo);
+template <typename T>
+class DefaultValue {
+ public:
+  // Sets the default value for type T; requires T to be
+  // copy-constructable and have a public destructor.
+  static void Set(T x) {
+    delete value_;
+    value_ = new T(x);
+  }
+
+  // Unsets the default value for type T.
+  static void Clear() {
+    delete value_;
+    value_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T.
+  static bool IsSet() { return value_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T>::Exists();
+  }
+
+  // Returns the default value for type T if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T Get() {
+    return value_ == NULL ?
+        internal::BuiltInDefaultValue<T>::Get() : *value_;
+  }
+ private:
+  static const T* value_;
+};
+
+// This partial specialization allows a user to set default values for
+// reference types.
+template <typename T>
+class DefaultValue<T&> {
+ public:
+  // Sets the default value for type T&.
+  static void Set(T& x) {  // NOLINT
+    address_ = &x;
+  }
+
+  // Unsets the default value for type T&.
+  static void Clear() {
+    address_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T&.
+  static bool IsSet() { return address_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T&>::Exists();
+  }
+
+  // Returns the default value for type T& if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T& Get() {
+    return address_ == NULL ?
+        internal::BuiltInDefaultValue<T&>::Get() : *address_;
+  }
+ private:
+  static T* address_;
+};
+
+// This specialization allows DefaultValue<void>::Get() to
+// compile.
+template <>
+class DefaultValue<void> {
+ public:
+  static bool Exists() { return true; }
+  static void Get() {}
+};
+
+// Points to the user-set default value for type T.
+template <typename T>
+const T* DefaultValue<T>::value_ = NULL;
+
+// Points to the user-set default value for type T&.
+template <typename T>
+T* DefaultValue<T&>::address_ = NULL;
+
+// Implement this interface to define an action for function type F.
+template <typename F>
+class ActionInterface {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  ActionInterface() {}
+  virtual ~ActionInterface() {}
+
+  // Performs the action.  This method is not const, as in general an
+  // action can have side effects and be stateful.  For example, a
+  // get-the-next-element-from-the-collection action will need to
+  // remember the current element.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface);
+};
+
+// An Action<F> is a copyable and IMMUTABLE (except by assignment)
+// object that represents an action to be taken when a mock function
+// of type F is called.  The implementation of Action<T> is just a
+// linked_ptr to const ActionInterface<T>, so copying is fairly cheap.
+// Don't inherit from Action!
+//
+// You can view an object implementing ActionInterface<F> as a
+// concrete action (including its current state), and an Action<F>
+// object as a handle to it.
+template <typename F>
+class Action {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  // Constructs a null Action.  Needed for storing Action objects in
+  // STL containers.
+  Action() : impl_(NULL) {}
+
+  // Constructs an Action from its implementation.  A NULL impl is
+  // used to represent the "do-default" action.
+  explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
+
+  // Copy constructor.
+  Action(const Action& action) : impl_(action.impl_) {}
+
+  // This constructor allows us to turn an Action<Func> object into an
+  // Action<F>, as long as F's arguments can be implicitly converted
+  // to Func's and Func's return type can be implicitly converted to
+  // F's.
+  template <typename Func>
+  explicit Action(const Action<Func>& action);
+
+  // Returns true iff this is the DoDefault() action.
+  bool IsDoDefault() const { return impl_.get() == NULL; }
+
+  // Performs the action.  Note that this method is const even though
+  // the corresponding method in ActionInterface is not.  The reason
+  // is that a const Action<F> means that it cannot be re-bound to
+  // another concrete action, not that the concrete action it binds to
+  // cannot change state.  (Think of the difference between a const
+  // pointer and a pointer to const.)
+  Result Perform(const ArgumentTuple& args) const {
+    internal::Assert(
+        !IsDoDefault(), __FILE__, __LINE__,
+        "You are using DoDefault() inside a composite action like "
+        "DoAll() or WithArgs().  This is not supported for technical "
+        "reasons.  Please instead spell out the default action, or "
+        "assign the default action to an Action variable and use "
+        "the variable in various places.");
+    return impl_->Perform(args);
+  }
+
+ private:
+  template <typename F1, typename F2>
+  friend class internal::ActionAdaptor;
+
+  internal::linked_ptr<ActionInterface<F> > impl_;
+};
+
+// The PolymorphicAction class template makes it easy to implement a
+// polymorphic action (i.e. an action that can be used in mock
+// functions of than one type, e.g. Return()).
+//
+// To define a polymorphic action, a user first provides a COPYABLE
+// implementation class that has a Perform() method template:
+//
+//   class FooAction {
+//    public:
+//     template <typename Result, typename ArgumentTuple>
+//     Result Perform(const ArgumentTuple& args) const {
+//       // Processes the arguments and returns a result, using
+//       // tr1::get<N>(args) to get the N-th (0-based) argument in the tuple.
+//     }
+//     ...
+//   };
+//
+// Then the user creates the polymorphic action using
+// MakePolymorphicAction(object) where object has type FooAction.  See
+// the definition of Return(void) and SetArgumentPointee<N>(value) for
+// complete examples.
+template <typename Impl>
+class PolymorphicAction {
+ public:
+  explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new MonomorphicImpl<F>(impl_));
+  }
+
+ private:
+  template <typename F>
+  class MonomorphicImpl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return impl_.template Perform<Result>(args);
+    }
+
+   private:
+    Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicAction);
+};
+
+// Creates an Action from its implementation and returns it.  The
+// created Action object owns the implementation.
+template <typename F>
+Action<F> MakeAction(ActionInterface<F>* impl) {
+  return Action<F>(impl);
+}
+
+// Creates a polymorphic action from its implementation.  This is
+// easier to use than the PolymorphicAction<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicAction(foo);
+// vs
+//   PolymorphicAction<TypeOfFoo>(foo);
+template <typename Impl>
+inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
+  return PolymorphicAction<Impl>(impl);
+}
+
+namespace internal {
+
+// Allows an Action<F2> object to pose as an Action<F1>, as long as F2
+// and F1 are compatible.
+template <typename F1, typename F2>
+class ActionAdaptor : public ActionInterface<F1> {
+ public:
+  typedef typename internal::Function<F1>::Result Result;
+  typedef typename internal::Function<F1>::ArgumentTuple ArgumentTuple;
+
+  explicit ActionAdaptor(const Action<F2>& from) : impl_(from.impl_) {}
+
+  virtual Result Perform(const ArgumentTuple& args) {
+    return impl_->Perform(args);
+  }
+
+ private:
+  const internal::linked_ptr<ActionInterface<F2> > impl_;
+
+  GTEST_DISALLOW_ASSIGN_(ActionAdaptor);
+};
+
+// Implements the polymorphic Return(x) action, which can be used in
+// any function that returns the type of x, regardless of the argument
+// types.
+//
+// Note: The value passed into Return must be converted into
+// Function<F>::Result when this action is cast to Action<F> rather than
+// when that action is performed. This is important in scenarios like
+//
+// MOCK_METHOD1(Method, T(U));
+// ...
+// {
+//   Foo foo;
+//   X x(&foo);
+//   EXPECT_CALL(mock, Method(_)).WillOnce(Return(x));
+// }
+//
+// In the example above the variable x holds reference to foo which leaves
+// scope and gets destroyed.  If copying X just copies a reference to foo,
+// that copy will be left with a hanging reference.  If conversion to T
+// makes a copy of foo, the above code is safe. To support that scenario, we
+// need to make sure that the type conversion happens inside the EXPECT_CALL
+// statement, and conversion of the result of Return to Action<T(U)> is a
+// good place for that.
+//
+template <typename R>
+class ReturnAction {
+ public:
+  // Constructs a ReturnAction object from the value to be returned.
+  // 'value' is passed by value instead of by const reference in order
+  // to allow Return("string literal") to compile.
+  explicit ReturnAction(R value) : value_(value) {}
+
+  // This template type conversion operator allows Return(x) to be
+  // used in ANY function that returns x's type.
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename Function<F>::Result Result;
+    GTEST_COMPILE_ASSERT_(
+        !internal::is_reference<Result>::value,
+        use_ReturnRef_instead_of_Return_to_return_a_reference);
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the Return(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    // The implicit cast is necessary when Result has more than one
+    // single-argument constructor (e.g. Result is std::vector<int>) and R
+    // has a type conversion operator template.  In that case, value_(value)
+    // won't compile as the compiler doesn't known which constructor of
+    // Result to call.  ImplicitCast_ forces the compiler to convert R to
+    // Result without considering explicit constructors, thus resolving the
+    // ambiguity. value_ is then initialized using its copy constructor.
+    explicit Impl(R value)
+        : value_(::testing::internal::ImplicitCast_<Result>(value)) {}
+
+    virtual Result Perform(const ArgumentTuple&) { return value_; }
+
+   private:
+    GTEST_COMPILE_ASSERT_(!internal::is_reference<Result>::value,
+                          Result_cannot_be_a_reference_type);
+    Result value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  R value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnAction);
+};
+
+// Implements the ReturnNull() action.
+class ReturnNullAction {
+ public:
+  // Allows ReturnNull() to be used in any pointer-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static Result Perform(const ArgumentTuple&) {
+    GTEST_COMPILE_ASSERT_(internal::is_pointer<Result>::value,
+                          ReturnNull_can_be_used_to_return_a_pointer_only);
+    return NULL;
+  }
+};
+
+// Implements the Return() action.
+class ReturnVoidAction {
+ public:
+  // Allows Return() to be used in any void-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static void Perform(const ArgumentTuple&) {
+    CompileAssertTypesEqual<void, Result>();
+  }
+};
+
+// Implements the polymorphic ReturnRef(x) action, which can be used
+// in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefAction {
+ public:
+  // Constructs a ReturnRefAction object from the reference to be returned.
+  explicit ReturnRefAction(T& ref) : ref_(ref) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRef(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRef(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(internal::is_reference<Result>::value,
+                          use_Return_instead_of_ReturnRef_to_return_a_value);
+    return Action<F>(new Impl<F>(ref_));
+  }
+
+ private:
+  // Implements the ReturnRef(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(T& ref) : ref_(ref) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return ref_;
+    }
+
+   private:
+    T& ref_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& ref_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefAction);
+};
+
+// Implements the polymorphic ReturnRefOfCopy(x) action, which can be
+// used in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefOfCopyAction {
+ public:
+  // Constructs a ReturnRefOfCopyAction object from the reference to
+  // be returned.
+  explicit ReturnRefOfCopyAction(const T& value) : value_(value) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRefOfCopy(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRefOfCopy(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<Result>::value,
+        use_Return_instead_of_ReturnRefOfCopy_to_return_a_value);
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the ReturnRefOfCopy(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const T& value) : value_(value) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return value_;
+    }
+
+   private:
+    T value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const T value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
+};
+
+// Implements the polymorphic DoDefault() action.
+class DoDefaultAction {
+ public:
+  // This template type conversion operator allows DoDefault() to be
+  // used in any function.
+  template <typename F>
+  operator Action<F>() const { return Action<F>(NULL); }
+};
+
+// Implements the Assign action to set a given pointer referent to a
+// particular value.
+template <typename T1, typename T2>
+class AssignAction {
+ public:
+  AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& /* args */) const {
+    *ptr_ = value_;
+  }
+
+ private:
+  T1* const ptr_;
+  const T2 value_;
+
+  GTEST_DISALLOW_ASSIGN_(AssignAction);
+};
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetErrnoAndReturn action to simulate return from
+// various system calls and libc functions.
+template <typename T>
+class SetErrnoAndReturnAction {
+ public:
+  SetErrnoAndReturnAction(int errno_value, T result)
+      : errno_(errno_value),
+        result_(result) {}
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& /* args */) const {
+    errno = errno_;
+    return result_;
+  }
+
+ private:
+  const int errno_;
+  const T result_;
+
+  GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction);
+};
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetArgumentPointee<N>(x) action for any function
+// whose N-th argument (0-based) is a pointer to x's type.  The
+// template parameter kIsProto is true iff type A is ProtocolMessage,
+// proto2::Message, or a sub-class of those.
+template <size_t N, typename A, bool kIsProto>
+class SetArgumentPointeeAction {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'value'.
+  explicit SetArgumentPointeeAction(const A& value) : value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    *::std::tr1::get<N>(args) = value_;
+  }
+
+ private:
+  const A value_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+template <size_t N, typename Proto>
+class SetArgumentPointeeAction<N, Proto, true> {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'proto'.  Both ProtocolMessage and
+  // proto2::Message have the CopyFrom() method, so the same
+  // implementation works for both.
+  explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) {
+    proto_->CopyFrom(proto);
+  }
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    ::std::tr1::get<N>(args)->CopyFrom(*proto_);
+  }
+
+ private:
+  const internal::linked_ptr<Proto> proto_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+// Implements the InvokeWithoutArgs(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  InvokeWithoutArgs(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeWithoutArgsAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeWithoutArgsAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  // Allows InvokeWithoutArgs(f) to be used as any action whose type is
+  // compatible with f.
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) { return function_impl_(); }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction);
+};
+
+// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodWithoutArgsAction {
+ public:
+  InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr)
+      : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) const {
+    return (obj_ptr_->*method_ptr_)();
+  }
+
+ private:
+  Class* const obj_ptr_;
+  const MethodPtr method_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction);
+};
+
+// Implements the IgnoreResult(action) action.
+template <typename A>
+class IgnoreResultAction {
+ public:
+  explicit IgnoreResultAction(const A& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename internal::Function<F>::Result Result;
+
+    // Asserts at compile time that F returns void.
+    CompileAssertTypesEqual<void, Result>();
+
+    return Action<F>(new Impl<F>(action_));
+  }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const A& action) : action_(action) {}
+
+    virtual void Perform(const ArgumentTuple& args) {
+      // Performs the action and ignores its result.
+      action_.Perform(args);
+    }
+
+   private:
+    // Type OriginalFunction is the same as F except that its return
+    // type is IgnoredValue.
+    typedef typename internal::Function<F>::MakeResultIgnoredValue
+        OriginalFunction;
+
+    const Action<OriginalFunction> action_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const A action_;
+
+  GTEST_DISALLOW_ASSIGN_(IgnoreResultAction);
+};
+
+// A ReferenceWrapper<T> object represents a reference to type T,
+// which can be either const or not.  It can be explicitly converted
+// from, and implicitly converted to, a T&.  Unlike a reference,
+// ReferenceWrapper<T> can be copied and can survive template type
+// inference.  This is used to support by-reference arguments in the
+// InvokeArgument<N>(...) action.  The idea was from "reference
+// wrappers" in tr1, which we don't have in our source tree yet.
+template <typename T>
+class ReferenceWrapper {
+ public:
+  // Constructs a ReferenceWrapper<T> object from a T&.
+  explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {}  // NOLINT
+
+  // Allows a ReferenceWrapper<T> object to be implicitly converted to
+  // a T&.
+  operator T&() const { return *pointer_; }
+ private:
+  T* pointer_;
+};
+
+// Allows the expression ByRef(x) to be printed as a reference to x.
+template <typename T>
+void PrintTo(const ReferenceWrapper<T>& ref, ::std::ostream* os) {
+  T& value = ref;
+  UniversalPrinter<T&>::Print(value, os);
+}
+
+// Does two actions sequentially.  Used for implementing the DoAll(a1,
+// a2, ...) action.
+template <typename Action1, typename Action2>
+class DoBothAction {
+ public:
+  DoBothAction(Action1 action1, Action2 action2)
+      : action1_(action1), action2_(action2) {}
+
+  // This template type conversion operator allows DoAll(a1, ..., a_n)
+  // to be used in ANY function of compatible type.
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new Impl<F>(action1_, action2_));
+  }
+
+ private:
+  // Implements the DoAll(...) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+    typedef typename Function<F>::MakeResultVoid VoidResult;
+
+    Impl(const Action<VoidResult>& action1, const Action<F>& action2)
+        : action1_(action1), action2_(action2) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      action1_.Perform(args);
+      return action2_.Perform(args);
+    }
+
+   private:
+    const Action<VoidResult> action1_;
+    const Action<F> action2_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  Action1 action1_;
+  Action2 action2_;
+
+  GTEST_DISALLOW_ASSIGN_(DoBothAction);
+};
+
+}  // namespace internal
+
+// An Unused object can be implicitly constructed from ANY value.
+// This is handy when defining actions that ignore some or all of the
+// mock function arguments.  For example, given
+//
+//   MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+//   MOCK_METHOD3(Bar, double(int index, double x, double y));
+//
+// instead of
+//
+//   double DistanceToOriginWithLabel(const string& label, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   double DistanceToOriginWithIndex(int index, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithLabel));
+//   EXEPCT_CALL(mock, Bar(5, _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithIndex));
+//
+// you could write
+//
+//   // We can declare any uninteresting argument as Unused.
+//   double DistanceToOrigin(Unused, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
+//   EXEPCT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
+typedef internal::IgnoredValue Unused;
+
+// This constructor allows us to turn an Action<From> object into an
+// Action<To>, as long as To's arguments can be implicitly converted
+// to From's and From's return type cann be implicitly converted to
+// To's.
+template <typename To>
+template <typename From>
+Action<To>::Action(const Action<From>& from)
+    : impl_(new internal::ActionAdaptor<To, From>(from)) {}
+
+// Creates an action that returns 'value'.  'value' is passed by value
+// instead of const reference - otherwise Return("string literal")
+// will trigger a compiler error about using array as initializer.
+template <typename R>
+internal::ReturnAction<R> Return(R value) {
+  return internal::ReturnAction<R>(value);
+}
+
+// Creates an action that returns NULL.
+inline PolymorphicAction<internal::ReturnNullAction> ReturnNull() {
+  return MakePolymorphicAction(internal::ReturnNullAction());
+}
+
+// Creates an action that returns from a void function.
+inline PolymorphicAction<internal::ReturnVoidAction> Return() {
+  return MakePolymorphicAction(internal::ReturnVoidAction());
+}
+
+// Creates an action that returns the reference to a variable.
+template <typename R>
+inline internal::ReturnRefAction<R> ReturnRef(R& x) {  // NOLINT
+  return internal::ReturnRefAction<R>(x);
+}
+
+// Creates an action that returns the reference to a copy of the
+// argument.  The copy is created when the action is constructed and
+// lives as long as the action.
+template <typename R>
+inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) {
+  return internal::ReturnRefOfCopyAction<R>(x);
+}
+
+// Creates an action that does the default action for the give mock function.
+inline internal::DoDefaultAction DoDefault() {
+  return internal::DoDefaultAction();
+}
+
+// Creates an action that sets the variable pointed by the N-th
+// (0-based) function argument to 'value'.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN)
+// This overload allows SetArgPointee() to accept a string literal.
+// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish
+// this overload from the templated version and emit a compile error.
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const char*, false> >
+SetArgPointee(const char* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const char*, false>(p));
+}
+
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const wchar_t*, false> >
+SetArgPointee(const wchar_t* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const wchar_t*, false>(p));
+}
+#endif
+
+// The following version is DEPRECATED.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgumentPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+// Creates an action that sets a pointer referent to a given value.
+template <typename T1, typename T2>
+PolymorphicAction<internal::AssignAction<T1, T2> > Assign(T1* ptr, T2 val) {
+  return MakePolymorphicAction(internal::AssignAction<T1, T2>(ptr, val));
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Creates an action that sets errno and returns the appropriate error.
+template <typename T>
+PolymorphicAction<internal::SetErrnoAndReturnAction<T> >
+SetErrnoAndReturn(int errval, T result) {
+  return MakePolymorphicAction(
+      internal::SetErrnoAndReturnAction<T>(errval, result));
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Various overloads for InvokeWithoutArgs().
+
+// Creates an action that invokes 'function_impl' with no argument.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeWithoutArgsAction<FunctionImpl> >
+InvokeWithoutArgs(FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeWithoutArgsAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with no argument.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> >
+InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodWithoutArgsAction<Class, MethodPtr>(
+          obj_ptr, method_ptr));
+}
+
+// Creates an action that performs an_action and throws away its
+// result.  In other words, it changes the return type of an_action to
+// void.  an_action MUST NOT return void, or the code won't compile.
+template <typename A>
+inline internal::IgnoreResultAction<A> IgnoreResult(const A& an_action) {
+  return internal::IgnoreResultAction<A>(an_action);
+}
+
+// Creates a reference wrapper for the given L-value.  If necessary,
+// you can explicitly specify the type of the reference.  For example,
+// suppose 'derived' is an object of type Derived, ByRef(derived)
+// would wrap a Derived&.  If you want to wrap a const Base& instead,
+// where Base is a base class of Derived, just write:
+//
+//   ByRef<const Base>(derived)
+template <typename T>
+inline internal::ReferenceWrapper<T> ByRef(T& l_value) {  // NOLINT
+  return internal::ReferenceWrapper<T>(l_value);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-cardinalities.h b/src/external/gmock-1.6.0/include/gmock/gmock-cardinalities.h
new file mode 100644 (file)
index 0000000..954a86e
--- /dev/null
@@ -0,0 +1,146 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used cardinalities.  More
+// cardinalities can be defined by the user implementing the
+// CardinalityInterface interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// To implement a cardinality Foo, define:
+//   1. a class FooCardinality that implements the
+//      CardinalityInterface interface, and
+//   2. a factory function that creates a Cardinality object from a
+//      const FooCardinality*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Cardinality objects can now be copied like plain values.
+
+// The implementation of a cardinality.
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface() {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return 0; }
+  virtual int ConservativeUpperBound() const { return INT_MAX; }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+
+// A Cardinality is a copyable and IMMUTABLE (except by assignment)
+// object that specifies how many times a mock function is expected to
+// be called.  The implementation of Cardinality is just a linked_ptr
+// to const CardinalityInterface, so copying is fairly cheap.
+// Don't inherit from Cardinality!
+class Cardinality {
+ public:
+  // Constructs a null cardinality.  Needed for storing Cardinality
+  // objects in STL containers.
+  Cardinality() {}
+
+  // Constructs a Cardinality from its implementation.
+  explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
+  int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const {
+    return impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  bool IsSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will over-saturate this
+  // cardinality, i.e. exceed the maximum number of allowed calls.
+  bool IsOverSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count) &&
+        !impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Describes self to an ostream
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the given actual call count to an ostream.
+  static void DescribeActualCallCountTo(int actual_call_count,
+                                        ::std::ostream* os);
+ private:
+  internal::linked_ptr<const CardinalityInterface> impl_;
+};
+
+// Creates a cardinality that allows at least n calls.
+Cardinality AtLeast(int n);
+
+// Creates a cardinality that allows at most n calls.
+Cardinality AtMost(int n);
+
+// Creates a cardinality that allows any number of calls.
+Cardinality AnyNumber();
+
+// Creates a cardinality that allows between min and max calls.
+Cardinality Between(int min, int max);
+
+// Creates a cardinality that allows exactly n calls.
+Cardinality Exactly(int n);
+
+// Creates a cardinality from its implementation.
+inline Cardinality MakeCardinality(const CardinalityInterface* c) {
+  return Cardinality(c);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-generated-actions.h b/src/external/gmock-1.6.0/include/gmock/gmock-generated-actions.h
new file mode 100644 (file)
index 0000000..635bb59
--- /dev/null
@@ -0,0 +1,2419 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+
+#include "gmock/gmock-actions.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+namespace internal {
+
+// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
+// function or method with the unpacked values, where F is a function
+// type that takes N arguments.
+template <typename Result, typename ArgumentTuple>
+class InvokeHelper;
+
+template <typename R>
+class InvokeHelper<R, ::std::tr1::tuple<> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<>&) {
+    return function();
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<>&) {
+    return (obj_ptr->*method_ptr)();
+  }
+};
+
+template <typename R, typename A1>
+class InvokeHelper<R, ::std::tr1::tuple<A1> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2,
+      A3>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3,
+      A4>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6,
+                            A7>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7,
+                            A8>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8, A9>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args),
+        get<8>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8, A9, A10>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        get<9>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9, A10>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args),
+        get<8>(args), get<9>(args));
+  }
+};
+
+// CallableHelper has static methods for invoking "callables",
+// i.e. function pointers and functors.  It uses overloading to
+// provide a uniform interface for invoking different kinds of
+// callables.  In particular, you can use:
+//
+//   CallableHelper<R>::Call(callable, a1, a2, ..., an)
+//
+// to invoke an n-ary callable, where R is its return type.  If an
+// argument, say a2, needs to be passed by reference, you should write
+// ByRef(a2) instead of a2 in the above expression.
+template <typename R>
+class CallableHelper {
+ public:
+  // Calls a nullary callable.
+  template <typename Function>
+  static R Call(Function function) { return function(); }
+
+  // Calls a unary callable.
+
+  // We deliberately pass a1 by value instead of const reference here
+  // in case it is a C-string literal.  If we had declared the
+  // parameter as 'const A1& a1' and write Call(function, "Hi"), the
+  // compiler would've thought A1 is 'char[3]', which causes trouble
+  // when you need to copy a value of type A1.  By declaring the
+  // parameter as 'A1 a1', the compiler will correctly infer that A1
+  // is 'const char*' when it sees Call(function, "Hi").
+  //
+  // Since this function is defined inline, the compiler can get rid
+  // of the copying of the arguments.  Therefore the performance won't
+  // be hurt.
+  template <typename Function, typename A1>
+  static R Call(Function function, A1 a1) { return function(a1); }
+
+  // Calls a binary callable.
+  template <typename Function, typename A1, typename A2>
+  static R Call(Function function, A1 a1, A2 a2) {
+    return function(a1, a2);
+  }
+
+  // Calls a ternary callable.
+  template <typename Function, typename A1, typename A2, typename A3>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3) {
+    return function(a1, a2, a3);
+  }
+
+  // Calls a 4-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4) {
+    return function(a1, a2, a3, a4);
+  }
+
+  // Calls a 5-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+    return function(a1, a2, a3, a4, a5);
+  }
+
+  // Calls a 6-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+    return function(a1, a2, a3, a4, a5, a6);
+  }
+
+  // Calls a 7-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7) {
+    return function(a1, a2, a3, a4, a5, a6, a7);
+  }
+
+  // Calls a 8-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8);
+  }
+
+  // Calls a 9-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8,
+      typename A9>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8, A9 a9) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  }
+
+  // Calls a 10-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8,
+      typename A9, typename A10>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8, A9 a9, A10 a10) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+  }
+
+};  // class CallableHelper
+
+// An INTERNAL macro for extracting the type of a tuple field.  It's
+// subject to change without notice - DO NOT USE IN USER CODE!
+#define GMOCK_FIELD_(Tuple, N) \
+    typename ::std::tr1::tuple_element<N, Tuple>::type
+
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
+// type of an n-ary function whose i-th (1-based) argument type is the
+// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
+// type, and whose return type is Result.  For example,
+//   SelectArgs<int, ::std::tr1::tuple<bool, char, double, long>, 0, 3>::type
+// is int(bool, long).
+//
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
+// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
+// For example,
+//   SelectArgs<int, ::std::tr1::tuple<bool, char, double>, 2, 0>::Select(
+//       ::std::tr1::make_tuple(true, 'a', 2.5))
+// returns ::std::tr1::tuple (2.5, true).
+//
+// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
+// in the range [0, 10].  Duplicates are allowed and they don't have
+// to be in an ascending or descending order.
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9, int k10>
+class SelectArgs {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9),
+      GMOCK_FIELD_(ArgumentTuple, k10));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args), get<k10>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple>
+class SelectArgs<Result, ArgumentTuple,
+                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type();
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& /* args */) {
+    using ::std::tr1::get;
+    return SelectedArgs();
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, k9, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args));
+  }
+};
+
+#undef GMOCK_FIELD_
+
+// Implements the WithArgs action.
+template <typename InnerAction, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1, int k10 = -1>
+class WithArgsAction {
+ public:
+  explicit WithArgsAction(const InnerAction& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const InnerAction& action) : action_(action) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return action_.Perform(SelectArgs<Result, ArgumentTuple, k1, k2, k3, k4,
+          k5, k6, k7, k8, k9, k10>::Select(args));
+    }
+
+   private:
+    typedef typename SelectArgs<Result, ArgumentTuple,
+        k1, k2, k3, k4, k5, k6, k7, k8, k9, k10>::type InnerFunctionType;
+
+    Action<InnerFunctionType> action_;
+  };
+
+  const InnerAction action_;
+
+  GTEST_DISALLOW_ASSIGN_(WithArgsAction);
+};
+
+// A macro from the ACTION* family (defined later in this file)
+// defines an action that can be used in a mock function.  Typically,
+// these actions only care about a subset of the arguments of the mock
+// function.  For example, if such an action only uses the second
+// argument, it can be used in any mock function that takes >= 2
+// arguments where the type of the second argument is compatible.
+//
+// Therefore, the action implementation must be prepared to take more
+// arguments than it needs.  The ExcessiveArg type is used to
+// represent those excessive arguments.  In order to keep the compiler
+// error messages tractable, we define it in the testing namespace
+// instead of testing::internal.  However, this is an INTERNAL TYPE
+// and subject to change without notice, so a user MUST NOT USE THIS
+// TYPE DIRECTLY.
+struct ExcessiveArg {};
+
+// A helper class needed for implementing the ACTION* macros.
+template <typename Result, class Impl>
+class ActionHelper {
+ public:
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<>(args, ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0>(args, get<0>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1>(args, get<0>(args),
+        get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2>(args, get<0>(args),
+        get<1>(args), get<2>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2,
+      A3>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3>(args, get<0>(args),
+        get<1>(args), get<2>(args), get<3>(args), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3,
+      A4>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), get<6>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6,
+        A7>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7,
+        A8>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8, typename A9>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8, A9>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7, A8,
+        A9>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        get<9>(args));
+  }
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
+// the selected arguments of the mock function to an_action and
+// performs it.  It serves as an adaptor between actions with
+// different argument lists.  C++ doesn't support default arguments for
+// function templates, so we have to overload it.
+template <int k1, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1>(action);
+}
+
+template <int k1, int k2, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2>(action);
+}
+
+template <int k1, int k2, int k3, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3>(action);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6,
+      k7>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7,
+      k8>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+    k9, k10>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(action);
+}
+
+// Creates an action that does actions a1, a2, ..., sequentially in
+// each invocation.
+template <typename Action1, typename Action2>
+inline internal::DoBothAction<Action1, Action2>
+DoAll(Action1 a1, Action2 a2) {
+  return internal::DoBothAction<Action1, Action2>(a1, a2);
+}
+
+template <typename Action1, typename Action2, typename Action3>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    Action3> >
+DoAll(Action1 a1, Action2 a2, Action3 a3) {
+  return DoAll(a1, DoAll(a2, a3));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, Action4> > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) {
+  return DoAll(a1, DoAll(a2, a3, a4));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    Action5> > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, Action6> > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    Action7> > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, Action8> > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    Action9> > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9, typename Action10>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    internal::DoBothAction<Action9, Action10> > > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9, Action10 a10) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10));
+}
+
+}  // namespace testing
+
+// The ACTION* family of macros can be used in a namespace scope to
+// define custom actions easily.  The syntax:
+//
+//   ACTION(name) { statements; }
+//
+// will define an action with the given name that executes the
+// statements.  The value returned by the statements will be used as
+// the return value of the action.  Inside the statements, you can
+// refer to the K-th (0-based) argument of the mock function by
+// 'argK', and refer to its type by 'argK_type'.  For example:
+//
+//   ACTION(IncrementArg1) {
+//     arg1_type temp = arg1;
+//     return ++(*temp);
+//   }
+//
+// allows you to write
+//
+//   ...WillOnce(IncrementArg1());
+//
+// You can also refer to the entire argument tuple and its type by
+// 'args' and 'args_type', and refer to the mock function type and its
+// return type by 'function_type' and 'return_type'.
+//
+// Note that you don't need to specify the types of the mock function
+// arguments.  However rest assured that your code is still type-safe:
+// you'll get a compiler error if *arg1 doesn't support the ++
+// operator, or if the type of ++(*arg1) isn't compatible with the
+// mock function's return type, for example.
+//
+// Sometimes you'll want to parameterize the action.   For that you can use
+// another macro:
+//
+//   ACTION_P(name, param_name) { statements; }
+//
+// For example:
+//
+//   ACTION_P(Add, n) { return arg0 + n; }
+//
+// will allow you to write:
+//
+//   ...WillOnce(Add(5));
+//
+// Note that you don't need to provide the type of the parameter
+// either.  If you need to reference the type of a parameter named
+// 'foo', you can write 'foo_type'.  For example, in the body of
+// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
+// of 'n'.
+//
+// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support
+// multi-parameter actions.
+//
+// For the purpose of typing, you can view
+//
+//   ACTION_Pk(Foo, p1, ..., pk) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// In particular, you can provide the template type arguments
+// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
+// although usually you can rely on the compiler to infer the types
+// for you automatically.  You can assign the result of expression
+// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
+// pk_type>.  This can be useful when composing actions.
+//
+// You can also overload actions with different numbers of parameters:
+//
+//   ACTION_P(Plus, a) { ... }
+//   ACTION_P2(Plus, a, b) { ... }
+//
+// While it's tempting to always use the ACTION* macros when defining
+// a new action, you should also consider implementing ActionInterface
+// or using MakePolymorphicAction() instead, especially if you need to
+// use the action a lot.  While these approaches require more work,
+// they give you more control on the types of the mock function
+// arguments and the action parameters, which in general leads to
+// better compiler error messages that pay off in the long run.  They
+// also allow overloading actions based on parameter types (as opposed
+// to just based on the number of parameters).
+//
+// CAVEAT:
+//
+// ACTION*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using ACTION*() inside
+// a function.
+//
+// MORE INFORMATION:
+//
+// To learn more about using these macros, please search for 'ACTION'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+// An internal macro needed for implementing ACTION*().
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
+    const args_type& args GTEST_ATTRIBUTE_UNUSED_,\
+    arg0_type arg0 GTEST_ATTRIBUTE_UNUSED_,\
+    arg1_type arg1 GTEST_ATTRIBUTE_UNUSED_,\
+    arg2_type arg2 GTEST_ATTRIBUTE_UNUSED_,\
+    arg3_type arg3 GTEST_ATTRIBUTE_UNUSED_,\
+    arg4_type arg4 GTEST_ATTRIBUTE_UNUSED_,\
+    arg5_type arg5 GTEST_ATTRIBUTE_UNUSED_,\
+    arg6_type arg6 GTEST_ATTRIBUTE_UNUSED_,\
+    arg7_type arg7 GTEST_ATTRIBUTE_UNUSED_,\
+    arg8_type arg8 GTEST_ATTRIBUTE_UNUSED_,\
+    arg9_type arg9 GTEST_ATTRIBUTE_UNUSED_
+
+// Sometimes you want to give an action explicit template parameters
+// that cannot be inferred from its value parameters.  ACTION() and
+// ACTION_P*() don't support that.  ACTION_TEMPLATE() remedies that
+// and can be viewed as an extension to ACTION() and ACTION_P*().
+//
+// The syntax:
+//
+//   ACTION_TEMPLATE(ActionName,
+//                   HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+//                   AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+//
+// defines an action template that takes m explicit template
+// parameters and n value parameters.  name_i is the name of the i-th
+// template parameter, and kind_i specifies whether it's a typename,
+// an integral constant, or a template.  p_i is the name of the i-th
+// value parameter.
+//
+// Example:
+//
+//   // DuplicateArg<k, T>(output) converts the k-th argument of the mock
+//   // function to type T and copies it to *output.
+//   ACTION_TEMPLATE(DuplicateArg,
+//                   HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+//                   AND_1_VALUE_PARAMS(output)) {
+//     *output = T(std::tr1::get<k>(args));
+//   }
+//   ...
+//     int n;
+//     EXPECT_CALL(mock, Foo(_, _))
+//         .WillOnce(DuplicateArg<1, unsigned char>(&n));
+//
+// To create an instance of an action template, write:
+//
+//   ActionName<t1, ..., t_m>(v1, ..., v_n)
+//
+// where the ts are the template arguments and the vs are the value
+// arguments.  The value argument types are inferred by the compiler.
+// If you want to explicitly specify the value argument types, you can
+// provide additional template arguments:
+//
+//   ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+//
+// where u_i is the desired type of v_i.
+//
+// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
+// number of value parameters, but not on the number of template
+// parameters.  Without the restriction, the meaning of the following
+// is unclear:
+//
+//   OverloadedAction<int, bool>(x);
+//
+// Are we using a single-template-parameter action where 'bool' refers
+// to the type of x, or are we using a two-template-parameter action
+// where the compiler is asked to infer the type of x?
+//
+// Implementation notes:
+//
+// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
+// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
+// implementing ACTION_TEMPLATE.  The main trick we use is to create
+// new macro invocations when expanding a macro.  For example, we have
+//
+//   #define ACTION_TEMPLATE(name, template_params, value_params)
+//       ... GMOCK_INTERNAL_DECL_##template_params ...
+//
+// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
+// to expand to
+//
+//       ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
+//
+// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
+// preprocessor will continue to expand it to
+//
+//       ... typename T ...
+//
+// This technique conforms to the C++ standard and is portable.  It
+// allows us to implement action templates using O(N) code, where N is
+// the maximum number of template/value parameters supported.  Without
+// using it, we'd have to devote O(N^2) amount of code to implement all
+// combinations of m and n.
+
+// Declares the template parameters.
+#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0
+#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) kind0 name0, kind1 name1
+#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) kind0 name0, kind1 name1, kind2 name2
+#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3
+#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \
+    kind2 name2, kind3 name3, kind4 name4
+#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5
+#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
+    kind5 name5, kind6 name6
+#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \
+    kind4 name4, kind5 name5, kind6 name6, kind7 name7
+#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \
+    kind8 name8
+#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \
+    kind6 name6, kind7 name7, kind8 name8, kind9 name9
+
+// Lists the template parameters.
+#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0
+#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) name0, name1
+#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) name0, name1, name2
+#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) name0, name1, name2, name3
+#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \
+    name4
+#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \
+    name2, name3, name4, name5
+#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) name0, name1, name2, name3, name4, name5, name6
+#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7
+#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \
+    name6, name7, name8
+#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \
+    name3, name4, name5, name6, name7, name8, name9
+
+// Declares the types of value parameters.
+#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \
+    typename p0##_type, typename p1##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \
+    typename p0##_type, typename p1##_type, typename p2##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type, typename p8##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \
+    typename p2##_type, typename p3##_type, typename p4##_type, \
+    typename p5##_type, typename p6##_type, typename p7##_type, \
+    typename p8##_type, typename p9##_type
+
+// Initializes the value parameters.
+#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\
+    ()
+#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\
+    (p0##_type gmock_p0) : p0(gmock_p0)
+#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\
+    (p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), p1(gmock_p1)
+#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2)
+#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3)
+#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4)
+#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5)
+#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6)
+#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7)
+#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8)
+#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+        p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8), p9(gmock_p9)
+
+// Declares the fields for storing the value parameters.
+#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0;
+#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \
+    p1##_type p1;
+#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \
+    p1##_type p1; p2##_type p2;
+#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \
+    p1##_type p1; p2##_type p2; p3##_type p3;
+#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4;
+#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5;
+#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6;
+#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6; p7##_type p7;
+#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8;
+#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \
+    p9##_type p9;
+
+// Lists the value parameters.
+#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0
+#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1
+#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2
+#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3
+#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \
+    p2, p3, p4
+#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \
+    p1, p2, p3, p4, p5
+#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0, p1, p2, p3, p4, p5, p6
+#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0, p1, p2, p3, p4, p5, p6, p7
+#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8
+#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9
+
+// Lists the value parameter types.
+#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \
+    p1##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \
+    p1##_type, p2##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    p0##_type, p1##_type, p2##_type, p3##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
+    p6##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type, p9##_type
+
+// Declares the value parameters.
+#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0
+#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \
+    p1##_type p1
+#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \
+    p1##_type p1, p2##_type p2
+#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \
+    p1##_type p1, p2##_type p2, p3##_type p3
+#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4
+#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5
+#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6
+#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6, p7##_type p7
+#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8
+#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+    p9##_type p9
+
+// The suffix of the class template implementing the action template.
+#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P
+#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2
+#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3
+#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4
+#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5
+#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6
+#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7
+#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) P8
+#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) P9
+#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) P10
+
+// The name of the class template implementing the action template.
+#define GMOCK_ACTION_CLASS_(name, value_params)\
+    GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
+
+#define ACTION_TEMPLATE(name, template_params, value_params)\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  class GMOCK_ACTION_CLASS_(name, value_params) {\
+   public:\
+    GMOCK_ACTION_CLASS_(name, value_params)\
+        GMOCK_INTERNAL_INIT_##value_params {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      GMOCK_INTERNAL_DEFN_##value_params\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(\
+          new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
+    }\
+    GMOCK_INTERNAL_DEFN_##value_params\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
+  };\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  inline GMOCK_ACTION_CLASS_(name, value_params)<\
+      GMOCK_INTERNAL_LIST_##template_params\
+      GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
+          GMOCK_INTERNAL_DECL_##value_params) {\
+    return GMOCK_ACTION_CLASS_(name, value_params)<\
+        GMOCK_INTERNAL_LIST_##template_params\
+        GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
+            GMOCK_INTERNAL_LIST_##value_params);\
+  }\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type,\
+      typename arg3_type, typename arg4_type, typename arg5_type,\
+      typename arg6_type, typename arg7_type, typename arg8_type,\
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      GMOCK_ACTION_CLASS_(name, value_params)<\
+          GMOCK_INTERNAL_LIST_##template_params\
+          GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
+              gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION(name)\
+  class name##Action {\
+   public:\
+    name##Action() {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl() {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>());\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Action);\
+  };\
+  inline name##Action name() {\
+    return name##Action();\
+  }\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##Action::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P(name, p0)\
+  template <typename p0##_type>\
+  class name##ActionP {\
+   public:\
+    name##ActionP(p0##_type gmock_p0) : p0(gmock_p0) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl(p0##_type gmock_p0) : p0(gmock_p0) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0));\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP);\
+  };\
+  template <typename p0##_type>\
+  inline name##ActionP<p0##_type> name(p0##_type p0) {\
+    return name##ActionP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP<p0##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P2(name, p0, p1)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##ActionP2 {\
+   public:\
+    name##ActionP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+          p1(gmock_p1) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##ActionP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##ActionP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP2<p0##_type, p1##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P3(name, p0, p1, p2)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##ActionP3 {\
+   public:\
+    name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \
+          p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##ActionP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##ActionP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP3<p0##_type, p1##_type, \
+          p2##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P4(name, p0, p1, p2, p3)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##ActionP4 {\
+   public:\
+    name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##ActionP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##ActionP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, p1, \
+        p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP4<p0##_type, p1##_type, p2##_type, \
+          p3##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P5(name, p0, p1, p2, p3, p4)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##ActionP5 {\
+   public:\
+    name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+          p4##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##ActionP6 {\
+   public:\
+    name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, \
+          p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##ActionP7 {\
+   public:\
+    name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##ActionP8 {\
+   public:\
+    name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), \
+          p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, \
+          p7##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##ActionP9 {\
+   public:\
+    name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, \
+          p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, \
+          p8##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##ActionP10 {\
+   public:\
+    name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8, p9));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, p8##_type, \
+          p9##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+// TODO(wan@google.com): move the following to a different .h file
+// such that we don't have to run 'pump' every time the code is
+// updated.
+namespace testing {
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Various overloads for InvokeArgument<N>().
+//
+// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
+// (0-based) argument, which must be a k-ary callable, of the mock
+// function, with arguments a1, a2, ..., a_k.
+//
+// Notes:
+//
+//   1. The arguments are passed by value by default.  If you need to
+//   pass an argument by reference, wrap it inside ByRef().  For
+//   example,
+//
+//     InvokeArgument<1>(5, string("Hello"), ByRef(foo))
+//
+//   passes 5 and string("Hello") by value, and passes foo by
+//   reference.
+//
+//   2. If the callable takes an argument by reference but ByRef() is
+//   not used, it will receive the reference to a copy of the value,
+//   instead of the original value.  For example, when the 0-th
+//   argument of the mock function takes a const string&, the action
+//
+//     InvokeArgument<0>(string("Hello"))
+//
+//   makes a copy of the temporary string("Hello") object and passes a
+//   reference of the copy, instead of the original temporary object,
+//   to the callable.  This makes it easy for a user to define an
+//   InvokeArgument action from temporary values and have it performed
+//   later.
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args));
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(p0)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+// Various overloads for ReturnNew<T>().
+//
+// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
+// instance of type T, constructed on the heap with constructor arguments
+// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_0_VALUE_PARAMS()) {
+  return new T();
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_1_VALUE_PARAMS(p0)) {
+  return new T(p0);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  return new T(p0, p1);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  return new T(p0, p1, p2);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  return new T(p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  return new T(p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  return new T(p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h b/src/external/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h
new file mode 100644 (file)
index 0000000..509d46c
--- /dev/null
@@ -0,0 +1,929 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-function-mockers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements function mockers of various arities.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+class FunctionMockerBase;
+
+// Note: class FunctionMocker really belongs to the ::testing
+// namespace.  However if we define it in ::testing, MSVC will
+// complain when classes in ::testing::internal declare it as a
+// friend class template.  To workaround this compiler bug, we define
+// FunctionMocker in ::testing::internal and import it into ::testing.
+template <typename F>
+class FunctionMocker;
+
+template <typename R>
+class FunctionMocker<R()> : public
+    internal::FunctionMockerBase<R()> {
+ public:
+  typedef R F();
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With() {
+    return this->current_spec();
+  }
+
+  R Invoke() {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple());
+  }
+};
+
+template <typename R, typename A1>
+class FunctionMocker<R(A1)> : public
+    internal::FunctionMockerBase<R(A1)> {
+ public:
+  typedef R F(A1);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class FunctionMocker<R(A1, A2)> : public
+    internal::FunctionMockerBase<R(A1, A2)> {
+ public:
+  typedef R F(A1, A2);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class FunctionMocker<R(A1, A2, A3)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3)> {
+ public:
+  typedef R F(A1, A2, A3);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class FunctionMocker<R(A1, A2, A3, A4)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
+ public:
+  typedef R F(A1, A2, A3, A4);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4,
+        m5));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9, const Matcher<A10>& m10) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9, m10));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9,
+      A10 a10) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10));
+  }
+};
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the FunctionMocker class template
+// is meant to be defined in the ::testing namespace.  The following
+// line is just a trick for working around a bug in MSVC 8.0, which
+// cannot handle it if we define FunctionMocker in ::testing.
+using internal::FunctionMocker;
+
+// The result type of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_RESULT_(tn, F) tn ::testing::internal::Function<F>::Result
+
+// The type of argument N of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_ARG_(tn, F, N) tn ::testing::internal::Function<F>::Argument##N
+
+// The matcher type for argument N of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MATCHER_(tn, F, N) const ::testing::Matcher<GMOCK_ARG_(tn, F, N)>&
+
+// The variable for mocking the given method.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MOCKER_(arity, constness, Method) \
+    GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD0_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method() constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 0, \
+        this_method_does_not_take_0_arguments); \
+    GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method() constness { \
+    GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(0, constness, Method).With(); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD1_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 1, \
+        this_method_does_not_take_1_argument); \
+    GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(1, constness, Method).Invoke(gmock_a1); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
+    GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD2_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 2, \
+        this_method_does_not_take_2_arguments); \
+    GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(2, constness, Method).Invoke(gmock_a1, gmock_a2); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
+    GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD3_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 3, \
+        this_method_does_not_take_3_arguments); \
+    GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(3, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
+    GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD4_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 4, \
+        this_method_does_not_take_4_arguments); \
+    GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(4, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
+    GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD5_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 5, \
+        this_method_does_not_take_5_arguments); \
+    GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(5, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
+    GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD6_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 6, \
+        this_method_does_not_take_6_arguments); \
+    GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(6, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
+    GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD7_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 7, \
+        this_method_does_not_take_7_arguments); \
+    GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(7, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
+    GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD8_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 8, \
+        this_method_does_not_take_8_arguments); \
+    GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(8, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
+    GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD9_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8, \
+                                 GMOCK_ARG_(tn, F, 9) gmock_a9) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 9, \
+        this_method_does_not_take_9_arguments); \
+    GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(9, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
+                     GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
+    GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD10_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8, \
+                                 GMOCK_ARG_(tn, F, 9) gmock_a9, \
+                                 GMOCK_ARG_(tn, F, 10) gmock_a10) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 10, \
+        this_method_does_not_take_10_arguments); \
+    GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(10, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
+                     GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
+                     GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
+    GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
+
+#define MOCK_METHOD0(m, F) GMOCK_METHOD0_(, , , m, F)
+#define MOCK_METHOD1(m, F) GMOCK_METHOD1_(, , , m, F)
+#define MOCK_METHOD2(m, F) GMOCK_METHOD2_(, , , m, F)
+#define MOCK_METHOD3(m, F) GMOCK_METHOD3_(, , , m, F)
+#define MOCK_METHOD4(m, F) GMOCK_METHOD4_(, , , m, F)
+#define MOCK_METHOD5(m, F) GMOCK_METHOD5_(, , , m, F)
+#define MOCK_METHOD6(m, F) GMOCK_METHOD6_(, , , m, F)
+#define MOCK_METHOD7(m, F) GMOCK_METHOD7_(, , , m, F)
+#define MOCK_METHOD8(m, F) GMOCK_METHOD8_(, , , m, F)
+#define MOCK_METHOD9(m, F) GMOCK_METHOD9_(, , , m, F)
+#define MOCK_METHOD10(m, F) GMOCK_METHOD10_(, , , m, F)
+
+#define MOCK_CONST_METHOD0(m, F) GMOCK_METHOD0_(, const, , m, F)
+#define MOCK_CONST_METHOD1(m, F) GMOCK_METHOD1_(, const, , m, F)
+#define MOCK_CONST_METHOD2(m, F) GMOCK_METHOD2_(, const, , m, F)
+#define MOCK_CONST_METHOD3(m, F) GMOCK_METHOD3_(, const, , m, F)
+#define MOCK_CONST_METHOD4(m, F) GMOCK_METHOD4_(, const, , m, F)
+#define MOCK_CONST_METHOD5(m, F) GMOCK_METHOD5_(, const, , m, F)
+#define MOCK_CONST_METHOD6(m, F) GMOCK_METHOD6_(, const, , m, F)
+#define MOCK_CONST_METHOD7(m, F) GMOCK_METHOD7_(, const, , m, F)
+#define MOCK_CONST_METHOD8(m, F) GMOCK_METHOD8_(, const, , m, F)
+#define MOCK_CONST_METHOD9(m, F) GMOCK_METHOD9_(, const, , m, F)
+#define MOCK_CONST_METHOD10(m, F) GMOCK_METHOD10_(, const, , m, F)
+
+#define MOCK_METHOD0_T(m, F) GMOCK_METHOD0_(typename, , , m, F)
+#define MOCK_METHOD1_T(m, F) GMOCK_METHOD1_(typename, , , m, F)
+#define MOCK_METHOD2_T(m, F) GMOCK_METHOD2_(typename, , , m, F)
+#define MOCK_METHOD3_T(m, F) GMOCK_METHOD3_(typename, , , m, F)
+#define MOCK_METHOD4_T(m, F) GMOCK_METHOD4_(typename, , , m, F)
+#define MOCK_METHOD5_T(m, F) GMOCK_METHOD5_(typename, , , m, F)
+#define MOCK_METHOD6_T(m, F) GMOCK_METHOD6_(typename, , , m, F)
+#define MOCK_METHOD7_T(m, F) GMOCK_METHOD7_(typename, , , m, F)
+#define MOCK_METHOD8_T(m, F) GMOCK_METHOD8_(typename, , , m, F)
+#define MOCK_METHOD9_T(m, F) GMOCK_METHOD9_(typename, , , m, F)
+#define MOCK_METHOD10_T(m, F) GMOCK_METHOD10_(typename, , , m, F)
+
+#define MOCK_CONST_METHOD0_T(m, F) GMOCK_METHOD0_(typename, const, , m, F)
+#define MOCK_CONST_METHOD1_T(m, F) GMOCK_METHOD1_(typename, const, , m, F)
+#define MOCK_CONST_METHOD2_T(m, F) GMOCK_METHOD2_(typename, const, , m, F)
+#define MOCK_CONST_METHOD3_T(m, F) GMOCK_METHOD3_(typename, const, , m, F)
+#define MOCK_CONST_METHOD4_T(m, F) GMOCK_METHOD4_(typename, const, , m, F)
+#define MOCK_CONST_METHOD5_T(m, F) GMOCK_METHOD5_(typename, const, , m, F)
+#define MOCK_CONST_METHOD6_T(m, F) GMOCK_METHOD6_(typename, const, , m, F)
+#define MOCK_CONST_METHOD7_T(m, F) GMOCK_METHOD7_(typename, const, , m, F)
+#define MOCK_CONST_METHOD8_T(m, F) GMOCK_METHOD8_(typename, const, , m, F)
+#define MOCK_CONST_METHOD9_T(m, F) GMOCK_METHOD9_(typename, const, , m, F)
+#define MOCK_CONST_METHOD10_T(m, F) GMOCK_METHOD10_(typename, const, , m, F)
+
+#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD0_(, , ct, m, F)
+#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD1_(, , ct, m, F)
+#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD2_(, , ct, m, F)
+#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD3_(, , ct, m, F)
+#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD4_(, , ct, m, F)
+#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD5_(, , ct, m, F)
+#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD6_(, , ct, m, F)
+#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD7_(, , ct, m, F)
+#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD8_(, , ct, m, F)
+#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD9_(, , ct, m, F)
+#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD10_(, , ct, m, F)
+
+#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(, const, ct, m, F)
+#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(, const, ct, m, F)
+#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(, const, ct, m, F)
+#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(, const, ct, m, F)
+#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(, const, ct, m, F)
+#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(, const, ct, m, F)
+#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(, const, ct, m, F)
+#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(, const, ct, m, F)
+#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(, const, ct, m, F)
+#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(, const, ct, m, F)
+#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(, const, ct, m, F)
+
+#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(typename, , ct, m, F)
+#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(typename, , ct, m, F)
+#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(typename, , ct, m, F)
+#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(typename, , ct, m, F)
+#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(typename, , ct, m, F)
+#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(typename, , ct, m, F)
+#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(typename, , ct, m, F)
+#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(typename, , ct, m, F)
+#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(typename, , ct, m, F)
+#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(typename, , ct, m, F)
+#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(typename, , ct, m, F)
+
+#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(typename, const, ct, m, F)
+
+// A MockFunction<F> class has one mock method whose type is F.  It is
+// useful when you just want your test code to emit some messages and
+// have Google Mock verify the right messages are sent (and perhaps at
+// the right times).  For example, if you are exercising code:
+//
+//   Foo(1);
+//   Foo(2);
+//   Foo(3);
+//
+// and want to verify that Foo(1) and Foo(3) both invoke
+// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
+//
+// TEST(FooTest, InvokesBarCorrectly) {
+//   MyMock mock;
+//   MockFunction<void(string check_point_name)> check;
+//   {
+//     InSequence s;
+//
+//     EXPECT_CALL(mock, Bar("a"));
+//     EXPECT_CALL(check, Call("1"));
+//     EXPECT_CALL(check, Call("2"));
+//     EXPECT_CALL(mock, Bar("a"));
+//   }
+//   Foo(1);
+//   check.Call("1");
+//   Foo(2);
+//   check.Call("2");
+//   Foo(3);
+// }
+//
+// The expectation spec says that the first Bar("a") must happen
+// before check point "1", the second Bar("a") must happen after check
+// point "2", and nothing should happen between the two check
+// points. The explicit check points make it easy to tell which
+// Bar("a") is called by which call to Foo().
+template <typename F>
+class MockFunction;
+
+template <typename R>
+class MockFunction<R()> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD0_T(Call, R());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0>
+class MockFunction<R(A0)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD1_T(Call, R(A0));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1>
+class MockFunction<R(A0, A1)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD2_T(Call, R(A0, A1));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2>
+class MockFunction<R(A0, A1, A2)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD3_T(Call, R(A0, A1, A2));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+class MockFunction<R(A0, A1, A2, A3)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4>
+class MockFunction<R(A0, A1, A2, A3, A4)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5>
+class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8,
+    typename A9>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-generated-matchers.h b/src/external/gmock-1.6.0/include/gmock/gmock-generated-matchers.h
new file mode 100644 (file)
index 0000000..6feaf1a
--- /dev/null
@@ -0,0 +1,2054 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-matchers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic matchers.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include "gmock/gmock-matchers.h"
+
+namespace testing {
+namespace internal {
+
+// The type of the i-th (0-based) field of Tuple.
+#define GMOCK_FIELD_TYPE_(Tuple, i) \
+    typename ::std::tr1::tuple_element<i, Tuple>::type
+
+// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
+// tuple of type Tuple.  It has two members:
+//
+//   type: a tuple type whose i-th field is the ki-th field of Tuple.
+//   GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
+//
+// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
+//
+//   type is tuple<int, bool>, and
+//   GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
+
+template <class Tuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class TupleFields;
+
+// This generic version is used when there are 10 selectors.
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8, int k9>
+class TupleFields {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8),
+      GMOCK_FIELD_TYPE_(Tuple, k9)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t), get<k9>(t));
+  }
+};
+
+// The following specialization is used for 0 ~ 9 selectors.
+
+template <class Tuple>
+class TupleFields<Tuple, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<> type;
+  static type GetSelectedFields(const Tuple& /* t */) {
+    using ::std::tr1::get;
+    return type();
+  }
+};
+
+template <class Tuple, int k0>
+class TupleFields<Tuple, k0, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1>
+class TupleFields<Tuple, k0, k1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2>
+class TupleFields<Tuple, k0, k1, k2, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3>
+class TupleFields<Tuple, k0, k1, k2, k3, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t));
+  }
+};
+
+#undef GMOCK_FIELD_TYPE_
+
+// Implements the Args() matcher.
+template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+ public:
+  // ArgsTuple may have top-level const or reference modifiers.
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
+  typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5,
+      k6, k7, k8, k9>::type SelectedArgs;
+  typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
+
+  template <typename InnerMatcher>
+  explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
+      : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
+
+  virtual bool MatchAndExplain(ArgsTuple args,
+                               MatchResultListener* listener) const {
+    const SelectedArgs& selected_args = GetSelectedArgs(args);
+    if (!listener->IsInterested())
+      return inner_matcher_.Matches(selected_args);
+
+    PrintIndices(listener->stream());
+    *listener << "are " << PrintToString(selected_args);
+
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(selected_args,
+                                                      &inner_listener);
+    PrintIfNotEmpty(inner_listener.str(), listener->stream());
+    return match;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static SelectedArgs GetSelectedArgs(ArgsTuple args) {
+    return TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8,
+        k9>::GetSelectedFields(args);
+  }
+
+  // Prints the indices of the selected fields.
+  static void PrintIndices(::std::ostream* os) {
+    *os << "whose fields (";
+    const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 };
+    for (int i = 0; i < 10; i++) {
+      if (indices[i] < 0)
+        break;
+
+      if (i >= 1)
+        *os << ", ";
+
+      *os << "#" << indices[i];
+    }
+    *os << ") ";
+  }
+
+  const MonomorphicInnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
+};
+
+template <class InnerMatcher, int k0 = -1, int k1 = -1, int k2 = -1,
+    int k3 = -1, int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1,
+    int k8 = -1, int k9 = -1>
+class ArgsMatcher {
+ public:
+  explicit ArgsMatcher(const InnerMatcher& inner_matcher)
+      : inner_matcher_(inner_matcher) {}
+
+  template <typename ArgsTuple>
+  operator Matcher<ArgsTuple>() const {
+    return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k0, k1, k2, k3, k4, k5,
+        k6, k7, k8, k9>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
+};
+
+// Implements ElementsAre() of 1-10 arguments.
+
+template <typename T1>
+class ElementsAreMatcher1 {
+ public:
+  explicit ElementsAreMatcher1(const T1& e1) : e1_(e1) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    // Nokia's Symbian Compiler has a nasty bug where the object put
+    // in a one-element local array is not destructed when the array
+    // goes out of scope.  This leads to obvious badness as we've
+    // added the linked_ptr in it to our other linked_ptrs list.
+    // Hence we implement ElementsAreMatcher1 specially to avoid using
+    // a local array.
+    const Matcher<const Element&> matcher =
+        MatcherCast<const Element&>(e1_);
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1));
+  }
+
+ private:
+  const T1& e1_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher1);
+};
+
+template <typename T1, typename T2>
+class ElementsAreMatcher2 {
+ public:
+  ElementsAreMatcher2(const T1& e1, const T2& e2) : e1_(e1), e2_(e2) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 2));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher2);
+};
+
+template <typename T1, typename T2, typename T3>
+class ElementsAreMatcher3 {
+ public:
+  ElementsAreMatcher3(const T1& e1, const T2& e2, const T3& e3) : e1_(e1),
+      e2_(e2), e3_(e3) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 3));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher3);
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ElementsAreMatcher4 {
+ public:
+  ElementsAreMatcher4(const T1& e1, const T2& e2, const T3& e3,
+      const T4& e4) : e1_(e1), e2_(e2), e3_(e3), e4_(e4) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 4));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher4);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ElementsAreMatcher5 {
+ public:
+  ElementsAreMatcher5(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 5));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher5);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ElementsAreMatcher6 {
+ public:
+  ElementsAreMatcher6(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6) : e1_(e1), e2_(e2), e3_(e3), e4_(e4),
+      e5_(e5), e6_(e6) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 6));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher6);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ElementsAreMatcher7 {
+ public:
+  ElementsAreMatcher7(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7) : e1_(e1), e2_(e2), e3_(e3),
+      e4_(e4), e5_(e5), e6_(e6), e7_(e7) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 7));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher7);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ElementsAreMatcher8 {
+ public:
+  ElementsAreMatcher8(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8) : e1_(e1),
+      e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6), e7_(e7), e8_(e8) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 8));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher8);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ElementsAreMatcher9 {
+ public:
+  ElementsAreMatcher9(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8,
+      const T9& e9) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6),
+      e7_(e7), e8_(e8), e9_(e9) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+      MatcherCast<const Element&>(e9_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 9));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+  const T9& e9_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher9);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ElementsAreMatcher10 {
+ public:
+  ElementsAreMatcher10(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+      const T10& e10) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6),
+      e7_(e7), e8_(e8), e9_(e9), e10_(e10) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+      MatcherCast<const Element&>(e9_),
+      MatcherCast<const Element&>(e10_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 10));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+  const T9& e9_;
+  const T10& e10_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher10);
+};
+
+}  // namespace internal
+
+// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
+// fields of it matches a_matcher.  C++ doesn't support default
+// arguments for function templates, so we have to overload it.
+template <typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher>(matcher);
+}
+
+template <int k1, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1>(matcher);
+}
+
+template <int k1, int k2, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2>(matcher);
+}
+
+template <int k1, int k2, int k3, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6,
+      k7>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7,
+      k8>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9,
+    k10>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(matcher);
+}
+
+// ElementsAre(e0, e1, ..., e_n) matches an STL-style container with
+// (n + 1) elements, where the i-th element in the container must
+// match the i-th argument in the list.  Each argument of
+// ElementsAre() can be either a value or a matcher.  We support up to
+// 10 arguments.
+//
+// NOTE: Since ElementsAre() cares about the order of the elements, it
+// must not be used with containers whose elements's order is
+// undefined (e.g. hash_map).
+
+inline internal::ElementsAreMatcher0 ElementsAre() {
+  return internal::ElementsAreMatcher0();
+}
+
+template <typename T1>
+inline internal::ElementsAreMatcher1<T1> ElementsAre(const T1& e1) {
+  return internal::ElementsAreMatcher1<T1>(e1);
+}
+
+template <typename T1, typename T2>
+inline internal::ElementsAreMatcher2<T1, T2> ElementsAre(const T1& e1,
+    const T2& e2) {
+  return internal::ElementsAreMatcher2<T1, T2>(e1, e2);
+}
+
+template <typename T1, typename T2, typename T3>
+inline internal::ElementsAreMatcher3<T1, T2, T3> ElementsAre(const T1& e1,
+    const T2& e2, const T3& e3) {
+  return internal::ElementsAreMatcher3<T1, T2, T3>(e1, e2, e3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline internal::ElementsAreMatcher4<T1, T2, T3, T4> ElementsAre(const T1& e1,
+    const T2& e2, const T3& e3, const T4& e4) {
+  return internal::ElementsAreMatcher4<T1, T2, T3, T4>(e1, e2, e3, e4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline internal::ElementsAreMatcher5<T1, T2, T3, T4,
+    T5> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5) {
+  return internal::ElementsAreMatcher5<T1, T2, T3, T4, T5>(e1, e2, e3, e4, e5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+inline internal::ElementsAreMatcher6<T1, T2, T3, T4, T5,
+    T6> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6) {
+  return internal::ElementsAreMatcher6<T1, T2, T3, T4, T5, T6>(e1, e2, e3, e4,
+      e5, e6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+inline internal::ElementsAreMatcher7<T1, T2, T3, T4, T5, T6,
+    T7> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7) {
+  return internal::ElementsAreMatcher7<T1, T2, T3, T4, T5, T6, T7>(e1, e2, e3,
+      e4, e5, e6, e7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+inline internal::ElementsAreMatcher8<T1, T2, T3, T4, T5, T6, T7,
+    T8> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8) {
+  return internal::ElementsAreMatcher8<T1, T2, T3, T4, T5, T6, T7, T8>(e1, e2,
+      e3, e4, e5, e6, e7, e8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+inline internal::ElementsAreMatcher9<T1, T2, T3, T4, T5, T6, T7, T8,
+    T9> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) {
+  return internal::ElementsAreMatcher9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(e1,
+      e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+inline internal::ElementsAreMatcher10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+    T10> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+    const T10& e10) {
+  return internal::ElementsAreMatcher10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+      T10>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
+}
+
+// ElementsAreArray(array) and ElementAreArray(array, count) are like
+// ElementsAre(), except that they take an array of values or
+// matchers.  The former form infers the size of 'array', which must
+// be a static C-style array.  In the latter form, 'array' can either
+// be a static array or a pointer to a dynamically created array.
+
+template <typename T>
+inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
+    const T* first, size_t count) {
+  return internal::ElementsAreArrayMatcher<T>(first, count);
+}
+
+template <typename T, size_t N>
+inline internal::ElementsAreArrayMatcher<T>
+ElementsAreArray(const T (&array)[N]) {
+  return internal::ElementsAreArrayMatcher<T>(array, N);
+}
+
+// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
+// sub-matchers.  AllOf is called fully qualified to prevent ADL from firing.
+
+template <typename Matcher1, typename Matcher2>
+inline internal::BothOfMatcher<Matcher1, Matcher2>
+AllOf(Matcher1 m1, Matcher2 m2) {
+  return internal::BothOfMatcher<Matcher1, Matcher2>(m1, m2);
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    Matcher3> >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, Matcher4> > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    Matcher5> > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, Matcher6> > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    Matcher7> > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, Matcher8> > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, internal::BothOfMatcher<Matcher8,
+    Matcher9> > > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8, m9));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9, typename Matcher10>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, internal::BothOfMatcher<Matcher8,
+    internal::BothOfMatcher<Matcher9, Matcher10> > > > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9, Matcher10 m10) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8, m9,
+      m10));
+}
+
+// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
+// sub-matchers.  AnyOf is called fully qualified to prevent ADL from firing.
+
+template <typename Matcher1, typename Matcher2>
+inline internal::EitherOfMatcher<Matcher1, Matcher2>
+AnyOf(Matcher1 m1, Matcher2 m2) {
+  return internal::EitherOfMatcher<Matcher1, Matcher2>(m1, m2);
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    Matcher3> >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, Matcher4> > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    Matcher5> > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, Matcher6> > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    Matcher7> > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, Matcher8> > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, internal::EitherOfMatcher<Matcher8,
+    Matcher9> > > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8, m9));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9, typename Matcher10>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, internal::EitherOfMatcher<Matcher8,
+    internal::EitherOfMatcher<Matcher9, Matcher10> > > > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9, Matcher10 m10) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8, m9,
+      m10));
+}
+
+}  // namespace testing
+
+
+// The MATCHER* family of macros can be used in a namespace scope to
+// define custom matchers easily.
+//
+// Basic Usage
+// ===========
+//
+// The syntax
+//
+//   MATCHER(name, description_string) { statements; }
+//
+// defines a matcher with the given name that executes the statements,
+// which must return a bool to indicate if the match succeeds.  Inside
+// the statements, you can refer to the value being matched by 'arg',
+// and refer to its type by 'arg_type'.
+//
+// The description string documents what the matcher does, and is used
+// to generate the failure message when the match fails.  Since a
+// MATCHER() is usually defined in a header file shared by multiple
+// C++ source files, we require the description to be a C-string
+// literal to avoid possible side effects.  It can be empty, in which
+// case we'll use the sequence of words in the matcher name as the
+// description.
+//
+// For example:
+//
+//   MATCHER(IsEven, "") { return (arg % 2) == 0; }
+//
+// allows you to write
+//
+//   // Expects mock_foo.Bar(n) to be called where n is even.
+//   EXPECT_CALL(mock_foo, Bar(IsEven()));
+//
+// or,
+//
+//   // Verifies that the value of some_expression is even.
+//   EXPECT_THAT(some_expression, IsEven());
+//
+// If the above assertion fails, it will print something like:
+//
+//   Value of: some_expression
+//   Expected: is even
+//     Actual: 7
+//
+// where the description "is even" is automatically calculated from the
+// matcher name IsEven.
+//
+// Argument Type
+// =============
+//
+// Note that the type of the value being matched (arg_type) is
+// determined by the context in which you use the matcher and is
+// supplied to you by the compiler, so you don't need to worry about
+// declaring it (nor can you).  This allows the matcher to be
+// polymorphic.  For example, IsEven() can be used to match any type
+// where the value of "(arg % 2) == 0" can be implicitly converted to
+// a bool.  In the "Bar(IsEven())" example above, if method Bar()
+// takes an int, 'arg_type' will be int; if it takes an unsigned long,
+// 'arg_type' will be unsigned long; and so on.
+//
+// Parameterizing Matchers
+// =======================
+//
+// Sometimes you'll want to parameterize the matcher.  For that you
+// can use another macro:
+//
+//   MATCHER_P(name, param_name, description_string) { statements; }
+//
+// For example:
+//
+//   MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+//
+// will allow you to write:
+//
+//   EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+//
+// which may lead to this message (assuming n is 10):
+//
+//   Value of: Blah("a")
+//   Expected: has absolute value 10
+//     Actual: -9
+//
+// Note that both the matcher description and its parameter are
+// printed, making the message human-friendly.
+//
+// In the matcher definition body, you can write 'foo_type' to
+// reference the type of a parameter named 'foo'.  For example, in the
+// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
+// 'value_type' to refer to the type of 'value'.
+//
+// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
+// support multi-parameter matchers.
+//
+// Describing Parameterized Matchers
+// =================================
+//
+// The last argument to MATCHER*() is a string-typed expression.  The
+// expression can reference all of the matcher's parameters and a
+// special bool-typed variable named 'negation'.  When 'negation' is
+// false, the expression should evaluate to the matcher's description;
+// otherwise it should evaluate to the description of the negation of
+// the matcher.  For example,
+//
+//   using testing::PrintToString;
+//
+//   MATCHER_P2(InClosedRange, low, hi,
+//       string(negation ? "is not" : "is") + " in range [" +
+//       PrintToString(low) + ", " + PrintToString(hi) + "]") {
+//     return low <= arg && arg <= hi;
+//   }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: is in range [4, 6]
+//   ...
+//   Expected: is not in range [2, 4]
+//
+// If you specify "" as the description, the failure message will
+// contain the sequence of words in the matcher name followed by the
+// parameter values printed as a tuple.  For example,
+//
+//   MATCHER_P2(InClosedRange, low, hi, "") { ... }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: in closed range (4, 6)
+//   ...
+//   Expected: not (in closed range (2, 4))
+//
+// Types of Matcher Parameters
+// ===========================
+//
+// For the purpose of typing, you can view
+//
+//   MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooMatcherPk<p1_type, ..., pk_type>
+//   Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// When you write Foo(v1, ..., vk), the compiler infers the types of
+// the parameters v1, ..., and vk for you.  If you are not happy with
+// the result of the type inference, you can specify the types by
+// explicitly instantiating the template, as in Foo<long, bool>(5,
+// false).  As said earlier, you don't get to (or need to) specify
+// 'arg_type' as that's determined by the context in which the matcher
+// is used.  You can assign the result of expression Foo(p1, ..., pk)
+// to a variable of type FooMatcherPk<p1_type, ..., pk_type>.  This
+// can be useful when composing matchers.
+//
+// While you can instantiate a matcher template with reference types,
+// passing the parameters by pointer usually makes your code more
+// readable.  If, however, you still want to pass a parameter by
+// reference, be aware that in the failure message generated by the
+// matcher you will see the value of the referenced object but not its
+// address.
+//
+// Explaining Match Results
+// ========================
+//
+// Sometimes the matcher description alone isn't enough to explain why
+// the match has failed or succeeded.  For example, when expecting a
+// long string, it can be very helpful to also print the diff between
+// the expected string and the actual one.  To achieve that, you can
+// optionally stream additional information to a special variable
+// named result_listener, whose type is a pointer to class
+// MatchResultListener:
+//
+//   MATCHER_P(EqualsLongString, str, "") {
+//     if (arg == str) return true;
+//
+//     *result_listener << "the difference: "
+///                     << DiffStrings(str, arg);
+//     return false;
+//   }
+//
+// Overloading Matchers
+// ====================
+//
+// You can overload matchers with different numbers of parameters:
+//
+//   MATCHER_P(Blah, a, description_string1) { ... }
+//   MATCHER_P2(Blah, a, b, description_string2) { ... }
+//
+// Caveats
+// =======
+//
+// When defining a new matcher, you should also consider implementing
+// MatcherInterface or using MakePolymorphicMatcher().  These
+// approaches require more work than the MATCHER* macros, but also
+// give you more control on the types of the value being matched and
+// the matcher parameters, which may leads to better compiler error
+// messages when the matcher is used wrong.  They also allow
+// overloading matchers based on parameter types (as opposed to just
+// based on the number of parameters).
+//
+// MATCHER*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using MATCHER*() inside
+// a function.
+//
+// More Information
+// ================
+//
+// To learn more about using these macros, please search for 'MATCHER'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+#define MATCHER(name, description)\
+  class name##Matcher {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl()\
+           {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<>()));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>());\
+    }\
+    name##Matcher() {\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Matcher);\
+  };\
+  inline name##Matcher name() {\
+    return name##Matcher();\
+  }\
+  template <typename arg_type>\
+  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P(name, p0, description)\
+  template <typename p0##_type>\
+  class name##MatcherP {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      explicit gmock_Impl(p0##_type gmock_p0)\
+           : p0(gmock_p0) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type>(p0)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0));\
+    }\
+    name##MatcherP(p0##_type gmock_p0) : p0(gmock_p0) {\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP);\
+  };\
+  template <typename p0##_type>\
+  inline name##MatcherP<p0##_type> name(p0##_type p0) {\
+    return name##MatcherP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P2(name, p0, p1, description)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##MatcherP2 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\
+           : p0(gmock_p0), p1(gmock_p1) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type>(p0, p1)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1));\
+    }\
+    name##MatcherP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP2<p0##_type, \
+      p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P3(name, p0, p1, p2, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##MatcherP3 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type>(p0, p1, \
+                    p2)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2));\
+    }\
+    name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP3<p0##_type, p1##_type, \
+      p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P4(name, p0, p1, p2, p3, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##MatcherP4 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, \
+                    p3##_type>(p0, p1, p2, p3)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3));\
+    }\
+    name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \
+        p1, p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##MatcherP5 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type>(p0, p1, p2, p3, p4)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4));\
+    }\
+    name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##MatcherP6 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5));\
+    }\
+    name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##MatcherP7 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, \
+                    p6)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6));\
+    }\
+    name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##MatcherP8 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, \
+                    p3, p4, p5, p6, p7)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7));\
+    }\
+    name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, \
+      p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##MatcherP9 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, \
+                    p8##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8));\
+    }\
+    name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, p7##_type, \
+      p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##MatcherP10 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8), p9(gmock_p9) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+                    p9##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\
+    }\
+    name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-generated-nice-strict.h b/src/external/gmock-1.6.0/include/gmock/gmock-generated-nice-strict.h
new file mode 100644 (file)
index 0000000..6099e81
--- /dev/null
@@ -0,0 +1,274 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements class templates NiceMock and StrictMock.
+//
+// Given a mock class MockFoo that is created using Google Mock,
+// NiceMock<MockFoo> is a subclass of MockFoo that allows
+// uninteresting calls (i.e. calls to mock methods that have no
+// EXPECT_CALL specs), and StrictMock<MockFoo> is a subclass of
+// MockFoo that treats all uninteresting calls as errors.
+//
+// NiceMock and StrictMock "inherits" the constructors of their
+// respective base class, with up-to 10 arguments.  Therefore you can
+// write NiceMock<MockFoo>(5, "a") to construct a nice mock where
+// MockFoo has a constructor that accepts (int, const char*), for
+// example.
+//
+// A known limitation is that NiceMock<MockFoo> and
+// StrictMock<MockFoo> only works for mock methods defined using the
+// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.  If a
+// mock method is defined in a base class of MockFoo, the "nice" or
+// "strict" modifier may not affect it, depending on the compiler.  In
+// particular, nesting NiceMock and StrictMock is NOT supported.
+//
+// Another known limitation is that the constructors of the base mock
+// cannot have arguments passed by non-const reference, which are
+// banned by the Google C++ style guide anyway.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <class MockClass>
+class NiceMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  NiceMock() {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit NiceMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~NiceMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
+};
+
+template <class MockClass>
+class StrictMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  StrictMock() {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1>
+  explicit StrictMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~StrictMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
+};
+
+// The following specializations catch some (relatively more common)
+// user errors of nesting nice and strict mocks.  They do NOT catch
+// all possible errors.
+
+// These specializations are declared but not defined, as NiceMock and
+// StrictMock cannot be nested.
+template <typename MockClass>
+class NiceMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<StrictMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<StrictMock<MockClass> >;
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-matchers.h b/src/external/gmock-1.6.0/include/gmock/gmock-matchers.h
new file mode 100644 (file)
index 0000000..c21fa51
--- /dev/null
@@ -0,0 +1,3066 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used argument matchers.  More
+// matchers can be defined by the user implementing the
+// MatcherInterface<T> interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+
+#include <algorithm>
+#include <limits>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherImpl that implements the
+//      MatcherInterface<T> interface, and
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherImpl*.
+//
+// The two-level delegation design makes it possible to allow a user
+// to write "v" instead of "Eq(v)" where a Matcher is expected, which
+// is impossible if we pass matchers by pointers.  It also eases
+// ownership management as Matcher objects can now be copied like
+// plain values.
+
+// MatchResultListener is an abstract class.  Its << operator can be
+// used by a matcher to explain why a value matches or doesn't match.
+//
+// TODO(wan@google.com): add method
+//   bool InterestedInWhy(bool result) const;
+// to indicate whether the listener is interested in why the match
+// result is 'result'.
+class MatchResultListener {
+ public:
+  // Creates a listener object with the given underlying ostream.  The
+  // listener does not own the ostream.
+  explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+  virtual ~MatchResultListener() = 0;  // Makes this class abstract.
+
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x) {
+    if (stream_ != NULL)
+      *stream_ << x;
+    return *this;
+  }
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream() { return stream_; }
+
+  // Returns true iff the listener is interested in an explanation of
+  // the match result.  A matcher's MatchAndExplain() method can use
+  // this information to avoid generating the explanation when no one
+  // intends to hear it.
+  bool IsInterested() const { return stream_ != NULL; }
+
+ private:
+  ::std::ostream* const stream_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
+};
+
+inline MatchResultListener::~MatchResultListener() {
+}
+
+// The implementation of a matcher.
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface() {}
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener', in the form of a non-restrictive relative
+  // clause ("which ...", "whose ...", etc) that describes x.  For
+  // example, the MatchAndExplain() method of the Pointee(...) matcher
+  // should generate an explanation like "which points to ...".
+  //
+  // You should override this method when defining a new matcher.
+  //
+  // It's the responsibility of the caller (Google Mock) to guarantee
+  // that 'listener' is not NULL.  This helps to simplify a matcher's
+  // implementation when it doesn't care about the performance, as it
+  // can talk to 'listener' without checking its validity first.
+  // However, in order to implement dummy listeners efficiently,
+  // listener->stream() may be NULL.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.  The function should print
+  // a verb phrase that describes the property a value matching this
+  // matcher should have.  The subject of the verb phrase is the value
+  // being matched.  For example, the DescribeTo() method of the Gt(7)
+  // matcher prints "is greater than 7".
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.  For
+  // example, if the description of this matcher is "is greater than
+  // 7", the negated description could be "is not greater than 7".
+  // You are not required to override this when implementing
+  // MatcherInterface, but it is highly advised so that your matcher
+  // can produce good error messages.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not (";
+    DescribeTo(os);
+    *os << ")";
+  }
+};
+
+namespace internal {
+
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+  DummyMatchResultListener() : MatchResultListener(NULL) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream.  The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+  explicit StreamMatchResultListener(::std::ostream* os)
+      : MatchResultListener(os) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
+};
+
+// A match result listener that stores the explanation in a string.
+class StringMatchResultListener : public MatchResultListener {
+ public:
+  StringMatchResultListener() : MatchResultListener(&ss_) {}
+
+  // Returns the explanation heard so far.
+  internal::string str() const { return ss_.str(); }
+
+ private:
+  ::std::stringstream ss_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener);
+};
+
+// An internal class for implementing Matcher<T>, which will derive
+// from it.  We put functionalities common to all Matcher<T>
+// specializations here to avoid code duplication.
+template <typename T>
+class MatcherBase {
+ public:
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return impl_->MatchAndExplain(x, listener);
+  }
+
+  // Returns true iff this matcher matches x.
+  bool Matches(T x) const {
+    DummyMatchResultListener dummy;
+    return MatchAndExplain(x, &dummy);
+  }
+
+  // Describes this matcher to an ostream.
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the negation of this matcher to an ostream.
+  void DescribeNegationTo(::std::ostream* os) const {
+    impl_->DescribeNegationTo(os);
+  }
+
+  // Explains why x matches, or doesn't match, the matcher.
+  void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    StreamMatchResultListener listener(os);
+    MatchAndExplain(x, &listener);
+  }
+
+ protected:
+  MatcherBase() {}
+
+  // Constructs a matcher from its implementation.
+  explicit MatcherBase(const MatcherInterface<T>* impl)
+      : impl_(impl) {}
+
+  virtual ~MatcherBase() {}
+
+ private:
+  // shared_ptr (util/gtl/shared_ptr.h) and linked_ptr have similar
+  // interfaces.  The former dynamically allocates a chunk of memory
+  // to hold the reference count, while the latter tracks all
+  // references using a circular linked list without allocating
+  // memory.  It has been observed that linked_ptr performs better in
+  // typical scenarios.  However, shared_ptr can out-perform
+  // linked_ptr when there are many more uses of the copy constructor
+  // than the default constructor.
+  //
+  // If performance becomes a problem, we should see if using
+  // shared_ptr helps.
+  ::testing::internal::linked_ptr<const MatcherInterface<T> > impl_;
+};
+
+}  // namespace internal
+
+// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
+// object that can check whether a value of type T matches.  The
+// implementation of Matcher<T> is just a linked_ptr to const
+// MatcherInterface<T>, so copying is fairly cheap.  Don't inherit
+// from Matcher!
+template <typename T>
+class Matcher : public internal::MatcherBase<T> {
+ public:
+  // Constructs a null matcher.  Needed for storing Matcher objects in STL
+  // containers.  A default-constructed matcher is not yet initialized.  You
+  // cannot use it until a valid value has been assigned to it.
+  Matcher() {}
+
+  // Constructs a matcher from its implementation.
+  explicit Matcher(const MatcherInterface<T>* impl)
+      : internal::MatcherBase<T>(impl) {}
+
+  // Implicit constructor here allows people to write
+  // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
+  Matcher(T value);  // NOLINT
+};
+
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a string
+// matcher is expected.
+template <>
+class Matcher<const internal::string&>
+    : public internal::MatcherBase<const internal::string&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const internal::string&>* impl)
+      : internal::MatcherBase<const internal::string&>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+template <>
+class Matcher<internal::string>
+    : public internal::MatcherBase<internal::string> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<internal::string>* impl)
+      : internal::MatcherBase<internal::string>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+// The PolymorphicMatcher class template makes it easy to implement a
+// polymorphic matcher (i.e. a matcher that can match values of more
+// than one type, e.g. Eq(n) and NotNull()).
+//
+// To define a polymorphic matcher, a user should provide an Impl
+// class that has a DescribeTo() method and a DescribeNegationTo()
+// method, and define a member function (or member function template)
+//
+//   bool MatchAndExplain(const Value& value,
+//                        MatchResultListener* listener) const;
+//
+// See the definition of NotNull() for a complete example.
+template <class Impl>
+class PolymorphicMatcher {
+ public:
+  explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
+
+  // Returns a mutable reference to the underlying matcher
+  // implementation object.
+  Impl& mutable_impl() { return impl_; }
+
+  // Returns an immutable reference to the underlying matcher
+  // implementation object.
+  const Impl& impl() const { return impl_; }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new MonomorphicImpl<T>(impl_));
+  }
+
+ private:
+  template <typename T>
+  class MonomorphicImpl : public MatcherInterface<T> {
+   public:
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      impl_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      impl_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return impl_.MatchAndExplain(x, listener);
+    }
+
+   private:
+    const Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher);
+};
+
+// Creates a matcher from its implementation.  This is easier to use
+// than the Matcher<T> constructor as it doesn't require you to
+// explicitly write the template argument, e.g.
+//
+//   MakeMatcher(foo);
+// vs
+//   Matcher<const string&>(foo);
+template <typename T>
+inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
+  return Matcher<T>(impl);
+};
+
+// Creates a polymorphic matcher from its implementation.  This is
+// easier to use than the PolymorphicMatcher<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicMatcher(foo);
+// vs
+//   PolymorphicMatcher<TypeOfFoo>(foo);
+template <class Impl>
+inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
+  return PolymorphicMatcher<Impl>(impl);
+}
+
+// In order to be safe and clear, casting between different matcher
+// types is done explicitly via MatcherCast<T>(m), which takes a
+// matcher m and returns a Matcher<T>.  It compiles only when T can be
+// statically converted to the argument type of m.
+template <typename T, typename M>
+Matcher<T> MatcherCast(M m);
+
+// Implements SafeMatcherCast().
+//
+// We use an intermediate class to do the actual safe casting as Nokia's
+// Symbian compiler cannot decide between
+// template <T, M> ... (M) and
+// template <T, U> ... (const Matcher<U>&)
+// for function templates but can for member function templates.
+template <typename T>
+class SafeMatcherCastImpl {
+ public:
+  // This overload handles polymorphic matchers only since monomorphic
+  // matchers are handled by the next one.
+  template <typename M>
+  static inline Matcher<T> Cast(M polymorphic_matcher) {
+    return Matcher<T>(polymorphic_matcher);
+  }
+
+  // This overload handles monomorphic matchers.
+  //
+  // In general, if type T can be implicitly converted to type U, we can
+  // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
+  // contravariant): just keep a copy of the original Matcher<U>, convert the
+  // argument from type T to U, and then pass it to the underlying Matcher<U>.
+  // The only exception is when U is a reference and T is not, as the
+  // underlying Matcher<U> may be interested in the argument's address, which
+  // is not preserved in the conversion from T to U.
+  template <typename U>
+  static inline Matcher<T> Cast(const Matcher<U>& matcher) {
+    // Enforce that T can be implicitly converted to U.
+    GTEST_COMPILE_ASSERT_((internal::ImplicitlyConvertible<T, U>::value),
+                          T_must_be_implicitly_convertible_to_U);
+    // Enforce that we are not converting a non-reference type T to a reference
+    // type U.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<T>::value || !internal::is_reference<U>::value,
+        cannot_convert_non_referentce_arg_to_reference);
+    // In case both T and U are arithmetic types, enforce that the
+    // conversion is not lossy.
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU;
+    const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
+    const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
+    GTEST_COMPILE_ASSERT_(
+        kTIsOther || kUIsOther ||
+        (internal::LosslessArithmeticConvertible<RawT, RawU>::value),
+        conversion_of_arithmetic_types_must_be_lossless);
+    return MatcherCast<T>(matcher);
+  }
+};
+
+template <typename T, typename M>
+inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) {
+  return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher);
+}
+
+// A<T>() returns a matcher that matches any value of type T.
+template <typename T>
+Matcher<T> A();
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// If the explanation is not empty, prints it to the ostream.
+inline void PrintIfNotEmpty(const internal::string& explanation,
+                            std::ostream* os) {
+  if (explanation != "" && os != NULL) {
+    *os << ", " << explanation;
+  }
+}
+
+// Returns true if the given type name is easy to read by a human.
+// This is used to decide whether printing the type of a value might
+// be helpful.
+inline bool IsReadableTypeName(const string& type_name) {
+  // We consider a type name readable if it's short or doesn't contain
+  // a template or function type.
+  return (type_name.length() <= 20 ||
+          type_name.find_first_of("<(") == string::npos);
+}
+
+// Matches the value against the given matcher, prints the value and explains
+// the match result to the listener. Returns the match result.
+// 'listener' must not be NULL.
+// Value cannot be passed by const reference, because some matchers take a
+// non-const argument.
+template <typename Value, typename T>
+bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
+                          MatchResultListener* listener) {
+  if (!listener->IsInterested()) {
+    // If the listener is not interested, we do not need to construct the
+    // inner explanation.
+    return matcher.Matches(value);
+  }
+
+  StringMatchResultListener inner_listener;
+  const bool match = matcher.MatchAndExplain(value, &inner_listener);
+
+  UniversalPrint(value, listener->stream());
+#if GTEST_HAS_RTTI
+  const string& type_name = GetTypeName<Value>();
+  if (IsReadableTypeName(type_name))
+    *listener->stream() << " (of type " << type_name << ")";
+#endif
+  PrintIfNotEmpty(inner_listener.str(), listener->stream());
+
+  return match;
+}
+
+// An internal helper class for doing compile-time loop on a tuple's
+// fields.
+template <size_t N>
+class TuplePrefix {
+ public:
+  // TuplePrefix<N>::Matches(matcher_tuple, value_tuple) returns true
+  // iff the first N fields of matcher_tuple matches the first N
+  // fields of value_tuple, respectively.
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& matcher_tuple,
+                      const ValueTuple& value_tuple) {
+    using ::std::tr1::get;
+    return TuplePrefix<N - 1>::Matches(matcher_tuple, value_tuple)
+        && get<N - 1>(matcher_tuple).Matches(get<N - 1>(value_tuple));
+  }
+
+  // TuplePrefix<N>::ExplainMatchFailuresTo(matchers, values, os)
+  // describes failures in matching the first N fields of matchers
+  // against the first N fields of values.  If there is no failure,
+  // nothing will be streamed to os.
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& matchers,
+                                     const ValueTuple& values,
+                                     ::std::ostream* os) {
+    using ::std::tr1::tuple_element;
+    using ::std::tr1::get;
+
+    // First, describes failures in the first N - 1 fields.
+    TuplePrefix<N - 1>::ExplainMatchFailuresTo(matchers, values, os);
+
+    // Then describes the failure (if any) in the (N - 1)-th (0-based)
+    // field.
+    typename tuple_element<N - 1, MatcherTuple>::type matcher =
+        get<N - 1>(matchers);
+    typedef typename tuple_element<N - 1, ValueTuple>::type Value;
+    Value value = get<N - 1>(values);
+    StringMatchResultListener listener;
+    if (!matcher.MatchAndExplain(value, &listener)) {
+      // TODO(wan): include in the message the name of the parameter
+      // as used in MOCK_METHOD*() when possible.
+      *os << "  Expected arg #" << N - 1 << ": ";
+      get<N - 1>(matchers).DescribeTo(os);
+      *os << "\n           Actual: ";
+      // We remove the reference in type Value to prevent the
+      // universal printer from printing the address of value, which
+      // isn't interesting to the user most of the time.  The
+      // matcher's MatchAndExplain() method handles the case when
+      // the address is interesting.
+      internal::UniversalPrint(value, os);
+      PrintIfNotEmpty(listener.str(), os);
+      *os << "\n";
+    }
+  }
+};
+
+// The base case.
+template <>
+class TuplePrefix<0> {
+ public:
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& /* matcher_tuple */,
+                      const ValueTuple& /* value_tuple */) {
+    return true;
+  }
+
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */,
+                                     const ValueTuple& /* values */,
+                                     ::std::ostream* /* os */) {}
+};
+
+// TupleMatches(matcher_tuple, value_tuple) returns true iff all
+// matchers in matcher_tuple match the corresponding fields in
+// value_tuple.  It is a compiler error if matcher_tuple and
+// value_tuple have different number of fields or incompatible field
+// types.
+template <typename MatcherTuple, typename ValueTuple>
+bool TupleMatches(const MatcherTuple& matcher_tuple,
+                  const ValueTuple& value_tuple) {
+  using ::std::tr1::tuple_size;
+  // Makes sure that matcher_tuple and value_tuple have the same
+  // number of fields.
+  GTEST_COMPILE_ASSERT_(tuple_size<MatcherTuple>::value ==
+                        tuple_size<ValueTuple>::value,
+                        matcher_and_value_have_different_numbers_of_fields);
+  return TuplePrefix<tuple_size<ValueTuple>::value>::
+      Matches(matcher_tuple, value_tuple);
+}
+
+// Describes failures in matching matchers against values.  If there
+// is no failure, nothing will be streamed to os.
+template <typename MatcherTuple, typename ValueTuple>
+void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
+                                const ValueTuple& values,
+                                ::std::ostream* os) {
+  using ::std::tr1::tuple_size;
+  TuplePrefix<tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo(
+      matchers, values, os);
+}
+
+// The MatcherCastImpl class template is a helper for implementing
+// MatcherCast().  We need this helper in order to partially
+// specialize the implementation of MatcherCast() (C++ allows
+// class/struct templates to be partially specialized, but not
+// function templates.).
+
+// This general version is used when MatcherCast()'s argument is a
+// polymorphic matcher (i.e. something that can be converted to a
+// Matcher but is not one yet; for example, Eq(value)).
+template <typename T, typename M>
+class MatcherCastImpl {
+ public:
+  static Matcher<T> Cast(M polymorphic_matcher) {
+    return Matcher<T>(polymorphic_matcher);
+  }
+};
+
+// This more specialized version is used when MatcherCast()'s argument
+// is already a Matcher.  This only compiles when type T can be
+// statically converted to type U.
+template <typename T, typename U>
+class MatcherCastImpl<T, Matcher<U> > {
+ public:
+  static Matcher<T> Cast(const Matcher<U>& source_matcher) {
+    return Matcher<T>(new Impl(source_matcher));
+  }
+
+ private:
+  class Impl : public MatcherInterface<T> {
+   public:
+    explicit Impl(const Matcher<U>& source_matcher)
+        : source_matcher_(source_matcher) {}
+
+    // We delegate the matching logic to the source matcher.
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      source_matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      source_matcher_.DescribeNegationTo(os);
+    }
+
+   private:
+    const Matcher<U> source_matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+};
+
+// This even more specialized version is used for efficiently casting
+// a matcher to its own type.
+template <typename T>
+class MatcherCastImpl<T, Matcher<T> > {
+ public:
+  static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
+};
+
+// Implements A<T>().
+template <typename T>
+class AnyMatcherImpl : public MatcherInterface<T> {
+ public:
+  virtual bool MatchAndExplain(
+      T /* x */, MatchResultListener* /* listener */) const { return true; }
+  virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; }
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    // This is mostly for completeness' safe, as it's not very useful
+    // to write Not(A<bool>()).  However we cannot completely rule out
+    // such a possibility, and it doesn't hurt to be prepared.
+    *os << "never matches";
+  }
+};
+
+// Implements _, a matcher that matches any value of any
+// type.  This is a polymorphic matcher, so we need a template type
+// conversion operator to make it appearing as a Matcher<T> for any
+// type T.
+class AnythingMatcher {
+ public:
+  template <typename T>
+  operator Matcher<T>() const { return A<T>(); }
+};
+
+// Implements a matcher that compares a given value with a
+// pre-supplied value using one of the ==, <=, <, etc, operators.  The
+// two values being compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq(5) can be
+// used to match an int, a short, a double, etc).  Therefore we use
+// a template type conversion operator in the implementation.
+//
+// We define this as a macro in order to eliminate duplicated source
+// code.
+//
+// The following template definition assumes that the Rhs parameter is
+// a "bare" type (i.e. neither 'const T' nor 'T&').
+#define GMOCK_IMPLEMENT_COMPARISON_MATCHER_( \
+    name, op, relation, negated_relation) \
+  template <typename Rhs> class name##Matcher { \
+   public: \
+    explicit name##Matcher(const Rhs& rhs) : rhs_(rhs) {} \
+    template <typename Lhs> \
+    operator Matcher<Lhs>() const { \
+      return MakeMatcher(new Impl<Lhs>(rhs_)); \
+    } \
+   private: \
+    template <typename Lhs> \
+    class Impl : public MatcherInterface<Lhs> { \
+     public: \
+      explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \
+      virtual bool MatchAndExplain(\
+          Lhs lhs, MatchResultListener* /* listener */) const { \
+        return lhs op rhs_; \
+      } \
+      virtual void DescribeTo(::std::ostream* os) const { \
+        *os << relation  " "; \
+        UniversalPrint(rhs_, os); \
+      } \
+      virtual void DescribeNegationTo(::std::ostream* os) const { \
+        *os << negated_relation  " "; \
+        UniversalPrint(rhs_, os); \
+      } \
+     private: \
+      Rhs rhs_; \
+      GTEST_DISALLOW_ASSIGN_(Impl); \
+    }; \
+    Rhs rhs_; \
+    GTEST_DISALLOW_ASSIGN_(name##Matcher); \
+  }
+
+// Implements Eq(v), Ge(v), Gt(v), Le(v), Lt(v), and Ne(v)
+// respectively.
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Eq, ==, "is equal to", "isn't equal to");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Ge, >=, "is >=", "isn't >=");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Gt, >, "is >", "isn't >");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Le, <=, "is <=", "isn't <=");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Lt, <, "is <", "isn't <");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Ne, !=, "isn't equal to", "is equal to");
+
+#undef GMOCK_IMPLEMENT_COMPARISON_MATCHER_
+
+// Implements the polymorphic IsNull() matcher, which matches any raw or smart
+// pointer that is NULL.
+class IsNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return GetRawPointer(p) == NULL;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "is NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "isn't NULL";
+  }
+};
+
+// Implements the polymorphic NotNull() matcher, which matches any raw or smart
+// pointer that is not NULL.
+class NotNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return GetRawPointer(p) != NULL;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is NULL";
+  }
+};
+
+// Ref(variable) matches any argument that is a reference to
+// 'variable'.  This matcher is polymorphic as it can match any
+// super type of the type of 'variable'.
+//
+// The RefMatcher template class implements Ref(variable).  It can
+// only be instantiated with a reference type.  This prevents a user
+// from mistakenly using Ref(x) to match a non-reference function
+// argument.  For example, the following will righteously cause a
+// compiler error:
+//
+//   int n;
+//   Matcher<int> m1 = Ref(n);   // This won't compile.
+//   Matcher<int&> m2 = Ref(n);  // This will compile.
+template <typename T>
+class RefMatcher;
+
+template <typename T>
+class RefMatcher<T&> {
+  // Google Mock is a generic framework and thus needs to support
+  // mocking any function types, including those that take non-const
+  // reference arguments.  Therefore the template parameter T (and
+  // Super below) can be instantiated to either a const type or a
+  // non-const type.
+ public:
+  // RefMatcher() takes a T& instead of const T&, as we want the
+  // compiler to catch using Ref(const_value) as a matcher for a
+  // non-const reference.
+  explicit RefMatcher(T& x) : object_(x) {}  // NOLINT
+
+  template <typename Super>
+  operator Matcher<Super&>() const {
+    // By passing object_ (type T&) to Impl(), which expects a Super&,
+    // we make sure that Super is a super type of T.  In particular,
+    // this catches using Ref(const_value) as a matcher for a
+    // non-const reference, as you cannot implicitly convert a const
+    // reference to a non-const reference.
+    return MakeMatcher(new Impl<Super>(object_));
+  }
+
+ private:
+  template <typename Super>
+  class Impl : public MatcherInterface<Super&> {
+   public:
+    explicit Impl(Super& x) : object_(x) {}  // NOLINT
+
+    // MatchAndExplain() takes a Super& (as opposed to const Super&)
+    // in order to match the interface MatcherInterface<Super&>.
+    virtual bool MatchAndExplain(
+        Super& x, MatchResultListener* listener) const {
+      *listener << "which is located @" << static_cast<const void*>(&x);
+      return &x == &object_;
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "references the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not reference the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+   private:
+    const Super& object_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& object_;
+
+  GTEST_DISALLOW_ASSIGN_(RefMatcher);
+};
+
+// Polymorphic helper functions for narrow and wide string matchers.
+inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) {
+  return String::CaseInsensitiveCStringEquals(lhs, rhs);
+}
+
+inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs,
+                                         const wchar_t* rhs) {
+  return String::CaseInsensitiveWideCStringEquals(lhs, rhs);
+}
+
+// String comparison for narrow or wide strings that can have embedded NUL
+// characters.
+template <typename StringType>
+bool CaseInsensitiveStringEquals(const StringType& s1,
+                                 const StringType& s2) {
+  // Are the heads equal?
+  if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) {
+    return false;
+  }
+
+  // Skip the equal heads.
+  const typename StringType::value_type nul = 0;
+  const size_t i1 = s1.find(nul), i2 = s2.find(nul);
+
+  // Are we at the end of either s1 or s2?
+  if (i1 == StringType::npos || i2 == StringType::npos) {
+    return i1 == i2;
+  }
+
+  // Are the tails equal?
+  return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1));
+}
+
+// String matchers.
+
+// Implements equality-based string matchers like StrEq, StrCaseNe, and etc.
+template <typename StringType>
+class StrEqualityMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  StrEqualityMatcher(const StringType& str, bool expect_eq,
+                     bool case_sensitive)
+      : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
+
+  // When expect_eq_ is true, returns true iff s is equal to string_;
+  // otherwise returns true iff s is not equal to string_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    if (s == NULL) {
+      return !expect_eq_;
+    }
+    return MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    const bool eq = case_sensitive_ ? s == string_ :
+        CaseInsensitiveStringEquals(s, string_);
+    return expect_eq_ == eq;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    DescribeToHelper(expect_eq_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    DescribeToHelper(!expect_eq_, os);
+  }
+
+ private:
+  void DescribeToHelper(bool expect_eq, ::std::ostream* os) const {
+    *os << (expect_eq ? "is " : "isn't ");
+    *os << "equal to ";
+    if (!case_sensitive_) {
+      *os << "(ignoring case) ";
+    }
+    UniversalPrint(string_, os);
+  }
+
+  const StringType string_;
+  const bool expect_eq_;
+  const bool case_sensitive_;
+
+  GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher);
+};
+
+// Implements the polymorphic HasSubstr(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class HasSubstrMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit HasSubstrMatcher(const StringType& substring)
+      : substring_(substring) {}
+
+  // These overloaded methods allow HasSubstr(substring) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s contains substring_ as a substring.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.find(substring_) != StringType::npos;
+  }
+
+  // Describes what this matcher matches.
+  void DescribeTo(::std::ostream* os) const {
+    *os << "has substring ";
+    UniversalPrint(substring_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has no substring ";
+    UniversalPrint(substring_, os);
+  }
+
+ private:
+  const StringType substring_;
+
+  GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher);
+};
+
+// Implements the polymorphic StartsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class StartsWithMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {
+  }
+
+  // These overloaded methods allow StartsWith(prefix) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s starts with prefix_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.length() >= prefix_.length() &&
+        s.substr(0, prefix_.length()) == prefix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "starts with ";
+    UniversalPrint(prefix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't start with ";
+    UniversalPrint(prefix_, os);
+  }
+
+ private:
+  const StringType prefix_;
+
+  GTEST_DISALLOW_ASSIGN_(StartsWithMatcher);
+};
+
+// Implements the polymorphic EndsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class EndsWithMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
+
+  // These overloaded methods allow EndsWith(suffix) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s ends with suffix_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.length() >= suffix_.length() &&
+        s.substr(s.length() - suffix_.length()) == suffix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "ends with ";
+    UniversalPrint(suffix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't end with ";
+    UniversalPrint(suffix_, os);
+  }
+
+ private:
+  const StringType suffix_;
+
+  GTEST_DISALLOW_ASSIGN_(EndsWithMatcher);
+};
+
+// Implements polymorphic matchers MatchesRegex(regex) and
+// ContainsRegex(regex), which can be used as a Matcher<T> as long as
+// T can be converted to a string.
+class MatchesRegexMatcher {
+ public:
+  MatchesRegexMatcher(const RE* regex, bool full_match)
+      : regex_(regex), full_match_(full_match) {}
+
+  // These overloaded methods allow MatchesRegex(regex) to be used as
+  // a Matcher<T> as long as T can be converted to string.  Returns
+  // true iff s matches regular expression regex.  When full_match_ is
+  // true, a full match is done; otherwise a partial match is done.
+  bool MatchAndExplain(const char* s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(internal::string(s), listener);
+  }
+
+  bool MatchAndExplain(const internal::string& s,
+                       MatchResultListener* /* listener */) const {
+    return full_match_ ? RE::FullMatch(s, *regex_) :
+        RE::PartialMatch(s, *regex_);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << (full_match_ ? "matches" : "contains")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't " << (full_match_ ? "match" : "contain")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+ private:
+  const internal::linked_ptr<const RE> regex_;
+  const bool full_match_;
+
+  GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher);
+};
+
+// Implements a matcher that compares the two fields of a 2-tuple
+// using one of the ==, <=, <, etc, operators.  The two fields being
+// compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq() can be
+// used to match a tuple<int, short>, a tuple<const long&, double>,
+// etc).  Therefore we use a template type conversion operator in the
+// implementation.
+//
+// We define this as a macro in order to eliminate duplicated source
+// code.
+#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op, relation) \
+  class name##2Matcher { \
+   public: \
+    template <typename T1, typename T2> \
+    operator Matcher< ::std::tr1::tuple<T1, T2> >() const { \
+      return MakeMatcher(new Impl< ::std::tr1::tuple<T1, T2> >); \
+    } \
+    template <typename T1, typename T2> \
+    operator Matcher<const ::std::tr1::tuple<T1, T2>&>() const { \
+      return MakeMatcher(new Impl<const ::std::tr1::tuple<T1, T2>&>); \
+    } \
+   private: \
+    template <typename Tuple> \
+    class Impl : public MatcherInterface<Tuple> { \
+     public: \
+      virtual bool MatchAndExplain( \
+          Tuple args, \
+          MatchResultListener* /* listener */) const { \
+        return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \
+      } \
+      virtual void DescribeTo(::std::ostream* os) const { \
+        *os << "are " relation;                                 \
+      } \
+      virtual void DescribeNegationTo(::std::ostream* os) const { \
+        *os << "aren't " relation; \
+      } \
+    }; \
+  }
+
+// Implements Eq(), Ge(), Gt(), Le(), Lt(), and Ne() respectively.
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==, "an equal pair");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Ge, >=, "a pair where the first >= the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Gt, >, "a pair where the first > the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Le, <=, "a pair where the first <= the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Lt, <, "a pair where the first < the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=, "an unequal pair");
+
+#undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
+
+// Implements the Not(...) matcher for a particular argument type T.
+// We do not nest it inside the NotMatcher class template, as that
+// will prevent different instantiations of NotMatcher from sharing
+// the same NotMatcherImpl<T> class.
+template <typename T>
+class NotMatcherImpl : public MatcherInterface<T> {
+ public:
+  explicit NotMatcherImpl(const Matcher<T>& matcher)
+      : matcher_(matcher) {}
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return !matcher_.MatchAndExplain(x, listener);
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    matcher_.DescribeNegationTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<T> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcherImpl);
+};
+
+// Implements the Not(m) matcher, which matches a value that doesn't
+// match matcher m.
+template <typename InnerMatcher>
+class NotMatcher {
+ public:
+  explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {}
+
+  // This template type conversion operator allows Not(m) to be used
+  // to match any type m can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
+  }
+
+ private:
+  InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcher);
+};
+
+// Implements the AllOf(m1, m2) matcher for a particular argument type
+// T. We do not nest it inside the BothOfMatcher class template, as
+// that will prevent different instantiations of BothOfMatcher from
+// sharing the same BothOfMatcherImpl<T> class.
+template <typename T>
+class BothOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") and (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") or (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ doesn't match x, we only need
+    // to explain why one of them fails.
+    StringMatchResultListener listener1;
+    if (!matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return false;
+    }
+
+    StringMatchResultListener listener2;
+    if (!matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return false;
+    }
+
+    // Otherwise we need to explain why *both* of them match.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return true;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl);
+};
+
+// Used for implementing the AllOf(m_1, ..., m_n) matcher, which
+// matches a value that matches all of the matchers m_1, ..., and m_n.
+template <typename Matcher1, typename Matcher2>
+class BothOfMatcher {
+ public:
+  BothOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // BothOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
+                                               SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcher);
+};
+
+// Implements the AnyOf(m1, m2) matcher for a particular argument type
+// T.  We do not nest it inside the AnyOfMatcher class template, as
+// that will prevent different instantiations of AnyOfMatcher from
+// sharing the same EitherOfMatcherImpl<T> class.
+template <typename T>
+class EitherOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") or (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") and (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ matches x, we just need to
+    // explain why *one* of them matches.
+    StringMatchResultListener listener1;
+    if (matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return true;
+    }
+
+    StringMatchResultListener listener2;
+    if (matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return true;
+    }
+
+    // Otherwise we need to explain why *both* of them fail.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return false;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcherImpl);
+};
+
+// Used for implementing the AnyOf(m_1, ..., m_n) matcher, which
+// matches a value that matches at least one of the matchers m_1, ...,
+// and m_n.
+template <typename Matcher1, typename Matcher2>
+class EitherOfMatcher {
+ public:
+  EitherOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // EitherOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new EitherOfMatcherImpl<T>(
+        SafeMatcherCast<T>(matcher1_), SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcher);
+};
+
+// Used for implementing Truly(pred), which turns a predicate into a
+// matcher.
+template <typename Predicate>
+class TrulyMatcher {
+ public:
+  explicit TrulyMatcher(Predicate pred) : predicate_(pred) {}
+
+  // This method template allows Truly(pred) to be used as a matcher
+  // for type T where T is the argument type of predicate 'pred'.  The
+  // argument is passed by reference as the predicate may be
+  // interested in the address of the argument.
+  template <typename T>
+  bool MatchAndExplain(T& x,  // NOLINT
+                       MatchResultListener* /* listener */) const {
+    // Without the if-statement, MSVC sometimes warns about converting
+    // a value to bool (warning 4800).
+    //
+    // We cannot write 'return !!predicate_(x);' as that doesn't work
+    // when predicate_(x) returns a class convertible to bool but
+    // having no operator!().
+    if (predicate_(x))
+      return true;
+    return false;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "satisfies the given predicate";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't satisfy the given predicate";
+  }
+
+ private:
+  Predicate predicate_;
+
+  GTEST_DISALLOW_ASSIGN_(TrulyMatcher);
+};
+
+// Used for implementing Matches(matcher), which turns a matcher into
+// a predicate.
+template <typename M>
+class MatcherAsPredicate {
+ public:
+  explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {}
+
+  // This template operator() allows Matches(m) to be used as a
+  // predicate on type T where m is a matcher on type T.
+  //
+  // The argument x is passed by reference instead of by value, as
+  // some matcher may be interested in its address (e.g. as in
+  // Matches(Ref(n))(x)).
+  template <typename T>
+  bool operator()(const T& x) const {
+    // We let matcher_ commit to a particular type here instead of
+    // when the MatcherAsPredicate object was constructed.  This
+    // allows us to write Matches(m) where m is a polymorphic matcher
+    // (e.g. Eq(5)).
+    //
+    // If we write Matcher<T>(matcher_).Matches(x) here, it won't
+    // compile when matcher_ has type Matcher<const T&>; if we write
+    // Matcher<const T&>(matcher_).Matches(x) here, it won't compile
+    // when matcher_ has type Matcher<T>; if we just write
+    // matcher_.Matches(x), it won't compile when matcher_ is
+    // polymorphic, e.g. Eq(5).
+    //
+    // MatcherCast<const T&>() is necessary for making the code work
+    // in all of the above situations.
+    return MatcherCast<const T&>(matcher_).Matches(x);
+  }
+
+ private:
+  M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(MatcherAsPredicate);
+};
+
+// For implementing ASSERT_THAT() and EXPECT_THAT().  The template
+// argument M must be a type that can be converted to a matcher.
+template <typename M>
+class PredicateFormatterFromMatcher {
+ public:
+  explicit PredicateFormatterFromMatcher(const M& m) : matcher_(m) {}
+
+  // This template () operator allows a PredicateFormatterFromMatcher
+  // object to act as a predicate-formatter suitable for using with
+  // Google Test's EXPECT_PRED_FORMAT1() macro.
+  template <typename T>
+  AssertionResult operator()(const char* value_text, const T& x) const {
+    // We convert matcher_ to a Matcher<const T&> *now* instead of
+    // when the PredicateFormatterFromMatcher object was constructed,
+    // as matcher_ may be polymorphic (e.g. NotNull()) and we won't
+    // know which type to instantiate it to until we actually see the
+    // type of x here.
+    //
+    // We write MatcherCast<const T&>(matcher_) instead of
+    // Matcher<const T&>(matcher_), as the latter won't compile when
+    // matcher_ has type Matcher<T> (e.g. An<int>()).
+    const Matcher<const T&> matcher = MatcherCast<const T&>(matcher_);
+    StringMatchResultListener listener;
+    if (MatchPrintAndExplain(x, matcher, &listener))
+      return AssertionSuccess();
+
+    ::std::stringstream ss;
+    ss << "Value of: " << value_text << "\n"
+       << "Expected: ";
+    matcher.DescribeTo(&ss);
+    ss << "\n  Actual: " << listener.str();
+    return AssertionFailure() << ss.str();
+  }
+
+ private:
+  const M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PredicateFormatterFromMatcher);
+};
+
+// A helper function for converting a matcher to a predicate-formatter
+// without the user needing to explicitly write the type.  This is
+// used for implementing ASSERT_THAT() and EXPECT_THAT().
+template <typename M>
+inline PredicateFormatterFromMatcher<M>
+MakePredicateFormatterFromMatcher(const M& matcher) {
+  return PredicateFormatterFromMatcher<M>(matcher);
+}
+
+// Implements the polymorphic floating point equality matcher, which
+// matches two float values using ULP-based approximation.  The
+// template is meant to be instantiated with FloatType being either
+// float or double.
+template <typename FloatType>
+class FloatingEqMatcher {
+ public:
+  // Constructor for FloatingEqMatcher.
+  // The matcher's input will be compared with rhs.  The matcher treats two
+  // NANs as equal if nan_eq_nan is true.  Otherwise, under IEEE standards,
+  // equality comparisons between NANs will always return false.
+  FloatingEqMatcher(FloatType rhs, bool nan_eq_nan) :
+    rhs_(rhs), nan_eq_nan_(nan_eq_nan) {}
+
+  // Implements floating point equality matcher as a Matcher<T>.
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(FloatType rhs, bool nan_eq_nan) :
+      rhs_(rhs), nan_eq_nan_(nan_eq_nan) {}
+
+    virtual bool MatchAndExplain(T value,
+                                 MatchResultListener* /* listener */) const {
+      const FloatingPoint<FloatType> lhs(value), rhs(rhs_);
+
+      // Compares NaNs first, if nan_eq_nan_ is true.
+      if (nan_eq_nan_ && lhs.is_nan()) {
+        return rhs.is_nan();
+      }
+
+      return lhs.AlmostEquals(rhs);
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      // os->precision() returns the previously set precision, which we
+      // store to restore the ostream to its original configuration
+      // after outputting.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(rhs_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "is NaN";
+        } else {
+          *os << "never matches";
+        }
+      } else {
+        *os << "is approximately " << rhs_;
+      }
+      os->precision(old_precision);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      // As before, get original precision.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(rhs_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "isn't NaN";
+        } else {
+          *os << "is anything";
+        }
+      } else {
+        *os << "isn't approximately " << rhs_;
+      }
+      // Restore original precision.
+      os->precision(old_precision);
+    }
+
+   private:
+    const FloatType rhs_;
+    const bool nan_eq_nan_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  // The following 3 type conversion operators allow FloatEq(rhs) and
+  // NanSensitiveFloatEq(rhs) to be used as a Matcher<float>, a
+  // Matcher<const float&>, or a Matcher<float&>, but nothing else.
+  // (While Google's C++ coding style doesn't allow arguments passed
+  // by non-const reference, we may see them in code not conforming to
+  // the style.  Therefore Google Mock needs to support them.)
+  operator Matcher<FloatType>() const {
+    return MakeMatcher(new Impl<FloatType>(rhs_, nan_eq_nan_));
+  }
+
+  operator Matcher<const FloatType&>() const {
+    return MakeMatcher(new Impl<const FloatType&>(rhs_, nan_eq_nan_));
+  }
+
+  operator Matcher<FloatType&>() const {
+    return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_));
+  }
+ private:
+  const FloatType rhs_;
+  const bool nan_eq_nan_;
+
+  GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher);
+};
+
+// Implements the Pointee(m) matcher for matching a pointer whose
+// pointee matches matcher m.  The pointer can be either raw or smart.
+template <typename InnerMatcher>
+class PointeeMatcher {
+ public:
+  explicit PointeeMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+  // This type conversion operator template allows Pointee(m) to be
+  // used as a matcher for any pointer type whose pointee type is
+  // compatible with the inner matcher, where type Pointer can be
+  // either a raw pointer or a smart pointer.
+  //
+  // The reason we do this instead of relying on
+  // MakePolymorphicMatcher() is that the latter is not flexible
+  // enough for implementing the DescribeTo() method of Pointee().
+  template <typename Pointer>
+  operator Matcher<Pointer>() const {
+    return MakeMatcher(new Impl<Pointer>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular pointer type.
+  template <typename Pointer>
+  class Impl : public MatcherInterface<Pointer> {
+   public:
+    typedef typename PointeeOf<GTEST_REMOVE_CONST_(  // NOLINT
+        GTEST_REMOVE_REFERENCE_(Pointer))>::type Pointee;
+
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<const Pointee&>(matcher)) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "points to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not point to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual bool MatchAndExplain(Pointer pointer,
+                                 MatchResultListener* listener) const {
+      if (GetRawPointer(pointer) == NULL)
+        return false;
+
+      *listener << "which points to ";
+      return MatchPrintAndExplain(*pointer, matcher_, listener);
+    }
+
+   private:
+    const Matcher<const Pointee&> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PointeeMatcher);
+};
+
+// Implements the Field() matcher for matching a field (i.e. member
+// variable) of an object.
+template <typename Class, typename FieldType>
+class FieldMatcher {
+ public:
+  FieldMatcher(FieldType Class::*field,
+               const Matcher<const FieldType&>& matcher)
+      : field_(field), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Field() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given field is ";
+    return MatchPrintAndExplain(obj.*field_, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a field, it must be a class/struct/union type and
+    // thus cannot be a pointer.  Therefore we pass false_type() as
+    // the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  const FieldType Class::*field_;
+  const Matcher<const FieldType&> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(FieldMatcher);
+};
+
+// Implements the Property() matcher for matching a property
+// (i.e. return value of a getter method) of an object.
+template <typename Class, typename PropertyType>
+class PropertyMatcher {
+ public:
+  // The property may have a reference type, so 'const PropertyType&'
+  // may cause double references and fail to compile.  That's why we
+  // need GTEST_REFERENCE_TO_CONST, which works regardless of
+  // PropertyType being a reference or not.
+  typedef GTEST_REFERENCE_TO_CONST_(PropertyType) RefToConstProperty;
+
+  PropertyMatcher(PropertyType (Class::*property)() const,
+                  const Matcher<RefToConstProperty>& matcher)
+      : property_(property), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T&value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Property() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given property is ";
+    // Cannot pass the return value (for example, int) to MatchPrintAndExplain,
+    // which takes a non-const reference as argument.
+    RefToConstProperty result = (obj.*property_)();
+    return MatchPrintAndExplain(result, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a property method, it must be a class/struct/union
+    // type and thus cannot be a pointer.  Therefore we pass
+    // false_type() as the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  PropertyType (Class::*property_)() const;
+  const Matcher<RefToConstProperty> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
+};
+
+// Type traits specifying various features of different functors for ResultOf.
+// The default template specifies features for functor objects.
+// Functor classes have to typedef argument_type and result_type
+// to be compatible with ResultOf.
+template <typename Functor>
+struct CallableTraits {
+  typedef typename Functor::result_type ResultType;
+  typedef Functor StorageType;
+
+  static void CheckIsValid(Functor /* functor */) {}
+  template <typename T>
+  static ResultType Invoke(Functor f, T arg) { return f(arg); }
+};
+
+// Specialization for function pointers.
+template <typename ArgType, typename ResType>
+struct CallableTraits<ResType(*)(ArgType)> {
+  typedef ResType ResultType;
+  typedef ResType(*StorageType)(ArgType);
+
+  static void CheckIsValid(ResType(*f)(ArgType)) {
+    GTEST_CHECK_(f != NULL)
+        << "NULL function pointer is passed into ResultOf().";
+  }
+  template <typename T>
+  static ResType Invoke(ResType(*f)(ArgType), T arg) {
+    return (*f)(arg);
+  }
+};
+
+// Implements the ResultOf() matcher for matching a return value of a
+// unary function of an object.
+template <typename Callable>
+class ResultOfMatcher {
+ public:
+  typedef typename CallableTraits<Callable>::ResultType ResultType;
+
+  ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
+      : callable_(callable), matcher_(matcher) {
+    CallableTraits<Callable>::CheckIsValid(callable_);
+  }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new Impl<T>(callable_, matcher_));
+  }
+
+ private:
+  typedef typename CallableTraits<Callable>::StorageType CallableStorageType;
+
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
+        : callable_(callable), matcher_(matcher) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
+      *listener << "which is mapped by the given callable to ";
+      // Cannot pass the return value (for example, int) to
+      // MatchPrintAndExplain, which takes a non-const reference as argument.
+      ResultType result =
+          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
+      return MatchPrintAndExplain(result, matcher_, listener);
+    }
+
+   private:
+    // Functors often define operator() as non-const method even though
+    // they are actualy stateless. But we need to use them even when
+    // 'this' is a const pointer. It's the user's responsibility not to
+    // use stateful callables with ResultOf(), which does't guarantee
+    // how many times the callable will be invoked.
+    mutable CallableStorageType callable_;
+    const Matcher<ResultType> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };  // class Impl
+
+  const CallableStorageType callable_;
+  const Matcher<ResultType> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
+};
+
+// Implements an equality matcher for any STL-style container whose elements
+// support ==. This matcher is like Eq(), but its failure explanations provide
+// more detailed information that is useful when the container is used as a set.
+// The failure message reports elements that are in one of the operands but not
+// the other. The failure messages do not report duplicate or out-of-order
+// elements in the containers (which don't properly matter to sets, but can
+// occur if the containers are vectors or lists, for example).
+//
+// Uses the container's const_iterator, value_type, operator ==,
+// begin(), and end().
+template <typename Container>
+class ContainerEqMatcher {
+ public:
+  typedef internal::StlContainerView<Container> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+
+  // We make a copy of rhs in case the elements in it are modified
+  // after this matcher is created.
+  explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<Container,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>();
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "equals ";
+    UniversalPrint(rhs_, os);
+  }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not equal ";
+    UniversalPrint(rhs_, os);
+  }
+
+  template <typename LhsContainer>
+  bool MatchAndExplain(const LhsContainer& lhs,
+                       MatchResultListener* listener) const {
+    // GTEST_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
+    // that causes LhsContainer to be a const type sometimes.
+    typedef internal::StlContainerView<GTEST_REMOVE_CONST_(LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+    if (lhs_stl_container == rhs_)
+      return true;
+
+    ::std::ostream* const os = listener->stream();
+    if (os != NULL) {
+      // Something is different. Check for extra values first.
+      bool printed_header = false;
+      for (typename LhsStlContainer::const_iterator it =
+               lhs_stl_container.begin();
+           it != lhs_stl_container.end(); ++it) {
+        if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) ==
+            rhs_.end()) {
+          if (printed_header) {
+            *os << ", ";
+          } else {
+            *os << "which has these unexpected elements: ";
+            printed_header = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+
+      // Now check for missing values.
+      bool printed_header2 = false;
+      for (typename StlContainer::const_iterator it = rhs_.begin();
+           it != rhs_.end(); ++it) {
+        if (internal::ArrayAwareFind(
+                lhs_stl_container.begin(), lhs_stl_container.end(), *it) ==
+            lhs_stl_container.end()) {
+          if (printed_header2) {
+            *os << ", ";
+          } else {
+            *os << (printed_header ? ",\nand" : "which")
+                << " doesn't have these expected elements: ";
+            printed_header2 = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  const StlContainer rhs_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
+};
+
+// Implements Pointwise(tuple_matcher, rhs_container).  tuple_matcher
+// must be able to be safely cast to Matcher<tuple<const T1&, const
+// T2&> >, where T1 and T2 are the types of elements in the LHS
+// container and the RHS container respectively.
+template <typename TupleMatcher, typename RhsContainer>
+class PointwiseMatcher {
+ public:
+  typedef internal::StlContainerView<RhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type RhsValue;
+
+  // Like ContainerEq, we make a copy of rhs in case the elements in
+  // it are modified after this matcher is created.
+  PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs)
+      : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<RhsContainer,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>();
+  }
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<
+         GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    typedef typename LhsStlContainer::value_type LhsValue;
+    // We pass the LHS value and the RHS value to the inner matcher by
+    // reference, as they may be expensive to copy.  We must use tuple
+    // instead of pair here, as a pair cannot hold references (C++ 98,
+    // 20.2.2 [lib.pairs]).
+    typedef std::tr1::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg;
+
+    Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs)
+        // mono_tuple_matcher_ holds a monomorphic version of the tuple matcher.
+        : mono_tuple_matcher_(SafeMatcherCast<InnerMatcherArg>(tuple_matcher)),
+          rhs_(rhs) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "contains " << rhs_.size()
+          << " values, where each value and its corresponding value in ";
+      UniversalPrinter<RhsStlContainer>::Print(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeTo(os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "doesn't contain exactly " << rhs_.size()
+          << " values, or contains a value x at some index i"
+          << " where x and the i-th value of ";
+      UniversalPrint(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(LhsContainer lhs,
+                                 MatchResultListener* listener) const {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      const size_t actual_size = lhs_stl_container.size();
+      if (actual_size != rhs_.size()) {
+        *listener << "which contains " << actual_size << " values";
+        return false;
+      }
+
+      typename LhsStlContainer::const_iterator left = lhs_stl_container.begin();
+      typename RhsStlContainer::const_iterator right = rhs_.begin();
+      for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
+        const InnerMatcherArg value_pair(*left, *right);
+
+        if (listener->IsInterested()) {
+          StringMatchResultListener inner_listener;
+          if (!mono_tuple_matcher_.MatchAndExplain(
+                  value_pair, &inner_listener)) {
+            *listener << "where the value pair (";
+            UniversalPrint(*left, listener->stream());
+            *listener << ", ";
+            UniversalPrint(*right, listener->stream());
+            *listener << ") at index #" << i << " don't match";
+            PrintIfNotEmpty(inner_listener.str(), listener->stream());
+            return false;
+          }
+        } else {
+          if (!mono_tuple_matcher_.Matches(value_pair))
+            return false;
+        }
+      }
+
+      return true;
+    }
+
+   private:
+    const Matcher<InnerMatcherArg> mono_tuple_matcher_;
+    const RhsStlContainer rhs_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+ private:
+  const TupleMatcher tuple_matcher_;
+  const RhsStlContainer rhs_;
+
+  GTEST_DISALLOW_ASSIGN_(PointwiseMatcher);
+};
+
+// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
+template <typename Container>
+class QuantifierMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InnerMatcher>
+  explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+           testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+  // Checks whether:
+  // * All elements in the container match, if all_elements_should_match.
+  // * Any element in the container matches, if !all_elements_should_match.
+  bool MatchAndExplainImpl(bool all_elements_should_match,
+                           Container container,
+                           MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    size_t i = 0;
+    for (typename StlContainer::const_iterator it = stl_container.begin();
+         it != stl_container.end(); ++it, ++i) {
+      StringMatchResultListener inner_listener;
+      const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+
+      if (matches != all_elements_should_match) {
+        *listener << "whose element #" << i
+                  << (matches ? " matches" : " doesn't match");
+        PrintIfNotEmpty(inner_listener.str(), listener->stream());
+        return !all_elements_should_match;
+      }
+    }
+    return all_elements_should_match;
+  }
+
+ protected:
+  const Matcher<const Element&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl);
+};
+
+// Implements Contains(element_matcher) for the given argument type Container.
+// Symmetric to EachMatcherImpl.
+template <typename Container>
+class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "contains at least one element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't contain any element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(false, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl);
+};
+
+// Implements Each(element_matcher) for the given argument type Container.
+// Symmetric to ContainsMatcherImpl.
+template <typename Container>
+class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit EachMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "only contains elements that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "contains some element that ";
+    this->inner_matcher_.DescribeNegationTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(true, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(EachMatcherImpl);
+};
+
+// Implements polymorphic Contains(element_matcher).
+template <typename M>
+class ContainsMatcher {
+ public:
+  explicit ContainsMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcher);
+};
+
+// Implements polymorphic Each(element_matcher).
+template <typename M>
+class EachMatcher {
+ public:
+  explicit EachMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(EachMatcher);
+};
+
+// Implements Key(inner_matcher) for the given argument pair type.
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename PairType>
+class KeyMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type KeyType;
+
+  template <typename InnerMatcher>
+  explicit KeyMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+          testing::SafeMatcherCast<const KeyType&>(inner_matcher)) {
+  }
+
+  // Returns true iff 'key_value.first' (the key) matches the inner matcher.
+  virtual bool MatchAndExplain(PairType key_value,
+                               MatchResultListener* listener) const {
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(key_value.first,
+                                                      &inner_listener);
+    const internal::string explanation = inner_listener.str();
+    if (explanation != "") {
+      *listener << "whose first field is a value " << explanation;
+    }
+    return match;
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't have a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<const KeyType&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcherImpl);
+};
+
+// Implements polymorphic Key(matcher_for_key).
+template <typename M>
+class KeyMatcher {
+ public:
+  explicit KeyMatcher(M m) : matcher_for_key_(m) {}
+
+  template <typename PairType>
+  operator Matcher<PairType>() const {
+    return MakeMatcher(new KeyMatcherImpl<PairType>(matcher_for_key_));
+  }
+
+ private:
+  const M matcher_for_key_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcher);
+};
+
+// Implements Pair(first_matcher, second_matcher) for the given argument pair
+// type with its two matchers. See Pair() function below.
+template <typename PairType>
+class PairMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type FirstType;
+  typedef typename RawPairType::second_type SecondType;
+
+  template <typename FirstMatcher, typename SecondMatcher>
+  PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(
+            testing::SafeMatcherCast<const FirstType&>(first_matcher)),
+        second_matcher_(
+            testing::SafeMatcherCast<const SecondType&>(second_matcher)) {
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeTo(os);
+    *os << ", and has a second field that ";
+    second_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeNegationTo(os);
+    *os << ", or has a second field that ";
+    second_matcher_.DescribeNegationTo(os);
+  }
+
+  // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
+  // matches second_matcher.
+  virtual bool MatchAndExplain(PairType a_pair,
+                               MatchResultListener* listener) const {
+    if (!listener->IsInterested()) {
+      // If the listener is not interested, we don't need to construct the
+      // explanation.
+      return first_matcher_.Matches(a_pair.first) &&
+             second_matcher_.Matches(a_pair.second);
+    }
+    StringMatchResultListener first_inner_listener;
+    if (!first_matcher_.MatchAndExplain(a_pair.first,
+                                        &first_inner_listener)) {
+      *listener << "whose first field does not match";
+      PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
+      return false;
+    }
+    StringMatchResultListener second_inner_listener;
+    if (!second_matcher_.MatchAndExplain(a_pair.second,
+                                         &second_inner_listener)) {
+      *listener << "whose second field does not match";
+      PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
+      return false;
+    }
+    ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
+                   listener);
+    return true;
+  }
+
+ private:
+  void ExplainSuccess(const internal::string& first_explanation,
+                      const internal::string& second_explanation,
+                      MatchResultListener* listener) const {
+    *listener << "whose both fields match";
+    if (first_explanation != "") {
+      *listener << ", where the first field is a value " << first_explanation;
+    }
+    if (second_explanation != "") {
+      *listener << ", ";
+      if (first_explanation != "") {
+        *listener << "and ";
+      } else {
+        *listener << "where ";
+      }
+      *listener << "the second field is a value " << second_explanation;
+    }
+  }
+
+  const Matcher<const FirstType&> first_matcher_;
+  const Matcher<const SecondType&> second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcherImpl);
+};
+
+// Implements polymorphic Pair(first_matcher, second_matcher).
+template <typename FirstMatcher, typename SecondMatcher>
+class PairMatcher {
+ public:
+  PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
+
+  template <typename PairType>
+  operator Matcher<PairType> () const {
+    return MakeMatcher(
+        new PairMatcherImpl<PairType>(
+            first_matcher_, second_matcher_));
+  }
+
+ private:
+  const FirstMatcher first_matcher_;
+  const SecondMatcher second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcher);
+};
+
+// Implements ElementsAre() and ElementsAreArray().
+template <typename Container>
+class ElementsAreMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename InputIter>
+  ElementsAreMatcherImpl(InputIter first, size_t a_count) {
+    matchers_.reserve(a_count);
+    InputIter it = first;
+    for (size_t i = 0; i != a_count; ++i, ++it) {
+      matchers_.push_back(MatcherCast<const Element&>(*it));
+    }
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "is empty";
+    } else if (count() == 1) {
+      *os << "has 1 element that ";
+      matchers_[0].DescribeTo(os);
+    } else {
+      *os << "has " << Elements(count()) << " where\n";
+      for (size_t i = 0; i != count(); ++i) {
+        *os << "element #" << i << " ";
+        matchers_[i].DescribeTo(os);
+        if (i + 1 < count()) {
+          *os << ",\n";
+        }
+      }
+    }
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "isn't empty";
+      return;
+    }
+
+    *os << "doesn't have " << Elements(count()) << ", or\n";
+    for (size_t i = 0; i != count(); ++i) {
+      *os << "element #" << i << " ";
+      matchers_[i].DescribeNegationTo(os);
+      if (i + 1 < count()) {
+        *os << ", or\n";
+      }
+    }
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    const size_t actual_count = stl_container.size();
+    if (actual_count != count()) {
+      // The element count doesn't match.  If the container is empty,
+      // there's no need to explain anything as Google Mock already
+      // prints the empty container.  Otherwise we just need to show
+      // how many elements there actually are.
+      if (actual_count != 0) {
+        *listener << "which has " << Elements(actual_count);
+      }
+      return false;
+    }
+
+    typename StlContainer::const_iterator it = stl_container.begin();
+    // explanations[i] is the explanation of the element at index i.
+    std::vector<internal::string> explanations(count());
+    for (size_t i = 0; i != count();  ++it, ++i) {
+      StringMatchResultListener s;
+      if (matchers_[i].MatchAndExplain(*it, &s)) {
+        explanations[i] = s.str();
+      } else {
+        // The container has the right size but the i-th element
+        // doesn't match its expectation.
+        *listener << "whose element #" << i << " doesn't match";
+        PrintIfNotEmpty(s.str(), listener->stream());
+        return false;
+      }
+    }
+
+    // Every element matches its expectation.  We need to explain why
+    // (the obvious ones can be skipped).
+    bool reason_printed = false;
+    for (size_t i = 0; i != count(); ++i) {
+      const internal::string& s = explanations[i];
+      if (!s.empty()) {
+        if (reason_printed) {
+          *listener << ",\nand ";
+        }
+        *listener << "whose element #" << i << " matches, " << s;
+        reason_printed = true;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  static Message Elements(size_t count) {
+    return Message() << count << (count == 1 ? " element" : " elements");
+  }
+
+  size_t count() const { return matchers_.size(); }
+  std::vector<Matcher<const Element&> > matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcherImpl);
+};
+
+// Implements ElementsAre() of 0 arguments.
+class ElementsAreMatcher0 {
+ public:
+  ElementsAreMatcher0() {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&>* const matchers = NULL;
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
+  }
+};
+
+// Implements ElementsAreArray().
+template <typename T>
+class ElementsAreArrayMatcher {
+ public:
+  ElementsAreArrayMatcher(const T* first, size_t count) :
+      first_(first), count_(count) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
+  }
+
+ private:
+  const T* const first_;
+  const size_t count_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher);
+};
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+string FormatMatcherDescription(bool negation, const char* matcher_name,
+                                const Strings& param_values);
+
+}  // namespace internal
+
+// Implements MatcherCast().
+template <typename T, typename M>
+inline Matcher<T> MatcherCast(M matcher) {
+  return internal::MatcherCastImpl<T, M>::Cast(matcher);
+}
+
+// _ is a matcher that matches anything of any type.
+//
+// This definition is fine as:
+//
+//   1. The C++ standard permits using the name _ in a namespace that
+//      is not the global namespace or ::std.
+//   2. The AnythingMatcher class has no data member or constructor,
+//      so it's OK to create global variables of this type.
+//   3. c-style has approved of using _ in this case.
+const internal::AnythingMatcher _ = {};
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> A() { return MakeMatcher(new internal::AnyMatcherImpl<T>()); }
+
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> An() { return A<T>(); }
+
+// Creates a polymorphic matcher that matches anything equal to x.
+// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
+// wouldn't compile.
+template <typename T>
+inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
+
+// Constructs a Matcher<T> from a 'value' of type T.  The constructed
+// matcher matches any value that's equal to 'value'.
+template <typename T>
+Matcher<T>::Matcher(T value) { *this = Eq(value); }
+
+// Creates a monomorphic matcher that matches anything with type Lhs
+// and equal to rhs.  A user may need to use this instead of Eq(...)
+// in order to resolve an overloading ambiguity.
+//
+// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
+// or Matcher<T>(x), but more readable than the latter.
+//
+// We could define similar monomorphic matchers for other comparison
+// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
+// it yet as those are used much less than Eq() in practice.  A user
+// can always write Matcher<T>(Lt(5)) to be explicit about the type,
+// for example.
+template <typename Lhs, typename Rhs>
+inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
+
+// Creates a polymorphic matcher that matches anything >= x.
+template <typename Rhs>
+inline internal::GeMatcher<Rhs> Ge(Rhs x) {
+  return internal::GeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything > x.
+template <typename Rhs>
+inline internal::GtMatcher<Rhs> Gt(Rhs x) {
+  return internal::GtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything <= x.
+template <typename Rhs>
+inline internal::LeMatcher<Rhs> Le(Rhs x) {
+  return internal::LeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything < x.
+template <typename Rhs>
+inline internal::LtMatcher<Rhs> Lt(Rhs x) {
+  return internal::LtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything != x.
+template <typename Rhs>
+inline internal::NeMatcher<Rhs> Ne(Rhs x) {
+  return internal::NeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches any NULL pointer.
+inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() {
+  return MakePolymorphicMatcher(internal::IsNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any non-NULL pointer.
+// This is convenient as Not(NULL) doesn't compile (the compiler
+// thinks that that expression is comparing a pointer with an integer).
+inline PolymorphicMatcher<internal::NotNullMatcher > NotNull() {
+  return MakePolymorphicMatcher(internal::NotNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any argument that
+// references variable x.
+template <typename T>
+inline internal::RefMatcher<T&> Ref(T& x) {  // NOLINT
+  return internal::RefMatcher<T&>(x);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, true);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<float> FloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, true);
+}
+
+// Creates a matcher that matches a pointer (raw or smart) that points
+// to a value that matches inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointeeMatcher<InnerMatcher> Pointee(
+    const InnerMatcher& inner_matcher) {
+  return internal::PointeeMatcher<InnerMatcher>(inner_matcher);
+}
+
+// Creates a matcher that matches an object whose given field matches
+// 'matcher'.  For example,
+//   Field(&Foo::number, Ge(5))
+// matches a Foo object x iff x.number >= 5.
+template <typename Class, typename FieldType, typename FieldMatcher>
+inline PolymorphicMatcher<
+  internal::FieldMatcher<Class, FieldType> > Field(
+    FieldType Class::*field, const FieldMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::FieldMatcher<Class, FieldType>(
+          field, MatcherCast<const FieldType&>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Field(&Foo::bar, m)
+  // to compile where bar is an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object whose given property
+// matches 'matcher'.  For example,
+//   Property(&Foo::str, StartsWith("hi"))
+// matches a Foo object x iff x.str() starts with "hi".
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<
+  internal::PropertyMatcher<Class, PropertyType> > Property(
+    PropertyType (Class::*property)() const, const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType>(
+          property,
+          MatcherCast<GTEST_REFERENCE_TO_CONST_(PropertyType)>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Property(&Foo::bar, m)
+  // to compile where bar() returns an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object iff the result of applying
+// a callable to x matches 'matcher'.
+// For example,
+//   ResultOf(f, StartsWith("hi"))
+// matches a Foo object x iff f(x) starts with "hi".
+// callable parameter can be a function, function pointer, or a functor.
+// Callable has to satisfy the following conditions:
+//   * It is required to keep no state affecting the results of
+//     the calls on it and make no assumptions about how many calls
+//     will be made. Any state it keeps must be protected from the
+//     concurrent access.
+//   * If it is a function object, it has to define type result_type.
+//     We recommend deriving your functor classes from std::unary_function.
+template <typename Callable, typename ResultOfMatcher>
+internal::ResultOfMatcher<Callable> ResultOf(
+    Callable callable, const ResultOfMatcher& matcher) {
+  return internal::ResultOfMatcher<Callable>(
+          callable,
+          MatcherCast<typename internal::CallableTraits<Callable>::ResultType>(
+              matcher));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   ResultOf(Function, m)
+  // to compile where Function() returns an int32 and m is a matcher for int64.
+}
+
+// String matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any string, std::string, or C string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::string> >
+    HasSubstr(const internal::string& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::string>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::string> >
+    StartsWith(const internal::string& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::string>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::string> >
+    EndsWith(const internal::string& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::string>(
+      suffix));
+}
+
+// Matches a string that fully matches regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::string& regex) {
+  return MatchesRegex(new internal::RE(regex));
+}
+
+// Matches a string that contains regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::string& regex) {
+  return ContainsRegex(new internal::RE(regex));
+}
+
+#if GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+// Wide string matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any wstring, std::wstring, or C wide string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::wstring> >
+    HasSubstr(const internal::wstring& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::wstring>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::wstring> >
+    StartsWith(const internal::wstring& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::wstring>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::wstring> >
+    EndsWith(const internal::wstring& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::wstring>(
+      suffix));
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field == the second field.
+inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field >= the second field.
+inline internal::Ge2Matcher Ge() { return internal::Ge2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field > the second field.
+inline internal::Gt2Matcher Gt() { return internal::Gt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field <= the second field.
+inline internal::Le2Matcher Le() { return internal::Le2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field < the second field.
+inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field != the second field.
+inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
+
+// Creates a matcher that matches any value of type T that m doesn't
+// match.
+template <typename InnerMatcher>
+inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) {
+  return internal::NotMatcher<InnerMatcher>(m);
+}
+
+// Returns a matcher that matches anything that satisfies the given
+// predicate.  The predicate can be any unary function or functor
+// whose return type can be implicitly converted to bool.
+template <typename Predicate>
+inline PolymorphicMatcher<internal::TrulyMatcher<Predicate> >
+Truly(Predicate pred) {
+  return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred));
+}
+
+// Returns a matcher that matches an equal container.
+// This matcher behaves like Eq(), but in the event of mismatch lists the
+// values that are included in one container but not the other. (Duplicate
+// values and order differences are not explained.)
+template <typename Container>
+inline PolymorphicMatcher<internal::ContainerEqMatcher<  // NOLINT
+                            GTEST_REMOVE_CONST_(Container)> >
+    ContainerEq(const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return MakePolymorphicMatcher(
+      internal::ContainerEqMatcher<RawContainer>(rhs));
+}
+
+// Matches an STL-style container or a native array that contains the
+// same number of elements as in rhs, where its i-th element and rhs's
+// i-th element (as a pair) satisfy the given pair matcher, for all i.
+// TupleMatcher must be able to be safely cast to Matcher<tuple<const
+// T1&, const T2&> >, where T1 and T2 are the types of elements in the
+// LHS container and the RHS container respectively.
+template <typename TupleMatcher, typename Container>
+inline internal::PointwiseMatcher<TupleMatcher,
+                                  GTEST_REMOVE_CONST_(Container)>
+Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return internal::PointwiseMatcher<TupleMatcher, RawContainer>(
+      tuple_matcher, rhs);
+}
+
+// Matches an STL-style container or a native array that contains at
+// least one element matching the given value or matcher.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   page_ids.insert(3);
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Contains(1));
+//   EXPECT_THAT(page_ids, Contains(Gt(2)));
+//   EXPECT_THAT(page_ids, Not(Contains(4)));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   EXPECT_THAT(page_lengths,
+//               Contains(::std::pair<const int, size_t>(1, 100)));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
+template <typename M>
+inline internal::ContainsMatcher<M> Contains(M matcher) {
+  return internal::ContainsMatcher<M>(matcher);
+}
+
+// Matches an STL-style container or a native array that contains only
+// elements matching the given value or matcher.
+//
+// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only
+// the messages are different.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   // Each(m) matches an empty container, regardless of what m is.
+//   EXPECT_THAT(page_ids, Each(Eq(1)));
+//   EXPECT_THAT(page_ids, Each(Eq(77)));
+//
+//   page_ids.insert(3);
+//   EXPECT_THAT(page_ids, Each(Gt(0)));
+//   EXPECT_THAT(page_ids, Not(Each(Gt(4))));
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Not(Each(Lt(2))));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   page_lengths[2] = 200;
+//   page_lengths[3] = 300;
+//   EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
+//   EXPECT_THAT(page_lengths, Each(Key(Le(3))));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
+template <typename M>
+inline internal::EachMatcher<M> Each(M matcher) {
+  return internal::EachMatcher<M>(matcher);
+}
+
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename M>
+inline internal::KeyMatcher<M> Key(M inner_matcher) {
+  return internal::KeyMatcher<M>(inner_matcher);
+}
+
+// Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field
+// matches first_matcher and whose 'second' field matches second_matcher.  For
+// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used
+// to match a std::map<int, string> that contains exactly one element whose key
+// is >= 5 and whose value equals "foo".
+template <typename FirstMatcher, typename SecondMatcher>
+inline internal::PairMatcher<FirstMatcher, SecondMatcher>
+Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) {
+  return internal::PairMatcher<FirstMatcher, SecondMatcher>(
+      first_matcher, second_matcher);
+}
+
+// Returns a predicate that is satisfied by anything that matches the
+// given matcher.
+template <typename M>
+inline internal::MatcherAsPredicate<M> Matches(M matcher) {
+  return internal::MatcherAsPredicate<M>(matcher);
+}
+
+// Returns true iff the value matches the matcher.
+template <typename T, typename M>
+inline bool Value(const T& value, M matcher) {
+  return testing::Matches(matcher)(value);
+}
+
+// Matches the value against the given matcher and explains the match
+// result to listener.
+template <typename T, typename M>
+inline bool ExplainMatchResult(
+    M matcher, const T& value, MatchResultListener* listener) {
+  return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
+}
+
+// AllArgs(m) is a synonym of m.  This is useful in
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
+//
+// which is easier to read than
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(Eq());
+template <typename InnerMatcher>
+inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
+
+// These macros allow using matchers to check values in Google Test
+// tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
+// succeed iff the value matches the matcher.  If the assertion fails,
+// the value and the description of the matcher will be printed.
+#define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-more-actions.h b/src/external/gmock-1.6.0/include/gmock/gmock-more-actions.h
new file mode 100644 (file)
index 0000000..fc5e5ca
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some actions that depend on gmock-generated-actions.h.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+
+#include <algorithm>
+
+#include "gmock/gmock-generated-actions.h"
+
+namespace testing {
+namespace internal {
+
+// Implements the Invoke(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  Invoke(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) {
+    return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
+  }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeAction);
+};
+
+// Implements the Invoke(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodAction {
+ public:
+  InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
+      : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
+        obj_ptr_, method_ptr_, args);
+  }
+
+ private:
+  Class* const obj_ptr_;
+  const MethodPtr method_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// Creates an action that invokes 'function_impl' with the mock
+// function's arguments.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
+    FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with the mock function's arguments.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
+    Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
+}
+
+// WithoutArgs(inner_action) can be used in a mock function with a
+// non-empty argument list to perform inner_action, which takes no
+// argument.  In other words, it adapts an action accepting no
+// argument to one that accepts (and ignores) arguments.
+template <typename InnerAction>
+inline internal::WithArgsAction<InnerAction>
+WithoutArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction>(action);
+}
+
+// WithArg<k>(an_action) creates an action that passes the k-th
+// (0-based) argument of the mock function to an_action and performs
+// it.  It adapts an action accepting one argument to one that accepts
+// multiple arguments.  For convenience, we also provide
+// WithArgs<k>(an_action) (defined below) as a synonym.
+template <int k, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k>
+WithArg(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k>(action);
+}
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Action ReturnArg<k>() returns the k-th argument of the mock function.
+ACTION_TEMPLATE(ReturnArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return std::tr1::get<k>(args);
+}
+
+// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
+// mock function to *pointer.
+ACTION_TEMPLATE(SaveArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = ::std::tr1::get<k>(args);
+}
+
+// Action SaveArgPointee<k>(pointer) saves the value pointed to
+// by the k-th (0-based) argument of the mock function to *pointer.
+ACTION_TEMPLATE(SaveArgPointee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = *::std::tr1::get<k>(args);
+}
+
+// Action SetArgReferee<k>(value) assigns 'value' to the variable
+// referenced by the k-th (0-based) argument of the mock function.
+ACTION_TEMPLATE(SetArgReferee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(value)) {
+  typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type;
+  // Ensures that argument #k is a reference.  If you get a compiler
+  // error on the next line, you are using SetArgReferee<k>(value) in
+  // a mock function whose k-th (0-based) argument is not a reference.
+  GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
+                        SetArgReferee_must_be_used_with_a_reference_argument);
+  ::std::tr1::get<k>(args) = value;
+}
+
+// Action SetArrayArgument<k>(first, last) copies the elements in
+// source range [first, last) to the array pointed to by the k-th
+// (0-based) argument, which can be either a pointer or an
+// iterator. The action does not take ownership of the elements in the
+// source range.
+ACTION_TEMPLATE(SetArrayArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(first, last)) {
+  // Microsoft compiler deprecates ::std::copy, so we want to suppress warning
+  // 4996 (Function call with parameters that may be unsafe) there.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996.
+#endif
+  ::std::copy(first, last, ::std::tr1::get<k>(args));
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif
+}
+
+// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
+// function.
+ACTION_TEMPLATE(DeleteArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  delete ::std::tr1::get<k>(args);
+}
+
+// This action returns the value pointed to by 'pointer'.
+ACTION_P(ReturnPointee, pointer) { return *pointer; }
+
+// Action Throw(exception) can be used in a mock function of any type
+// to throw the given exception.  Any copyable value can be thrown.
+#if GTEST_HAS_EXCEPTIONS
+
+// Suppresses the 'unreachable code' warning that VC generates in opt modes.
+# ifdef _MSC_VER
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4702)  // Temporarily disables warning 4702.
+# endif
+ACTION_P(Throw, exception) { throw exception; }
+# ifdef _MSC_VER
+#  pragma warning(pop)           // Restores the warning state.
+# endif
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock-spec-builders.h b/src/external/gmock-1.6.0/include/gmock/gmock-spec-builders.h
new file mode 100644 (file)
index 0000000..400d4d7
--- /dev/null
@@ -0,0 +1,1749 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the ON_CALL() and EXPECT_CALL() macros.
+//
+// A user can use the ON_CALL() macro to specify the default action of
+// a mock method.  The syntax is:
+//
+//   ON_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matcher)
+//       .WillByDefault(action);
+//
+//  where the .With() clause is optional.
+//
+// A user can use the EXPECT_CALL() macro to specify an expectation on
+// a mock method.  The syntax is:
+//
+//   EXPECT_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matchers)
+//       .Times(cardinality)
+//       .InSequence(sequences)
+//       .After(expectations)
+//       .WillOnce(action)
+//       .WillRepeatedly(action)
+//       .RetiresOnSaturation();
+//
+// where all clauses are optional, and .InSequence()/.After()/
+// .WillOnce() can appear any number of times.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// An abstract handle of an expectation.
+class Expectation;
+
+// A set of expectation handles.
+class ExpectationSet;
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// Implements a mock function.
+template <typename F> class FunctionMocker;
+
+// Base class for expectations.
+class ExpectationBase;
+
+// Implements an expectation.
+template <typename F> class TypedExpectation;
+
+// Helper class for testing the Expectation class template.
+class ExpectationTester;
+
+// Base class for function mockers.
+template <typename F> class FunctionMockerBase;
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+//
+// The reason we don't use more fine-grained protection is: when a
+// mock function Foo() is called, it needs to consult its expectations
+// to see which one should be picked.  If another thread is allowed to
+// call a mock function (either Foo() or a different one) at the same
+// time, it could affect the "retired" attributes of Foo()'s
+// expectations when InSequence() is used, and thus affect which
+// expectation gets picked.  Therefore, we sequence all mock function
+// calls to ensure the integrity of the mock objects' states.
+GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Untyped base class for ActionResultHolder<R>.
+class UntypedActionResultHolderBase;
+
+// Abstract base class of FunctionMockerBase.  This is the
+// type-agnostic part of the function mocker interface.  Its pure
+// virtual methods are implemented by FunctionMockerBase.
+class UntypedFunctionMockerBase {
+ public:
+  UntypedFunctionMockerBase();
+  virtual ~UntypedFunctionMockerBase();
+
+  // Verifies that all expectations on this mock function have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  // L >= g_gmock_mutex
+  bool VerifyAndClearExpectationsLocked();
+
+  // Clears the ON_CALL()s set on this mock function.
+  // L >= g_gmock_mutex
+  virtual void ClearDefaultActionsLocked() = 0;
+
+  // In all of the following Untyped* functions, it's the caller's
+  // responsibility to guarantee the correctness of the arguments'
+  // types.
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,
+      const string& call_description) const = 0;
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action,
+      const void* untyped_args) const = 0;
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  // L < g_gmock_mutex
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const = 0;
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  // L < g_gmock_mutex
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) = 0;
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const = 0;
+
+  // Sets the mock object this mock method belongs to, and registers
+  // this information in the global mock registry.  Will be called
+  // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+  // method.
+  // TODO(wan@google.com): rename to SetAndRegisterOwner().
+  // L < g_gmock_mutex
+  void RegisterOwner(const void* mock_obj);
+
+  // Sets the mock object this mock method belongs to, and sets the
+  // name of the mock function.  Will be called upon each invocation
+  // of this mock function.
+  // L < g_gmock_mutex
+  void SetOwnerAndName(const void* mock_obj, const char* name);
+
+  // Returns the mock object this mock method belongs to.  Must be
+  // called after RegisterOwner() or SetOwnerAndName() has been
+  // called.
+  // L < g_gmock_mutex
+  const void* MockObject() const;
+
+  // Returns the name of this mock method.  Must be called after
+  // SetOwnerAndName() has been called.
+  // L < g_gmock_mutex
+  const char* Name() const;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.  The caller is responsible for deleting the
+  // result.
+  // L < g_gmock_mutex
+  const UntypedActionResultHolderBase* UntypedInvokeWith(
+      const void* untyped_args);
+
+ protected:
+  typedef std::vector<const void*> UntypedOnCallSpecs;
+
+  typedef std::vector<internal::linked_ptr<ExpectationBase> >
+  UntypedExpectations;
+
+  // Returns an Expectation object that references and co-owns exp,
+  // which must be an expectation on this mock function.
+  Expectation GetHandleOf(ExpectationBase* exp);
+
+  // Address of the mock object this mock method belongs to.  Only
+  // valid after this mock method has been called or
+  // ON_CALL/EXPECT_CALL has been invoked on it.
+  const void* mock_obj_;  // Protected by g_gmock_mutex.
+
+  // Name of the function being mocked.  Only valid after this mock
+  // method has been called.
+  const char* name_;  // Protected by g_gmock_mutex.
+
+  // All default action specs for this function mocker.
+  UntypedOnCallSpecs untyped_on_call_specs_;
+
+  // All expectations for this function mocker.
+  UntypedExpectations untyped_expectations_;
+};  // class UntypedFunctionMockerBase
+
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
+ public:
+  // The arguments are the location of the ON_CALL() statement.
+  UntypedOnCallSpecBase(const char* a_file, int a_line)
+      : file_(a_file), line_(a_line), last_clause_(kNone) {}
+
+  // Where in the source file was the default action spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+
+ protected:
+  // Gives each clause in the ON_CALL() statement a name.
+  enum Clause {
+    // Do not change the order of the enum members!  The run-time
+    // syntax checking relies on it.
+    kNone,
+    kWith,
+    kWillByDefault
+  };
+
+  // Asserts that the ON_CALL() statement has a certain property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the ON_CALL() statement has a certain property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  const char* file_;
+  int line_;
+
+  // The last clause in the ON_CALL() statement as seen so far.
+  // Initially kNone and changes as the statement is parsed.
+  Clause last_clause_;
+};  // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
+template <typename F>
+class OnCallSpec : public UntypedOnCallSpecBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs an OnCallSpec object from the information inside
+  // the parenthesis of an ON_CALL() statement.
+  OnCallSpec(const char* a_file, int a_line,
+             const ArgumentMatcherTuple& matchers)
+      : UntypedOnCallSpecBase(a_file, a_line),
+        matchers_(matchers),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()) {
+  }
+
+  // Implements the .With() clause.
+  OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
+    // Makes sure this is called at most once.
+    ExpectSpecProperty(last_clause_ < kWith,
+                       ".With() cannot appear "
+                       "more than once in an ON_CALL().");
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    return *this;
+  }
+
+  // Implements the .WillByDefault() clause.
+  OnCallSpec& WillByDefault(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ < kWillByDefault,
+                       ".WillByDefault() must appear "
+                       "exactly once in an ON_CALL().");
+    last_clause_ = kWillByDefault;
+
+    ExpectSpecProperty(!action.IsDoDefault(),
+                       "DoDefault() cannot be used in ON_CALL().");
+    action_ = action;
+    return *this;
+  }
+
+  // Returns true iff the given arguments match the matchers.
+  bool Matches(const ArgumentTuple& args) const {
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns the action specified by the user.
+  const Action<F>& GetAction() const {
+    AssertSpecProperty(last_clause_ == kWillByDefault,
+                       ".WillByDefault() must appear exactly "
+                       "once in an ON_CALL().");
+    return action_;
+  }
+
+ private:
+  // The information in statement
+  //
+  //   ON_CALL(mock_object, Method(matchers))
+  //       .With(multi-argument-matcher)
+  //       .WillByDefault(action);
+  //
+  // is recorded in the data members like this:
+  //
+  //   source file that contains the statement => file_
+  //   line number of the statement            => line_
+  //   matchers                                => matchers_
+  //   multi-argument-matcher                  => extra_matcher_
+  //   action                                  => action_
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> action_;
+};  // class OnCallSpec
+
+// Possible reactions on uninteresting calls.  TODO(wan@google.com):
+// rename the enum values to the kFoo style.
+enum CallReaction {
+  ALLOW,
+  WARN,
+  FAIL
+};
+
+}  // namespace internal
+
+// Utilities for manipulating mock objects.
+class Mock {
+ public:
+  // The following public methods can be called concurrently.
+
+  // Tells Google Mock to ignore mock_obj when checking for leaked
+  // mock objects.
+  static void AllowLeak(const void* mock_obj);
+
+  // Verifies and clears all expectations on the given mock object.
+  // If the expectations aren't satisfied, generates one or more
+  // Google Test non-fatal failures and returns false.
+  static bool VerifyAndClearExpectations(void* mock_obj);
+
+  // Verifies all expectations on the given mock object and clears its
+  // default actions and expectations.  Returns true iff the
+  // verification was successful.
+  static bool VerifyAndClear(void* mock_obj);
+ private:
+  friend class internal::UntypedFunctionMockerBase;
+
+  // Needed for a function mocker to register itself (so that we know
+  // how to clear a mock object).
+  template <typename F>
+  friend class internal::FunctionMockerBase;
+
+  template <typename M>
+  friend class NiceMock;
+
+  template <typename M>
+  friend class StrictMock;
+
+  // Tells Google Mock to allow uninteresting calls on the given mock
+  // object.
+  // L < g_gmock_mutex
+  static void AllowUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock to warn the user about uninteresting calls on
+  // the given mock object.
+  // L < g_gmock_mutex
+  static void WarnUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock to fail uninteresting calls on the given mock
+  // object.
+  // L < g_gmock_mutex
+  static void FailUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock the given mock object is being destroyed and
+  // its entry in the call-reaction table should be removed.
+  // L < g_gmock_mutex
+  static void UnregisterCallReaction(const void* mock_obj);
+
+  // Returns the reaction Google Mock will have on uninteresting calls
+  // made on the given mock object.
+  // L < g_gmock_mutex
+  static internal::CallReaction GetReactionOnUninterestingCalls(
+      const void* mock_obj);
+
+  // Verifies that all expectations on the given mock object have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  // L >= g_gmock_mutex
+  static bool VerifyAndClearExpectationsLocked(void* mock_obj);
+
+  // Clears all ON_CALL()s set on the given mock object.
+  // L >= g_gmock_mutex
+  static void ClearDefaultActionsLocked(void* mock_obj);
+
+  // Registers a mock object and a mock method it owns.
+  // L < g_gmock_mutex
+  static void Register(const void* mock_obj,
+                       internal::UntypedFunctionMockerBase* mocker);
+
+  // Tells Google Mock where in the source code mock_obj is used in an
+  // ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+  // information helps the user identify which object it is.
+  // L < g_gmock_mutex
+  static void RegisterUseByOnCallOrExpectCall(
+      const void* mock_obj, const char* file, int line);
+
+  // Unregisters a mock method; removes the owning mock object from
+  // the registry when the last mock method associated with it has
+  // been unregistered.  This is called only in the destructor of
+  // FunctionMockerBase.
+  // L >= g_gmock_mutex
+  static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker);
+};  // class Mock
+
+// An abstract handle of an expectation.  Useful in the .After()
+// clause of EXPECT_CALL() for setting the (partial) order of
+// expectations.  The syntax:
+//
+//   Expectation e1 = EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(e1)...;
+//
+// sets two expectations where the latter can only be matched after
+// the former has been satisfied.
+//
+// Notes:
+//   - This class is copyable and has value semantics.
+//   - Constness is shallow: a const Expectation object itself cannot
+//     be modified, but the mutable methods of the ExpectationBase
+//     object it references can be called via expectation_base().
+//   - The constructors and destructor are defined out-of-line because
+//     the Symbian WINSCW compiler wants to otherwise instantiate them
+//     when it sees this class definition, at which point it doesn't have
+//     ExpectationBase available yet, leading to incorrect destruction
+//     in the linked_ptr (or compilation errors if using a checking
+//     linked_ptr).
+class Expectation {
+ public:
+  // Constructs a null object that doesn't reference any expectation.
+  Expectation();
+
+  ~Expectation();
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   Expectation e = EXPECT_CALL(...);
+  // syntax.
+  //
+  // A TypedExpectation object stores its pre-requisites as
+  // Expectation objects, and needs to call the non-const Retire()
+  // method on the ExpectationBase objects they reference.  Therefore
+  // Expectation must receive a *non-const* reference to the
+  // ExpectationBase object.
+  Expectation(internal::ExpectationBase& exp);  // NOLINT
+
+  // The compiler-generated copy ctor and operator= work exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs references the same expectation as this object does.
+  bool operator==(const Expectation& rhs) const {
+    return expectation_base_ == rhs.expectation_base_;
+  }
+
+  bool operator!=(const Expectation& rhs) const { return !(*this == rhs); }
+
+ private:
+  friend class ExpectationSet;
+  friend class Sequence;
+  friend class ::testing::internal::ExpectationBase;
+  friend class ::testing::internal::UntypedFunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::FunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::TypedExpectation;
+
+  // This comparator is needed for putting Expectation objects into a set.
+  class Less {
+   public:
+    bool operator()(const Expectation& lhs, const Expectation& rhs) const {
+      return lhs.expectation_base_.get() < rhs.expectation_base_.get();
+    }
+  };
+
+  typedef ::std::set<Expectation, Less> Set;
+
+  Expectation(
+      const internal::linked_ptr<internal::ExpectationBase>& expectation_base);
+
+  // Returns the expectation this object references.
+  const internal::linked_ptr<internal::ExpectationBase>&
+  expectation_base() const {
+    return expectation_base_;
+  }
+
+  // A linked_ptr that co-owns the expectation this handle references.
+  internal::linked_ptr<internal::ExpectationBase> expectation_base_;
+};
+
+// A set of expectation handles.  Useful in the .After() clause of
+// EXPECT_CALL() for setting the (partial) order of expectations.  The
+// syntax:
+//
+//   ExpectationSet es;
+//   es += EXPECT_CALL(...)...;
+//   es += EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(es)...;
+//
+// sets three expectations where the last one can only be matched
+// after the first two have both been satisfied.
+//
+// This class is copyable and has value semantics.
+class ExpectationSet {
+ public:
+  // A bidirectional iterator that can read a const element in the set.
+  typedef Expectation::Set::const_iterator const_iterator;
+
+  // An object stored in the set.  This is an alias of Expectation.
+  typedef Expectation::Set::value_type value_type;
+
+  // Constructs an empty set.
+  ExpectationSet() {}
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   ExpectationSet es = EXPECT_CALL(...);
+  // syntax.
+  ExpectationSet(internal::ExpectationBase& exp) {  // NOLINT
+    *this += Expectation(exp);
+  }
+
+  // This single-argument ctor implements implicit conversion from
+  // Expectation and thus must not be explicit.  This allows either an
+  // Expectation or an ExpectationSet to be used in .After().
+  ExpectationSet(const Expectation& e) {  // NOLINT
+    *this += e;
+  }
+
+  // The compiler-generator ctor and operator= works exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs contains the same set of Expectation objects
+  // as this does.
+  bool operator==(const ExpectationSet& rhs) const {
+    return expectations_ == rhs.expectations_;
+  }
+
+  bool operator!=(const ExpectationSet& rhs) const { return !(*this == rhs); }
+
+  // Implements the syntax
+  //   expectation_set += EXPECT_CALL(...);
+  ExpectationSet& operator+=(const Expectation& e) {
+    expectations_.insert(e);
+    return *this;
+  }
+
+  int size() const { return static_cast<int>(expectations_.size()); }
+
+  const_iterator begin() const { return expectations_.begin(); }
+  const_iterator end() const { return expectations_.end(); }
+
+ private:
+  Expectation::Set expectations_;
+};
+
+
+// Sequence objects are used by a user to specify the relative order
+// in which the expectations should match.  They are copyable (we rely
+// on the compiler-defined copy constructor and assignment operator).
+class Sequence {
+ public:
+  // Constructs an empty sequence.
+  Sequence() : last_expectation_(new Expectation) {}
+
+  // Adds an expectation to this sequence.  The caller must ensure
+  // that no other thread is accessing this Sequence object.
+  void AddExpectation(const Expectation& expectation) const;
+
+ private:
+  // The last expectation in this sequence.  We use a linked_ptr here
+  // because Sequence objects are copyable and we want the copies to
+  // be aliases.  The linked_ptr allows the copies to co-own and share
+  // the same Expectation object.
+  internal::linked_ptr<Expectation> last_expectation_;
+};  // class Sequence
+
+// An object of this type causes all EXPECT_CALL() statements
+// encountered in its scope to be put in an anonymous sequence.  The
+// work is done in the constructor and destructor.  You should only
+// create an InSequence object on the stack.
+//
+// The sole purpose for this class is to support easy definition of
+// sequential expectations, e.g.
+//
+//   {
+//     InSequence dummy;  // The name of the object doesn't matter.
+//
+//     // The following expectations must match in the order they appear.
+//     EXPECT_CALL(a, Bar())...;
+//     EXPECT_CALL(a, Baz())...;
+//     ...
+//     EXPECT_CALL(b, Xyz())...;
+//   }
+//
+// You can create InSequence objects in multiple threads, as long as
+// they are used to affect different mock objects.  The idea is that
+// each thread can create and set up its own mocks as if it's the only
+// thread.  However, for clarity of your tests we recommend you to set
+// up mocks in the main thread unless you have a good reason not to do
+// so.
+class InSequence {
+ public:
+  InSequence();
+  ~InSequence();
+ private:
+  bool sequence_created_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InSequence);  // NOLINT
+} GTEST_ATTRIBUTE_UNUSED_;
+
+namespace internal {
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+extern ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Base class for implementing expectations.
+//
+// There are two reasons for having a type-agnostic base class for
+// Expectation:
+//
+//   1. We need to store collections of expectations of different
+//   types (e.g. all pre-requisites of a particular expectation, all
+//   expectations in a sequence).  Therefore these expectation objects
+//   must share a common base class.
+//
+//   2. We can avoid binary code bloat by moving methods not depending
+//   on the template argument of Expectation to the base class.
+//
+// This class is internal and mustn't be used by user code directly.
+class ExpectationBase {
+ public:
+  // source_text is the EXPECT_CALL(...) source that created this Expectation.
+  ExpectationBase(const char* file, int line, const string& source_text);
+
+  virtual ~ExpectationBase();
+
+  // Where in the source file was the expectation spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+  const char* source_text() const { return source_text_.c_str(); }
+  // Returns the cardinality specified in the expectation spec.
+  const Cardinality& cardinality() const { return cardinality_; }
+
+  // Describes the source file location of this expectation.
+  void DescribeLocationTo(::std::ostream* os) const {
+    *os << FormatFileLocation(file(), line()) << " ";
+  }
+
+  // Describes how many times a function call matching this
+  // expectation has occurred.
+  // L >= g_gmock_mutex
+  void DescribeCallCountTo(::std::ostream* os) const;
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
+
+ protected:
+  friend class ::testing::Expectation;
+  friend class UntypedFunctionMockerBase;
+
+  enum Clause {
+    // Don't change the order of the enum members!
+    kNone,
+    kWith,
+    kTimes,
+    kInSequence,
+    kAfter,
+    kWillOnce,
+    kWillRepeatedly,
+    kRetiresOnSaturation
+  };
+
+  typedef std::vector<const void*> UntypedActions;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() = 0;
+
+  // Asserts that the EXPECT_CALL() statement has the given property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the EXPECT_CALL() statement has the given property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  // Explicitly specifies the cardinality of this expectation.  Used
+  // by the subclasses to implement the .Times() clause.
+  void SpecifyCardinality(const Cardinality& cardinality);
+
+  // Returns true iff the user specified the cardinality explicitly
+  // using a .Times().
+  bool cardinality_specified() const { return cardinality_specified_; }
+
+  // Sets the cardinality of this expectation spec.
+  void set_cardinality(const Cardinality& a_cardinality) {
+    cardinality_ = a_cardinality;
+  }
+
+  // The following group of methods should only be called after the
+  // EXPECT_CALL() statement, and only when g_gmock_mutex is held by
+  // the current thread.
+
+  // Retires all pre-requisites of this expectation.
+  // L >= g_gmock_mutex
+  void RetireAllPreRequisites();
+
+  // Returns true iff this expectation is retired.
+  // L >= g_gmock_mutex
+  bool is_retired() const {
+    g_gmock_mutex.AssertHeld();
+    return retired_;
+  }
+
+  // Retires this expectation.
+  // L >= g_gmock_mutex
+  void Retire() {
+    g_gmock_mutex.AssertHeld();
+    retired_ = true;
+  }
+
+  // Returns true iff this expectation is satisfied.
+  // L >= g_gmock_mutex
+  bool IsSatisfied() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSatisfiedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is saturated.
+  // L >= g_gmock_mutex
+  bool IsSaturated() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is over-saturated.
+  // L >= g_gmock_mutex
+  bool IsOverSaturated() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsOverSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff all pre-requisites of this expectation are satisfied.
+  // L >= g_gmock_mutex
+  bool AllPrerequisitesAreSatisfied() const;
+
+  // Adds unsatisfied pre-requisites of this expectation to 'result'.
+  // L >= g_gmock_mutex
+  void FindUnsatisfiedPrerequisites(ExpectationSet* result) const;
+
+  // Returns the number this expectation has been invoked.
+  // L >= g_gmock_mutex
+  int call_count() const {
+    g_gmock_mutex.AssertHeld();
+    return call_count_;
+  }
+
+  // Increments the number this expectation has been invoked.
+  // L >= g_gmock_mutex
+  void IncrementCallCount() {
+    g_gmock_mutex.AssertHeld();
+    call_count_++;
+  }
+
+  // Checks the action count (i.e. the number of WillOnce() and
+  // WillRepeatedly() clauses) against the cardinality if this hasn't
+  // been done before.  Prints a warning if there are too many or too
+  // few actions.
+  // L < mutex_
+  void CheckActionCountIfNotDone() const;
+
+  friend class ::testing::Sequence;
+  friend class ::testing::internal::ExpectationTester;
+
+  template <typename Function>
+  friend class TypedExpectation;
+
+  // Implements the .Times() clause.
+  void UntypedTimes(const Cardinality& a_cardinality);
+
+  // This group of fields are part of the spec and won't change after
+  // an EXPECT_CALL() statement finishes.
+  const char* file_;          // The file that contains the expectation.
+  int line_;                  // The line number of the expectation.
+  const string source_text_;  // The EXPECT_CALL(...) source text.
+  // True iff the cardinality is specified explicitly.
+  bool cardinality_specified_;
+  Cardinality cardinality_;            // The cardinality of the expectation.
+  // The immediate pre-requisites (i.e. expectations that must be
+  // satisfied before this expectation can be matched) of this
+  // expectation.  We use linked_ptr in the set because we want an
+  // Expectation object to be co-owned by its FunctionMocker and its
+  // successors.  This allows multiple mock objects to be deleted at
+  // different times.
+  ExpectationSet immediate_prerequisites_;
+
+  // This group of fields are the current state of the expectation,
+  // and can change as the mock function is called.
+  int call_count_;  // How many times this expectation has been invoked.
+  bool retired_;    // True iff this expectation has retired.
+  UntypedActions untyped_actions_;
+  bool extra_matcher_specified_;
+  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
+  bool retires_on_saturation_;
+  Clause last_clause_;
+  mutable bool action_count_checked_;  // Under mutex_.
+  mutable Mutex mutex_;  // Protects action_count_checked_.
+
+  GTEST_DISALLOW_ASSIGN_(ExpectationBase);
+};  // class ExpectationBase
+
+// Impements an expectation for the given function type.
+template <typename F>
+class TypedExpectation : public ExpectationBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+  typedef typename Function<F>::Result Result;
+
+  TypedExpectation(FunctionMockerBase<F>* owner,
+                   const char* a_file, int a_line, const string& a_source_text,
+                   const ArgumentMatcherTuple& m)
+      : ExpectationBase(a_file, a_line, a_source_text),
+        owner_(owner),
+        matchers_(m),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()),
+        repeated_action_(DoDefault()) {}
+
+  virtual ~TypedExpectation() {
+    // Check the validity of the action count if it hasn't been done
+    // yet (for example, if the expectation was never used).
+    CheckActionCountIfNotDone();
+    for (UntypedActions::const_iterator it = untyped_actions_.begin();
+         it != untyped_actions_.end(); ++it) {
+      delete static_cast<const Action<F>*>(*it);
+    }
+  }
+
+  // Implements the .With() clause.
+  TypedExpectation& With(const Matcher<const ArgumentTuple&>& m) {
+    if (last_clause_ == kWith) {
+      ExpectSpecProperty(false,
+                         ".With() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWith,
+                         ".With() must be the first "
+                         "clause in an EXPECT_CALL().");
+    }
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    extra_matcher_specified_ = true;
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(const Cardinality& a_cardinality) {
+    ExpectationBase::UntypedTimes(a_cardinality);
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(int n) {
+    return Times(Exactly(n));
+  }
+
+  // Implements the .InSequence() clause.
+  TypedExpectation& InSequence(const Sequence& s) {
+    ExpectSpecProperty(last_clause_ <= kInSequence,
+                       ".InSequence() cannot appear after .After(),"
+                       " .WillOnce(), .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kInSequence;
+
+    s.AddExpectation(GetHandle());
+    return *this;
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2) {
+    return InSequence(s1).InSequence(s2);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3) {
+    return InSequence(s1, s2).InSequence(s3);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4) {
+    return InSequence(s1, s2, s3).InSequence(s4);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4,
+                               const Sequence& s5) {
+    return InSequence(s1, s2, s3, s4).InSequence(s5);
+  }
+
+  // Implements that .After() clause.
+  TypedExpectation& After(const ExpectationSet& s) {
+    ExpectSpecProperty(last_clause_ <= kAfter,
+                       ".After() cannot appear after .WillOnce(),"
+                       " .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kAfter;
+
+    for (ExpectationSet::const_iterator it = s.begin(); it != s.end(); ++it) {
+      immediate_prerequisites_ += *it;
+    }
+    return *this;
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2) {
+    return After(s1).After(s2);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3) {
+    return After(s1, s2).After(s3);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4) {
+    return After(s1, s2, s3).After(s4);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4,
+                          const ExpectationSet& s5) {
+    return After(s1, s2, s3, s4).After(s5);
+  }
+
+  // Implements the .WillOnce() clause.
+  TypedExpectation& WillOnce(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ <= kWillOnce,
+                       ".WillOnce() cannot appear after "
+                       ".WillRepeatedly() or .RetiresOnSaturation().");
+    last_clause_ = kWillOnce;
+
+    untyped_actions_.push_back(new Action<F>(action));
+    if (!cardinality_specified()) {
+      set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
+    }
+    return *this;
+  }
+
+  // Implements the .WillRepeatedly() clause.
+  TypedExpectation& WillRepeatedly(const Action<F>& action) {
+    if (last_clause_ == kWillRepeatedly) {
+      ExpectSpecProperty(false,
+                         ".WillRepeatedly() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWillRepeatedly,
+                         ".WillRepeatedly() cannot appear "
+                         "after .RetiresOnSaturation().");
+    }
+    last_clause_ = kWillRepeatedly;
+    repeated_action_specified_ = true;
+
+    repeated_action_ = action;
+    if (!cardinality_specified()) {
+      set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
+    }
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Implements the .RetiresOnSaturation() clause.
+  TypedExpectation& RetiresOnSaturation() {
+    ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
+                       ".RetiresOnSaturation() cannot appear "
+                       "more than once.");
+    last_clause_ = kRetiresOnSaturation;
+    retires_on_saturation_ = true;
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Returns the matchers for the arguments as specified inside the
+  // EXPECT_CALL() macro.
+  const ArgumentMatcherTuple& matchers() const {
+    return matchers_;
+  }
+
+  // Returns the matcher specified by the .With() clause.
+  const Matcher<const ArgumentTuple&>& extra_matcher() const {
+    return extra_matcher_;
+  }
+
+  // Returns the action specified by the .WillRepeatedly() clause.
+  const Action<F>& repeated_action() const { return repeated_action_; }
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
+    if (extra_matcher_specified_) {
+      *os << "    Expected args: ";
+      extra_matcher_.DescribeTo(os);
+      *os << "\n";
+    }
+  }
+
+ private:
+  template <typename Function>
+  friend class FunctionMockerBase;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() {
+    return owner_->GetHandleOf(this);
+  }
+
+  // The following methods will be called only after the EXPECT_CALL()
+  // statement finishes and when the current thread holds
+  // g_gmock_mutex.
+
+  // Returns true iff this expectation matches the given arguments.
+  // L >= g_gmock_mutex
+  bool Matches(const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns true iff this expectation should handle the given arguments.
+  // L >= g_gmock_mutex
+  bool ShouldHandleArguments(const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+
+    // In case the action count wasn't checked when the expectation
+    // was defined (e.g. if this expectation has no WillRepeatedly()
+    // or RetiresOnSaturation() clause), we check it when the
+    // expectation is used for the first time.
+    CheckActionCountIfNotDone();
+    return !is_retired() && AllPrerequisitesAreSatisfied() && Matches(args);
+  }
+
+  // Describes the result of matching the arguments against this
+  // expectation to the given ostream.
+  // L >= g_gmock_mutex
+  void ExplainMatchResultTo(const ArgumentTuple& args,
+                            ::std::ostream* os) const {
+    g_gmock_mutex.AssertHeld();
+
+    if (is_retired()) {
+      *os << "         Expected: the expectation is active\n"
+          << "           Actual: it is retired\n";
+    } else if (!Matches(args)) {
+      if (!TupleMatches(matchers_, args)) {
+        ExplainMatchFailureTupleTo(matchers_, args, os);
+      }
+      StringMatchResultListener listener;
+      if (!extra_matcher_.MatchAndExplain(args, &listener)) {
+        *os << "    Expected args: ";
+        extra_matcher_.DescribeTo(os);
+        *os << "\n           Actual: don't match";
+
+        internal::PrintIfNotEmpty(listener.str(), os);
+        *os << "\n";
+      }
+    } else if (!AllPrerequisitesAreSatisfied()) {
+      *os << "         Expected: all pre-requisites are satisfied\n"
+          << "           Actual: the following immediate pre-requisites "
+          << "are not satisfied:\n";
+      ExpectationSet unsatisfied_prereqs;
+      FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
+      int i = 0;
+      for (ExpectationSet::const_iterator it = unsatisfied_prereqs.begin();
+           it != unsatisfied_prereqs.end(); ++it) {
+        it->expectation_base()->DescribeLocationTo(os);
+        *os << "pre-requisite #" << i++ << "\n";
+      }
+      *os << "                   (end of pre-requisites)\n";
+    } else {
+      // This line is here just for completeness' sake.  It will never
+      // be executed as currently the ExplainMatchResultTo() function
+      // is called only when the mock function call does NOT match the
+      // expectation.
+      *os << "The call matches the expectation.\n";
+    }
+  }
+
+  // Returns the action that should be taken for the current invocation.
+  // L >= g_gmock_mutex
+  const Action<F>& GetCurrentAction(const FunctionMockerBase<F>* mocker,
+                                    const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    const int count = call_count();
+    Assert(count >= 1, __FILE__, __LINE__,
+           "call_count() is <= 0 when GetCurrentAction() is "
+           "called - this should never happen.");
+
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    if (action_count > 0 && !repeated_action_specified_ &&
+        count > action_count) {
+      // If there is at least one WillOnce() and no WillRepeatedly(),
+      // we warn the user when the WillOnce() clauses ran out.
+      ::std::stringstream ss;
+      DescribeLocationTo(&ss);
+      ss << "Actions ran out in " << source_text() << "...\n"
+         << "Called " << count << " times, but only "
+         << action_count << " WillOnce()"
+         << (action_count == 1 ? " is" : "s are") << " specified - ";
+      mocker->DescribeDefaultActionTo(args, &ss);
+      Log(WARNING, ss.str(), 1);
+    }
+
+    return count <= action_count ?
+        *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
+        repeated_action();
+  }
+
+  // Given the arguments of a mock function call, if the call will
+  // over-saturate this expectation, returns the default action;
+  // otherwise, returns the next action in this expectation.  Also
+  // describes *what* happened to 'what', and explains *why* Google
+  // Mock does it to 'why'.  This method is not const as it calls
+  // IncrementCallCount().  A return value of NULL means the default
+  // action.
+  // L >= g_gmock_mutex
+  const Action<F>* GetActionForArguments(const FunctionMockerBase<F>* mocker,
+                                         const ArgumentTuple& args,
+                                         ::std::ostream* what,
+                                         ::std::ostream* why) {
+    g_gmock_mutex.AssertHeld();
+    if (IsSaturated()) {
+      // We have an excessive call.
+      IncrementCallCount();
+      *what << "Mock function called more times than expected - ";
+      mocker->DescribeDefaultActionTo(args, what);
+      DescribeCallCountTo(why);
+
+      // TODO(wan@google.com): allow the user to control whether
+      // unexpected calls should fail immediately or continue using a
+      // flag --gmock_unexpected_calls_are_fatal.
+      return NULL;
+    }
+
+    IncrementCallCount();
+    RetireAllPreRequisites();
+
+    if (retires_on_saturation_ && IsSaturated()) {
+      Retire();
+    }
+
+    // Must be done after IncrementCount()!
+    *what << "Mock function call matches " << source_text() <<"...\n";
+    return &(GetCurrentAction(mocker, args));
+  }
+
+  // All the fields below won't change once the EXPECT_CALL()
+  // statement finishes.
+  FunctionMockerBase<F>* const owner_;
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> repeated_action_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation);
+};  // class TypedExpectation
+
+// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
+// specifying the default behavior of, or expectation on, a mock
+// function.
+
+// Note: class MockSpec really belongs to the ::testing namespace.
+// However if we define it in ::testing, MSVC will complain when
+// classes in ::testing::internal declare it as a friend class
+// template.  To workaround this compiler bug, we define MockSpec in
+// ::testing::internal and import it into ::testing.
+
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message);
+
+template <typename F>
+class MockSpec {
+ public:
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename internal::Function<F>::ArgumentMatcherTuple
+      ArgumentMatcherTuple;
+
+  // Constructs a MockSpec object, given the function mocker object
+  // that the spec is associated with.
+  explicit MockSpec(internal::FunctionMockerBase<F>* function_mocker)
+      : function_mocker_(function_mocker) {}
+
+  // Adds a new default action spec to the function mocker and returns
+  // the newly created spec.
+  internal::OnCallSpec<F>& InternalDefaultActionSetAt(
+      const char* file, int line, const char* obj, const char* call) {
+    LogWithLocation(internal::INFO, file, line,
+        string("ON_CALL(") + obj + ", " + call + ") invoked");
+    return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
+  }
+
+  // Adds a new expectation spec to the function mocker and returns
+  // the newly created spec.
+  internal::TypedExpectation<F>& InternalExpectedAt(
+      const char* file, int line, const char* obj, const char* call) {
+    const string source_text(string("EXPECT_CALL(") + obj + ", " + call + ")");
+    LogWithLocation(internal::INFO, file, line, source_text + " invoked");
+    return function_mocker_->AddNewExpectation(
+        file, line, source_text, matchers_);
+  }
+
+ private:
+  template <typename Function>
+  friend class internal::FunctionMocker;
+
+  void SetMatchers(const ArgumentMatcherTuple& matchers) {
+    matchers_ = matchers;
+  }
+
+  // The function mocker that owns this spec.
+  internal::FunctionMockerBase<F>* const function_mocker_;
+  // The argument matchers specified in the spec.
+  ArgumentMatcherTuple matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(MockSpec);
+};  // class MockSpec
+
+// MSVC warns about using 'this' in base member initializer list, so
+// we need to temporarily disable the warning.  We have to do it for
+// the entire class to suppress the warning, even though it's about
+// the constructor only.
+
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4355)  // Temporarily disables warning 4355.
+#endif  // _MSV_VER
+
+// C++ treats the void type specially.  For example, you cannot define
+// a void-typed variable or pass a void value to a function.
+// ActionResultHolder<T> holds a value of type T, where T must be a
+// copyable type or void (T doesn't need to be default-constructable).
+// It hides the syntactic difference between void and other types, and
+// is used to unify the code for invoking both void-returning and
+// non-void-returning mock functions.
+
+// Untyped base class for ActionResultHolder<T>.
+class UntypedActionResultHolderBase {
+ public:
+  virtual ~UntypedActionResultHolderBase() {}
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const = 0;
+};
+
+// This generic definition is used when T is not void.
+template <typename T>
+class ActionResultHolder : public UntypedActionResultHolderBase {
+ public:
+  explicit ActionResultHolder(T a_value) : value_(a_value) {}
+
+  // The compiler-generated copy constructor and assignment operator
+  // are exactly what we need, so we don't need to define them.
+
+  // Returns the held value and deletes this object.
+  T GetValueAndDelete() const {
+    T retval(value_);
+    delete this;
+    return retval;
+  }
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const {
+    *os << "\n          Returns: ";
+    // T may be a reference type, so we don't use UniversalPrint().
+    UniversalPrinter<T>::Print(value_, os);
+  }
+
+  // Performs the given mock function's default action and returns the
+  // result in a new-ed ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    return new ActionResultHolder(
+        func_mocker->PerformDefaultAction(args, call_description));
+  }
+
+  // Performs the given action and returns the result in a new-ed
+  // ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder*
+  PerformAction(const Action<F>& action,
+                const typename Function<F>::ArgumentTuple& args) {
+    return new ActionResultHolder(action.Perform(args));
+  }
+
+ private:
+  T value_;
+
+  // T could be a reference type, so = isn't supported.
+  GTEST_DISALLOW_ASSIGN_(ActionResultHolder);
+};
+
+// Specialization for T = void.
+template <>
+class ActionResultHolder<void> : public UntypedActionResultHolderBase {
+ public:
+  void GetValueAndDelete() const { delete this; }
+
+  virtual void PrintAsActionResult(::std::ostream* /* os */) const {}
+
+  // Performs the given mock function's default action and returns NULL;
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    func_mocker->PerformDefaultAction(args, call_description);
+    return NULL;
+  }
+
+  // Performs the given action and returns NULL.
+  template <typename F>
+  static ActionResultHolder* PerformAction(
+      const Action<F>& action,
+      const typename Function<F>::ArgumentTuple& args) {
+    action.Perform(args);
+    return NULL;
+  }
+};
+
+// The base of the function mocker class for the given function type.
+// We put the methods in this class instead of its child to avoid code
+// bloat.
+template <typename F>
+class FunctionMockerBase : public UntypedFunctionMockerBase {
+ public:
+  typedef typename Function<F>::Result Result;
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  FunctionMockerBase() : current_spec_(this) {}
+
+  // The destructor verifies that all expectations on this mock
+  // function have been satisfied.  If not, it will report Google Test
+  // non-fatal failures for the violations.
+  // L < g_gmock_mutex
+  virtual ~FunctionMockerBase() {
+    MutexLock l(&g_gmock_mutex);
+    VerifyAndClearExpectationsLocked();
+    Mock::UnregisterLocked(this);
+    ClearDefaultActionsLocked();
+  }
+
+  // Returns the ON_CALL spec that matches this mock function with the
+  // given arguments; returns NULL if no matching ON_CALL is found.
+  // L = *
+  const OnCallSpec<F>* FindOnCallSpec(
+      const ArgumentTuple& args) const {
+    for (UntypedOnCallSpecs::const_reverse_iterator it
+             = untyped_on_call_specs_.rbegin();
+         it != untyped_on_call_specs_.rend(); ++it) {
+      const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+      if (spec->Matches(args))
+        return spec;
+    }
+
+    return NULL;
+  }
+
+  // Performs the default action of this mock function on the given arguments
+  // and returns the result. Asserts with a helpful call descrption if there is
+  // no valid return value. This method doesn't depend on the mutable state of
+  // this object, and thus can be called concurrently without locking.
+  // L = *
+  Result PerformDefaultAction(const ArgumentTuple& args,
+                              const string& call_description) const {
+    const OnCallSpec<F>* const spec =
+        this->FindOnCallSpec(args);
+    if (spec != NULL) {
+      return spec->GetAction().Perform(args);
+    }
+    Assert(DefaultValue<Result>::Exists(), "", -1,
+           call_description + "\n    The mock function has no default action "
+           "set, and its return type has no default value set.");
+    return DefaultValue<Result>::Get();
+  }
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.  The caller is responsible for deleting the result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,  // must point to an ArgumentTuple
+      const string& call_description) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformDefaultAction(this, args, call_description);
+  }
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.  The caller is responsible for deleting the
+  // result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action, const void* untyped_args) const {
+    // Make a copy of the action before performing it, in case the
+    // action deletes the mock object (and thus deletes itself).
+    const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformAction(action, args);
+  }
+
+  // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+  // clears the ON_CALL()s set on this mock function.
+  // L >= g_gmock_mutex
+  virtual void ClearDefaultActionsLocked() {
+    g_gmock_mutex.AssertHeld();
+    for (UntypedOnCallSpecs::const_iterator it =
+             untyped_on_call_specs_.begin();
+         it != untyped_on_call_specs_.end(); ++it) {
+      delete static_cast<const OnCallSpec<F>*>(*it);
+    }
+    untyped_on_call_specs_.clear();
+  }
+
+ protected:
+  template <typename Function>
+  friend class MockSpec;
+
+  typedef ActionResultHolder<Result> ResultHolder;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.
+  // L < g_gmock_mutex
+  Result InvokeWith(const ArgumentTuple& args) {
+    return static_cast<const ResultHolder*>(
+        this->UntypedInvokeWith(&args))->GetValueAndDelete();
+  }
+
+  // Adds and returns a default action spec for this mock function.
+  // L < g_gmock_mutex
+  OnCallSpec<F>& AddNewOnCallSpec(
+      const char* file, int line,
+      const ArgumentMatcherTuple& m) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+    untyped_on_call_specs_.push_back(on_call_spec);
+    return *on_call_spec;
+  }
+
+  // Adds and returns an expectation spec for this mock function.
+  // L < g_gmock_mutex
+  TypedExpectation<F>& AddNewExpectation(
+      const char* file,
+      int line,
+      const string& source_text,
+      const ArgumentMatcherTuple& m) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    TypedExpectation<F>* const expectation =
+        new TypedExpectation<F>(this, file, line, source_text, m);
+    const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+    untyped_expectations_.push_back(untyped_expectation);
+
+    // Adds this expectation into the implicit sequence if there is one.
+    Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
+    if (implicit_sequence != NULL) {
+      implicit_sequence->AddExpectation(Expectation(untyped_expectation));
+    }
+
+    return *expectation;
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F>& current_spec() { return current_spec_; }
+
+ private:
+  template <typename Func> friend class TypedExpectation;
+
+  // Some utilities needed for implementing UntypedInvokeWith().
+
+  // Describes what default action will be performed for the given
+  // arguments.
+  // L = *
+  void DescribeDefaultActionTo(const ArgumentTuple& args,
+                               ::std::ostream* os) const {
+    const OnCallSpec<F>* const spec = FindOnCallSpec(args);
+
+    if (spec == NULL) {
+      *os << (internal::type_equals<Result, void>::value ?
+              "returning directly.\n" :
+              "returning default value.\n");
+    } else {
+      *os << "taking default action specified at:\n"
+          << FormatFileLocation(spec->file(), spec->line()) << "\n";
+    }
+  }
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  // L < g_gmock_mutex
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    *os << "Uninteresting mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    *os << "    Function call: " << Name();
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  //
+  // Critical section: We must find the matching expectation and the
+  // corresponding action that needs to be taken in an ATOMIC
+  // transaction.  Otherwise another thread may call this mock
+  // method in the middle and mess up the state.
+  //
+  // However, performing the action has to be left out of the critical
+  // section.  The reason is that we have no control on what the
+  // action does (it can invoke an arbitrary user function or even a
+  // mock function) and excessive locking could cause a dead lock.
+  // L < g_gmock_mutex
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    MutexLock l(&g_gmock_mutex);
+    TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+    if (exp == NULL) {  // A match wasn't found.
+      this->FormatUnexpectedCallMessageLocked(args, what, why);
+      return NULL;
+    }
+
+    // This line must be done before calling GetActionForArguments(),
+    // which will increment the call count for *exp and thus affect
+    // its saturation status.
+    *is_excessive = exp->IsSaturated();
+    const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
+    if (action != NULL && action->IsDoDefault())
+      action = NULL;  // Normalize "do default" to NULL.
+    *untyped_action = action;
+    return exp;
+  }
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the arguments, or NULL if no
+  // expectation matches them.
+  // L >= g_gmock_mutex
+  TypedExpectation<F>* FindMatchingExpectationLocked(
+      const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    for (typename UntypedExpectations::const_reverse_iterator it =
+             untyped_expectations_.rbegin();
+         it != untyped_expectations_.rend(); ++it) {
+      TypedExpectation<F>* const exp =
+          static_cast<TypedExpectation<F>*>(it->get());
+      if (exp->ShouldHandleArguments(args)) {
+        return exp;
+      }
+    }
+    return NULL;
+  }
+
+  // Returns a message that the arguments don't match any expectation.
+  // L >= g_gmock_mutex
+  void FormatUnexpectedCallMessageLocked(const ArgumentTuple& args,
+                                         ::std::ostream* os,
+                                         ::std::ostream* why) const {
+    g_gmock_mutex.AssertHeld();
+    *os << "\nUnexpected mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    PrintTriedExpectationsLocked(args, why);
+  }
+
+  // Prints a list of expectations that have been tried against the
+  // current mock function call.
+  // L >= g_gmock_mutex
+  void PrintTriedExpectationsLocked(const ArgumentTuple& args,
+                                    ::std::ostream* why) const {
+    g_gmock_mutex.AssertHeld();
+    const int count = static_cast<int>(untyped_expectations_.size());
+    *why << "Google Mock tried the following " << count << " "
+         << (count == 1 ? "expectation, but it didn't match" :
+             "expectations, but none matched")
+         << ":\n";
+    for (int i = 0; i < count; i++) {
+      TypedExpectation<F>* const expectation =
+          static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
+      *why << "\n";
+      expectation->DescribeLocationTo(why);
+      if (count > 1) {
+        *why << "tried expectation #" << i << ": ";
+      }
+      *why << expectation->source_text() << "...\n";
+      expectation->ExplainMatchResultTo(args, why);
+      expectation->DescribeCallCountTo(why);
+    }
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F> current_spec_;
+
+  // There is no generally useful and implementable semantics of
+  // copying a mock object, so copying a mock is usually a user error.
+  // Thus we disallow copying function mockers.  If the user really
+  // wants to copy a mock object, he should implement his own copy
+  // operation, for example:
+  //
+  //   class MockFoo : public Foo {
+  //    public:
+  //     // Defines a copy constructor explicitly.
+  //     MockFoo(const MockFoo& src) {}
+  //     ...
+  //   };
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
+};  // class FunctionMockerBase
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif  // _MSV_VER
+
+// Implements methods of FunctionMockerBase.
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures and
+// returns false if not.
+// L >= g_gmock_mutex
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg);
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the MockSpec class template is
+// meant to be defined in the ::testing namespace.  The following line
+// is just a trick for working around a bug in MSVC 8.0, which cannot
+// handle it if we define MockSpec in ::testing.
+using internal::MockSpec;
+
+// Const(x) is a convenient function for obtaining a const reference
+// to x.  This is useful for setting expectations on an overloaded
+// const mock method, e.g.
+//
+//   class MockFoo : public FooInterface {
+//    public:
+//     MOCK_METHOD0(Bar, int());
+//     MOCK_CONST_METHOD0(Bar, int&());
+//   };
+//
+//   MockFoo foo;
+//   // Expects a call to non-const MockFoo::Bar().
+//   EXPECT_CALL(foo, Bar());
+//   // Expects a call to const MockFoo::Bar().
+//   EXPECT_CALL(Const(foo), Bar());
+template <typename T>
+inline const T& Const(const T& x) { return x; }
+
+// Constructs an Expectation object that references and co-owns exp.
+inline Expectation::Expectation(internal::ExpectationBase& exp)  // NOLINT
+    : expectation_base_(exp.GetHandle().expectation_base()) {}
+
+}  // namespace testing
+
+// A separate macro is required to avoid compile errors when the name
+// of the method used in call is a result of macro expansion.
+// See CompilesWithMethodNameExpandedFromMacro tests in
+// internal/gmock-spec-builders_test.cc for more details.
+#define GMOCK_ON_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalDefaultActionSetAt(__FILE__, __LINE__, \
+                                                    #obj, #call)
+#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
+
+#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
+#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/gmock.h b/src/external/gmock-1.6.0/include/gmock/gmock.h
new file mode 100644 (file)
index 0000000..ba9fa28
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This is the main header file a user should include.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
+
+// This file implements the following syntax:
+//
+//   ON_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .WillByDefault(...);
+//
+// where With() is optional and WillByDefault() must appear exactly
+// once.
+//
+//   EXPECT_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .Times(...) ?
+//     .InSequence(...) *
+//     .WillOnce(...) *
+//     .WillRepeatedly(...) ?
+//     .RetiresOnSaturation() ? ;
+//
+// where all clauses are optional and WillOnce() can be repeated.
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-generated-actions.h"
+#include "gmock/gmock-generated-function-mockers.h"
+#include "gmock/gmock-generated-matchers.h"
+#include "gmock/gmock-more-actions.h"
+#include "gmock/gmock-generated-nice-strict.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+namespace testing {
+
+// Declares Google Mock flags that we want a user to use programmatically.
+GMOCK_DECLARE_bool_(catch_leaked_mocks);
+GMOCK_DECLARE_string_(verbose);
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses the command line for the flags
+// that Google Mock recognizes.  Whenever a Google Mock flag is seen,
+// it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+void InitGoogleMock(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleMock(int* argc, wchar_t** argv);
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/internal/gmock-generated-internal-utils.h b/src/external/gmock-1.6.0/include/gmock/internal/gmock-generated-internal-utils.h
new file mode 100644 (file)
index 0000000..1b52dce
--- /dev/null
@@ -0,0 +1,277 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file contains template meta-programming utility classes needed
+// for implementing Google Mock.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <typename T>
+class Matcher;
+
+namespace internal {
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+// This is used in implementing the IgnoreResult(a) action.
+class IgnoredValue {
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  template <typename T>
+  IgnoredValue(const T&) {}
+};
+
+// MatcherTuple<T>::type is a tuple type where each field is a Matcher
+// for the corresponding field in tuple type T.
+template <typename Tuple>
+struct MatcherTuple;
+
+template <>
+struct MatcherTuple< ::std::tr1::tuple<> > {
+  typedef ::std::tr1::tuple< > type;
+};
+
+template <typename A1>
+struct MatcherTuple< ::std::tr1::tuple<A1> > {
+  typedef ::std::tr1::tuple<Matcher<A1> > type;
+};
+
+template <typename A1, typename A2>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2> > type;
+};
+
+template <typename A1, typename A2, typename A3>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>,
+      Matcher<A4> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9, typename A10>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>,
+      Matcher<A10> > type;
+};
+
+// Template struct Function<F>, where F must be a function type, contains
+// the following typedefs:
+//
+//   Result:               the function's return type.
+//   ArgumentN:            the type of the N-th argument, where N starts with 1.
+//   ArgumentTuple:        the tuple type consisting of all parameters of F.
+//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
+//                         parameters of F.
+//   MakeResultVoid:       the function type obtained by substituting void
+//                         for the return type of F.
+//   MakeResultIgnoredValue:
+//                         the function type obtained by substituting Something
+//                         for the return type of F.
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+  typedef R Result;
+  typedef ::std::tr1::tuple<> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid();
+  typedef IgnoredValue MakeResultIgnoredValue();
+};
+
+template <typename R, typename A1>
+struct Function<R(A1)>
+    : Function<R()> {
+  typedef A1 Argument1;
+  typedef ::std::tr1::tuple<A1> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1);
+  typedef IgnoredValue MakeResultIgnoredValue(A1);
+};
+
+template <typename R, typename A1, typename A2>
+struct Function<R(A1, A2)>
+    : Function<R(A1)> {
+  typedef A2 Argument2;
+  typedef ::std::tr1::tuple<A1, A2> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2);
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+struct Function<R(A1, A2, A3)>
+    : Function<R(A1, A2)> {
+  typedef A3 Argument3;
+  typedef ::std::tr1::tuple<A1, A2, A3> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+struct Function<R(A1, A2, A3, A4)>
+    : Function<R(A1, A2, A3)> {
+  typedef A4 Argument4;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+struct Function<R(A1, A2, A3, A4, A5)>
+    : Function<R(A1, A2, A3, A4)> {
+  typedef A5 Argument5;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+struct Function<R(A1, A2, A3, A4, A5, A6)>
+    : Function<R(A1, A2, A3, A4, A5)> {
+  typedef A6 Argument6;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7)>
+    : Function<R(A1, A2, A3, A4, A5, A6)> {
+  typedef A7 Argument7;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7)> {
+  typedef A8 Argument8;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+  typedef A9 Argument9;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+  typedef A10 Argument10;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+      A10> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9, A10);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h b/src/external/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h
new file mode 100644 (file)
index 0000000..f0fd868
--- /dev/null
@@ -0,0 +1,463 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+
+#include "gmock/internal/gmock-generated-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+string ConvertIdentifierNameToWords(const char* id_name);
+
+// PointeeOf<Pointer>::type is the type of a value pointed to by a
+// Pointer, which can be either a smart pointer or a raw pointer.  The
+// following default implementation is for the case where Pointer is a
+// smart pointer.
+template <typename Pointer>
+struct PointeeOf {
+  // Smart pointer classes define type element_type as the type of
+  // their pointees.
+  typedef typename Pointer::element_type type;
+};
+// This specialization is for the raw pointer case.
+template <typename T>
+struct PointeeOf<T*> { typedef T type; };  // NOLINT
+
+// GetRawPointer(p) returns the raw pointer underlying p when p is a
+// smart pointer, or returns p itself when p is already a raw pointer.
+// The following default implementation is for the smart pointer case.
+template <typename Pointer>
+inline typename Pointer::element_type* GetRawPointer(const Pointer& p) {
+  return p.get();
+}
+// This overloaded version is for the raw pointer case.
+template <typename Element>
+inline Element* GetRawPointer(Element* p) { return p; }
+
+// This comparator allows linked_ptr to be stored in sets.
+template <typename T>
+struct LinkedPtrLessThan {
+  bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
+                  const ::testing::internal::linked_ptr<T>& rhs) const {
+    return lhs.get() < rhs.get();
+  }
+};
+
+// Symbian compilation can be done with wchar_t being either a native
+// type or a typedef.  Using Google Mock with OpenC without wchar_t
+// should require the definition of _STLP_NO_WCHAR_T.
+//
+// MSVC treats wchar_t as a native type usually, but treats it as the
+// same as unsigned short when the compiler option /Zc:wchar_t- is
+// specified.  It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
+// is a native type.
+#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
+    (defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
+// wchar_t is a typedef.
+#else
+# define GMOCK_WCHAR_T_IS_NATIVE_ 1
+#endif
+
+// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
+// Using them is a bad practice and not portable.  So DON'T use them.
+//
+// Still, Google Mock is designed to work even if the user uses signed
+// wchar_t or unsigned wchar_t (obviously, assuming the compiler
+// supports them).
+//
+// To gcc,
+//   wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
+#ifdef __GNUC__
+// signed/unsigned wchar_t are valid types.
+# define GMOCK_HAS_SIGNED_WCHAR_T_ 1
+#endif
+
+// In what follows, we use the term "kind" to indicate whether a type
+// is bool, an integer type (excluding bool), a floating-point type,
+// or none of them.  This categorization is useful for determining
+// when a matcher argument type can be safely converted to another
+// type in the implementation of SafeMatcherCast.
+enum TypeKind {
+  kBool, kInteger, kFloatingPoint, kOther
+};
+
+// KindOf<T>::value is the kind of type T.
+template <typename T> struct KindOf {
+  enum { value = kOther };  // The default kind.
+};
+
+// This macro declares that the kind of 'type' is 'kind'.
+#define GMOCK_DECLARE_KIND_(type, kind) \
+  template <> struct KindOf<type> { enum { value = kind }; }
+
+GMOCK_DECLARE_KIND_(bool, kBool);
+
+// All standard integer types.
+GMOCK_DECLARE_KIND_(char, kInteger);
+GMOCK_DECLARE_KIND_(signed char, kInteger);
+GMOCK_DECLARE_KIND_(unsigned char, kInteger);
+GMOCK_DECLARE_KIND_(short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(int, kInteger);
+GMOCK_DECLARE_KIND_(unsigned int, kInteger);
+GMOCK_DECLARE_KIND_(long, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned long, kInteger);  // NOLINT
+
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DECLARE_KIND_(wchar_t, kInteger);
+#endif
+
+// Non-standard integer types.
+GMOCK_DECLARE_KIND_(Int64, kInteger);
+GMOCK_DECLARE_KIND_(UInt64, kInteger);
+
+// All standard floating-point types.
+GMOCK_DECLARE_KIND_(float, kFloatingPoint);
+GMOCK_DECLARE_KIND_(double, kFloatingPoint);
+GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
+
+#undef GMOCK_DECLARE_KIND_
+
+// Evaluates to the kind of 'type'.
+#define GMOCK_KIND_OF_(type) \
+  static_cast< ::testing::internal::TypeKind>( \
+      ::testing::internal::KindOf<type>::value)
+
+// Evaluates to true iff integer type T is signed.
+#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
+
+// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
+// is true iff arithmetic type From can be losslessly converted to
+// arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types, kFromKind is the kind of
+// From, and kToKind is the kind of To; the value is
+// implementation-defined when the above pre-condition is violated.
+template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
+struct LosslessArithmeticConvertibleImpl : public false_type {};
+
+// Converting bool to bool is lossless.
+template <>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any integer type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any floating-point type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
+    : public true_type {};  // NOLINT
+
+// Converting an integer to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting an integer to another non-bool integer is lossless iff
+// the target type's range encloses the source type's range.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
+    : public bool_constant<
+      // When converting from a smaller size to a larger size, we are
+      // fine as long as we are not converting from signed to unsigned.
+      ((sizeof(From) < sizeof(To)) &&
+       (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
+      // When converting between the same size, the signedness must match.
+      ((sizeof(From) == sizeof(To)) &&
+       (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {};  // NOLINT
+
+#undef GMOCK_IS_SIGNED_
+
+// Converting an integer to a floating-point type may be lossy, since
+// the format of a floating-point number is implementation-defined.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to an integer is lossy.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to another floating-point is lossless
+// iff the target type is at least as big as the source type.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<
+  kFloatingPoint, From, kFloatingPoint, To>
+    : public bool_constant<sizeof(From) <= sizeof(To)> {};  // NOLINT
+
+// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
+// type From can be losslessly converted to arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types; the value is
+// implementation-defined when the above pre-condition is violated.
+template <typename From, typename To>
+struct LosslessArithmeticConvertible
+    : public LosslessArithmeticConvertibleImpl<
+  GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {};  // NOLINT
+
+// This interface knows how to report a Google Mock failure (either
+// non-fatal or fatal).
+class FailureReporterInterface {
+ public:
+  // The type of a failure (either non-fatal or fatal).
+  enum FailureType {
+    NONFATAL, FATAL
+  };
+
+  virtual ~FailureReporterInterface() {}
+
+  // Reports a failure that occurred at the given source file location.
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) = 0;
+};
+
+// Returns the failure reporter used by Google Mock.
+FailureReporterInterface* GetFailureReporter();
+
+// Asserts that condition is true; aborts the process with the given
+// message if condition is false.  We cannot use LOG(FATAL) or CHECK()
+// as Google Mock might be used to mock the log sink itself.  We
+// inline this function to prevent it from showing up in the stack
+// trace.
+inline void Assert(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::FATAL,
+                                        file, line, msg);
+  }
+}
+inline void Assert(bool condition, const char* file, int line) {
+  Assert(condition, file, line, "Assertion failed.");
+}
+
+// Verifies that condition is true; generates a non-fatal failure if
+// condition is false.
+inline void Expect(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::NONFATAL,
+                                        file, line, msg);
+  }
+}
+inline void Expect(bool condition, const char* file, int line) {
+  Expect(condition, file, line, "Expectation failed.");
+}
+
+// Severity level of a log.
+enum LogSeverity {
+  INFO = 0,
+  WARNING = 1
+};
+
+// Valid values for the --gmock_verbose flag.
+
+// All logs (informational and warnings) are printed.
+const char kInfoVerbosity[] = "info";
+// Only warnings are printed.
+const char kWarningVerbosity[] = "warning";
+// No logs are printed.
+const char kErrorVerbosity[] = "error";
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+bool LogIsVisible(LogSeverity severity);
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
+
+// TODO(wan@google.com): group all type utilities together.
+
+// Type traits.
+
+// is_reference<T>::value is non-zero iff T is a reference type.
+template <typename T> struct is_reference : public false_type {};
+template <typename T> struct is_reference<T&> : public true_type {};
+
+// type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
+template <typename T1, typename T2> struct type_equals : public false_type {};
+template <typename T> struct type_equals<T, T> : public true_type {};
+
+// remove_reference<T>::type removes the reference from type T, if any.
+template <typename T> struct remove_reference { typedef T type; };  // NOLINT
+template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
+
+// Invalid<T>() returns an invalid value of type T.  This is useful
+// when a value of type T is needed for compilation, but the statement
+// will not really be executed (or we don't care if the statement
+// crashes).
+template <typename T>
+inline T Invalid() {
+  return *static_cast<typename remove_reference<T>::type*>(NULL);
+}
+template <>
+inline void Invalid<void>() {}
+
+// Given a raw type (i.e. having no top-level reference or const
+// modifier) RawContainer that's either an STL-style container or a
+// native array, class StlContainerView<RawContainer> has the
+// following members:
+//
+//   - type is a type that provides an STL-style container view to
+//     (i.e. implements the STL container concept for) RawContainer;
+//   - const_reference is a type that provides a reference to a const
+//     RawContainer;
+//   - ConstReference(raw_container) returns a const reference to an STL-style
+//     container view to raw_container, which is a RawContainer.
+//   - Copy(raw_container) returns an STL-style container view of a
+//     copy of raw_container, which is a RawContainer.
+//
+// This generic version is used when RawContainer itself is already an
+// STL-style container.
+template <class RawContainer>
+class StlContainerView {
+ public:
+  typedef RawContainer type;
+  typedef const type& const_reference;
+
+  static const_reference ConstReference(const RawContainer& container) {
+    // Ensures that RawContainer is not a const type.
+    testing::StaticAssertTypeEq<RawContainer,
+        GTEST_REMOVE_CONST_(RawContainer)>();
+    return container;
+  }
+  static type Copy(const RawContainer& container) { return container; }
+};
+
+// This specialization is used when RawContainer is a native array type.
+template <typename Element, size_t N>
+class StlContainerView<Element[N]> {
+ public:
+  typedef GTEST_REMOVE_CONST_(Element) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  // NativeArray<T> can represent a native array either by value or by
+  // reference (selected by a constructor argument), so 'const type'
+  // can be used to reference a const native array.  We cannot
+  // 'typedef const type& const_reference' here, as that would mean
+  // ConstReference() has to return a reference to a local variable.
+  typedef const type const_reference;
+
+  static const_reference ConstReference(const Element (&array)[N]) {
+    // Ensures that Element is not a const type.
+    testing::StaticAssertTypeEq<Element, RawElement>();
+#if GTEST_OS_SYMBIAN
+    // The Nokia Symbian compiler confuses itself in template instantiation
+    // for this call without the cast to Element*:
+    // function call '[testing::internal::NativeArray<char *>].NativeArray(
+    //     {lval} const char *[4], long, testing::internal::RelationToSource)'
+    //     does not match
+    // 'testing::internal::NativeArray<char *>::NativeArray(
+    //     char *const *, unsigned int, testing::internal::RelationToSource)'
+    // (instantiating: 'testing::internal::ContainsMatcherImpl
+    //     <const char * (&)[4]>::Matches(const char * (&)[4]) const')
+    // (instantiating: 'testing::internal::StlContainerView<char *[4]>::
+    //     ConstReference(const char * (&)[4])')
+    // (and though the N parameter type is mismatched in the above explicit
+    // conversion of it doesn't help - only the conversion of the array).
+    return type(const_cast<Element*>(&array[0]), N, kReference);
+#else
+    return type(array, N, kReference);
+#endif  // GTEST_OS_SYMBIAN
+  }
+  static type Copy(const Element (&array)[N]) {
+#if GTEST_OS_SYMBIAN
+    return type(const_cast<Element*>(&array[0]), N, kCopy);
+#else
+    return type(array, N, kCopy);
+#endif  // GTEST_OS_SYMBIAN
+  }
+};
+
+// This specialization is used when RawContainer is a native array
+// represented as a (pointer, size) tuple.
+template <typename ElementPointer, typename Size>
+class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
+ public:
+  typedef GTEST_REMOVE_CONST_(
+      typename internal::PointeeOf<ElementPointer>::type) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  typedef const type const_reference;
+
+  static const_reference ConstReference(
+      const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    using ::std::tr1::get;
+    return type(get<0>(array), get<1>(array), kReference);
+  }
+  static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    using ::std::tr1::get;
+    return type(get<0>(array), get<1>(array), kCopy);
+  }
+};
+
+// The following specialization prevents the user from instantiating
+// StlContainer with a reference type.
+template <typename T> class StlContainerView<T&>;
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
diff --git a/src/external/gmock-1.6.0/include/gmock/internal/gmock-port.h b/src/external/gmock-1.6.0/include/gmock/internal/gmock-port.h
new file mode 100644 (file)
index 0000000..3b9cc47
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vadimb@google.com (Vadim Berman)
+//
+// Low-level types and utilities for porting Google Mock to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <iostream>
+
+// Most of the types needed for porting Google Mock are also required
+// for Google Test and are defined in gtest-port.h.
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+
+// To avoid conditional compilation everywhere, we make it
+// gmock-port.h's responsibility to #include the header implementing
+// tr1/tuple.  gmock-port.h does this via gtest-port.h, which is
+// guaranteed to pull in the tuple header.
+
+// For MS Visual C++, check the compiler version. At least VS 2003 is
+// required to compile Google Mock.
+#if defined(_MSC_VER) && _MSC_VER < 1310
+# error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
+#endif
+
+// Macro for referencing flags.  This is public as we want the user to
+// use this syntax to reference Google Mock flags.
+#define GMOCK_FLAG(name) FLAGS_gmock_##name
+
+// Macros for declaring flags.
+#define GMOCK_DECLARE_bool_(name) extern bool GMOCK_FLAG(name)
+#define GMOCK_DECLARE_int32_(name) \
+    extern ::testing::internal::Int32 GMOCK_FLAG(name)
+#define GMOCK_DECLARE_string_(name) \
+    extern ::testing::internal::String GMOCK_FLAG(name)
+
+// Macros for defining flags.
+#define GMOCK_DEFINE_bool_(name, default_val, doc) \
+    bool GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_int32_(name, default_val, doc) \
+    ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_string_(name, default_val, doc) \
+    ::testing::internal::String GMOCK_FLAG(name) = (default_val)
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
diff --git a/src/external/gmock-1.6.0/src/gmock-all.cc b/src/external/gmock-1.6.0/src/gmock-all.cc
new file mode 100644 (file)
index 0000000..7aebce7
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Mocking Framework (Google Mock)
+//
+// This file #includes all Google Mock implementation .cc files.  The
+// purpose is to allow a user to build Google Mock by compiling this
+// file alone.
+
+// This line ensures that gmock.h can be compiled on its own, even
+// when it's fused.
+#include "gmock/gmock.h"
+
+// The following lines pull in the real gmock *.cc files.
+#include "src/gmock-cardinalities.cc"
+#include "src/gmock-internal-utils.cc"
+#include "src/gmock-matchers.cc"
+#include "src/gmock-spec-builders.cc"
+#include "src/gmock.cc"
diff --git a/src/external/gmock-1.6.0/src/gmock-cardinalities.cc b/src/external/gmock-1.6.0/src/gmock-cardinalities.cc
new file mode 100644 (file)
index 0000000..1a7902b
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements cardinalities.
+
+#include "gmock/gmock-cardinalities.h"
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+namespace {
+
+// Implements the Between(m, n) cardinality.
+class BetweenCardinalityImpl : public CardinalityInterface {
+ public:
+  BetweenCardinalityImpl(int min, int max)
+      : min_(min >= 0 ? min : 0),
+        max_(max >= min_ ? max : min_) {
+    std::stringstream ss;
+    if (min < 0) {
+      ss << "The invocation lower bound must be >= 0, "
+         << "but is actually " << min << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (max < 0) {
+      ss << "The invocation upper bound must be >= 0, "
+         << "but is actually " << max << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (min > max) {
+      ss << "The invocation upper bound (" << max
+         << ") must be >= the invocation lower bound (" << min
+         << ").";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    }
+  }
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return min_; }
+  virtual int ConservativeUpperBound() const { return max_; }
+
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return min_ <= call_count && call_count <= max_ ;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return call_count >= max_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const;
+ private:
+  const int min_;
+  const int max_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
+};
+
+// Formats "n times" in a human-friendly way.
+inline internal::string FormatTimes(int n) {
+  if (n == 1) {
+    return "once";
+  } else if (n == 2) {
+    return "twice";
+  } else {
+    std::stringstream ss;
+    ss << n << " times";
+    return ss.str();
+  }
+}
+
+// Describes the Between(m, n) cardinality in human-friendly text.
+void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
+  if (min_ == 0) {
+    if (max_ == 0) {
+      *os << "never called";
+    } else if (max_ == INT_MAX) {
+      *os << "called any number of times";
+    } else {
+      *os << "called at most " << FormatTimes(max_);
+    }
+  } else if (min_ == max_) {
+    *os << "called " << FormatTimes(min_);
+  } else if (max_ == INT_MAX) {
+    *os << "called at least " << FormatTimes(min_);
+  } else {
+    // 0 < min_ < max_ < INT_MAX
+    *os << "called between " << min_ << " and " << max_ << " times";
+  }
+}
+
+}  // Unnamed namespace
+
+// Describes the given call count to an ostream.
+void Cardinality::DescribeActualCallCountTo(int actual_call_count,
+                                            ::std::ostream* os) {
+  if (actual_call_count > 0) {
+    *os << "called " << FormatTimes(actual_call_count);
+  } else {
+    *os << "never called";
+  }
+}
+
+// Creates a cardinality that allows at least n calls.
+Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
+
+// Creates a cardinality that allows at most n calls.
+Cardinality AtMost(int n) { return Between(0, n); }
+
+// Creates a cardinality that allows any number of calls.
+Cardinality AnyNumber() { return AtLeast(0); }
+
+// Creates a cardinality that allows between min and max calls.
+Cardinality Between(int min, int max) {
+  return Cardinality(new BetweenCardinalityImpl(min, max));
+}
+
+// Creates a cardinality that allows exactly n calls.
+Cardinality Exactly(int n) { return Between(n, n); }
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/src/gmock-internal-utils.cc b/src/external/gmock-1.6.0/src/gmock-internal-utils.cc
new file mode 100644 (file)
index 0000000..dd38132
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#include "gmock/internal/gmock-internal-utils.h"
+
+#include <ctype.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+string ConvertIdentifierNameToWords(const char* id_name) {
+  string result;
+  char prev_char = '\0';
+  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
+    // We don't care about the current locale as the input is
+    // guaranteed to be a valid C++ identifier name.
+    const bool starts_new_word = IsUpper(*p) ||
+        (!IsAlpha(prev_char) && IsLower(*p)) ||
+        (!IsDigit(prev_char) && IsDigit(*p));
+
+    if (IsAlNum(*p)) {
+      if (starts_new_word && result != "")
+        result += ' ';
+      result += ToLower(*p);
+    }
+  }
+  return result;
+}
+
+// This class reports Google Mock failures as Google Test failures.  A
+// user can define another class in a similar fashion if he intends to
+// use Google Mock with a testing framework other than Google Test.
+class GoogleTestFailureReporter : public FailureReporterInterface {
+ public:
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) {
+    AssertHelper(type == FATAL ?
+                 TestPartResult::kFatalFailure :
+                 TestPartResult::kNonFatalFailure,
+                 file,
+                 line,
+                 message.c_str()) = Message();
+    if (type == FATAL) {
+      posix::Abort();
+    }
+  }
+};
+
+// Returns the global failure reporter.  Will create a
+// GoogleTestFailureReporter and return it the first time called.
+FailureReporterInterface* GetFailureReporter() {
+  // Points to the global failure reporter used by Google Mock.  gcc
+  // guarantees that the following use of failure_reporter is
+  // thread-safe.  We may need to add additional synchronization to
+  // protect failure_reporter if we port Google Mock to other
+  // compilers.
+  static FailureReporterInterface* const failure_reporter =
+      new GoogleTestFailureReporter();
+  return failure_reporter;
+}
+
+// Protects global resources (stdout in particular) used by Log().
+static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+bool LogIsVisible(LogSeverity severity) {
+  if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
+    // Always show the log if --gmock_verbose=info.
+    return true;
+  } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
+    // Always hide it if --gmock_verbose=error.
+    return false;
+  } else {
+    // If --gmock_verbose is neither "info" nor "error", we treat it
+    // as "warning" (its default value).
+    return severity == WARNING;
+  }
+}
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+void Log(LogSeverity severity, const string& message,
+         int stack_frames_to_skip) {
+  if (!LogIsVisible(severity))
+    return;
+
+  // Ensures that logs from different threads don't interleave.
+  MutexLock l(&g_log_mutex);
+
+  // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
+  // macro.
+
+  if (severity == WARNING) {
+    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
+    std::cout << "\nGMOCK WARNING:";
+  }
+  // Pre-pends a new-line to message if it doesn't start with one.
+  if (message.empty() || message[0] != '\n') {
+    std::cout << "\n";
+  }
+  std::cout << message;
+  if (stack_frames_to_skip >= 0) {
+#ifdef NDEBUG
+    // In opt mode, we have to be conservative and skip no stack frame.
+    const int actual_to_skip = 0;
+#else
+    // In dbg mode, we can do what the caller tell us to do (plus one
+    // for skipping this function's stack frame).
+    const int actual_to_skip = stack_frames_to_skip + 1;
+#endif  // NDEBUG
+
+    // Appends a new-line to message if it doesn't end with one.
+    if (!message.empty() && *message.rbegin() != '\n') {
+      std::cout << "\n";
+    }
+    std::cout << "Stack trace:\n"
+         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+             ::testing::UnitTest::GetInstance(), actual_to_skip);
+  }
+  std::cout << ::std::flush;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/src/gmock-matchers.cc b/src/external/gmock-1.6.0/src/gmock-matchers.cc
new file mode 100644 (file)
index 0000000..a5e6824
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements Matcher<const string&>, Matcher<string>, and
+// utilities for defining matchers.
+
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-generated-matchers.h"
+
+#include <string.h>
+#include <sstream>
+#include <string>
+
+namespace testing {
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const internal::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+namespace internal {
+
+// Joins a vector of strings as if they are fields of a tuple; returns
+// the joined string.
+string JoinAsTuple(const Strings& fields) {
+  switch (fields.size()) {
+    case 0:
+      return "";
+    case 1:
+      return fields[0];
+    default:
+      string result = "(" + fields[0];
+      for (size_t i = 1; i < fields.size(); i++) {
+        result += ", ";
+        result += fields[i];
+      }
+      result += ")";
+      return result;
+  }
+}
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+string FormatMatcherDescription(bool negation, const char* matcher_name,
+                                const Strings& param_values) {
+  string result = ConvertIdentifierNameToWords(matcher_name);
+  if (param_values.size() >= 1)
+    result += " " + JoinAsTuple(param_values);
+  return negation ? "not (" + result + ")" : result;
+}
+
+}  // namespace internal
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/src/gmock-spec-builders.cc b/src/external/gmock-1.6.0/src/gmock-spec-builders.cc
new file mode 100644 (file)
index 0000000..aa33cc4
--- /dev/null
@@ -0,0 +1,797 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the spec builder syntax (ON_CALL and
+// EXPECT_CALL).
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <stdlib.h>
+#include <iostream>  // NOLINT
+#include <map>
+#include <set>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
+# include <unistd.h>  // NOLINT
+#endif
+
+namespace testing {
+namespace internal {
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message) {
+  ::std::ostringstream s;
+  s << file << ":" << line << ": " << message << ::std::endl;
+  Log(severity, s.str(), 0);
+}
+
+// Constructs an ExpectationBase object.
+ExpectationBase::ExpectationBase(const char* a_file,
+                                 int a_line,
+                                 const string& a_source_text)
+    : file_(a_file),
+      line_(a_line),
+      source_text_(a_source_text),
+      cardinality_specified_(false),
+      cardinality_(Exactly(1)),
+      call_count_(0),
+      retired_(false),
+      extra_matcher_specified_(false),
+      repeated_action_specified_(false),
+      retires_on_saturation_(false),
+      last_clause_(kNone),
+      action_count_checked_(false) {}
+
+// Destructs an ExpectationBase object.
+ExpectationBase::~ExpectationBase() {}
+
+// Explicitly specifies the cardinality of this expectation.  Used by
+// the subclasses to implement the .Times() clause.
+void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
+  cardinality_specified_ = true;
+  cardinality_ = a_cardinality;
+}
+
+// Retires all pre-requisites of this expectation.
+void ExpectationBase::RetireAllPreRequisites() {
+  if (is_retired()) {
+    // We can take this short-cut as we never retire an expectation
+    // until we have retired all its pre-requisites.
+    return;
+  }
+
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    ExpectationBase* const prerequisite = it->expectation_base().get();
+    if (!prerequisite->is_retired()) {
+      prerequisite->RetireAllPreRequisites();
+      prerequisite->Retire();
+    }
+  }
+}
+
+// Returns true iff all pre-requisites of this expectation have been
+// satisfied.
+// L >= g_gmock_mutex
+bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (!(it->expectation_base()->IsSatisfied()) ||
+        !(it->expectation_base()->AllPrerequisitesAreSatisfied()))
+      return false;
+  }
+  return true;
+}
+
+// Adds unsatisfied pre-requisites of this expectation to 'result'.
+// L >= g_gmock_mutex
+void ExpectationBase::FindUnsatisfiedPrerequisites(
+    ExpectationSet* result) const {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (it->expectation_base()->IsSatisfied()) {
+      // If *it is satisfied and has a call count of 0, some of its
+      // pre-requisites may not be satisfied yet.
+      if (it->expectation_base()->call_count_ == 0) {
+        it->expectation_base()->FindUnsatisfiedPrerequisites(result);
+      }
+    } else {
+      // Now that we know *it is unsatisfied, we are not so interested
+      // in whether its pre-requisites are satisfied.  Therefore we
+      // don't recursively call FindUnsatisfiedPrerequisites() here.
+      *result += *it;
+    }
+  }
+}
+
+// Describes how many times a function call matching this
+// expectation has occurred.
+// L >= g_gmock_mutex
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const {
+  g_gmock_mutex.AssertHeld();
+
+  // Describes how many times the function is expected to be called.
+  *os << "         Expected: to be ";
+  cardinality().DescribeTo(os);
+  *os << "\n           Actual: ";
+  Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+  // Describes the state of the expectation (e.g. is it satisfied?
+  // is it active?).
+  *os << " - " << (IsOverSaturated() ? "over-saturated" :
+                   IsSaturated() ? "saturated" :
+                   IsSatisfied() ? "satisfied" : "unsatisfied")
+      << " and "
+      << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before.  Prints a warning if there are too many or too
+// few actions.
+// L < mutex_
+void ExpectationBase::CheckActionCountIfNotDone() const {
+  bool should_check = false;
+  {
+    MutexLock l(&mutex_);
+    if (!action_count_checked_) {
+      action_count_checked_ = true;
+      should_check = true;
+    }
+  }
+
+  if (should_check) {
+    if (!cardinality_specified_) {
+      // The cardinality was inferred - no need to check the action
+      // count against it.
+      return;
+    }
+
+    // The cardinality was explicitly specified.
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    const int upper_bound = cardinality().ConservativeUpperBound();
+    const int lower_bound = cardinality().ConservativeLowerBound();
+    bool too_many;  // True if there are too many actions, or false
+    // if there are too few.
+    if (action_count > upper_bound ||
+        (action_count == upper_bound && repeated_action_specified_)) {
+      too_many = true;
+    } else if (0 < action_count && action_count < lower_bound &&
+               !repeated_action_specified_) {
+      too_many = false;
+    } else {
+      return;
+    }
+
+    ::std::stringstream ss;
+    DescribeLocationTo(&ss);
+    ss << "Too " << (too_many ? "many" : "few")
+       << " actions specified in " << source_text() << "...\n"
+       << "Expected to be ";
+    cardinality().DescribeTo(&ss);
+    ss << ", but has " << (too_many ? "" : "only ")
+       << action_count << " WillOnce()"
+       << (action_count == 1 ? "" : "s");
+    if (repeated_action_specified_) {
+      ss << " and a WillRepeatedly()";
+    }
+    ss << ".";
+    Log(WARNING, ss.str(), -1);  // -1 means "don't print stack trace".
+  }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+  if (last_clause_ == kTimes) {
+    ExpectSpecProperty(false,
+                       ".Times() cannot appear "
+                       "more than once in an EXPECT_CALL().");
+  } else {
+    ExpectSpecProperty(last_clause_ < kTimes,
+                       ".Times() cannot appear after "
+                       ".InSequence(), .WillOnce(), .WillRepeatedly(), "
+                       "or .RetiresOnSaturation().");
+  }
+  last_clause_ = kTimes;
+
+  SpecifyCardinality(a_cardinality);
+}
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg) {
+  switch (reaction) {
+    case ALLOW:
+      Log(INFO, msg, 3);
+      break;
+    case WARN:
+      Log(WARNING, msg, 3);
+      break;
+    default:  // FAIL
+      Expect(false, NULL, -1, msg);
+  }
+}
+
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+    : mock_obj_(NULL), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry.  Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) {
+  {
+    MutexLock l(&g_gmock_mutex);
+    mock_obj_ = mock_obj;
+  }
+  Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function.  Will be called upon each invocation of this
+// mock function.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::SetOwnerAndName(
+    const void* mock_obj, const char* name) {
+  // We protect name_ under g_gmock_mutex in case this mock function
+  // is called from two threads concurrently.
+  MutexLock l(&g_gmock_mutex);
+  mock_obj_ = mock_obj;
+  name_ = name;
+}
+
+// Returns the name of the function being mocked.  Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const void* UntypedFunctionMockerBase::MockObject() const {
+  const void* mock_obj;
+  {
+    // We protect mock_obj_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(mock_obj_ != NULL, __FILE__, __LINE__,
+           "MockObject() must not be called before RegisterOwner() or "
+           "SetOwnerAndName() has been called.");
+    mock_obj = mock_obj_;
+  }
+  return mock_obj;
+}
+
+// Returns the name of this mock method.  Must be called after
+// SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const char* UntypedFunctionMockerBase::Name() const {
+  const char* name;
+  {
+    // We protect name_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(name_ != NULL, __FILE__, __LINE__,
+           "Name() must not be called before SetOwnerAndName() has "
+           "been called.");
+    name = name_;
+  }
+  return name;
+}
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it.  The caller is responsible
+// for deleting the result.
+// L < g_gmock_mutex
+const UntypedActionResultHolderBase*
+UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) {
+  if (untyped_expectations_.size() == 0) {
+    // No expectation is set on this mock method - we have an
+    // uninteresting call.
+
+    // We must get Google Mock's reaction on uninteresting calls
+    // made on this mock object BEFORE performing the action,
+    // because the action may DELETE the mock object and make the
+    // following expression meaningless.
+    const CallReaction reaction =
+        Mock::GetReactionOnUninterestingCalls(MockObject());
+
+    // True iff we need to print this call's arguments and return
+    // value.  This definition must be kept in sync with
+    // the behavior of ReportUninterestingCall().
+    const bool need_to_report_uninteresting_call =
+        // If the user allows this uninteresting call, we print it
+        // only when he wants informational messages.
+        reaction == ALLOW ? LogIsVisible(INFO) :
+        // If the user wants this to be a warning, we print it only
+        // when he wants to see warnings.
+        reaction == WARN ? LogIsVisible(WARNING) :
+        // Otherwise, the user wants this to be an error, and we
+        // should always print detailed information in the error.
+        true;
+
+    if (!need_to_report_uninteresting_call) {
+      // Perform the action without printing the call information.
+      return this->UntypedPerformDefaultAction(untyped_args, "");
+    }
+
+    // Warns about the uninteresting call.
+    ::std::stringstream ss;
+    this->UntypedDescribeUninterestingCall(untyped_args, &ss);
+
+    // Calculates the function result.
+    const UntypedActionResultHolderBase* const result =
+        this->UntypedPerformDefaultAction(untyped_args, ss.str());
+
+    // Prints the function result.
+    if (result != NULL)
+      result->PrintAsActionResult(&ss);
+
+    ReportUninterestingCall(reaction, ss.str());
+    return result;
+  }
+
+  bool is_excessive = false;
+  ::std::stringstream ss;
+  ::std::stringstream why;
+  ::std::stringstream loc;
+  const void* untyped_action = NULL;
+
+  // The UntypedFindMatchingExpectation() function acquires and
+  // releases g_gmock_mutex.
+  const ExpectationBase* const untyped_expectation =
+      this->UntypedFindMatchingExpectation(
+          untyped_args, &untyped_action, &is_excessive,
+          &ss, &why);
+  const bool found = untyped_expectation != NULL;
+
+  // True iff we need to print the call's arguments and return value.
+  // This definition must be kept in sync with the uses of Expect()
+  // and Log() in this function.
+  const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
+  if (!need_to_report_call) {
+    // Perform the action without printing the call information.
+    return
+        untyped_action == NULL ?
+        this->UntypedPerformDefaultAction(untyped_args, "") :
+        this->UntypedPerformAction(untyped_action, untyped_args);
+  }
+
+  ss << "    Function call: " << Name();
+  this->UntypedPrintArgs(untyped_args, &ss);
+
+  // In case the action deletes a piece of the expectation, we
+  // generate the message beforehand.
+  if (found && !is_excessive) {
+    untyped_expectation->DescribeLocationTo(&loc);
+  }
+
+  const UntypedActionResultHolderBase* const result =
+      untyped_action == NULL ?
+      this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
+      this->UntypedPerformAction(untyped_action, untyped_args);
+  if (result != NULL)
+    result->PrintAsActionResult(&ss);
+  ss << "\n" << why.str();
+
+  if (!found) {
+    // No expectation matches this call - reports a failure.
+    Expect(false, NULL, -1, ss.str());
+  } else if (is_excessive) {
+    // We had an upper-bound violation and the failure message is in ss.
+    Expect(false, untyped_expectation->file(),
+           untyped_expectation->line(), ss.str());
+  } else {
+    // We had an expected call and the matching expectation is
+    // described in ss.
+    Log(INFO, loc.str() + ss.str(), 2);
+  }
+
+  return result;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    if (it->get() == exp) {
+      return Expectation(*it);
+    }
+  }
+
+  Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+  return Expectation();
+  // The above statement is just to make the code compile, and will
+  // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures
+// and returns false if not.
+// L >= g_gmock_mutex
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() {
+  g_gmock_mutex.AssertHeld();
+  bool expectations_met = true;
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    ExpectationBase* const untyped_expectation = it->get();
+    if (untyped_expectation->IsOverSaturated()) {
+      // There was an upper-bound violation.  Since the error was
+      // already reported when it occurred, there is no need to do
+      // anything here.
+      expectations_met = false;
+    } else if (!untyped_expectation->IsSatisfied()) {
+      expectations_met = false;
+      ::std::stringstream ss;
+      ss  << "Actual function call count doesn't match "
+          << untyped_expectation->source_text() << "...\n";
+      // No need to show the source file location of the expectation
+      // in the description, as the Expect() call that follows already
+      // takes care of it.
+      untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+      untyped_expectation->DescribeCallCountTo(&ss);
+      Expect(false, untyped_expectation->file(),
+             untyped_expectation->line(), ss.str());
+    }
+  }
+  untyped_expectations_.clear();
+  return expectations_met;
+}
+
+}  // namespace internal
+
+// Class Mock.
+
+namespace {
+
+typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
+
+// The current state of a mock object.  Such information is needed for
+// detecting leaked mock objects and explicitly verifying a mock's
+// expectations.
+struct MockObjectState {
+  MockObjectState()
+      : first_used_file(NULL), first_used_line(-1), leakable(false) {}
+
+  // Where in the source file an ON_CALL or EXPECT_CALL is first
+  // invoked on this mock object.
+  const char* first_used_file;
+  int first_used_line;
+  ::std::string first_used_test_case;
+  ::std::string first_used_test;
+  bool leakable;  // true iff it's OK to leak the object.
+  FunctionMockers function_mockers;  // All registered methods of the object.
+};
+
+// A global registry holding the state of all mock objects that are
+// alive.  A mock object is added to this registry the first time
+// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it.  It
+// is removed from the registry in the mock object's destructor.
+class MockObjectRegistry {
+ public:
+  // Maps a mock object (identified by its address) to its state.
+  typedef std::map<const void*, MockObjectState> StateMap;
+
+  // This destructor will be called when a program exits, after all
+  // tests in it have been run.  By then, there should be no mock
+  // object alive.  Therefore we report any living object as test
+  // failure, unless the user explicitly asked us to ignore it.
+  ~MockObjectRegistry() {
+    // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
+    // a macro.
+
+    if (!GMOCK_FLAG(catch_leaked_mocks))
+      return;
+
+    int leaked_count = 0;
+    for (StateMap::const_iterator it = states_.begin(); it != states_.end();
+         ++it) {
+      if (it->second.leakable)  // The user said it's fine to leak this object.
+        continue;
+
+      // TODO(wan@google.com): Print the type of the leaked object.
+      // This can help the user identify the leaked object.
+      std::cout << "\n";
+      const MockObjectState& state = it->second;
+      std::cout << internal::FormatFileLocation(state.first_used_file,
+                                                state.first_used_line);
+      std::cout << " ERROR: this mock object";
+      if (state.first_used_test != "") {
+        std::cout << " (used in test " << state.first_used_test_case << "."
+             << state.first_used_test << ")";
+      }
+      std::cout << " should be deleted but never is. Its address is @"
+           << it->first << ".";
+      leaked_count++;
+    }
+    if (leaked_count > 0) {
+      std::cout << "\nERROR: " << leaked_count
+           << " leaked mock " << (leaked_count == 1 ? "object" : "objects")
+           << " found at program exit.\n";
+      std::cout.flush();
+      ::std::cerr.flush();
+      // RUN_ALL_TESTS() has already returned when this destructor is
+      // called.  Therefore we cannot use the normal Google Test
+      // failure reporting mechanism.
+      _exit(1);  // We cannot call exit() as it is not reentrant and
+                 // may already have been called.
+    }
+  }
+
+  StateMap& states() { return states_; }
+ private:
+  StateMap states_;
+};
+
+// Protected by g_gmock_mutex.
+MockObjectRegistry g_mock_object_registry;
+
+// Maps a mock object to the reaction Google Mock should have when an
+// uninteresting method is called.  Protected by g_gmock_mutex.
+std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
+
+// Sets the reaction Google Mock should have when an uninteresting
+// method of the given mock object is called.
+// L < g_gmock_mutex
+void SetReactionOnUninterestingCalls(const void* mock_obj,
+                                     internal::CallReaction reaction) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction[mock_obj] = reaction;
+}
+
+}  // namespace
+
+// Tells Google Mock to allow uninteresting calls on the given mock
+// object.
+// L < g_gmock_mutex
+void Mock::AllowUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW);
+}
+
+// Tells Google Mock to warn the user about uninteresting calls on the
+// given mock object.
+// L < g_gmock_mutex
+void Mock::WarnUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::WARN);
+}
+
+// Tells Google Mock to fail uninteresting calls on the given mock
+// object.
+// L < g_gmock_mutex
+void Mock::FailUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::FAIL);
+}
+
+// Tells Google Mock the given mock object is being destroyed and its
+// entry in the call-reaction table should be removed.
+// L < g_gmock_mutex
+void Mock::UnregisterCallReaction(const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction.erase(mock_obj);
+}
+
+// Returns the reaction Google Mock will have on uninteresting calls
+// made on the given mock object.
+// L < g_gmock_mutex
+internal::CallReaction Mock::GetReactionOnUninterestingCalls(
+    const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
+      internal::WARN : g_uninteresting_call_reaction[mock_obj];
+}
+
+// Tells Google Mock to ignore mock_obj when checking for leaked mock
+// objects.
+// L < g_gmock_mutex
+void Mock::AllowLeak(const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].leakable = true;
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+// L < g_gmock_mutex
+bool Mock::VerifyAndClearExpectations(void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies all expectations on the given mock object and clears its
+// default actions and expectations.  Returns true iff the
+// verification was successful.
+// L < g_gmock_mutex
+bool Mock::VerifyAndClear(void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  ClearDefaultActionsLocked(mock_obj);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+// L >= g_gmock_mutex
+bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) {
+  internal::g_gmock_mutex.AssertHeld();
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No EXPECT_CALL() was set on the given mock object.
+    return true;
+  }
+
+  // Verifies and clears the expectations on each mock method in the
+  // given mock object.
+  bool expectations_met = true;
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    if (!(*it)->VerifyAndClearExpectationsLocked()) {
+      expectations_met = false;
+    }
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by ClearDefaultActionsLocked().
+  return expectations_met;
+}
+
+// Registers a mock object and a mock method it owns.
+// L < g_gmock_mutex
+void Mock::Register(const void* mock_obj,
+                    internal::UntypedFunctionMockerBase* mocker) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
+}
+
+// Tells Google Mock where in the source code mock_obj is used in an
+// ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+// information helps the user identify which object it is.
+// L < g_gmock_mutex
+void Mock::RegisterUseByOnCallOrExpectCall(
+    const void* mock_obj, const char* file, int line) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  MockObjectState& state = g_mock_object_registry.states()[mock_obj];
+  if (state.first_used_file == NULL) {
+    state.first_used_file = file;
+    state.first_used_line = line;
+    const TestInfo* const test_info =
+        UnitTest::GetInstance()->current_test_info();
+    if (test_info != NULL) {
+      // TODO(wan@google.com): record the test case name when the
+      // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
+      // TearDownTestCase().
+      state.first_used_test_case = test_info->test_case_name();
+      state.first_used_test = test_info->name();
+    }
+  }
+}
+
+// Unregisters a mock method; removes the owning mock object from the
+// registry when the last mock method associated with it has been
+// unregistered.  This is called only in the destructor of
+// FunctionMockerBase.
+// L >= g_gmock_mutex
+void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) {
+  internal::g_gmock_mutex.AssertHeld();
+  for (MockObjectRegistry::StateMap::iterator it =
+           g_mock_object_registry.states().begin();
+       it != g_mock_object_registry.states().end(); ++it) {
+    FunctionMockers& mockers = it->second.function_mockers;
+    if (mockers.erase(mocker) > 0) {
+      // mocker was in mockers and has been just removed.
+      if (mockers.empty()) {
+        g_mock_object_registry.states().erase(it);
+      }
+      return;
+    }
+  }
+}
+
+// Clears all ON_CALL()s set on the given mock object.
+// L >= g_gmock_mutex
+void Mock::ClearDefaultActionsLocked(void* mock_obj) {
+  internal::g_gmock_mutex.AssertHeld();
+
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No ON_CALL() was set on the given mock object.
+    return;
+  }
+
+  // Clears the default actions for each mock method in the given mock
+  // object.
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    (*it)->ClearDefaultActionsLocked();
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by VerifyAndClearExpectationsLocked().
+}
+
+Expectation::Expectation() {}
+
+Expectation::Expectation(
+    const internal::linked_ptr<internal::ExpectationBase>& an_expectation_base)
+    : expectation_base_(an_expectation_base) {}
+
+Expectation::~Expectation() {}
+
+// Adds an expectation to a sequence.
+void Sequence::AddExpectation(const Expectation& expectation) const {
+  if (*last_expectation_ != expectation) {
+    if (last_expectation_->expectation_base() != NULL) {
+      expectation.expectation_base()->immediate_prerequisites_
+          += *last_expectation_;
+    }
+    *last_expectation_ = expectation;
+  }
+}
+
+// Creates the implicit sequence if there isn't one.
+InSequence::InSequence() {
+  if (internal::g_gmock_implicit_sequence.get() == NULL) {
+    internal::g_gmock_implicit_sequence.set(new Sequence);
+    sequence_created_ = true;
+  } else {
+    sequence_created_ = false;
+  }
+}
+
+// Deletes the implicit sequence if it was created by the constructor
+// of this object.
+InSequence::~InSequence() {
+  if (sequence_created_) {
+    delete internal::g_gmock_implicit_sequence.get();
+    internal::g_gmock_implicit_sequence.set(NULL);
+  }
+}
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/src/gmock.cc b/src/external/gmock-1.6.0/src/gmock.cc
new file mode 100644 (file)
index 0000000..700bcb2
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+// TODO(wan@google.com): support using environment variables to
+// control the flag values, like what Google Test does.
+
+GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
+                   "true iff Google Mock should report leaked mock objects "
+                   "as failures.");
+
+GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
+                     "Controls how verbose Google Mock's output is."
+                     "  Valid values:\n"
+                     "  info    - prints all messages.\n"
+                     "  warning - prints warnings and errors.\n"
+                     "  error   - prints errors only.");
+
+namespace internal {
+
+// Parses a string as a command line flag.  The string should have the
+// format "--gmock_flag=value".  When def_optional is true, the
+// "=value" part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseGoogleMockFlagValue(const char* str,
+                                            const char* flag,
+                                            bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--gmock_".
+  const String flag_str = String::Format("--gmock_%s", flag);
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a Google Mock bool flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
+                                    bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for a Google Mock string flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
+                                      String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// The internal implementation of InitGoogleMock().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleMockImpl(int* argc, CharType** argv) {
+  // Makes sure Google Test is initialized.  InitGoogleTest() is
+  // idempotent, so it's fine if the user has already called it.
+  InitGoogleTest(argc, argv);
+  if (*argc <= 0) return;
+
+  for (int i = 1; i != *argc; i++) {
+    const String arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    // Do we see a Google Mock flag?
+    if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
+                                &GMOCK_FLAG(catch_leaked_mocks)) ||
+        ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+}
+
+}  // namespace internal
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses a command line for the flags that
+// Google Mock recognizes.  Whenever a Google Mock flag is seen, it is
+// removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+void InitGoogleMock(int* argc, char** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleMock(int* argc, wchar_t** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+}  // namespace testing
diff --git a/src/external/gmock-1.6.0/src/gmock_main.cc b/src/external/gmock-1.6.0/src/gmock_main.cc
new file mode 100644 (file)
index 0000000..9d8aea2
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <iostream>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
+// causes a link error when _tmain is defined in a static library and UNICODE
+// is enabled. For this reason instead of _tmain, main function is used on
+// Windows. See the following link to track the current status of this bug:
+// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464  // NOLINT
+#if GTEST_OS_WINDOWS_MOBILE
+# include <tchar.h>  // NOLINT
+
+int _tmain(int argc, TCHAR** argv) {
+#else
+int main(int argc, char** argv) {
+#endif  // GTEST_OS_WINDOWS_MOBILE
+  std::cout << "Running main() from gmock_main.cc\n";
+  // Since Google Mock depends on Google Test, InitGoogleMock() is
+  // also responsible for initializing Google Test.  Therefore there's
+  // no need for calling testing::InitGoogleTest() separately.
+  testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/gmxlib/.cvsignore b/src/gmxlib/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/gmxlib/.gitignore b/src/gmxlib/.gitignore
deleted file mode 100644 (file)
index 17435c8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-version.c
diff --git a/src/gmxlib/CMakeLists.txt b/src/gmxlib/CMakeLists.txt
deleted file mode 100644 (file)
index 4a681b2..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-
-
-# add target that generates version.c every time a make is run
-# only do this if we generate the version
-if(USE_VERSION_H)
-    add_custom_target(gmx_version ALL
-            COMMAND ${CMAKE_COMMAND} 
-                -D GIT_EXECUTABLE="${GIT_EXECUTABLE}"
-                -D GIT_VERSION="${GIT_VERSION}"
-                -D PROJECT_VERSION="${PROJECT_VERSION}"
-                -D PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}"
-                -D VERSION_C_CMAKEIN="${CMAKE_SOURCE_DIR}/src/gmxlib/version.c.cmakein"
-                -D VERSION_C_OUT="${CMAKE_CURRENT_BINARY_DIR}/version.c"
-                -P ${CMAKE_SOURCE_DIR}/cmake/gmxGenerateVersionInfo.cmake 
-            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/gmxlib 
-            DEPENDS ${CMAKE_SOURCE_DIR}/src/gmxlib/version.c.cmakein
-            COMMENT "Generating version information")
-endif()
-
-# The nonbonded directory contains subdirectories that are only
-# conditionally built, so we cannot use a GLOB_RECURSE here.
-file(GLOB GMXLIB_SOURCES *.c 
-     selection/*.c trajana/*.c
-     statistics/*.c nonbonded/*.c nonbonded/nb_kernel_c/*.c)
-
-# This source file is generated
-file(GLOB VERSION_SOURCE version.c)
-
-if(VERSION_SOURCE)
-       list(REMOVE_ITEM GMXLIB_SOURCES ${VERSION_SOURCE})
-endif(VERSION_SOURCE)
-
-# add version.c to the list of sources and tell cmake that it is generated
-if(USE_VERSION_H)
-LIST(APPEND GMXLIB_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/version.c) # auto-generated
-set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/version.c 
-                PROPERTIES GENERATED true)
-endif()
-
-if(GMX_DOUBLE)
-  set(SSETYPE sse2)
-else()
-  set(SSETYPE sse)
-endif()
-
-if(GMX_IA32_ASM)
-  file(GLOB GMX_SSEKERNEL_C_SRC   nonbonded/nb_kernel_ia32_${SSETYPE}/*.c)
-  if(GMX_ASM_USEASM-NASM)
-    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_ia32_${SSETYPE}/*intel_syntax*.s)    
-  else()
-    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_ia32_${SSETYPE}/*${SSETYPE}.s nonbonded/nb_kernel_ia32_${SSETYPE}/*asm.s)
-  endif()
-endif(GMX_IA32_ASM)
-
-if(GMX_X86_64_ASM)
-  file(GLOB GMX_SSEKERNEL_C_SRC   nonbonded/nb_kernel_x86_64_${SSETYPE}/*.c)
-  if(GMX_ASM_USEASM-NASM)
-    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_x86_64_${SSETYPE}/*intel_syntax*.s)
-  else()
-    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_x86_64_${SSETYPE}/*${SSETYPE}.s nonbonded/nb_kernel_x86_64_${SSETYPE}/*asm.s)
-  endif()
-endif(GMX_X86_64_ASM)
-
-if(GMX_FORTRAN)
-  if (GMX_DOUBLE)
-    file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_f77_double/*.[cf])
-  else(GMX_DOUBLE)
-    file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_f77_single/*.[cf])
-  endif(GMX_DOUBLE)
-endif(GMX_FORTRAN)
-
-if(GMX_POWER6)
-  file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_power6/*.[cF])
-endif(GMX_POWER6)
-
-if(GMX_BLUEGENE)
-  file(GLOB GMX_BLUEGENE_C_SRC nonbonded/nb_kernel_bluegene/*.c)
-endif(GMX_BLUEGENE)
-
-if(GMX_PPC_ALTIVEC)
-  file(GLOB GMX_PPC_ALTIVEC_SRC nonbonded/nb_kernel_ppc_altivec/*.c)
-endif(GMX_PPC_ALTIVEC)
-
-if(NOT GMX_EXTERNAL_BLAS)
-  file(GLOB BLAS_SOURCES gmx_blas/*.c)
-endif(NOT GMX_EXTERNAL_BLAS)
-
-if(NOT GMX_EXTERNAL_LAPACK)
-  file(GLOB LAPACK_SOURCES gmx_lapack/*.c)
-endif(NOT GMX_EXTERNAL_LAPACK)
-
-# This would be the standard way to include thread_mpi, but we want libgmx
-# to link the functions directly
-#if(GMX_THREADS)
-#    add_subdirectory(thread_mpi)
-#endif(GMX_THREADS)
-#target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES} ${THREAD_MPI_LIB})
-
-# Files called xxx_test.c are test drivers with a main() function for module xxx.c,
-# so they should not be included in the library
-file(GLOB_RECURSE NOT_GMXLIB_SOURCES *_test.c *\#*)
-list(REMOVE_ITEM GMXLIB_SOURCES ${NOT_GMXLIB_SOURCES})  
-# Selection has test_ instead of _test.
-file(GLOB SELECTION_TEST selection/test*)
-list(REMOVE_ITEM GMXLIB_SOURCES ${SELECTION_TEST})
-
-# only fiddle with assembly kernels if we're not doing OpenMM build
-if(NOT GMX_OPENMM) 
-if(GMX_ASM_USEASM-NASM)
-  enable_language(ASM-NASM)
-
-  # if NASM is used, we need a special build command for windows...
-  FOREACH(SRC ${GMX_SSEKERNEL_ASM_SRC})
-    GET_FILENAME_COMPONENT(FILE_BASE ${SRC} NAME_WE)
-    SET(OBJ ${CMAKE_CURRENT_BINARY_DIR}/${FILE_BASE}${CMAKE_C_OUTPUT_EXTENSION})
-
-    ADD_CUSTOM_COMMAND(OUTPUT ${OBJ}
-                       MAIN_DEPENDENCY ${SRC}
-                       COMMAND ${CMAKE_ASM-NASM_COMPILER} -f ${CMAKE_ASM-NASM_OBJECT_FORMAT} -o ${OBJ} ${SRC})
-
-    SET(ALL_ASM_OBJS ${ALL_ASM_OBJS} ${OBJ})
-  ENDFOREACH(SRC ${GMX_SSEKERNEL_ASM_SRC})
-  set(GMX_SSEKERNEL_ASM_SRC ${ALL_ASM_OBJS})
-
-else(GMX_ASM_USEASM-NASM)
-
-  enable_language(ASM-ATT)
-  SET(CMAKE_ASM-ATT_COMPILER ${CMAKE_C_COMPILER})
-  if(GMX_IA32_ASM)
-    set_source_files_properties(${GMX_SSEKERNEL_ASM_SRC} PROPERTIES COMPILE_FLAGS "-c -m32")
-  else()
-    set_source_files_properties(${GMX_SSEKERNEL_ASM_SRC} PROPERTIES COMPILE_FLAGS "-c -m64")
-  endif()
-
-endif(GMX_ASM_USEASM-NASM)
-endif(NOT GMX_OPENMM)
-
-add_library(gmx ${GMXLIB_SOURCES} ${BLAS_SOURCES} ${LAPACK_SOURCES} ${GMX_SSEKERNEL_C_SRC} ${GMX_SSEKERNEL_ASM_SRC} ${FORTRAN_SOURCES} ${GMX_BLUEGENE_C_SRC} ${GMX_PPC_ALTIVEC_SRC} ${THREAD_MPI_SRC})
-target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES}  ${THREAD_LIB})
-if(USE_VERSION_H)
-       add_dependencies(gmx gmx_version) 
-endif()
-set_target_properties(gmx PROPERTIES OUTPUT_NAME "gmx${GMX_LIBS_SUFFIX}" SOVERSION ${SOVERSION} INSTALL_NAME_DIR "${LIB_INSTALL_DIR}")
-
-install(TARGETS gmx DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libgmx.pc.cmakein ${CMAKE_CURRENT_BINARY_DIR}/libgmx.pc @ONLY)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgmx.pc
-        DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
-        RENAME "libgmx${GMX_LIBS_SUFFIX}.pc"
-        COMPONENT development)
-
diff --git a/src/gmxlib/libgmx.pc.cmakein b/src/gmxlib/libgmx.pc.cmakein
deleted file mode 100644 (file)
index dd9f8ad..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCL_INSTALL_DIR@
-
-Name: libgmx
-Description: Gromacs default lib
-URL: http://www.gromacs.org
-Version: @PROJECT_VERSION@
-Requires:
-Libs.private: -lm @CMAKE_THREAD_LIBS_INIT@ @PKG_DL_LIBS@
-Libs: -L${libdir} -lgmx@GMX_LIBS_SUFFIX@
-Cflags: -I${includedir} @PKG_CFLAGS@
-
diff --git a/src/gmxlib/mvdata.c b/src/gmxlib/mvdata.c
deleted file mode 100644 (file)
index e25baaf..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-/* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sysstuff.h>
-#include <string.h>
-#include "typedefs.h"
-#include "main.h"
-#include "mvdata.h"
-#include "network.h"
-#include "smalloc.h"
-#include "gmx_fatal.h"
-#include "symtab.h"
-#include "vec.h"
-#include "tgroup.h"
-
-#define   block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
-/* Probably the test for (nr) > 0 in the next macro is only needed
- * on BlueGene(/L), where IBM's MPI_Bcast will segfault after
- * dereferencing a null pointer, even when no data is to be transferred. */
-#define  nblock_bc(cr,nr,d) { if ((nr) > 0) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr)); }
-#define    snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
-/* Dirty macro with bAlloc not as an argument */
-#define nblock_abc(cr,nr,d) { if (bAlloc) snew((d),(nr)); nblock_bc(cr,(nr),(d)); }
-
-static void bc_string(const t_commrec *cr,t_symtab *symtab,char ***s)
-{
-  int handle;
-  
-  if (MASTER(cr)) {
-    handle = lookup_symtab(symtab,*s);
-  }
-  block_bc(cr,handle);
-  if (!MASTER(cr)) {
-    *s = get_symtab_handle(symtab,handle);
-  }
-}
-
-static void bc_strings(const t_commrec *cr,t_symtab *symtab,int nr,char ****nm)
-{
-  int  i;
-  int  *handle;
-  char ***NM;
-
-  snew(handle,nr);
-  if (MASTER(cr)) {
-    NM = *nm;
-    for(i=0; (i<nr); i++)
-      handle[i] = lookup_symtab(symtab,NM[i]);
-  }
-  nblock_bc(cr,nr,handle);
-
-  if (!MASTER(cr)) {
-    snew_bc(cr,*nm,nr);
-    NM = *nm;
-    for (i=0; (i<nr); i++) 
-      (*nm)[i] = get_symtab_handle(symtab,handle[i]);
-  }
-  sfree(handle);
-}
-
-static void bc_strings_resinfo(const t_commrec *cr,t_symtab *symtab,
-                              int nr,t_resinfo *resinfo)
-{
-  int  i;
-  int  *handle;
-
-  snew(handle,nr);
-  if (MASTER(cr)) {
-    for(i=0; (i<nr); i++)
-      handle[i] = lookup_symtab(symtab,resinfo[i].name);
-  }
-  nblock_bc(cr,nr,handle);
-
-  if (!MASTER(cr)) {
-    for (i=0; (i<nr); i++) 
-      resinfo[i].name = get_symtab_handle(symtab,handle[i]);
-  }
-  sfree(handle);
-}
-
-static void bc_symtab(const t_commrec *cr,t_symtab *symtab)
-{
-  int i,nr,len;
-  t_symbuf *symbuf;
-
-  block_bc(cr,symtab->nr);
-  nr = symtab->nr;
-  snew_bc(cr,symtab->symbuf,1);
-  symbuf = symtab->symbuf;
-  symbuf->bufsize = nr;
-  snew_bc(cr,symbuf->buf,nr);
-  for (i=0; i<nr; i++) {
-    if (MASTER(cr))
-      len = strlen(symbuf->buf[i]) + 1;
-    block_bc(cr,len);
-    snew_bc(cr,symbuf->buf[i],len);
-    nblock_bc(cr,len,symbuf->buf[i]);
-  }
-}
-
-static void bc_block(const t_commrec *cr,t_block *block)
-{
-  block_bc(cr,block->nr);
-  snew_bc(cr,block->index,block->nr+1);
-  nblock_bc(cr,block->nr+1,block->index);
-}
-
-static void bc_blocka(const t_commrec *cr,t_blocka *block)
-{
-  block_bc(cr,block->nr);
-  snew_bc(cr,block->index,block->nr+1);
-  nblock_bc(cr,block->nr+1,block->index);
-  block_bc(cr,block->nra);
-  if (block->nra) {
-    snew_bc(cr,block->a,block->nra);
-    nblock_bc(cr,block->nra,block->a);
-  }
-}
-
-static void bc_grps(const t_commrec *cr,t_grps grps[])
-{
-  int i;
-  
-  for(i=0; (i<egcNR); i++) {
-    block_bc(cr,grps[i].nr);
-    snew_bc(cr,grps[i].nm_ind,grps[i].nr);
-    nblock_bc(cr,grps[i].nr,grps[i].nm_ind);
-  }
-}
-
-static void bc_atoms(const t_commrec *cr,t_symtab *symtab,t_atoms *atoms)
-{
-  int dummy;
-
-  block_bc(cr,atoms->nr);
-  snew_bc(cr,atoms->atom,atoms->nr);
-  nblock_bc(cr,atoms->nr,atoms->atom);
-  bc_strings(cr,symtab,atoms->nr,&atoms->atomname);
-  block_bc(cr,atoms->nres);
-  snew_bc(cr,atoms->resinfo,atoms->nres);
-  nblock_bc(cr,atoms->nres,atoms->resinfo);
-  bc_strings_resinfo(cr,symtab,atoms->nres,atoms->resinfo);
-  /* QMMM requires atomtypes to be known on all nodes as well */
-  bc_strings(cr,symtab,atoms->nr,&atoms->atomtype);
-  bc_strings(cr,symtab,atoms->nr,&atoms->atomtypeB);
-}
-
-static void bc_groups(const t_commrec *cr,t_symtab *symtab,
-                     int natoms,gmx_groups_t *groups)
-{
-  int dummy;
-  int g,n;
-
-  bc_grps(cr,groups->grps);
-  block_bc(cr,groups->ngrpname);
-  bc_strings(cr,symtab,groups->ngrpname,&groups->grpname);
-  for(g=0; g<egcNR; g++) {
-    if (MASTER(cr)) {
-      if (groups->grpnr[g]) {
-       n = natoms;
-      } else {
-       n = 0;
-      }
-    }
-    block_bc(cr,n);
-    if (n == 0) {
-      groups->grpnr[g] = NULL;
-    } else {
-      snew_bc(cr,groups->grpnr[g],n);
-      nblock_bc(cr,n,groups->grpnr[g]);
-    }
-  }
-  if (debug) fprintf(debug,"after bc_groups\n");
-}
-
-void bcast_state_setup(const t_commrec *cr,t_state *state)
-{
-  block_bc(cr,state->natoms);
-  block_bc(cr,state->ngtc);
-  block_bc(cr,state->nnhpres);
-  block_bc(cr,state->nhchainlength);
-  block_bc(cr,state->nrng);
-  block_bc(cr,state->nrngi);
-  block_bc(cr,state->flags);
-}
-
-void bcast_state(const t_commrec *cr,t_state *state,gmx_bool bAlloc)
-{
-  int i,nnht,nnhtp;
-
-  bcast_state_setup(cr,state);
-
-  nnht = (state->ngtc)*(state->nhchainlength); 
-  nnhtp = (state->nnhpres)*(state->nhchainlength); 
-
-  if (MASTER(cr)) {
-    bAlloc = FALSE;
-  }
-  if (bAlloc) {
-    state->nalloc = state->natoms;
-  }
-  for(i=0; i<estNR; i++) {
-    if (state->flags & (1<<i)) {
-      switch (i) {
-      case estLAMBDA:  block_bc(cr,state->lambda); break;
-      case estBOX:     block_bc(cr,state->box); break;
-      case estBOX_REL: block_bc(cr,state->box_rel); break;
-      case estBOXV:    block_bc(cr,state->boxv); break;
-      case estPRES_PREV: block_bc(cr,state->pres_prev); break;
-      case estSVIR_PREV: block_bc(cr,state->svir_prev); break;
-      case estFVIR_PREV: block_bc(cr,state->fvir_prev); break;
-      case estNH_XI:   nblock_abc(cr,nnht,state->nosehoover_xi); break;
-      case estNH_VXI:  nblock_abc(cr,nnht,state->nosehoover_vxi); break;
-      case estNHPRES_XI:   nblock_abc(cr,nnhtp,state->nhpres_xi); break;
-      case estNHPRES_VXI:  nblock_abc(cr,nnhtp,state->nhpres_vxi); break;
-      case estTC_INT:  nblock_abc(cr,state->ngtc,state->therm_integral); break;
-      case estVETA:    block_bc(cr,state->veta); break;
-      case estVOL0:    block_bc(cr,state->vol0); break;
-      case estX:       nblock_abc(cr,state->natoms,state->x); break;
-      case estV:       nblock_abc(cr,state->natoms,state->v); break;
-      case estSDX:     nblock_abc(cr,state->natoms,state->sd_X); break;
-      case estCGP:     nblock_abc(cr,state->natoms,state->cg_p); break;
-         case estLD_RNG:  if(state->nrngi == 1) nblock_abc(cr,state->nrng,state->ld_rng); break;
-         case estLD_RNGI: if(state->nrngi == 1) nblock_abc(cr,state->nrngi,state->ld_rngi); break;
-      case estDISRE_INITF: block_bc(cr,state->hist.disre_initf); break;
-      case estDISRE_RM3TAV:
-          block_bc(cr,state->hist.ndisrepairs);
-          nblock_abc(cr,state->hist.ndisrepairs,state->hist.disre_rm3tav);
-          break;
-      case estORIRE_INITF: block_bc(cr,state->hist.orire_initf); break;
-      case estORIRE_DTAV:
-          block_bc(cr,state->hist.norire_Dtav);
-          nblock_abc(cr,state->hist.norire_Dtav,state->hist.orire_Dtav);
-          break;
-      default:
-          gmx_fatal(FARGS,
-                    "Communication is not implemented for %s in bcast_state",
-                    est_names[i]);
-      }
-    }
-  }
-}
-
-static void bc_ilists(const t_commrec *cr,t_ilist *ilist)
-{
-  int ftype;
-
-  /* Here we only communicate the non-zero length ilists */
-  if (MASTER(cr)) {
-    for(ftype=0; ftype<F_NRE; ftype++) {
-      if (ilist[ftype].nr > 0) {
-       block_bc(cr,ftype);
-       block_bc(cr,ilist[ftype].nr);
-       nblock_bc(cr,ilist[ftype].nr,ilist[ftype].iatoms);
-      }
-    }
-    ftype = -1;
-    block_bc(cr,ftype);
-  } else {
-    for(ftype=0; ftype<F_NRE; ftype++) {
-      ilist[ftype].nr = 0;
-    }
-    do {
-      block_bc(cr,ftype);
-      if (ftype >= 0) {
-       block_bc(cr,ilist[ftype].nr);
-       snew_bc(cr,ilist[ftype].iatoms,ilist[ftype].nr);
-       nblock_bc(cr,ilist[ftype].nr,ilist[ftype].iatoms);
-      }
-    } while (ftype >= 0);
-  }
-
-  if (debug) fprintf(debug,"after bc_ilists\n");
-}
-
-static void bc_idef(const t_commrec *cr,t_idef *idef)
-{
-  block_bc(cr,idef->ntypes);
-  block_bc(cr,idef->atnr);
-  snew_bc(cr,idef->functype,idef->ntypes);
-  snew_bc(cr,idef->iparams,idef->ntypes);
-  nblock_bc(cr,idef->ntypes,idef->functype);
-  nblock_bc(cr,idef->ntypes,idef->iparams);
-  block_bc(cr,idef->fudgeQQ);
-  bc_ilists(cr,idef->il);
-  block_bc(cr,idef->ilsort);
-}
-
-static void bc_cmap(const t_commrec *cr, gmx_cmap_t *cmap_grid)
-{
-       int i,j,nelem,ngrid;
-       
-       block_bc(cr,cmap_grid->ngrid);
-       block_bc(cr,cmap_grid->grid_spacing);
-       
-       ngrid = cmap_grid->ngrid;
-       nelem = cmap_grid->grid_spacing * cmap_grid->grid_spacing;
-       
-       if(ngrid>0)
-       {
-               snew_bc(cr,cmap_grid->cmapdata,ngrid);
-               
-               for(i=0;i<ngrid;i++)
-               {
-                       snew_bc(cr,cmap_grid->cmapdata[i].cmap,4*nelem);
-                       nblock_bc(cr,4*nelem,cmap_grid->cmapdata[i].cmap);
-               }
-       }
-}
-
-static void bc_ffparams(const t_commrec *cr,gmx_ffparams_t *ffp)
-{
-  int i;
-  
-  block_bc(cr,ffp->ntypes);
-  block_bc(cr,ffp->atnr);
-  snew_bc(cr,ffp->functype,ffp->ntypes);
-  snew_bc(cr,ffp->iparams,ffp->ntypes);
-  nblock_bc(cr,ffp->ntypes,ffp->functype);
-  nblock_bc(cr,ffp->ntypes,ffp->iparams);
-  block_bc(cr,ffp->reppow);
-  block_bc(cr,ffp->fudgeQQ);
-  bc_cmap(cr,&ffp->cmap_grid);
-}
-
-static void bc_grpopts(const t_commrec *cr,t_grpopts *g)
-{
-    int i,n;
-    
-    block_bc(cr,g->ngtc);
-    block_bc(cr,g->ngacc);
-    block_bc(cr,g->ngfrz);
-    block_bc(cr,g->ngener);
-    snew_bc(cr,g->nrdf,g->ngtc);
-    snew_bc(cr,g->tau_t,g->ngtc);
-    snew_bc(cr,g->ref_t,g->ngtc);
-    snew_bc(cr,g->acc,g->ngacc);
-    snew_bc(cr,g->nFreeze,g->ngfrz);
-    snew_bc(cr,g->egp_flags,g->ngener*g->ngener);
-    
-    nblock_bc(cr,g->ngtc,g->nrdf);
-    nblock_bc(cr,g->ngtc,g->tau_t);
-    nblock_bc(cr,g->ngtc,g->ref_t);
-    nblock_bc(cr,g->ngacc,g->acc);
-    nblock_bc(cr,g->ngfrz,g->nFreeze);
-    nblock_bc(cr,g->ngener*g->ngener,g->egp_flags);
-    snew_bc(cr,g->annealing,g->ngtc);
-    snew_bc(cr,g->anneal_npoints,g->ngtc);
-    snew_bc(cr,g->anneal_time,g->ngtc);
-    snew_bc(cr,g->anneal_temp,g->ngtc);
-    nblock_bc(cr,g->ngtc,g->annealing);
-    nblock_bc(cr,g->ngtc,g->anneal_npoints);
-    for(i=0;(i<g->ngtc); i++) {
-        n = g->anneal_npoints[i];
-        if (n > 0) {
-         snew_bc(cr,g->anneal_time[i],n);
-         snew_bc(cr,g->anneal_temp[i],n);
-         nblock_bc(cr,n,g->anneal_time[i]);
-         nblock_bc(cr,n,g->anneal_temp[i]);
-        }
-    }
-    
-    /* QMMM stuff, see inputrec */
-    block_bc(cr,g->ngQM);
-    snew_bc(cr,g->QMmethod,g->ngQM);
-    snew_bc(cr,g->QMbasis,g->ngQM);
-    snew_bc(cr,g->QMcharge,g->ngQM);
-    snew_bc(cr,g->QMmult,g->ngQM);
-    snew_bc(cr,g->bSH,g->ngQM);
-    snew_bc(cr,g->CASorbitals,g->ngQM);
-    snew_bc(cr,g->CASelectrons,g->ngQM);
-    snew_bc(cr,g->SAon,g->ngQM);
-    snew_bc(cr,g->SAoff,g->ngQM);
-    snew_bc(cr,g->SAsteps,g->ngQM);
-    
-    if (g->ngQM)
-    {
-        nblock_bc(cr,g->ngQM,g->QMmethod);
-        nblock_bc(cr,g->ngQM,g->QMbasis);
-        nblock_bc(cr,g->ngQM,g->QMcharge);
-        nblock_bc(cr,g->ngQM,g->QMmult);
-        nblock_bc(cr,g->ngQM,g->bSH);
-        nblock_bc(cr,g->ngQM,g->CASorbitals);
-        nblock_bc(cr,g->ngQM,g->CASelectrons);
-        nblock_bc(cr,g->ngQM,g->SAon);
-        nblock_bc(cr,g->ngQM,g->SAoff);
-        nblock_bc(cr,g->ngQM,g->SAsteps);
-        /* end of QMMM stuff */
-    }
-}
-
-static void bc_cosines(const t_commrec *cr,t_cosines *cs)
-{
-  block_bc(cr,cs->n);
-  snew_bc(cr,cs->a,cs->n);
-  snew_bc(cr,cs->phi,cs->n);
-  if (cs->n > 0) {
-    nblock_bc(cr,cs->n,cs->a);
-    nblock_bc(cr,cs->n,cs->phi);
-  }
-}
-
-static void bc_pullgrp(const t_commrec *cr,t_pullgrp *pgrp)
-{
-  block_bc(cr,*pgrp);
-  if (pgrp->nat > 0) {
-    snew_bc(cr,pgrp->ind,pgrp->nat);
-    nblock_bc(cr,pgrp->nat,pgrp->ind);
-  }
-  if (pgrp->nweight > 0) {
-    snew_bc(cr,pgrp->weight,pgrp->nweight);
-    nblock_bc(cr,pgrp->nweight,pgrp->weight);
-  }
-}
-
-static void bc_pull(const t_commrec *cr,t_pull *pull)
-{
-  int g;
-
-  block_bc(cr,*pull);
-  snew_bc(cr,pull->grp,pull->ngrp+1);
-  for(g=0; g<pull->ngrp+1; g++)
-  {
-      bc_pullgrp(cr,&pull->grp[g]);
-  }
-}
-
-static void bc_inputrec(const t_commrec *cr,t_inputrec *inputrec)
-{
-  gmx_bool bAlloc=TRUE;
-  int i;
-  
-  block_bc(cr,*inputrec);
-  snew_bc(cr,inputrec->flambda,inputrec->n_flambda);
-  nblock_bc(cr,inputrec->n_flambda,inputrec->flambda);
-  bc_grpopts(cr,&(inputrec->opts));
-  if (inputrec->ePull != epullNO) {
-    snew_bc(cr,inputrec->pull,1);
-    bc_pull(cr,inputrec->pull);
-  }
-  for(i=0; (i<DIM); i++) {
-    bc_cosines(cr,&(inputrec->ex[i]));
-    bc_cosines(cr,&(inputrec->et[i]));
-  }
-}
-
-static void bc_moltype(const t_commrec *cr,t_symtab *symtab,
-                      gmx_moltype_t *moltype)
-{
-  bc_string(cr,symtab,&moltype->name);
-  bc_atoms(cr,symtab,&moltype->atoms);
-  if (debug) fprintf(debug,"after bc_atoms\n");
-
-  bc_ilists(cr,moltype->ilist);
-  bc_block(cr,&moltype->cgs);
-  bc_blocka(cr,&moltype->excls);
-}
-
-static void bc_molblock(const t_commrec *cr,gmx_molblock_t *molb)
-{
-  gmx_bool bAlloc=TRUE;
-  
-  block_bc(cr,molb->type);
-  block_bc(cr,molb->nmol);
-  block_bc(cr,molb->natoms_mol);
-  block_bc(cr,molb->nposres_xA);
-  if (molb->nposres_xA > 0) {
-    snew_bc(cr,molb->posres_xA,molb->nposres_xA);
-    nblock_bc(cr,molb->nposres_xA*DIM,molb->posres_xA[0]);
-  }
-  block_bc(cr,molb->nposres_xB);
-  if (molb->nposres_xB > 0) {
-    snew_bc(cr,molb->posres_xB,molb->nposres_xB);
-    nblock_bc(cr,molb->nposres_xB*DIM,molb->posres_xB[0]);
-  }
-  if (debug) fprintf(debug,"after bc_molblock\n");
-}
-
-static void bc_atomtypes(const t_commrec *cr, t_atomtypes *atomtypes)
-{
-  int nr;
-
-  block_bc(cr,atomtypes->nr);
-
-  nr = atomtypes->nr;
-
-  snew_bc(cr,atomtypes->radius,nr);
-  snew_bc(cr,atomtypes->vol,nr);
-  snew_bc(cr,atomtypes->surftens,nr);
-  snew_bc(cr,atomtypes->gb_radius,nr);
-  snew_bc(cr,atomtypes->S_hct,nr);
-
-  nblock_bc(cr,nr,atomtypes->radius);
-  nblock_bc(cr,nr,atomtypes->vol);
-  nblock_bc(cr,nr,atomtypes->surftens);
-  nblock_bc(cr,nr,atomtypes->gb_radius);
-  nblock_bc(cr,nr,atomtypes->S_hct);
-}
-
-
-void bcast_ir_mtop(const t_commrec *cr,t_inputrec *inputrec,gmx_mtop_t *mtop)
-{
-  int i; 
-  if (debug) fprintf(debug,"in bc_data\n");
-  bc_inputrec(cr,inputrec);
-  if (debug) fprintf(debug,"after bc_inputrec\n");
-  bc_symtab(cr,&mtop->symtab);
-  if (debug) fprintf(debug,"after bc_symtab\n");
-  bc_string(cr,&mtop->symtab,&mtop->name);
-  if (debug) fprintf(debug,"after bc_name\n");
-
-  bc_ffparams(cr,&mtop->ffparams);
-
-  block_bc(cr,mtop->nmoltype);
-  snew_bc(cr,mtop->moltype,mtop->nmoltype);
-  for(i=0; i<mtop->nmoltype; i++) {
-    bc_moltype(cr,&mtop->symtab,&mtop->moltype[i]);
-  }
-
-  block_bc(cr,mtop->nmolblock);
-  snew_bc(cr,mtop->molblock,mtop->nmolblock);
-  for(i=0; i<mtop->nmolblock; i++) {
-    bc_molblock(cr,&mtop->molblock[i]);
-  }
-
-  block_bc(cr,mtop->natoms);
-
-  bc_atomtypes(cr,&mtop->atomtypes);
-
-  bc_block(cr,&mtop->mols);
-  bc_groups(cr,&mtop->symtab,mtop->natoms,&mtop->groups);
-}
diff --git a/src/gmxlib/names.c b/src/gmxlib/names.c
deleted file mode 100644 (file)
index 9f9ad81..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "typedefs.h"
-#include "names.h"
-
-/* note: these arrays should correspond to enums in include/types/enums.h */
-
-const char *epbc_names[epbcNR+1]=
-{
-  "xyz", "no", "xy", "screw", NULL
-};
-
-const char *ens_names[ensNR+1]=
-{
-  "Grid","Simple", NULL
-};
-
-const char *ei_names[eiNR+1]=
-{
-  "md", "steep", "cg", "bd", "sd", "nm", "l-bfgs", "tpi", "tpic", "sd1", "md-vv", "md-vv-avek",NULL 
-};
-
-const char *bool_names[BOOL_NR+1]=
-{
-  "FALSE","TRUE", NULL
-};
-
-const char *yesno_names[BOOL_NR+1]=
-{
-  "no","yes", NULL
-};
-
-const char *ptype_str[eptNR+1] = {
-  "Atom", "Nucleus", "Shell", "Bond", "VSite", NULL
-};
-
-const char *eel_names[eelNR+1] = {
-  "Cut-off", "Reaction-Field", "Generalized-Reaction-Field",
-  "PME", "Ewald", "PPPM", "Poisson", "Switch", "Shift", "User", 
-  "Generalized-Born", "Reaction-Field-nec", "Encad-shift", 
-  "PME-User", "PME-Switch", "PME-User-Switch", 
-  "Reaction-Field-zero", NULL
-};
-
-const char *eewg_names[eewgNR+1] = {
-  "3d", "3dc", NULL
-};
-
-const char *evdw_names[evdwNR+1] = {
-  "Cut-off", "Switch", "Shift", "User", "Encad-shift", NULL
-};
-
-const char *econstr_names[econtNR+1] = {
-  "Lincs", "Shake", NULL
-};
-
-const char *egrp_nm[egNR+1] = { 
-  "Coul-SR","LJ-SR","Buck-SR", "Coul-LR", "LJ-LR", "Buck-LR",
-  "Coul-14", "LJ-14", NULL
-};
-
-const char *etcoupl_names[etcNR+1] = {
-  "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-interval", "V-rescale", NULL
-}; /* yes is alias for berendsen */
-
-const char *epcoupl_names[epcNR+1] = {
-  "No", "Berendsen", "Parrinello-Rahman", "Isotropic", "MTTK", NULL
-}; /* isotropic is alias for berendsen */
-
-const char *epcoupltype_names[epctNR+1] = {
-  "Isotropic", "Semiisotropic", "Anisotropic", "Surface-Tension", NULL
-};
-
-const char *erefscaling_names[erscNR+1] = {
-  "No", "All", "COM", NULL
-};
-
-const char *edisre_names[edrNR+1] = {
-  "No", "Simple", "Ensemble", NULL
-};
-
-const char *edisreweighting_names[edrwNR+1] = {
-  "Conservative", "Equal", NULL
-};
-
-const char *enbf_names[eNBF_NR+1] = {
-  "", "LJ", "Buckingham", NULL
-};
-
-const char *ecomb_names[eCOMB_NR+1] = {
-  "", "Geometric", "Arithmetic", "GeomSigEps", NULL
-};
-
-const char *gtypes[egcNR+1] = {
-  "T-Coupling", "Energy Mon.", "Acceleration", "Freeze",
-  "User1", "User2", "VCM", "XTC", "Or. Res. Fit", "QMMM", NULL
-};
-
-const char *efep_names[efepNR+1] = {
-  "no", "yes", NULL
-};
-
-const char *separate_dhdl_file_names[sepdhdlfileNR+1] = {
-  "yes", "no", NULL
-};
-
-const char *dhdl_derivatives_names[dhdlderivativesNR+1] = {
-  "yes", "no", NULL
-};
-
-const char *esol_names[esolNR+1] = {
-  "No", "SPC", "TIP4p", NULL
-};
-
-const char *enlist_names[enlistNR+1] = {
-  "Atom-Atom", "SPC-Atom", "SPC-SPC", "TIP4p-Atom", "TIP4p-TIP4p", "CG-CG", NULL
-};
-
-const char *edispc_names[edispcNR+1] = {
-  "No", "EnerPres", "Ener", "AllEnerPres", "AllEner", NULL
-};
-
-const char *ecm_names[ecmNR+1] = { 
-  "Linear", "Angular", "None", NULL 
-};
-
-const char *eann_names[eannNR+1] = {
-  "No", "Single", "Periodic", NULL
-};
-
-const char *eis_names[eisNR+1] = {
-       "No", "GBSA", NULL
-};
-
-const char *egb_names[egbNR+1] = {
-  "Still", "HCT", "OBC", NULL
-};
-
-const char *esa_names[esaNR+1] = {
-  "Ace-approximation", "None", "Still", NULL
-};
-
-const char *ewt_names[ewtNR+1] = {
-  "9-3", "10-4", "table", "12-6", NULL
-};
-
-const char *epull_names[epullNR+1] = { 
-  "no", "umbrella", "constraint", "constant-force", NULL
-};
-
-const char *epullg_names[epullgNR+1] = { 
-  "distance", "direction", "cylinder", "position", "direction-periodic", NULL
-};
-
-const char *eQMmethod_names[eQMmethodNR+1] = {
-  "AM1", "PM3", "RHF",
-  "UHF", "DFT", "B3LYP", "MP2", "CASSCF","B3LYPLAN",
-  "DIRECT", NULL
-};
-
-const char *eQMbasis_names[eQMbasisNR+1] = {
-  "STO3G", "STO-3G", "3-21G",
-  "3-21G*", "3-21+G*", "6-21G",
-  "6-31G", "6-31G*", "6-31+G*",
-  "6-311G", NULL
-};
-
-const char *eQMMMscheme_names[eQMMMschemeNR+1] = {
-  "normal", "ONIOM", NULL
-};
-
-const char *eMultentOpt_names[eMultentOptNR+1] = {
-  "multiple_entries", "no", "use_last", NULL
-};
-
diff --git a/src/gmxlib/network.c b/src/gmxlib/network.c
deleted file mode 100644 (file)
index 6933021..0000000
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include "gmx_fatal.h"
-#include "main.h"
-#include "smalloc.h"
-#include "network.h"
-#include "copyrite.h"
-#include "statutil.h"
-#include "ctype.h"
-#include "macros.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#include "mpelogging.h"
-
-/* The source code in this file should be thread-safe. 
-      Please keep it that way. */
-
-gmx_bool gmx_mpi_initialized(void)
-{
-  int n;
-#ifndef GMX_MPI
-  return 0;
-#else
-  MPI_Initialized(&n);
-  
-  return n;
-#endif
-}
-
-int gmx_setup(int *argc,char **argv,int *nnodes)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_setup");
-  return 0;
-#else
-  char   buf[256];
-  int    resultlen;               /* actual length of node name      */
-  int    i,flag;
-  int  mpi_num_nodes;
-  int  mpi_my_rank;
-  char mpi_hostname[MPI_MAX_PROCESSOR_NAME];
-
-  /* Call the MPI routines */
-#ifdef GMX_LIB_MPI
-#ifdef GMX_FAHCORE
-  (void) fah_MPI_Init(argc,&argv);
-#else
-  (void) MPI_Init(argc,&argv);
-#endif
-#endif
-  (void) MPI_Comm_size( MPI_COMM_WORLD, &mpi_num_nodes );
-  (void) MPI_Comm_rank( MPI_COMM_WORLD, &mpi_my_rank );
-  (void) MPI_Get_processor_name( mpi_hostname, &resultlen );
-
-
-#ifdef USE_MPE
-  /* MPE logging routines. Get event IDs from MPE: */
-  /* General events */
-  ev_timestep1               = MPE_Log_get_event_number( );
-  ev_timestep2               = MPE_Log_get_event_number( );
-  ev_force_start             = MPE_Log_get_event_number( );
-  ev_force_finish            = MPE_Log_get_event_number( );
-  ev_do_fnbf_start           = MPE_Log_get_event_number( );
-  ev_do_fnbf_finish          = MPE_Log_get_event_number( );
-  ev_ns_start                = MPE_Log_get_event_number( );
-  ev_ns_finish               = MPE_Log_get_event_number( );
-  ev_calc_bonds_start        = MPE_Log_get_event_number( );
-  ev_calc_bonds_finish       = MPE_Log_get_event_number( );
-  ev_global_stat_start       = MPE_Log_get_event_number( );
-  ev_global_stat_finish      = MPE_Log_get_event_number( );
-  ev_virial_start            = MPE_Log_get_event_number( );
-  ev_virial_finish           = MPE_Log_get_event_number( );
-  
-  /* Shift related events */
-  ev_shift_start             = MPE_Log_get_event_number( );
-  ev_shift_finish            = MPE_Log_get_event_number( );
-  ev_unshift_start           = MPE_Log_get_event_number( );
-  ev_unshift_finish          = MPE_Log_get_event_number( );
-  ev_mk_mshift_start         = MPE_Log_get_event_number( );
-  ev_mk_mshift_finish        = MPE_Log_get_event_number( );
-  
-  /* PME related events */
-  ev_pme_start               = MPE_Log_get_event_number( );
-  ev_pme_finish              = MPE_Log_get_event_number( );
-  ev_spread_on_grid_start    = MPE_Log_get_event_number( );
-  ev_spread_on_grid_finish   = MPE_Log_get_event_number( );
-  ev_sum_qgrid_start         = MPE_Log_get_event_number( );
-  ev_sum_qgrid_finish        = MPE_Log_get_event_number( );
-  ev_gmxfft3d_start          = MPE_Log_get_event_number( );
-  ev_gmxfft3d_finish         = MPE_Log_get_event_number( );
-  ev_solve_pme_start         = MPE_Log_get_event_number( );
-  ev_solve_pme_finish        = MPE_Log_get_event_number( );
-  ev_gather_f_bsplines_start = MPE_Log_get_event_number( );
-  ev_gather_f_bsplines_finish= MPE_Log_get_event_number( );
-  ev_reduce_start            = MPE_Log_get_event_number( );
-  ev_reduce_finish           = MPE_Log_get_event_number( );
-  ev_rscatter_start          = MPE_Log_get_event_number( );
-  ev_rscatter_finish         = MPE_Log_get_event_number( );
-  ev_alltoall_start          = MPE_Log_get_event_number( );
-  ev_alltoall_finish         = MPE_Log_get_event_number( );
-  ev_pmeredist_start         = MPE_Log_get_event_number( );
-  ev_pmeredist_finish        = MPE_Log_get_event_number( );
-  ev_init_pme_start          = MPE_Log_get_event_number( );      
-  ev_init_pme_finish         = MPE_Log_get_event_number( );
-  ev_send_coordinates_start  = MPE_Log_get_event_number( );
-  ev_send_coordinates_finish = MPE_Log_get_event_number( );
-  ev_update_fr_start         = MPE_Log_get_event_number( );
-  ev_update_fr_finish        = MPE_Log_get_event_number( );
-  ev_clear_rvecs_start       = MPE_Log_get_event_number( );
-  ev_clear_rvecs_finish      = MPE_Log_get_event_number( ); 
-  ev_update_start            = MPE_Log_get_event_number( ); 
-  ev_update_finish           = MPE_Log_get_event_number( ); 
-  ev_output_start            = MPE_Log_get_event_number( ); 
-  ev_output_finish           = MPE_Log_get_event_number( ); 
-  ev_sum_lrforces_start      = MPE_Log_get_event_number( ); 
-  ev_sum_lrforces_finish     = MPE_Log_get_event_number( ); 
-  ev_sort_start              = MPE_Log_get_event_number( );
-  ev_sort_finish             = MPE_Log_get_event_number( );
-  ev_sum_qgrid_start         = MPE_Log_get_event_number( );
-  ev_sum_qgrid_finish        = MPE_Log_get_event_number( );
-  
-  /* Essential dynamics related events */
-  ev_edsam_start             = MPE_Log_get_event_number( );
-  ev_edsam_finish            = MPE_Log_get_event_number( );
-  ev_get_coords_start        = MPE_Log_get_event_number( );
-  ev_get_coords_finish       = MPE_Log_get_event_number( );
-  ev_ed_apply_cons_start     = MPE_Log_get_event_number( );
-  ev_ed_apply_cons_finish    = MPE_Log_get_event_number( );
-  ev_fit_to_reference_start  = MPE_Log_get_event_number( );
-  ev_fit_to_reference_finish = MPE_Log_get_event_number( );
-  
-  /* describe events: */
-  if ( mpi_my_rank == 0 ) 
-  {
-    /* General events */
-    MPE_Describe_state(ev_timestep1,               ev_timestep2,                "timestep START",  "magenta" );
-    MPE_Describe_state(ev_force_start,             ev_force_finish,             "force",           "cornflower blue" );
-    MPE_Describe_state(ev_do_fnbf_start,           ev_do_fnbf_finish,           "do_fnbf",         "navy" );
-    MPE_Describe_state(ev_ns_start,                ev_ns_finish,                "neighbor search", "tomato" );
-    MPE_Describe_state(ev_calc_bonds_start,        ev_calc_bonds_finish,        "bonded forces",   "slate blue" );
-    MPE_Describe_state(ev_global_stat_start,       ev_global_stat_finish,       "global stat",     "firebrick3");
-    MPE_Describe_state(ev_update_fr_start,         ev_update_fr_finish,         "update forcerec", "goldenrod");
-    MPE_Describe_state(ev_clear_rvecs_start,       ev_clear_rvecs_finish,       "clear rvecs",     "bisque");
-    MPE_Describe_state(ev_update_start,            ev_update_finish,            "update",          "cornsilk");
-    MPE_Describe_state(ev_output_start,            ev_output_finish,            "output",          "black");
-    MPE_Describe_state(ev_virial_start,            ev_virial_finish,            "calc_virial",     "thistle4");
-    
-    /* PME related events */
-    MPE_Describe_state(ev_pme_start,               ev_pme_finish,               "doing PME",       "grey" );
-    MPE_Describe_state(ev_spread_on_grid_start,    ev_spread_on_grid_finish,    "spread",          "dark orange" );   
-    MPE_Describe_state(ev_sum_qgrid_start,         ev_sum_qgrid_finish,         "sum qgrid",       "slate blue");
-    MPE_Describe_state(ev_gmxfft3d_start,          ev_gmxfft3d_finish,          "fft3d",           "snow2" );   
-    MPE_Describe_state(ev_solve_pme_start,         ev_solve_pme_finish,         "solve PME",       "indian red" );   
-    MPE_Describe_state(ev_gather_f_bsplines_start, ev_gather_f_bsplines_finish, "bsplines",        "light sea green" );   
-    MPE_Describe_state(ev_reduce_start,            ev_reduce_finish,            "reduce",          "cyan1" );
-    MPE_Describe_state(ev_rscatter_start,          ev_rscatter_finish,          "rscatter",        "cyan3" );
-    MPE_Describe_state(ev_alltoall_start,          ev_alltoall_finish,          "alltoall",        "LightCyan4" );
-    MPE_Describe_state(ev_pmeredist_start,         ev_pmeredist_finish,         "pmeredist",       "thistle" );
-    MPE_Describe_state(ev_init_pme_start,          ev_init_pme_finish,          "init PME",        "snow4");
-    MPE_Describe_state(ev_send_coordinates_start,  ev_send_coordinates_finish,  "send_coordinates","blue");
-    MPE_Describe_state(ev_sum_lrforces_start,      ev_sum_lrforces_finish,      "sum_LRforces",    "lime green");
-    MPE_Describe_state(ev_sort_start,              ev_sort_finish,              "sort pme atoms",  "brown");
-    MPE_Describe_state(ev_sum_qgrid_start,         ev_sum_qgrid_finish,         "sum charge grid", "medium orchid");
-    
-    /* Shift related events */
-    MPE_Describe_state(ev_shift_start,             ev_shift_finish,             "shift",           "orange");
-    MPE_Describe_state(ev_unshift_start,           ev_unshift_finish,           "unshift",         "dark orange");    
-    MPE_Describe_state(ev_mk_mshift_start,         ev_mk_mshift_finish,         "mk_mshift",       "maroon");
-        
-    /* Essential dynamics related events */
-    MPE_Describe_state(ev_edsam_start,             ev_edsam_finish,             "EDSAM",           "deep sky blue");
-    MPE_Describe_state(ev_get_coords_start,        ev_get_coords_finish,        "ED get coords",   "steel blue");
-    MPE_Describe_state(ev_ed_apply_cons_start,     ev_ed_apply_cons_finish,     "ED apply constr", "forest green");
-    MPE_Describe_state(ev_fit_to_reference_start,  ev_fit_to_reference_finish,  "ED fit to ref",   "lavender");
-       
-  }
-  MPE_Init_log();
-#endif
-#ifdef GMX_LIB_MPI 
-  fprintf(stderr,"NNODES=%d, MYRANK=%d, HOSTNAME=%s\n",
-         mpi_num_nodes,mpi_my_rank,mpi_hostname);
-#endif
-  
-  *nnodes=mpi_num_nodes;
-  
-  return mpi_my_rank;
-#endif
-}
-
-int  gmx_node_num(void)
-{
-#ifndef GMX_MPI
-  return 1;
-#else
-  int i;
-  (void) MPI_Comm_size(MPI_COMM_WORLD, &i);
-  return i;
-#endif
-}
-
-int gmx_node_rank(void)
-{
-#ifndef GMX_MPI
-  return 0;
-#else
-  int i;
-  (void) MPI_Comm_rank(MPI_COMM_WORLD, &i);
-  return i;
-#endif
-}
-
-void gmx_setup_nodecomm(FILE *fplog,t_commrec *cr)
-{
-  gmx_nodecomm_t *nc;
-  int  n,rank,resultlen,hostnum,i,j,ng,ni;
-#ifdef GMX_MPI
-  char mpi_hostname[MPI_MAX_PROCESSOR_NAME],num[MPI_MAX_PROCESSOR_NAME];
-#endif
-
-  /* Many MPI implementations do not optimize MPI_Allreduce
-   * (and probably also other global communication calls)
-   * for multi-core nodes connected by a network.
-   * We can optimize such communication by using one MPI call
-   * within each node and one between the nodes.
-   * For MVAPICH2 and Intel MPI this reduces the time for
-   * the global_stat communication by 25%
-   * for 2x2-core 3 GHz Woodcrest connected by mixed DDR/SDR Infiniband.
-   * B. Hess, November 2007
-   */
-
-  nc = &cr->nc;
-
-  nc->bUse = FALSE;
-#ifndef GMX_THREADS
-  if (getenv("GMX_NO_NODECOMM") == NULL) {
-#ifdef GMX_MPI
-    MPI_Comm_size(cr->mpi_comm_mygroup,&n);
-    MPI_Comm_rank(cr->mpi_comm_mygroup,&rank);
-    MPI_Get_processor_name(mpi_hostname,&resultlen);
-    /* This procedure can only differentiate nodes with host names
-     * that end on unique numbers.
-     */
-    i = 0;
-    j = 0;
-    /* Only parse the host name up to the first dot */
-    while(i < resultlen && mpi_hostname[i] != '.') {
-      if (isdigit(mpi_hostname[i])) {
-       num[j++] = mpi_hostname[i];
-      }
-      i++;
-    }
-    num[j] = '\0';
-    if (j == 0) {
-      hostnum = 0;
-    } else {
-      /* Use only the last 9 decimals, so we don't overflow an int */
-      hostnum = strtol(num + max(0,j-9), NULL, 10); 
-    }
-
-    if (debug) {
-      fprintf(debug,
-             "In gmx_setup_nodecomm: splitting communicator of size %d\n",
-             n);
-      fprintf(debug,"In gmx_setup_nodecomm: hostname '%s', hostnum %d\n",
-             mpi_hostname,hostnum);
-    }
-
-    /* The intra-node communicator, split on node number */
-    MPI_Comm_split(cr->mpi_comm_mygroup,hostnum,rank,&nc->comm_intra);
-    MPI_Comm_rank(nc->comm_intra,&nc->rank_intra);
-    if (debug) {
-      fprintf(debug,"In gmx_setup_nodecomm: node rank %d rank_intra %d\n",
-             rank,nc->rank_intra);
-    }
-    /* The inter-node communicator, split on rank_intra.
-     * We actually only need the one for rank=0,
-     * but it is easier to create them all.
-     */
-    MPI_Comm_split(cr->mpi_comm_mygroup,nc->rank_intra,rank,&nc->comm_inter);
-    /* Check if this really created two step communication */
-    MPI_Comm_size(nc->comm_inter,&ng);
-    MPI_Comm_size(nc->comm_intra,&ni);
-    if (debug) {
-      fprintf(debug,"In gmx_setup_nodecomm: groups %d, my group size %d\n",
-             ng,ni);
-    }
-    if ((ng > 1 && ng < n) || (ni > 1 && ni < n)) {
-      nc->bUse = TRUE;
-      if (fplog)
-       fprintf(fplog,"Using two step summing over %d groups of on average %.1f processes\n\n",ng,(real)n/(real)ng);
-      if (nc->rank_intra > 0)
-       MPI_Comm_free(&nc->comm_inter);
-    } else {
-      /* One group or all processes in a separate group, use normal summing */
-      MPI_Comm_free(&nc->comm_inter);
-      MPI_Comm_free(&nc->comm_intra);
-    }
-#endif
-  }
-#endif
-}
-
-void gmx_barrier(const t_commrec *cr)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_barrier");
-#else
-  MPI_Barrier(cr->mpi_comm_mygroup);
-#endif
-}
-
-void gmx_abort(int noderank,int nnodes,int errorno)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_abort");
-#else
-#ifdef GMX_THREADS
-  fprintf(stderr,"Halting program %s\n",ShortProgram());
-  thanx(stderr);
-  exit(1);
-#else
-  if (nnodes > 1)
-  {
-      fprintf(stderr,"Halting parallel program %s on CPU %d out of %d\n",
-              ShortProgram(),noderank,nnodes);
-  }
-  else
-  {
-      fprintf(stderr,"Halting program %s\n",ShortProgram());
-  }
-
-  thanx(stderr);
-  MPI_Abort(MPI_COMM_WORLD,errorno);
-  exit(1);
-#endif
-#endif
-}
-
-void gmx_bcast(int nbytes,void *b,const t_commrec *cr)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_bast");
-#else
-  MPI_Bcast(b,nbytes,MPI_BYTE,MASTERRANK(cr),cr->mpi_comm_mygroup);
-#endif
-}
-
-void gmx_bcast_sim(int nbytes,void *b,const t_commrec *cr)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_bast");
-#else
-  MPI_Bcast(b,nbytes,MPI_BYTE,MASTERRANK(cr),cr->mpi_comm_mysim);
-#endif
-}
-
-void gmx_sumd(int nr,double r[],const t_commrec *cr)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumd");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    if (cr->nc.bUse) {
-        if (cr->nc.rank_intra == 0)
-        {
-            /* Use two step summing. */
-            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,0,
-                       cr->nc.comm_intra);
-            /* Sum the roots of the internal (intra) buffers. */
-            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,
-                          cr->nc.comm_inter);
-        }
-        else
-        {
-            /* This is here because of the silly MPI specification
-                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
-            MPI_Reduce(r,NULL,nr,MPI_DOUBLE,MPI_SUM,0,cr->nc.comm_intra);
-        }
-        MPI_Bcast(r,nr,MPI_DOUBLE,0,cr->nc.comm_intra);
-    } 
-    else 
-    {
-        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM, 
-                      cr->mpi_comm_mygroup);
-    }
-#else
-    int i;
-
-    if (nr > cr->mpb->dbuf_alloc) {
-        cr->mpb->dbuf_alloc = nr;
-        srenew(cr->mpb->dbuf,cr->mpb->dbuf_alloc);
-    }
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        MPI_Allreduce(r,cr->mpb->dbuf,nr,MPI_DOUBLE,MPI_SUM,cr->nc.comm_intra);
-        if (cr->nc.rank_intra == 0) {
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(cr->mpb->dbuf,r,nr,MPI_DOUBLE,MPI_SUM, 
-                          cr->nc.comm_inter);
-        }
-        MPI_Bcast(r,nr,MPI_DOUBLE,0,cr->nc.comm_intra);
-    } else {
-        MPI_Allreduce(r,cr->mpb->dbuf,nr,MPI_DOUBLE,MPI_SUM,
-                      cr->mpi_comm_mygroup);
-        for(i=0; i<nr; i++)
-            r[i] = cr->mpb->dbuf[i];
-    }
-#endif
-#endif
-}
-
-void gmx_sumf(int nr,float r[],const t_commrec *cr)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumf");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    if (cr->nc.bUse) {
-        /* Use two step summing.  */
-        if (cr->nc.rank_intra == 0)
-        {
-            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,0,
-                       cr->nc.comm_intra);
-            /* Sum the roots of the internal (intra) buffers */
-            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,
-                          cr->nc.comm_inter);
-        }
-        else
-        {
-            /* This is here because of the silly MPI specification
-                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
-            MPI_Reduce(r,NULL,nr,MPI_FLOAT,MPI_SUM,0,cr->nc.comm_intra);
-        }
-        MPI_Bcast(r,nr,MPI_FLOAT,0,cr->nc.comm_intra);
-    } 
-    else 
-    {
-        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,cr->mpi_comm_mygroup);
-    }
-#else
-    int i;
-
-    if (nr > cr->mpb->fbuf_alloc) {
-        cr->mpb->fbuf_alloc = nr;
-        srenew(cr->mpb->fbuf,cr->mpb->fbuf_alloc);
-    }
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        MPI_Allreduce(r,cr->mpb->fbuf,nr,MPI_FLOAT,MPI_SUM,cr->nc.comm_intra);
-        if (cr->nc.rank_intra == 0) {
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(cr->mpb->fbuf,r,nr,MPI_FLOAT,MPI_SUM, 
-                          cr->nc.comm_inter);
-        }
-        MPI_Bcast(r,nr,MPI_FLOAT,0,cr->nc.comm_intra);
-    } else {
-        MPI_Allreduce(r,cr->mpb->fbuf,nr,MPI_FLOAT,MPI_SUM,
-                      cr->mpi_comm_mygroup);
-        for(i=0; i<nr; i++)
-            r[i] = cr->mpb->fbuf[i];
-    }
-#endif
-#endif
-}
-
-void gmx_sumi(int nr,int r[],const t_commrec *cr)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumi");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        if (cr->nc.rank_intra == 0) 
-        {
-            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,0,cr->nc.comm_intra);
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,cr->nc.comm_inter);
-        }
-        else
-        {
-            /* This is here because of the silly MPI specification
-                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
-            MPI_Reduce(r,NULL,nr,MPI_INT,MPI_SUM,0,cr->nc.comm_intra);
-        }
-        MPI_Bcast(r,nr,MPI_INT,0,cr->nc.comm_intra);
-    } 
-    else 
-    {
-        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,cr->mpi_comm_mygroup);
-    }
-#else
-    int i;
-
-    if (nr > cr->mpb->ibuf_alloc) {
-        cr->mpb->ibuf_alloc = nr;
-        srenew(cr->mpb->ibuf,cr->mpb->ibuf_alloc);
-    }
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        MPI_Allreduce(r,cr->mpb->ibuf,nr,MPI_INT,MPI_SUM,cr->nc.comm_intra);
-        if (cr->nc.rank_intra == 0) {
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(cr->mpb->ibuf,r,nr,MPI_INT,MPI_SUM,cr->nc.comm_inter);
-        }
-        MPI_Bcast(r,nr,MPI_INT,0,cr->nc.comm_intra);
-    } else {
-        MPI_Allreduce(r,cr->mpb->ibuf,nr,MPI_INT,MPI_SUM,cr->mpi_comm_mygroup);
-        for(i=0; i<nr; i++)
-            r[i] = cr->mpb->ibuf[i];
-    }
-#endif
-#endif
-}
-
-void gmx_sumli(int nr,gmx_large_int_t r[],const t_commrec *cr)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumli");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        if (cr->nc.rank_intra == 0) 
-        {
-            MPI_Reduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,0,
-                       cr->nc.comm_intra);
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                          cr->nc.comm_inter);
-        }
-        else
-        {
-            /* This is here because of the silly MPI specification
-                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
-            MPI_Reduce(r,NULL,nr,GMX_MPI_LARGE_INT,MPI_SUM,0,cr->nc.comm_intra);
-        }
-        MPI_Bcast(r,nr,GMX_MPI_LARGE_INT,0,cr->nc.comm_intra);
-    } 
-    else 
-    {
-        MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,cr->mpi_comm_mygroup);
-    }
-#else
-    int i;
-
-    if (nr > cr->mpb->libuf_alloc) {
-        cr->mpb->libuf_alloc = nr;
-        srenew(cr->mpb->libuf,cr->mpb->libuf_alloc);
-    }
-    if (cr->nc.bUse) {
-        /* Use two step summing */
-        MPI_Allreduce(r,cr->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                      cr->nc.comm_intra);
-        if (cr->nc.rank_intra == 0) {
-            /* Sum with the buffers reversed */
-            MPI_Allreduce(cr->mpb->libuf,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                          cr->nc.comm_inter);
-        }
-        MPI_Bcast(r,nr,GMX_MPI_LARGE_INT,0,cr->nc.comm_intra);
-    } else {
-        MPI_Allreduce(r,cr->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                      cr->mpi_comm_mygroup);
-        for(i=0; i<nr; i++)
-            r[i] = cr->mpb->libuf[i];
-    }
-#endif
-#endif
-}
-
-
-
-#ifdef GMX_MPI
-void gmx_sumd_comm(int nr,double r[],MPI_Comm mpi_comm)
-{
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,mpi_comm);
-#else
-    /* this function is only used in code that is not performance critical,
-       (during setup, when comm_rec is not the appropriate communication  
-       structure), so this isn't as bad as it looks. */
-    double *buf;
-    int i;
-
-    snew(buf, nr);
-    MPI_Allreduce(r,buf,nr,MPI_DOUBLE,MPI_SUM,mpi_comm);
-    for(i=0; i<nr; i++)
-        r[i] = buf[i];
-    sfree(buf);
-#endif
-}
-#endif
-
-#ifdef GMX_MPI
-void gmx_sumf_comm(int nr,float r[],MPI_Comm mpi_comm)
-{
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,mpi_comm);
-#else
-    /* this function is only used in code that is not performance critical,
-       (during setup, when comm_rec is not the appropriate communication  
-       structure), so this isn't as bad as it looks. */
-    float *buf;
-    int i;
-
-    snew(buf, nr);
-    MPI_Allreduce(r,buf,nr,MPI_FLOAT,MPI_SUM,mpi_comm);
-    for(i=0; i<nr; i++)
-        r[i] = buf[i];
-    sfree(buf);
-#endif
-}
-#endif
-
-void gmx_sumd_sim(int nr,double r[],const gmx_multisim_t *ms)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_sumd_sim");
-#else
-  gmx_sumd_comm(nr,r,ms->mpi_comm_masters);
-#endif
-}
-
-void gmx_sumf_sim(int nr,float r[],const gmx_multisim_t *ms)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_sumf_sim");
-#else
-  gmx_sumf_comm(nr,r,ms->mpi_comm_masters);
-#endif
-}
-
-void gmx_sumi_sim(int nr,int r[], const gmx_multisim_t *ms)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumi_sim");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,ms->mpi_comm_masters);
-#else
-    /* this is thread-unsafe, but it will do for now: */
-    int i;
-
-    if (nr > ms->mpb->ibuf_alloc) {
-        ms->mpb->ibuf_alloc = nr;
-        srenew(ms->mpb->ibuf,ms->mpb->ibuf_alloc);
-    }
-    MPI_Allreduce(r,ms->mpb->ibuf,nr,MPI_INT,MPI_SUM,ms->mpi_comm_masters);
-    for(i=0; i<nr; i++)
-        r[i] = ms->mpb->ibuf[i];
-#endif
-#endif
-}
-
-void gmx_sumli_sim(int nr,gmx_large_int_t r[], const gmx_multisim_t *ms)
-{
-#ifndef GMX_MPI
-    gmx_call("gmx_sumli_sim");
-#else
-#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
-    MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                  ms->mpi_comm_masters);
-#else
-    /* this is thread-unsafe, but it will do for now: */
-    int i;
-
-    if (nr > ms->mpb->libuf_alloc) {
-        ms->mpb->libuf_alloc = nr;
-        srenew(ms->mpb->libuf,ms->mpb->libuf_alloc);
-    }
-    MPI_Allreduce(r,ms->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
-                  ms->mpi_comm_masters);
-    for(i=0; i<nr; i++)
-        r[i] = ms->mpb->libuf[i];
-#endif
-#endif
-}
-
-
-void gmx_finalize(void)
-{
-#ifndef GMX_MPI
-  gmx_call("gmx_finalize");
-#else
-  int ret;
-
-  /* just as a check; we don't want to finalize twice */
-  int finalized;
-  MPI_Finalized(&finalized);
-  if (finalized)
-      return;
-
-  /* We sync the processes here to try to avoid problems
-   * with buggy MPI implementations that could cause
-   * unfinished processes to terminate.
-   */
-  MPI_Barrier(MPI_COMM_WORLD);
-
-  /*
-  if (DOMAINDECOMP(cr)) {
-    if (cr->npmenodes > 0 || cr->dd->bCartesian) 
-      MPI_Comm_free(&cr->mpi_comm_mygroup);
-    if (cr->dd->bCartesian)
-      MPI_Comm_free(&cr->mpi_comm_mysim);
-  }
-  */
-
-  /* Apparently certain mpich implementations cause problems
-   * with MPI_Finalize. In that case comment out MPI_Finalize.
-   */
-  if (debug)
-    fprintf(debug,"Will call MPI_Finalize now\n");
-
-  ret = MPI_Finalize();
-  if (debug)
-    fprintf(debug,"Return code from MPI_Finalize = %d\n",ret);
-#endif
-}
-
diff --git a/src/gmxlib/selection/.cvsignore b/src/gmxlib/selection/.cvsignore
deleted file mode 100644 (file)
index 02b0523..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
diff --git a/src/gmxlib/selection/compiler.c b/src/gmxlib/selection/compiler.c
deleted file mode 100644 (file)
index 45ca192..0000000
+++ /dev/null
@@ -1,2825 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Selection compilation and optimization.
- *
- * \todo
- * Better error handling and memory management in error situations.
- * At least, the main compilation function leaves the selection collection in
- * a bad state if an error occurs.
- *
- * \todo
- * The memory usage could still be optimized.
- * Use of memory pooling could still be extended, and a lot of redundant
- * gmin/gmax data could be eliminated for complex arithmetic expressions.
- */
-/*! \internal
- * \page selcompiler Selection compilation
- *
- * The compiler takes the selection element tree from the selection parser
- * (see \ref selparser) as input. The selection parser is quite independent of
- * selection evaluation details, and the compiler processes the tree to
- * conform to what the evaluation functions expect.
- * For better control and optimization possibilities, the compilation is
- * done on all selections simultaneously.
- * Hence, all the selections should be parsed before the compiler can be
- * called.
- *
- * The compiler initializes all fields in \c t_selelem not initialized by
- * the parser: \c t_selelem::v (some fields have already been initialized by
- * the parser), \c t_selelem::evaluate, and \c t_selelem::u (again, some
- * elements have been initialized in the parser).
- * The \c t_selelem::cdata field is used during the compilation to store
- * internal data, but the data is freed when the compiler returns.
- *
- * In addition to initializing the elements, the compiler reorganizes the tree
- * to simplify and optimize evaluation. The compiler also evaluates the static
- * parts of the selection: in the end of the compilation, static parts have
- * been replaced by the result of the evaluation.
- *
- * The compiler is called by calling gmx_ana_selcollection_compile().
- * This functions then does the compilation in several passes over the
- * \c t_selelem tree.
- *  -# Subexpressions are extracted: a separate root is created for each
- *     subexpression, and placed before the expression is first used.
- *     Currently, only variables and expressions used to evaluate parameter
- *     values are extracted, but common subexpression could also be detected
- *     here.
- *  -# A second pass with simple reordering and initialization is done:
- *    -# Boolean expressions are combined such that one element can evaluate,
- *       e.g., "A and B and C". The subexpressions in gmx_boolean expression are
- *       reordered such that static expressions come first without otherwise
- *       altering the relative order of the expressions.
- *    -# The \c t_selelem::evaluate field is set to the correct evaluation
- *       function from evaluate.h.
- *    -# The compiler data structure is allocated for each element, and
- *       the fields are initialized, with the exception of the contents of
- *       \c gmax and \c gmin fields.  In reality, several passes are made
- *       to completely initialize the structure, because some flags are set
- *       recursively based on which elements refer to an element, and these
- *       flags need to be set to initialize other fields.
- *    .
- *  -# The evaluation function of all elements is replaced with the
- *     analyze_static() function to be able to initialize the element before
- *     the actual evaluation function is called.
- *     The evaluation machinery is then called to initialize the whole tree,
- *     while simultaneously evaluating the static expressions.
- *     During the evaluation, track is kept of the smallest and largest
- *     possible selections, and these are stored in the internal compiler
- *     data structure for each element.
- *     To be able to do this for all possible values of dynamical expressions,
- *     special care needs to be taken with gmx_boolean expressions because they
- *     are short-circuiting. This is done through the
- *     \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
- *     of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
- *     of \c BOOL_AND are evaluated to largest possible groups.
- *     Memory is also allocated to store the results of the evaluation.
- *     For each element, analyze_static() calls the actual evaluation function
- *     after the element has been properly initialized.
- *  -# Another evaluation pass is done over subexpressions with more than
- *     one reference to them. These cannot be completely processed during the
- *     first pass, because it is not known whether later references require
- *     additional evaluation of static expressions.
- *  -# Unused subexpressions are removed. For efficiency reasons (and to avoid
- *     some checks), this is actually done several times already earlier in
- *     the compilation process.
- *  -# Most of the processing is now done, and the next pass simply sets the
- *     evaluation group of root elements to the largest selection as determined
- *     in pass 3.  For root elements of subexpressions that should not be
- *     evaluated before they are referred to, the evaluation group/function is
- *     cleared.  At the same time, position calculation data is initialized for
- *     for selection method elements that require it.  Compiler data is also
- *     freed as it is no longer needed.
- *  -# A final pass initializes the total masses and charges in the
- *     \c gmx_ana_selection_t data structures.
- *
- * The actual evaluation of the selection is described in the documentation
- * of the functions in evaluate.h.
- *
- * \todo
- * Some combinations of method parameter flags are not yet properly treated by
- * the compiler or the evaluation functions in evaluate.c. All the ones used by
- * currently implemented methods should work, but new combinations might not.
- *
- *
- * \section selcompiler_tree Element tree after compilation
- *
- * After the compilation, the selection element tree is suitable for
- * gmx_ana_selcollection_evaluate().
- * Enough memory has been allocated for \ref t_selelem::v
- * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
- * selection to be evaluated without allocating any memory.
- *
- *
- * \subsection selcompiler_tree_root Root elements
- *
- * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
- * These are used for two purposes:
- *  -# A selection that should be evaluated.
- *     These elements appear in the same order as the selections in the input.
- *     For these elements, \ref t_selelem::v has been set to the maximum
- *     possible group that the selection can evaluate to (only for dynamic
- *     selections), and \ref t_selelem::cgrp has been set to use a NULL group
- *     for evaluation.
- *  -# A subexpression that appears in one or more selections.
- *     Each selection that gives a value for a method parameter is a
- *     potential subexpression, as is any variable value.
- *     Only subexpressions that require evaluation for each frame are left
- *     after the selection is compiled.
- *     Each subexpression appears in the chain before any references to it.
- *     For these elements, \c t_selelem::cgrp has been set to the group
- *     that should be used to evaluate the subexpression.
- *     If \c t_selelem::cgrp is empty, the total evaluation group is not known
- *     in advance or it is more efficient to evaluate the subexpression only
- *     when it is referenced.  If this is the case, \c t_selelem::evaluate is
- *     also NULL.
- *
- * The children of the \ref SEL_ROOT elements can be used to distinguish
- * the two types of root elements from each other; the rules are the same
- * as for the parsed tree (see \ref selparser_tree_root).
- * Subexpressions are treated as if they had been provided through variables.
- *
- * Selection names are stored as after parsing (see \ref selparser_tree_root).
- *
- *
- * \subsection selcompiler_tree_const Constant elements
- *
- * All (sub)selections that do not require particle positions have been
- * replaced with \ref SEL_CONST elements.
- * Constant elements from the parser are also retained if present in
- * dynamic parts of the selections.
- * Several constant elements with a NULL \c t_selelem::evaluate are left for
- * debugging purposes; of these, only the ones for \ref BOOL_OR expressions are
- * used during evaluation.
- *
- * The value is stored in \c t_selelem::v, and for group values with an
- * evaluation function set, also in \c t_selelem::cgrp.
- * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
- * could never be selected) have been removed from the value.
- *
- * \ref SEL_CONST elements have no children.
- *
- *
- * \subsection selcompiler_tree_method Method evaluation elements
- *
- * All selection methods that need to be evaluated dynamically are described
- * by a \ref SEL_EXPRESSION element. The \c t_selelem::method and
- * \c t_selelem::mdata fields have already been initialized by the parser,
- * and the compiler only calls the initialization functions in the method
- * data structure to do some additional initialization of these fields at
- * appropriate points. If the \c t_selelem::pc data field has been created by
- * the parser, the compiler initializes the data structure properly once the
- * required positions are known. If the \c t_selelem::pc field is NULL after
- * the parser, but the method provides only sel_updatefunc_pos(), an
- * appropriate position calculation data structure is created.
- * If \c t_selelem::pc is not NULL, \c t_selelem::pos is also initialized
- * to hold the positions calculated.
- *
- * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
- * parameter values that need to be evaluated for each frame. See the next
- * section for more details.
- * \ref SEL_CONST children can also appear, and stand for parameters that get
- * their value from a static expression. These elements are present only for
- * debugging purposes: they always have a NULL evaluation function.
- *
- *
- * \subsection selcompiler_tree_subexpr Subexpression elements
- *
- * As described in \ref selcompiler_tree_root, subexpressions are created
- * for each variable and each expression that gives a value to a selection
- * method parameter. As the only child of the \ref SEL_ROOT element,
- * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
- * element has a single child, which evaluates the actual expression.
- * After compilation, only subexpressions that require particle positions
- * for evaluation are left.
- * For non-variable subexpression, automatic names have been generated to
- * help in debugging.
- *
- * For \ref SEL_SUBEXPR elements, memory has been allocated for
- * \c t_selelem::cgrp to store the group for which the expression has been
- * evaluated during the current frame.  This is only done if full subexpression
- * evaluation by _gmx_sel_evaluate_subexpr() is needed; the other evaluation
- * functions do not require this memory.
- *
- * \ref SEL_SUBEXPRREF elements are used to describe references to
- * subexpressions. They have always a single child, which is the
- * \ref SEL_SUBEXPR element being referenced.
- *
- * If a subexpression is used only once, the evaluation has been optimized by
- * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
- * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
- * by the evaluation functions).  In such cases, the evaluation routines for the
- * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
- * information, but do not unnecessarily copy the values.
- *
- *
- * \subsection selcompiler_tree_gmx_bool Boolean elements
- *
- * \ref SEL_BOOLEAN elements have been merged such that one element
- * may carry out evaluation of more than one operation of the same type.
- * The static parts of the expressions have been evaluated, and are placed
- * in the first child. These are followed by the dynamic expressions, in the
- * order provided by the user.
- *
- *
- * \subsection selcompiler_tree_arith Arithmetic elements
- *
- * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
- * calculated.
- * Currently, no other processing is done.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-#include <stdarg.h>
-
-#include <smalloc.h>
-#include <string2.h>
-#include <vec.h>
-
-#include <indexutil.h>
-#include <poscalc.h>
-#include <selection.h>
-#include <selmethod.h>
-
-#include "evaluate.h"
-#include "keywords.h"
-#include "mempool.h"
-#include "selcollection.h"
-#include "selelem.h"
-
-/*! \internal \brief
- * Compiler flags.
- */
-enum
-{
-    /*! \brief
-     * Whether a subexpression needs to evaluated for all atoms.
-     *
-     * This flag is set for \ref SEL_SUBEXPR elements that are used to
-     * evaluate non-atom-valued selection method parameters, as well as
-     * those that are used directly as values of selections.
-     */
-    SEL_CDATA_FULLEVAL    =  1,
-    /*! \brief
-     * Whether the whole subexpression should be treated as static.
-     *
-     * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
-     * but it is also FALSE for static elements within common subexpressions.
-     */
-    SEL_CDATA_STATIC      =  2,
-    /** Whether the subexpression will always be evaluated in the same group. */
-    SEL_CDATA_STATICEVAL  =  4,
-    /** Whether the compiler evaluation routine should return the maximal selection. */
-    SEL_CDATA_EVALMAX     =  8,
-    /** Whether memory has been allocated for \p gmin and \p gmax. */
-    SEL_CDATA_MINMAXALLOC = 16,
-    /** Whether subexpressions use simple pass evaluation functions. */
-    SEL_CDATA_SIMPLESUBEXPR = 32,
-    /** Whether this expressions is a part of a common subexpression. */
-    SEL_CDATA_COMMONSUBEXPR = 64 
-};
-
-/*! \internal \brief
- * Internal data structure used by the compiler.
- */
-typedef struct t_compiler_data
-{
-    /** The real evaluation method. */
-    sel_evalfunc     evaluate;
-    /** Flags for specifying how to treat this element during compilation. */
-    int              flags;
-    /** Smallest selection that can be selected by the subexpression. */
-    gmx_ana_index_t *gmin;
-    /** Largest selection that can be selected by the subexpression. */
-    gmx_ana_index_t *gmax;
-} t_compiler_data;
-
-
-/********************************************************************
- * COMPILER UTILITY FUNCTIONS
- ********************************************************************/
-
-static void
-print_group_info(FILE *fp, const char *name, t_selelem *sel, gmx_ana_index_t *g)
-{
-    fprintf(fp, " %s=", name);
-    if (!g)
-    {
-        fprintf(fp, "(null)");
-    }
-    else if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
-    {
-        fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
-    }
-    else if (sel->v.type == GROUP_VALUE && g == sel->v.u.g)
-    {
-        fprintf(fp, "(static, %p)", (void*)g);
-    }
-    else
-    {
-        fprintf(fp, "%p", (void*)g);
-    }
-}
-
-/*!
- * \param[in] fp      File handle to receive the output.
- * \param[in] sel     Selection element to print.
- * \param[in] level   Indentation level, starting from zero.
- */
-void
-_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level)
-{
-    if (!sel->cdata)
-    {
-        return;
-    }
-    fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
-    if (sel->cdata->flags & SEL_CDATA_FULLEVAL)
-    {
-        fprintf(fp, "F");
-    }
-    if (!(sel->cdata->flags & SEL_CDATA_STATIC))
-    {
-        fprintf(fp, "D");
-    }
-    if (sel->cdata->flags & SEL_CDATA_STATICEVAL)
-    {
-        fprintf(fp, "S");
-    }
-    if (sel->cdata->flags & SEL_CDATA_EVALMAX)
-    {
-        fprintf(fp, "M");
-    }
-    if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
-    {
-        fprintf(fp, "A");
-    }
-    if (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
-    {
-        fprintf(fp, "Ss");
-    }
-    if (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
-    {
-        fprintf(fp, "Sc");
-    }
-    if (!sel->cdata->flags)
-    {
-        fprintf(fp, "0");
-    }
-    fprintf(fp, " eval=");
-    _gmx_sel_print_evalfunc_name(fp, sel->cdata->evaluate);
-    print_group_info(fp, "gmin", sel, sel->cdata->gmin);
-    print_group_info(fp, "gmax", sel, sel->cdata->gmax);
-    fprintf(fp, "\n");
-}
-
-/*!
- * \param  sel Selection to free.
- *
- * This function only frees the data for the given selection, not its children.
- * It is safe to call the function when compiler data has not been allocated
- * or has already been freed; in such a case, nothing is done.
- */
-void
-_gmx_selelem_free_compiler_data(t_selelem *sel)
-{
-    if (sel->cdata)
-    {
-        sel->evaluate = sel->cdata->evaluate;
-        if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
-        {
-            sel->cdata->gmin->name = NULL;
-            sel->cdata->gmax->name = NULL;
-            gmx_ana_index_deinit(sel->cdata->gmin);
-            gmx_ana_index_deinit(sel->cdata->gmax);
-            sfree(sel->cdata->gmin);
-            sfree(sel->cdata->gmax);
-        }
-        sfree(sel->cdata);
-    }
-    sel->cdata = NULL;
-}
-
-/*! \brief
- * Allocates memory for storing the evaluated value of a selection element.
- *
- * \param     sel   Selection element to initialize
- * \param[in] isize Maximum evaluation group size.
- * \param[in] bChildEval TRUE if children have already been processed.
- * \returns   TRUE if the memory was allocated, FALSE if children need to
- *   be processed first.
- *
- * If called more than once, memory is (re)allocated to ensure that the
- * maximum of the \p isize values can be stored.
- */
-static gmx_bool
-alloc_selection_data(t_selelem *sel, int isize, gmx_bool bChildEval)
-{
-    int        nalloc;
-
-    if (sel->mempool)
-    {
-        return TRUE;
-    }
-    /* Find out the number of elements to allocate */
-    if (sel->flags & SEL_SINGLEVAL)
-    {
-        nalloc = 1;
-    }
-    else if (sel->flags & SEL_ATOMVAL)
-    {
-        nalloc = isize;
-    }
-    else /* sel->flags should contain SEL_VARNUMVAL */
-    {
-        t_selelem *child;
-
-        if (!bChildEval)
-        {
-            return FALSE;
-        }
-        child = (sel->type == SEL_SUBEXPRREF ? sel->child : sel);
-        if (child->type == SEL_SUBEXPR)
-        {
-            child = child->child;
-        }
-        nalloc = (sel->v.type == POS_VALUE) ? child->v.u.p->nr : child->v.nr;
-    }
-    /* For positions, we actually want to allocate just a single structure
-     * for nalloc positions. */
-    if (sel->v.type == POS_VALUE)
-    {
-        isize  = nalloc;
-        nalloc = 1;
-    }
-    /* Allocate memory for sel->v.u if needed */
-    if (sel->flags & SEL_ALLOCVAL)
-    {
-        _gmx_selvalue_reserve(&sel->v, nalloc);
-    }
-    /* Reserve memory inside group and position structures if
-     * SEL_ALLOCDATA is set. */
-    if (sel->flags & SEL_ALLOCDATA)
-    {
-        if (sel->v.type == GROUP_VALUE)
-        {
-            gmx_ana_index_reserve(sel->v.u.g, isize);
-        }
-        else if (sel->v.type == POS_VALUE)
-        {
-            gmx_ana_pos_reserve(sel->v.u.p, isize, 0);
-        }
-    }
-    return TRUE;
-}
-
-/*! \brief
- * Replace the evaluation function of each element in the subtree.
- *
- * \param     sel  Root of the selection subtree to process.
- * \param[in] eval The new evaluation function.
- */
-static void
-set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
-{
-    sel->evaluate = eval;
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem *child = sel->child;
-        while (child)
-        {
-            set_evaluation_function(child, eval);
-            child = child->next;
-        }
-    }
-}
-
-
-/********************************************************************
- * SUBEXPRESSION PROCESSING
- ********************************************************************/
-
-/*! \brief
- * Reverses the chain of selection elements starting at \p root.
- *
- * \param   root First selection in the whole selection chain.
- * \returns The new first element for the chain.
- */
-static t_selelem *
-reverse_selelem_chain(t_selelem *root)
-{
-    t_selelem *item;
-    t_selelem *prev;
-    t_selelem *next;
-
-    prev = NULL;
-    item = root;
-    while (item)
-    {
-        next = item->next;
-        item->next = prev;
-        prev = item;
-        item = next;
-    }
-    return prev;
-}
-
-/*! \brief
- * Removes subexpressions that don't have any references.
- *
- * \param     root First selection in the whole selection chain.
- * \returns   The new first element for the chain.
- *
- * The elements are processed in reverse order to correctly detect
- * subexpressions only referred to by other subexpressions.
- */
-static t_selelem *
-remove_unused_subexpressions(t_selelem *root)
-{
-    t_selelem *item;
-    t_selelem *prev;
-    t_selelem *next;
-
-    root = reverse_selelem_chain(root);
-    while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
-    {
-        next = root->next;
-        _gmx_selelem_free(root);
-        root = next;
-    }
-    prev = root;
-    item = root->next;
-    while (item)
-    {
-        next = item->next;
-        if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
-        {
-            prev->next = next;
-            _gmx_selelem_free(item);
-        }
-        else
-        {
-            prev = item;
-        }
-        item = next;
-    }
-    return reverse_selelem_chain(root);
-}
-
-/*! \brief
- * Creates a name with a running number for a subexpression.
- *
- * \param[in,out] sel The subexpression to be named.
- * \param[in]     i   Running number for the subexpression.
- *
- * The name of the selection becomes "SubExpr N", where N is \p i;
- * Memory is allocated for the name and the name is stored both in
- * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
- * is freed by _gmx_selelem_free().
- */
-static void
-create_subexpression_name(t_selelem *sel, int i)
-{
-    int   len, ret;
-    char *name;
-
-    len = 8 + (int)log10(abs(i)) + 3;
-    snew(name, len+1);
-    /* FIXME: snprintf used to be used here for extra safety, but this
-     * requires extra checking on Windows since it only provides a
-     * non-C99-conforming implementation as _snprintf()... */
-    ret = sprintf(name, "SubExpr %d", i);
-    if (ret < 0 || ret > len)
-    {
-        sfree(name);
-        name = NULL;
-    }
-    sel->name        = name;
-    sel->u.cgrp.name = name;
-}
-
-/*! \brief
- * Processes and extracts subexpressions from a given selection subtree.
- *
- * \param   sel      Root of the subtree to process.
- * \param   subexprn Pointer to a subexpression counter.
- * \returns Pointer to a chain of subselections, or NULL if none were found.
- *
- * This function finds recursively all \ref SEL_SUBEXPRREF elements below
- * the given root element and ensures that their children are within
- * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
- * that contain the subexpression as their children and returns the first
- * of these root elements.
- */
-static t_selelem *
-extract_item_subselections(t_selelem *sel, int *subexprn)
-{
-    t_selelem *root;
-    t_selelem *subexpr;
-    t_selelem *child;
-
-    root = subexpr = NULL;
-    child = sel->child;
-    while (child)
-    {
-        if (!root)
-        {
-            root = subexpr = extract_item_subselections(child, subexprn);
-        }
-        else
-        {
-            subexpr->next = extract_item_subselections(child, subexprn);
-        }
-        while (subexpr && subexpr->next)
-        {
-            subexpr = subexpr->next;
-        }
-        /* The latter check excludes variable references.
-         * It also excludes subexpression elements that have already been
-         * processed, because they are given a name when they are first
-         * encountered.
-         * TODO: There should be a more robust mechanism (probably a dedicated
-         * flag) for detecting parser-generated subexpressions than relying on
-         * a NULL name field. */
-        if (child->type == SEL_SUBEXPRREF && (child->child->type != SEL_SUBEXPR
-                                              || child->child->name == NULL))
-        {
-            /* Create the root element for the subexpression */
-            if (!root)
-            {
-                root = subexpr = _gmx_selelem_create(SEL_ROOT);
-            }
-            else
-            {
-                subexpr->next = _gmx_selelem_create(SEL_ROOT);
-                subexpr       = subexpr->next;
-            }
-            /* Create the subexpression element and/or
-             * move the actual subexpression under the created element. */
-            if (child->child->type != SEL_SUBEXPR)
-            {
-                subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
-                _gmx_selelem_set_vtype(subexpr->child, child->v.type);
-                subexpr->child->child = child->child;
-                child->child          = subexpr->child;
-            }
-            else
-            {
-                subexpr->child = child->child;
-            }
-            create_subexpression_name(subexpr->child, ++*subexprn);
-            subexpr->child->refcount++;
-            /* Set the flags for the created elements */
-            subexpr->flags          |= (child->flags & SEL_VALFLAGMASK);
-            subexpr->child->flags   |= (child->flags & SEL_VALFLAGMASK);
-        }
-        child = child->next;
-    }
-
-    return root;
-}
-
-/*! \brief
- * Extracts subexpressions of the selection chain.
- * 
- * \param   sel First selection in the whole selection chain.
- * \returns The new first element for the chain.
- *
- * Finds all the subexpressions (and their subexpressions) in the
- * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
- * elements for them.
- * \ref SEL_ROOT elements are also created for each subexpression
- * and inserted into the selection chain before the expressions that
- * refer to them.
- */
-static t_selelem *
-extract_subexpressions(t_selelem *sel)
-{
-    t_selelem   *root, *item, *next;
-    int          subexprn;
-
-    subexprn = 0;
-    root = NULL;
-    next = sel;
-    while (next)
-    {
-        item = extract_item_subselections(next, &subexprn);
-        if (item)
-        {
-            if (!root)
-            {
-                root = item;
-            }
-            else
-            {
-                sel->next = item;
-            }
-            while (item->next)
-            {
-                item = item->next;
-            }
-            item->next = next;
-        }
-        else if (!root)
-        {
-            root = next;
-        }
-        sel = next;
-        next = next->next;
-    }
-    return root;
-}
-
-
-/********************************************************************
- * BOOLEAN OPERATION REORDERING
- ********************************************************************/
-
-/*! \brief
- * Removes redundant gmx_boolean selection elements.
- *
- * \param  sel Root of the selection subtree to optimize.
- *
- * This function merges similar gmx_boolean operations (e.g., (A or B) or C becomes
- * a single OR operation with three operands).
- */
-static void
-optimize_gmx_boolean_expressions(t_selelem *sel)
-{
-    t_selelem *child, *prev;
-
-    /* Do recursively for children */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        prev  = NULL;
-        child = sel->child;
-        while (child)
-        {
-            optimize_gmx_boolean_expressions(child);
-            /* Remove double negations */
-            if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
-                && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
-            {
-                /* Move the doubly negated expression up two levels */
-                if (!prev)
-                {
-                    sel->child = child->child->child;
-                    prev       = sel->child;
-                }
-                else
-                {
-                    prev->next = child->child->child;
-                    prev       = prev->next;
-                }
-                child->child->child->next = child->next;
-                /* Remove the two negations */
-                child->child->child = NULL;
-                child->next         = NULL;
-                _gmx_selelem_free(child);
-                child = prev;
-            }
-            prev  = child;
-            child = child->next;
-        }
-    }
-    if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
-    {
-        return;
-    }
-    /* Merge subsequent binary operations */
-    prev  = NULL;
-    child = sel->child;
-    while (child)
-    {
-        if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
-        {
-            if (!prev)
-            {
-                sel->child = child->child;
-                prev       = sel->child;
-            }
-            else
-            {
-                prev->next = child->child;
-            }
-            while (prev->next)
-            {
-                prev = prev->next;
-            }
-            prev->next = child->next;
-            sfree(child->v.u.g);
-            sfree(child);
-            child = prev->next;
-        }
-        else
-        {
-            prev = child;
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Reorders children of gmx_boolean expressions such that static selections
- * come first.
- *
- * \param  sel Root of the selection subtree to reorder.
- *
- * The relative order of static expressions does not change.
- * The same is true for the dynamic expressions.
- */
-static void
-reorder_gmx_boolean_static_children(t_selelem *sel)
-{
-    t_selelem *child, *prev, *next;
-
-    /* Do recursively for children */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        child = sel->child;
-        while (child)
-        {
-            reorder_gmx_boolean_static_children(child);
-            child = child->next;
-        }
-    }
-
-    /* Reorder gmx_boolean expressions such that static selections come first */
-    if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
-    {
-        t_selelem  start;
-
-        start.next = sel->child;
-        prev  = &start;
-        child = &start;
-        while (child->next)
-        {
-            /* child is the last handled static expression */
-            /* prev is the last handled non-static expression */
-            next = prev->next;
-            while (next && (next->flags & SEL_DYNAMIC))
-            {
-                prev = next;
-                next = next->next;
-            }
-            /* next is now the first static expression after child */
-            if (!next)
-            {
-                break;
-            }
-            /* Reorder such that next comes after child */
-            if (prev != child)
-            {
-                prev->next  = next->next;
-                next->next  = child->next;
-                child->next = next;
-            }
-            else
-            {
-                prev = prev->next;
-            }
-            /* Advance child by one */
-            child = next;
-        }
-
-        sel->child = start.next;
-    }
-}
-
-
-/********************************************************************
- * ARITHMETIC EXPRESSION PROCESSING
- ********************************************************************/
-
-/*! \brief
- * Processes arithmetic expressions to simplify and speed up evaluation.
- *
- * \param  sel Root of the selection subtree to process.
- *
- * Currently, this function only converts integer constants to reals
- * within arithmetic expressions.
- */
-static gmx_bool
-optimize_arithmetic_expressions(t_selelem *sel)
-{
-    t_selelem  *child;
-    gmx_bool        bOk;
-
-    /* Do recursively for children. */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        child = sel->child;
-        while (child)
-        {
-            bOk = optimize_arithmetic_expressions(child);
-            if (!bOk)
-            {
-                return bOk;
-            }
-            child = child->next;
-        }
-    }
-
-    if (sel->type != SEL_ARITHMETIC)
-    {
-        return TRUE;
-    }
-
-    /* Convert integer constants to reals. */
-    child = sel->child;
-    while (child)
-    {
-        if (child->v.type == INT_VALUE)
-        {
-            real  *r;
-
-            if (child->type != SEL_CONST)
-            {
-                gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
-                return FALSE;
-            }
-            snew(r, 1);
-            r[0] = child->v.u.i[0];
-            sfree(child->v.u.i);
-            child->v.u.r = r;
-            child->v.type = REAL_VALUE;
-        }
-        else if (child->v.type != REAL_VALUE)
-        {
-            gmx_bug("Internal error");
-            return FALSE;
-        }
-        child = child->next;
-    }
-    return TRUE;
-}
-
-
-/********************************************************************
- * EVALUATION PREPARATION COMPILER
- ********************************************************************/
-
-/*! \brief
- * Sets the evaluation functions for the selection (sub)tree.
- *
- * \param[in,out] sel Root of the selection subtree to process.
- * \returns       TRUE on success, FALSE if any subexpression fails.
- *
- * This function sets the evaluation function (\c t_selelem::evaluate)
- * for the selection elements.
- */
-static gmx_bool
-init_item_evalfunc(t_selelem *sel)
-{
-    /* Process children. */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem *child;
-
-        child = sel->child;
-        while (child)
-        {
-            if (!init_item_evalfunc(child))
-            {
-                return FALSE;
-            }
-            child = child->next;
-        }
-    }
-
-    /* Set the evaluation function */
-    switch (sel->type)
-    {
-        case SEL_CONST:
-            if (sel->v.type == GROUP_VALUE)
-            {
-                sel->evaluate = &_gmx_sel_evaluate_static;
-            }
-            break;
-
-        case SEL_EXPRESSION:
-            if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
-                && sel->u.expr.method->init_frame)
-            {
-                sel->flags |= SEL_INITFRAME;
-            }
-            sel->evaluate = &_gmx_sel_evaluate_method;
-            break;
-
-        case SEL_ARITHMETIC:
-            sel->evaluate = &_gmx_sel_evaluate_arithmetic;
-            break;
-
-        case SEL_MODIFIER:
-            if (sel->v.type != NO_VALUE)
-            {
-                sel->evaluate = &_gmx_sel_evaluate_modifier;
-            }
-            break;
-
-        case SEL_BOOLEAN:
-            switch (sel->u.boolt)
-            {
-                case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
-                case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
-                case BOOL_OR:  sel->evaluate = &_gmx_sel_evaluate_or;  break;
-                case BOOL_XOR:
-                    gmx_impl("xor expressions not implemented");
-                    return FALSE;
-            }
-            break;
-
-        case SEL_ROOT:
-            sel->evaluate = &_gmx_sel_evaluate_root;
-            break;
-
-        case SEL_SUBEXPR:
-            sel->evaluate = (sel->refcount == 2
-                             ? &_gmx_sel_evaluate_subexpr_simple
-                             : &_gmx_sel_evaluate_subexpr);
-            break;
-
-        case SEL_SUBEXPRREF:
-            sel->name     = sel->child->name;
-            sel->evaluate = (sel->child->refcount == 2
-                             ? &_gmx_sel_evaluate_subexprref_simple
-                             : &_gmx_sel_evaluate_subexprref);
-            break;
-    }
-
-    return TRUE;
-}
-
-/*! \brief
- * Sets the memory pool for selection elements that can use it.
- *
- * \param     sel      Root of the selection subtree to process.
- * \param[in] mempool  Memory pool to use.
- */
-static void
-setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
-{
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem         *child;
-
-        child = sel->child;
-        while (child)
-        {
-            if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
-                || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
-                    && !(child->flags & SEL_SINGLEVAL))
-                || (sel->type == SEL_SUBEXPR && sel->refcount > 2))
-            {
-                child->mempool = mempool;
-                if (child->type == SEL_SUBEXPRREF
-                    && child->child->refcount == 2)
-                {
-                    child->child->child->mempool = mempool;
-                }
-            }
-            setup_memory_pooling(child, mempool);
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Prepares the selection (sub)tree for evaluation.
- *
- * \param[in,out] sel Root of the selection subtree to prepare.
- *
- * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
- * structure if required.
- */
-static void
-init_item_evaloutput(t_selelem *sel)
-{
-    /* Process children. */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem *child;
-
-        child = sel->child;
-        while (child)
-        {
-            init_item_evaloutput(child);
-            child = child->next;
-        }
-    }
-
-    if (sel->type == SEL_SUBEXPR && sel->refcount == 2)
-    {
-        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
-        {
-            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
-        }
-    }
-    else if (sel->type == SEL_SUBEXPR
-             && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
-    {
-        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
-        sel->cdata->evaluate = sel->evaluate;
-        sel->child->mempool = NULL;
-        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
-        {
-            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
-        }
-    }
-    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
-    {
-        if (sel->v.u.ptr)
-        {
-            _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
-            _gmx_selelem_free_values(sel->child->child);
-            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-            sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
-            _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
-        }
-        else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
-        {
-            _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
-        }
-        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-    }
-
-    /* Make sure that the group/position structure is allocated. */
-    if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
-    {
-        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
-        {
-            _gmx_selvalue_reserve(&sel->v, 1);
-            sel->v.nr = 1;
-        }
-    }
-}
-
-
-/********************************************************************
- * COMPILER DATA INITIALIZATION
- ********************************************************************/
-
-/*! \brief
- * Allocates memory for the compiler data and initializes the structure.
- *
- * \param sel Root of the selection subtree to process.
- */
-static void
-init_item_compilerdata(t_selelem *sel)
-{
-    t_selelem   *child;
-
-    /* Allocate the compiler data structure */
-    snew(sel->cdata, 1);
-
-    /* Store the real evaluation method because the compiler will replace it */
-    sel->cdata->evaluate = sel->evaluate;
-
-    /* Initialize the flags */
-    sel->cdata->flags = SEL_CDATA_STATICEVAL;
-    if (!(sel->flags & SEL_DYNAMIC))
-    {
-        sel->cdata->flags |= SEL_CDATA_STATIC;
-    }
-    if (sel->type == SEL_SUBEXPR)
-    {
-        sel->cdata->flags |= SEL_CDATA_EVALMAX;
-    }
-    /* Set the full evaluation flag for subexpressions that require it;
-     * the subexpression has already been initialized, so we can simply
-     * access its compilation flags.*/
-    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
-    {
-        child = sel->child;
-        while (child)
-        {
-            if (!(child->flags & SEL_ATOMVAL) && child->child)
-            {
-                child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
-            }
-            child = child->next;
-        }
-    }
-    else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
-    {
-        sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
-    }
-
-    /* Initialize children */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        child = sel->child;
-        while (child)
-        {
-            init_item_compilerdata(child);
-            child = child->next;
-        }
-    }
-
-    /* Determine whether we should evaluate the minimum or the maximum
-     * for the children of this element. */
-    if (sel->type == SEL_BOOLEAN)
-    {
-        gmx_bool  bEvalMax;
-
-        bEvalMax = (sel->u.boolt == BOOL_AND);
-        child = sel->child;
-        while (child)
-        {
-            if (bEvalMax)
-            {
-                child->cdata->flags |= SEL_CDATA_EVALMAX;
-            }
-            else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
-            {
-                child->child->cdata->flags |= SEL_CDATA_EVALMAX;
-            }
-            child = child->next;
-        }
-    }
-    else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
-             || sel->type == SEL_SUBEXPR)
-    {
-        child = sel->child;
-        while (child)
-        {
-            child->cdata->flags |= SEL_CDATA_EVALMAX;
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Initializes the static evaluation flag for a selection subtree.
- *
- * \param[in,out] sel  Root of the selection subtree to process.
- *
- * Sets the \c bStaticEval in the compiler data structure:
- * for any element for which the evaluation group may depend on the trajectory
- * frame, the flag is cleared.
- *
- * reorder_gmx_boolean_static_children() should have been called.
- */
-static void
-init_item_staticeval(t_selelem *sel)
-{
-    t_selelem   *child;
-
-    /* Subexpressions with full evaluation should always have bStaticEval,
-     * so don't do anything if a reference to them is encountered. */
-    if (sel->type == SEL_SUBEXPRREF
-        && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
-    {
-        return;
-    }
-
-    /* Propagate the bStaticEval flag to children if it is not set */
-    if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
-    {
-        child = sel->child;
-        while (child)
-        {
-            if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
-                || (child->flags & SEL_ATOMVAL))
-            {
-                if (child->cdata->flags & SEL_CDATA_STATICEVAL)
-                {
-                    child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
-                    init_item_staticeval(child);
-                }
-            }
-            child = child->next;
-        }
-    }
-    else /* bStaticEval is set */
-    {
-        /* For gmx_boolean expressions, any expression after the first dynamic
-         * expression should not have bStaticEval. */
-        if (sel->type == SEL_BOOLEAN)
-        {
-            child = sel->child;
-            while (child && !(child->flags & SEL_DYNAMIC))
-            {
-                child = child->next;
-            }
-            if (child)
-            {
-                child = child->next;
-            }
-            while (child)
-            {
-                child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
-                child = child->next;
-            }
-        }
-
-        /* Process the children */
-        child = sel->child;
-        while (child)
-        {
-            init_item_staticeval(child);
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Initializes compiler flags for subexpressions.
- *
- * \param sel Root of the selection subtree to process.
- */
-static void
-init_item_subexpr_flags(t_selelem *sel)
-{
-    if (sel->type == SEL_SUBEXPR)
-    {
-        if (sel->refcount == 2)
-        {
-            sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
-        }
-        else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
-        {
-            sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
-        }
-    }
-    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
-    {
-        sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
-    }
-
-    /* Process children, but only follow subexpression references if the
-     * common subexpression flag needs to be propagated. */
-    if (sel->type != SEL_SUBEXPRREF
-        || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
-            && sel->child->refcount > 2))
-    {
-        t_selelem *child = sel->child;
-
-        while (child)
-        {
-            if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
-            {
-                if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
-                {
-                    child->cdata->flags |=
-                        (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
-                }
-                init_item_subexpr_flags(child);
-            }
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Initializes the gmin and gmax fields of the compiler data structure.
- *
- * \param sel Root of the selection subtree to process.
- */
-static void
-init_item_minmax_groups(t_selelem *sel)
-{
-    /* Process children. */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem *child;
-
-        child = sel->child;
-        while (child)
-        {
-            init_item_minmax_groups(child);
-            child = child->next;
-        }
-    }
-
-    /* Initialize the minimum and maximum evaluation groups. */
-    if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
-    {
-        if (sel->v.type == GROUP_VALUE
-            && (sel->cdata->flags & SEL_CDATA_STATIC))
-        {
-            sel->cdata->gmin = sel->v.u.g;
-            sel->cdata->gmax = sel->v.u.g;
-        }
-        else if (sel->type == SEL_SUBEXPR
-                 && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
-                     || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
-        {
-            sel->cdata->gmin = sel->child->cdata->gmin;
-            sel->cdata->gmax = sel->child->cdata->gmax;
-        }
-        else
-        {
-            sel->cdata->flags |= SEL_CDATA_MINMAXALLOC;
-            snew(sel->cdata->gmin, 1);
-            snew(sel->cdata->gmax, 1);
-        }
-    }
-}
-
-
-/********************************************************************
- * EVALUATION GROUP INITIALIZATION
- ********************************************************************/
-
-/*! \brief
- * Initializes evaluation groups for root items.
- *
- * \param[in,out] sc   Selection collection data.
- *
- * The evaluation group of each \ref SEL_ROOT element corresponding to a
- * selection in \p sc is set to \p gall.  The same is done for \ref SEL_ROOT
- * elements corresponding to subexpressions that need full evaluation.
- */
-static void
-initialize_evalgrps(gmx_ana_selcollection_t *sc)
-{
-    t_selelem   *root;
-
-    root = sc->root;
-    while (root)
-    {
-        if (root->child->type != SEL_SUBEXPR
-            || (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
-        {
-            gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
-                              root->u.cgrp.name, 0);
-        }
-        root = root->next;
-    }
-}
-
-
-/********************************************************************
- * STATIC ANALYSIS
- ********************************************************************/
-
-/*! \brief
- * Marks a subtree completely dynamic or undoes such a change.
- *
- * \param     sel      Selection subtree to mark.
- * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
- *   selection subtree is cleared. If FALSE, the flag is restored to
- *   using \ref SEL_DYNAMIC.
- *
- * Does not descend into parameters of methods unless the parameters
- * are evaluated for each atom.
- */
-static void
-mark_subexpr_dynamic(t_selelem *sel, gmx_bool bDynamic)
-{
-    t_selelem *child;
-
-    if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
-    {
-        sel->cdata->flags |= SEL_CDATA_STATIC;
-    }
-    else
-    {
-        sel->cdata->flags &= ~SEL_CDATA_STATIC;
-    }
-    child = sel->child;
-    while (child)
-    {
-        if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
-            || (child->u.param->flags & SPAR_ATOMVAL))
-        {
-            mark_subexpr_dynamic(child, bDynamic);
-        }
-        child = child->next;
-    }
-}
-
-/*! \brief
- * Frees memory for subexpressions that are no longer needed.
- *
- * \param     sel      Selection subtree to check.
- *
- * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
- * elements that are not referred to by anything else except their own root
- * element. If such elements are found, all memory allocated for them is freed
- * except the actual element. The element is left because otherwise a dangling
- * pointer would be left at the root element, which is not traversed by this
- * function. Later compilation passes remove the stub elements.
- */
-static void
-release_subexpr_memory(t_selelem *sel)
-{
-    if (sel->type == SEL_SUBEXPR)
-    {
-        if (sel->refcount == 2)
-        {
-            release_subexpr_memory(sel->child);
-            sel->name = NULL;
-            _gmx_selelem_free_chain(sel->child);
-            _gmx_selelem_free_values(sel);
-            _gmx_selelem_free_exprdata(sel);
-            _gmx_selelem_free_compiler_data(sel);
-            sel->child = NULL;
-        }
-    }
-    else
-    {
-        t_selelem *child;
-
-        child = sel->child;
-        while (child)
-        {
-            release_subexpr_memory(child);
-            child = child->next;
-        }
-    }
-}
-
-/*! \brief
- * Makes an evaluated selection element static.
- *
- * \param     sel   Selection element to make static.
- *
- * The evaluated value becomes the value of the static element.
- * The element type is changed to SEL_CONST and the children are
- * deleted.
- */
-static void
-make_static(t_selelem *sel)
-{
-    /* If this is a subexpression reference and the data is stored in the
-     * child, we transfer data ownership before doing anything else. */
-    if (sel->type == SEL_SUBEXPRREF
-        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
-    {
-        if (sel->child->child->flags & SEL_ALLOCDATA)
-        {
-            sel->flags |= SEL_ALLOCDATA;
-            sel->child->child->flags &= ~SEL_ALLOCDATA;
-        }
-        if (sel->child->child->flags & SEL_ALLOCVAL)
-        {
-            sel->flags |= SEL_ALLOCVAL;
-            sel->v.nalloc = sel->child->child->v.nalloc;
-            sel->child->child->flags &= ~SEL_ALLOCVAL;
-            sel->child->child->v.nalloc = -1;
-        }
-    }
-    /* When we reach here for parameter elements, the value is already
-     * stored in the parent element, so make sure that it is not freed
-     * through this element. */
-    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
-    {
-        sel->u.param->val.nalloc = sel->v.nalloc;
-        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-        sel->v.nalloc = -1;
-    }
-    /* Free the children. */
-    release_subexpr_memory(sel);
-    _gmx_selelem_free_chain(sel->child);
-    sel->child           = NULL;
-    /* Free the expression data as it is no longer needed */
-    _gmx_selelem_free_exprdata(sel);
-    /* Make the item static */
-    sel->name            = NULL;
-    sel->type            = SEL_CONST;
-    sel->evaluate        = NULL;
-    sel->cdata->evaluate = NULL;
-    /* Set the group value.
-     * free_exprdata above frees the cgrp group, so we can just override it. */
-    if (sel->v.type == GROUP_VALUE)
-    {
-        gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
-    }
-}
-
-/*! \brief
- * Evaluates a constant expression during analyze_static().
- *
- * \param[in]     data Evaluation data.
- * \param[in,out] sel Selection to process.
- * \param[in]     g   The evaluation group.
- * \returns       0 on success, a non-zero error code on error.
- */
-static int
-process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int  rc;
-
-    rc = 0;
-    if (sel->v.type == GROUP_VALUE)
-    {
-        if (sel->cdata->evaluate)
-        {
-            rc = sel->cdata->evaluate(data, sel, g);
-        }
-    }
-    /* Other constant expressions do not need evaluation */
-    return rc;
-}
-
-/*! \brief
- * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
- *
- * \param[in,out] sel Selection to process.
- *
- * Copies the value pointer of \p sel to \c sel->u.param if one is present
- * and should receive the value from the compiler
- * (most parameter values are handled during parsing).
- * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
- * the function does nothing.
- * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
- * \ref SPAR_ATOMVAL, the function returns immediately.
- */
-static void
-store_param_val(t_selelem *sel)
-{
-    /* Return immediately if there is no parameter. */
-    if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
-    {
-        return;
-    }
-
-    /* Or if the value does not need storing. */
-    if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
-    {
-        return;
-    }
-
-    if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
-        || sel->v.type == STR_VALUE)
-    {
-        _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
-    }
-}
-
-/*! \brief
- * Handles the initialization of a selection method during analyze_static() pass.
- *
- * \param[in,out] sel Selection element to process.
- * \param[in]     top Topology structure.
- * \param[in]     isize Size of the evaluation group for the element.
- * \returns       0 on success, a non-zero error code on return.
- *
- * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
- * method.
- * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
- * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
- */
-static int
-init_method(t_selelem *sel, t_topology *top, int isize)
-{
-    t_selelem *child;
-    gmx_bool       bAtomVal;
-    int        rc;
-
-    /* Find out whether there are any atom-valued parameters */
-    bAtomVal = FALSE;
-    child = sel->child;
-    while (child)
-    {
-        if (child->flags & SEL_ATOMVAL)
-        {
-            bAtomVal = TRUE;
-        }
-        child = child->next;
-    }
-
-    /* Initialize the method */
-    if (sel->u.expr.method->init
-        && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
-    {
-        sel->flags |= SEL_METHODINIT;
-        rc = sel->u.expr.method->init(top, sel->u.expr.method->nparams,
-                sel->u.expr.method->param, sel->u.expr.mdata);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    if (bAtomVal || !(sel->flags & SEL_OUTINIT))
-    {
-        sel->flags |= SEL_OUTINIT;
-        if (sel->u.expr.method->outinit)
-        {
-            rc = sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
-            {
-                alloc_selection_data(sel, isize, TRUE);
-            }
-        }
-        else
-        {
-            alloc_selection_data(sel, isize, TRUE);
-            if ((sel->flags & SEL_DYNAMIC)
-                && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
-            {
-                sel->v.nr = isize;
-            }
-            /* If the method is char-valued, pre-allocate the strings. */
-            if (sel->u.expr.method->flags & SMETH_CHARVAL)
-            {
-                int  i;
-
-                /* A sanity check */
-                if (sel->v.type != STR_VALUE)
-                {
-                    gmx_bug("internal error");
-                    return -1;
-                }
-                sel->flags |= SEL_ALLOCDATA;
-                for (i = 0; i < isize; ++i)
-                {
-                    if (sel->v.u.s[i] == NULL)
-                    {
-                        snew(sel->v.u.s[i], 2);
-                    }
-                }
-            }
-        }
-        /* Clear the values for dynamic output to avoid valgrind warnings. */
-        if ((sel->flags & SEL_DYNAMIC) && sel->v.type == REAL_VALUE)
-        {
-            int i;
-
-            for (i = 0; i < sel->v.nr; ++i)
-            {
-                sel->v.u.r[i] = 0.0;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*! \brief
- * Evaluates the static part of a gmx_boolean expression.
- *
- * \param[in]     data Evaluation data.
- * \param[in,out] sel Boolean selection element whose children should be
- *   processed.
- * \param[in]     g   The evaluation group.
- * \returns       0 on success, a non-zero error code on error.
- *
- * reorder_item_static_children() should have been called.
- */
-static int
-evaluate_gmx_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
-                             gmx_ana_index_t *g)
-{
-    t_selelem *child, *next;
-    int        rc;
-
-    /* Find the last static subexpression */
-    child = sel->child;
-    while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
-    {
-        child = child->next;
-    }
-    if (!(child->cdata->flags & SEL_CDATA_STATIC))
-    {
-        return 0;
-    }
-
-    /* Evalute the static part if there is more than one expression */
-    if (child != sel->child)
-    {
-        next  = child->next;
-        child->next = NULL;
-        rc = sel->cdata->evaluate(data, sel, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        /* Replace the subexpressions with the result */
-        _gmx_selelem_free_chain(sel->child);
-        snew(child, 1);
-        child->type       = SEL_CONST;
-        child->flags      = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
-        _gmx_selelem_set_vtype(child, GROUP_VALUE);
-        child->evaluate   = NULL;
-        _gmx_selvalue_reserve(&child->v, 1);
-        gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
-        init_item_compilerdata(child);
-        init_item_minmax_groups(child);
-        child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
-        child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
-        child->next = next;
-        sel->child = child;
-    }
-    else if (child->evaluate)
-    {
-        rc = child->evaluate(data, child, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    /* Set the evaluation function for the constant element.
-     * We never need to evaluate the element again during compilation,
-     * but we may need to evaluate the static part again if the
-     * expression is not an OR with a static evaluation group.
-     * If we reach here with a NOT expression, the NOT expression
-     * is also static, and will be made a constant later, so don't waste
-     * time copying the group. */
-    child->evaluate = NULL;
-    if (sel->u.boolt == BOOL_NOT
-        || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
-            && sel->u.boolt == BOOL_OR))
-    {
-        child->cdata->evaluate = NULL;
-    }
-    else
-    {
-        child->cdata->evaluate = &_gmx_sel_evaluate_static;
-        /* The cgrp has only been allocated if it originated from an
-         * external index group. In that case, we need special handling
-         * to preserve the name of the group and to not leak memory.
-         * If cgrp has been set in make_static(), it is not allocated,
-         * and hence we can overwrite it safely. */
-        if (child->u.cgrp.nalloc_index > 0)
-        {
-            char *name = child->u.cgrp.name;
-            gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, FALSE);
-            gmx_ana_index_squeeze(&child->u.cgrp);
-            child->u.cgrp.name = name;
-        }
-        else
-        {
-            gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, TRUE);
-        }
-    }
-    return 0;
-}
-
-/*! \brief
- * Evaluates the minimum and maximum groups for a gmx_boolean expression.
- *
- * \param[in]  sel  \ref SEL_BOOLEAN element currently being evaluated.
- * \param[in]  g    Group for which \p sel has been evaluated.
- * \param[out] gmin Largest subset of the possible values of \p sel.
- * \param[out] gmax Smallest superset of the possible values of \p sel.
- *
- * This is a helper function for analyze_static() that is called for
- * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
- * It uses the minimum and maximum groups of the children to calculate
- * the minimum and maximum groups for \p sel, and also updates the static
- * part of \p sel (which is in the first child) if the children give
- * cause for this.
- *
- * This function may allocate some extra memory for \p gmin and \p gmax,
- * but as these groups are freed at the end of analyze_static() (which is
- * reached shortly after this function returns), this should not be a major
- * problem.
- */
-static void
-evaluate_gmx_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
-                             gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
-{
-    t_selelem *child;
-
-    switch (sel->u.boolt)
-    {
-        case BOOL_NOT:
-            gmx_ana_index_reserve(gmin, g->isize);
-            gmx_ana_index_reserve(gmax, g->isize);
-            gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
-            gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
-            break;
-
-        case BOOL_AND:
-            gmx_ana_index_copy(gmin, sel->child->cdata->gmin, TRUE);
-            gmx_ana_index_copy(gmax, sel->child->cdata->gmax, TRUE);
-            child = sel->child->next;
-            while (child && gmax->isize > 0)
-            {
-                gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
-                gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
-                child = child->next;
-            }
-            /* Update the static part if other expressions limit it */
-            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
-                && sel->child->v.u.g->isize > gmax->isize)
-            {
-                gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
-                gmx_ana_index_squeeze(sel->child->v.u.g);
-                if (sel->child->u.cgrp.isize > 0)
-                {
-                    gmx_ana_index_copy(&sel->child->u.cgrp, gmax, FALSE);
-                    gmx_ana_index_squeeze(&sel->child->u.cgrp);
-                }
-            }
-            break;
-
-        case BOOL_OR:
-            /* We can assume here that the gmin of children do not overlap
-             * because of the way _gmx_sel_evaluate_or() works. */
-            gmx_ana_index_reserve(gmin, g->isize);
-            gmx_ana_index_reserve(gmax, g->isize);
-            gmx_ana_index_copy(gmin, sel->child->cdata->gmin, FALSE);
-            gmx_ana_index_copy(gmax, sel->child->cdata->gmax, FALSE);
-            child = sel->child->next;
-            while (child && gmin->isize < g->isize)
-            {
-                gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
-                gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
-                child = child->next;
-            }
-            /* Update the static part if other expressions have static parts
-             * that are not included. */
-            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
-                && sel->child->v.u.g->isize < gmin->isize)
-            {
-                gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
-                gmx_ana_index_copy(sel->child->v.u.g, gmin, FALSE);
-                if (sel->child->u.cgrp.isize > 0)
-                {
-                    gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
-                    gmx_ana_index_copy(&sel->child->u.cgrp, gmin, FALSE);
-                }
-            }
-            break;
-
-        case BOOL_XOR: /* Should not be reached */
-            gmx_impl("xor expressions not implemented");
-            break;
-    }
-}
-
-/*! \brief
- * Evaluates the static parts of \p sel and analyzes the structure.
- * 
- * \param[in]     data Evaluation data.
- * \param[in,out] sel  Selection currently being evaluated.
- * \param[in]     g    Group for which \p sel should be evaluated.
- * \returns       0 on success, a non-zero error code on error.
- *
- * This function is used as the replacement for the \c t_selelem::evaluate
- * function pointer.
- * It does the single most complex task in the compiler: after all elements
- * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
- * have been properly initialized, enough memory has been allocated for
- * storing the value of each expression, and the static parts of the 
- * expressions have been evaluated.
- * The above is exactly true only for elements other than subexpressions:
- * another pass is required for subexpressions that are referred to more than
- * once and whose evaluation group is not known in advance.
- */
-static int
-analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    t_selelem       *child, *next;
-    gmx_bool             bDoMinMax;
-    int              rc;
-
-    if (sel->type != SEL_ROOT && g)
-    {
-        alloc_selection_data(sel, g->isize, FALSE);
-    }
-
-    bDoMinMax = (sel->cdata->flags & SEL_CDATA_MINMAXALLOC);
-    if (sel->type != SEL_SUBEXPR && bDoMinMax)
-    {
-        gmx_ana_index_deinit(sel->cdata->gmin);
-        gmx_ana_index_deinit(sel->cdata->gmax);
-    }
-
-    /* TODO: This switch is awfully long... */
-    rc = 0;
-    switch (sel->type)
-    {
-        case SEL_CONST:
-            rc = process_const(data, sel, g);
-            break;
-
-        case SEL_EXPRESSION:
-        case SEL_MODIFIER:
-            rc = _gmx_sel_evaluate_method_params(data, sel, g);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            rc = init_method(sel, data->top, g->isize);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            if (!(sel->flags & SEL_DYNAMIC))
-            {
-                rc = sel->cdata->evaluate(data, sel, g);
-                if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
-                {
-                    make_static(sel);
-                }
-            }
-            else
-            {
-                /* Modifiers need to be evaluated even though they process
-                 * positions to get the modified output groups from the
-                 * maximum possible selections. */
-                if (sel->type == SEL_MODIFIER)
-                {
-                    rc = sel->cdata->evaluate(data, sel, g);
-                }
-                if (bDoMinMax)
-                {
-                    gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
-                }
-            }
-            break;
-
-        case SEL_BOOLEAN:
-            if (!(sel->flags & SEL_DYNAMIC))
-            {
-                rc = sel->cdata->evaluate(data, sel, g);
-                if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
-                {
-                    make_static(sel);
-                }
-            }
-            else
-            {
-                /* Evalute the static part if there is more than one expression */
-                rc = evaluate_gmx_boolean_static_part(data, sel, g);
-                if (rc != 0)
-                {
-                    return rc;
-                }
-
-                /* Evaluate the selection.
-                 * If the type is gmx_boolean, we must explicitly handle the
-                 * static part evaluated in evaluate_gmx_boolean_static_part()
-                 * here because g may be larger. */
-                if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
-                {
-                    rc = sel->cdata->evaluate(data, sel, sel->child->v.u.g);
-                }
-                else
-                {
-                    rc = sel->cdata->evaluate(data, sel, g);
-                }
-                if (rc != 0)
-                {
-                    return rc;
-                }
-
-                /* Evaluate minimal and maximal selections */
-                evaluate_gmx_boolean_minmax_grps(sel, g, sel->cdata->gmin,
-                                             sel->cdata->gmax);
-            }
-            break;
-
-        case SEL_ARITHMETIC:
-            rc = sel->cdata->evaluate(data, sel, g);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            if (!(sel->flags & SEL_DYNAMIC))
-            {
-                if (sel->cdata->flags & SEL_CDATA_STATIC)
-                {
-                    make_static(sel);
-                }
-            }
-            else if (bDoMinMax)
-            {
-                gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
-            }
-            break;
-
-        case SEL_ROOT:
-            rc = sel->cdata->evaluate(data, sel, g);
-            break;
-
-        case SEL_SUBEXPR:
-            if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
-            {
-                rc = sel->cdata->evaluate(data, sel, g);
-                _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
-            }
-            else if (sel->u.cgrp.isize == 0)
-            {
-                gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
-                rc = sel->cdata->evaluate(data, sel, g);
-                if (bDoMinMax)
-                {
-                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
-                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
-                }
-            }
-            else
-            {
-                int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
-                if (isize > 0)
-                {
-                    isize += sel->u.cgrp.isize;
-                    gmx_ana_index_reserve(&sel->u.cgrp, isize);
-                    alloc_selection_data(sel, isize, FALSE);
-                }
-                rc = sel->cdata->evaluate(data, sel, g);
-                if (isize > 0 && bDoMinMax)
-                {
-                    gmx_ana_index_reserve(sel->cdata->gmin,
-                                          sel->cdata->gmin->isize
-                                          + sel->child->cdata->gmin->isize);
-                    gmx_ana_index_reserve(sel->cdata->gmax,
-                                          sel->cdata->gmax->isize
-                                          + sel->child->cdata->gmax->isize);
-                    gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
-                                        sel->child->cdata->gmin);
-                    gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
-                                        sel->child->cdata->gmax);
-                }
-            }
-            break;
-
-        case SEL_SUBEXPRREF:
-            if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
-            {
-                /* The subexpression should have been evaluated if g is NULL
-                 * (i.e., this is a method parameter or a direct value of a
-                 * selection). */
-                alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
-            }
-            rc = sel->cdata->evaluate(data, sel, g);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
-                && (sel->child->child->flags & SEL_ALLOCVAL))
-            {
-                _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
-            }
-            /* Store the parameter value if required */
-            store_param_val(sel);
-            if (!(sel->flags & SEL_DYNAMIC))
-            {
-                if (sel->cdata->flags & SEL_CDATA_STATIC)
-                {
-                    make_static(sel);
-                }
-            }
-            else if (bDoMinMax)
-            {
-                if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
-                {
-                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
-                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
-                }
-                else
-                {
-                    gmx_ana_index_reserve(sel->cdata->gmin,
-                                          min(g->isize, sel->child->cdata->gmin->isize));
-                    gmx_ana_index_reserve(sel->cdata->gmax,
-                                          min(g->isize, sel->child->cdata->gmax->isize));
-                    gmx_ana_index_intersection(sel->cdata->gmin,
-                                               sel->child->cdata->gmin, g);
-                    gmx_ana_index_intersection(sel->cdata->gmax,
-                                               sel->child->cdata->gmax, g);
-                }
-            }
-            break;
-    }
-    /* Exit if there was some problem */
-    if (rc != 0)
-    {
-        return rc;
-    }
-
-    /* Update the minimal and maximal evaluation groups */
-    if (bDoMinMax)
-    {
-        gmx_ana_index_squeeze(sel->cdata->gmin);
-        gmx_ana_index_squeeze(sel->cdata->gmax);
-        sfree(sel->cdata->gmin->name);
-        sfree(sel->cdata->gmax->name);
-        sel->cdata->gmin->name = NULL;
-        sel->cdata->gmax->name = NULL;
-    }
-
-    /* Replace the result of the evaluation */
-    /* This is not necessary for subexpressions or for gmx_boolean negations
-     * because the evaluation function already has done it properly. */
-    if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
-        && sel->type != SEL_SUBEXPR
-        && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
-    {
-        if (sel->cdata->flags & SEL_CDATA_EVALMAX)
-        {
-            gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
-        }
-        else
-        {
-            gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, FALSE);
-        }
-    }
-
-    return 0;
-}
-
-
-/********************************************************************
- * EVALUATION GROUP INITIALIZATION
- ********************************************************************/
-
-/*! \brief
- * Initializes the evaluation group for a \ref SEL_ROOT element.
- *
- * \param     root Root element to initialize.
- * \param[in] gall Group of all atoms.
- *
- * Checks whether it is necessary to evaluate anything through the root
- * element, and either clears the evaluation function or initializes the
- * evaluation group.
- */
-static void
-init_root_item(t_selelem *root, gmx_ana_index_t *gall)
-{
-    t_selelem   *expr;
-    char        *name;
-
-    expr = root->child;
-    /* Subexpressions with non-static evaluation group should not be
-     * evaluated by the root, and neither should be single-reference
-     * subexpressions that don't evaluate for all atoms. */
-    if (expr->type == SEL_SUBEXPR
-        && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
-            || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
-                && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
-    {
-        root->evaluate = NULL;
-        if (root->cdata)
-        {
-            root->cdata->evaluate = NULL;
-        }
-    }
-
-    /* Set the evaluation group */
-    name = root->u.cgrp.name;
-    if (root->evaluate)
-    {
-        /* Non-atom-valued non-group expressions don't care about the group, so
-         * don't allocate any memory for it. */
-        if ((expr->flags & SEL_VARNUMVAL)
-            || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
-        {
-            gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
-        }
-        else if (expr->cdata->gmax->isize == gall->isize)
-        {
-            /* Save some memory by only referring to the global group. */
-            gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
-        }
-        else
-        {
-            gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
-        }
-        /* For selections, store the maximum group for
-         * gmx_ana_selcollection_evaluate_fin() as the value of the root
-         * element (unused otherwise). */
-        if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
-        {
-            t_selelem *child = expr;
-
-            /* TODO: This code is copied from parsetree.c; it would be better
-             * to have this hardcoded only in one place. */
-            while (child->type == SEL_MODIFIER)
-            {
-                child = child->child;
-                if (child->type == SEL_SUBEXPRREF)
-                {
-                    child = child->child->child;
-                }
-            }
-            if (child->type == SEL_SUBEXPRREF)
-            {
-                child = child->child->child;
-            }
-            if (child->child->flags & SEL_DYNAMIC)
-            {
-                _gmx_selelem_set_vtype(root, GROUP_VALUE);
-                root->flags  |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
-                _gmx_selvalue_reserve(&root->v, 1);
-                gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
-            }
-        }
-    }
-    else
-    {
-        gmx_ana_index_clear(&root->u.cgrp);
-    }
-    root->u.cgrp.name = name;
-}
-
-
-/********************************************************************
- * FINAL SUBEXPRESSION OPTIMIZATION
- ********************************************************************/
-
-/*! \brief
- * Optimizes subexpression evaluation.
- *
- * \param     sel Root of the selection subtree to process.
- *
- * Optimizes away some unnecessary evaluation of subexpressions that are only
- * referenced once.
- */
-static void
-postprocess_item_subexpressions(t_selelem *sel)
-{
-    /* Process children. */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        t_selelem *child;
-
-        child = sel->child;
-        while (child)
-        {
-            postprocess_item_subexpressions(child);
-            child = child->next;
-        }
-    }
-
-    /* Replace the evaluation function of statically evaluated subexpressions
-     * for which the static group was not known in advance. */
-    if (sel->type == SEL_SUBEXPR && sel->refcount > 2
-        && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
-        && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
-    {
-        char *name;
-
-        /* We need to free memory allocated for the group, because it is no
-         * longer needed (and would be lost on next call to the evaluation
-         * function). But we need to preserve the name. */
-        name = sel->u.cgrp.name;
-        gmx_ana_index_deinit(&sel->u.cgrp);
-        sel->u.cgrp.name = name;
-
-        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
-        if (sel->cdata)
-        {
-            sel->cdata->evaluate = sel->evaluate;
-        }
-        _gmx_selelem_free_values(sel->child);
-        sel->child->mempool = NULL;
-        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
-        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-    }
-
-    /* Adjust memory allocation flags for subexpressions that are used only
-     * once.  This is not strictly necessary, but we do it to have the memory
-     * managed consistently for all types of subexpressions. */
-    if (sel->type == SEL_SUBEXPRREF
-        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
-    {
-        if (sel->child->child->flags & SEL_ALLOCVAL)
-        {
-            sel->flags |= SEL_ALLOCVAL;
-            sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
-            sel->v.nalloc = sel->child->child->v.nalloc;
-            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-            sel->child->child->v.nalloc = -1;
-        }
-    }
-
-    /* Do the same for subexpressions that are evaluated at once for all atoms. */
-    if (sel->type == SEL_SUBEXPR
-        && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
-        && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
-    {
-        sel->flags |= SEL_ALLOCVAL;
-        sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
-        sel->v.nalloc = sel->child->v.nalloc;
-        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-        sel->child->v.nalloc = -1;
-    }
-}
-
-
-/********************************************************************
- * COM CALCULATION INITIALIZATION
- ********************************************************************/
-
-/*! \brief
- * Initializes COM/COG calculation for method expressions that require it.
- *
- * \param     sel    Selection subtree to process.
- * \param[in,out] pcc   Position calculation collection to use.
- * \param[in] type   Default position calculation type.
- * \param[in] flags  Flags for default position calculation.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Searches recursively through the selection tree for dynamic
- * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
- * function.
- * For each such element found, position calculation is initialized
- * for the maximal evaluation group.
- * The type of the calculation is determined by \p type and \p flags.
- * No calculation is initialized if \p type equals \ref POS_ATOM and
- * the method also defines the \c gmx_ana_selmethod_t::update method.
- */
-static int
-init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
-               e_poscalc_t type, int flags)
-{
-    t_selelem *child;
-    int        rc;
-
-    /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
-    if (sel->type == SEL_EXPRESSION && sel->u.expr.method
-        && sel->u.expr.method->pupdate)
-    {
-        if (!sel->u.expr.method->update || type != POS_ATOM)
-        {
-            /* Create a default calculation if one does not yet exist */
-            int cflags;
-            cflags = 0;
-            if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
-            {
-                cflags |= POS_DYNAMIC;
-            }
-            if (!sel->u.expr.pc)
-            {
-                cflags |= flags;
-                rc = gmx_ana_poscalc_create(&sel->u.expr.pc, pcc, type, cflags);
-                if (rc != 0)
-                {
-                    return rc;
-                }
-            }
-            else
-            {
-                gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
-            }
-            gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
-            snew(sel->u.expr.pos, 1);
-            gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
-        }
-    }
-
-    /* Call recursively for all children unless the children have already been processed */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        child = sel->child;
-        while (child)
-        {
-            rc = init_item_comg(child, pcc, type, flags);
-            if (rc != 0)
-            {
-                return rc;
-            }
-            child = child->next;
-        }
-    }
-    return 0;
-}
-
-
-/********************************************************************
- * COMPILER DATA FREEING
- ********************************************************************/
-
-/*! \brief
- * Frees the allocated compiler data recursively.
- *
- * \param     sel Root of the selection subtree to process.
- *
- * Frees the data allocated for the compilation process.
- */
-static void
-free_item_compilerdata(t_selelem *sel)
-{
-    t_selelem *child;
-
-    /* Free compilation data */
-    _gmx_selelem_free_compiler_data(sel);
-
-    /* Call recursively for all children unless the children have already been processed */
-    if (sel->type != SEL_SUBEXPRREF)
-    {
-        child = sel->child;
-        while (child)
-        {
-            free_item_compilerdata(child);
-            child = child->next;
-        }
-    }
-}
-
-
-/********************************************************************
- * MASS AND CHARGE CALCULATION
- ********************************************************************/
-
-/*! \brief
- * Initializes total masses and charges for selections.
- *
- * \param[in]     top   Topology information.
- * \param[in]     ngrps Number of elements in the \p sel array.
- * \param[in,out] sel   Array of selections to update.
- * \param[in]     bMaskOnly TRUE if the positions will always be calculated
- *   for all atoms, i.e., the masses/charges do not change.
- */
-static void
-calculate_mass_charge(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
-                      gmx_bool bMaskOnly)
-{
-    int   g, b, i;
-
-    for (g = 0; g < ngrps; ++g)
-    {
-        sel[g]->g = sel[g]->p.g;
-        snew(sel[g]->orgm, sel[g]->p.nr);
-        snew(sel[g]->orgq, sel[g]->p.nr);
-        for (b = 0; b < sel[g]->p.nr; ++b)
-        {
-            sel[g]->orgq[b] = 0;
-            if (top)
-            {
-                sel[g]->orgm[b] = 0;
-                for (i = sel[g]->p.m.mapb.index[b]; i < sel[g]->p.m.mapb.index[b+1]; ++i)
-                {
-                    sel[g]->orgm[b] += top->atoms.atom[sel[g]->g->index[i]].m;
-                    sel[g]->orgq[b] += top->atoms.atom[sel[g]->g->index[i]].q;
-                }
-            }
-            else
-            {
-                sel[g]->orgm[b] = 1;
-            }
-        }
-        if (sel[g]->bDynamic && !bMaskOnly)
-        {
-            snew(sel[g]->m, sel[g]->p.nr);
-            snew(sel[g]->q, sel[g]->p.nr);
-            for (b = 0; b < sel[g]->p.nr; ++b)
-            {
-                sel[g]->m[b] = sel[g]->orgm[b];
-                sel[g]->q[b] = sel[g]->orgq[b];
-            }
-        }
-        else
-        {
-            sel[g]->m = sel[g]->orgm;
-            sel[g]->q = sel[g]->orgq;
-        }
-    }
-}
-
-
-/********************************************************************
- * MAIN COMPILATION FUNCTION
- ********************************************************************/
-
-/*!
- * \param[in,out] sc     Selection collection to debug.
- * \param[in]     bDebug If TRUE, later call to gmx_ana_selcollection_compile()
- *     will print out intermediate selection trees.
- */
-void
-gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, gmx_bool bDebug)
-{
-    sc->bDebugCompile = bDebug;
-}
-
-/*!
- * \param[in,out] sc Selection collection to be compiled.
- * \returns       0 on successful compilation, a non-zero error code on error.
- *
- * Before compilation, the selection collection should have been initialized
- * with gmx_ana_selcollection_parse_*().
- * The compiled selection collection can be passed to
- * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
- * If an error occurs, \p sc is cleared.
- *
- * The covered fraction information in \p sc is initialized to
- * \ref CFRAC_NONE.
- */
-int
-gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
-{
-    gmx_sel_evaluate_t  evaldata;
-    t_selelem   *item;
-    e_poscalc_t  post;
-    int          flags;
-    int          rc;
-
-    rc = _gmx_sel_mempool_create(&sc->mempool);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
-                           sc->top, NULL, NULL);
-
-    /* Clear the symbol table because it is not possible to parse anything
-     * after compilation, and variable references in the symbol table can
-     * also mess up the compilation and/or become invalid.
-     */
-    _gmx_selcollection_clear_symtab(sc);
-
-    /* Remove any unused variables. */
-    sc->root = remove_unused_subexpressions(sc->root);
-    /* Extract subexpressions into separate roots */
-    sc->root = extract_subexpressions(sc->root);
-
-    /* Initialize the evaluation callbacks and process the tree structure
-     * to conform to the expectations of the callback functions. */
-    /* Also, initialize and allocate the compiler data structure */
-    item = sc->root;
-    while (item)
-    {
-        /* Process gmx_boolean and arithmetic expressions. */
-        optimize_gmx_boolean_expressions(item);
-        reorder_gmx_boolean_static_children(item);
-        if (!optimize_arithmetic_expressions(item))
-        {
-            /* FIXME: Clean up the collection */
-            return -1;
-        }
-        /* Initialize evaluation function. */
-        if (!init_item_evalfunc(item))
-        {
-            /* FIXME: Clean up the collection */
-            return -1;
-        }
-        setup_memory_pooling(item, sc->mempool);
-        /* Initialize the compiler data */
-        init_item_compilerdata(item);
-        init_item_staticeval(item);
-        item = item->next;
-    }
-    /* Initialize subexpression flags and evaluation output.
-     * Requires compiler flags for the full tree. */
-    item = sc->root;
-    while (item)
-    {
-        init_item_subexpr_flags(item);
-        init_item_evaloutput(item);
-        item = item->next;
-    }
-    /* Initialize minimum/maximum index groups.
-     * Requires evaluation output for the full tree. */
-    item = sc->root;
-    while (item)
-    {
-        init_item_minmax_groups(item);
-        item = item->next;
-    }
-    /* Initialize the evaluation index groups */
-    initialize_evalgrps(sc);
-
-    if (sc->bDebugCompile)
-    {
-        fprintf(stderr, "\nTree after initial compiler processing:\n");
-        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
-    }
-
-    /* Evaluate all static parts of the selection and analyze the tree
-     * to allocate enough memory to store the value of each dynamic subtree. */
-    item = sc->root;
-    while (item)
-    {
-        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
-        {
-            mark_subexpr_dynamic(item->child, TRUE);
-        }
-        set_evaluation_function(item, &analyze_static);
-        rc = item->evaluate(&evaldata, item, NULL);
-        if (rc != 0)
-        {
-            /* FIXME: Clean up the collection */
-            return rc;
-        }
-        item = item->next;
-    }
-
-    /* At this point, static subexpressions no longer have references to them,
-     * so they can be removed. */
-    sc->root = remove_unused_subexpressions(sc->root);
-
-    if (sc->bDebugCompile)
-    {
-        fprintf(stderr, "\nTree after first analysis pass:\n");
-        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
-    }
-
-    /* Do a second pass to evaluate static parts of common subexpressions */
-    item = sc->root;
-    while (item)
-    {
-        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
-        {
-            gmx_bool bMinMax = item->child->cdata->flags & SEL_CDATA_MINMAXALLOC;
-
-            mark_subexpr_dynamic(item->child, FALSE);
-            item->child->u.cgrp.isize = 0;
-            /* We won't clear item->child->v.u.g here, because it may
-             * be static, and hence actually point to item->child->cdata->gmax,
-             * which is used below. We could also check whether this is the
-             * case and only clear the group otherwise, but because the value
-             * is actually overwritten immediately in the evaluate call, we
-             * won't, because similar problems may arise if gmax handling ever
-             * changes and the check were not updated.
-             * For the same reason, we clear the min/max flag so that the
-             * evaluation group doesn't get messed up. */
-            set_evaluation_function(item, &analyze_static);
-            item->child->cdata->flags &= ~SEL_CDATA_MINMAXALLOC;
-            rc = item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
-            if (bMinMax)
-            {
-                item->child->cdata->flags |= SEL_CDATA_MINMAXALLOC;
-            }
-            if (rc != 0)
-            {
-                /* FIXME: Clean up the collection */
-                return rc;
-            }
-        }
-        item = item->next;
-    }
-
-    /* We need a yet another pass of subexpression removal to remove static
-     * subexpressions referred to by common dynamic subexpressions. */
-    sc->root = remove_unused_subexpressions(sc->root);
-
-    if (sc->bDebugCompile)
-    {
-        fprintf(stderr, "\nTree after second analysis pass:\n");
-        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
-    }
-
-    /* Initialize evaluation groups, position calculations for methods, perform
-     * some final optimization, and free the memory allocated for the
-     * compilation. */
-    /* By default, use whole residues/molecules. */
-    flags = POS_COMPLWHOLE;
-    rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &post, &flags);
-    if (rc != 0)
-    {
-        gmx_bug("invalid default reference position type");
-        /* FIXME: Clean up the collection */
-        return rc;
-    }
-    item = sc->root;
-    while (item)
-    {
-        init_root_item(item, &sc->gall);
-        postprocess_item_subexpressions(item);
-        rc = init_item_comg(item, sc->pcc, post, flags);
-        if (rc != 0)
-        {
-            /* FIXME: Clean up the collection */
-            return rc;
-        }
-        free_item_compilerdata(item);
-        item = item->next;
-    }
-
-    /* Allocate memory for the evaluation memory pool. */
-    rc = _gmx_sel_mempool_reserve(sc->mempool, 0);
-    if (rc != 0)
-    {
-        return rc;
-    }
-
-    /* Finish up by calculating total masses and charges. */
-    calculate_mass_charge(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
-
-    return 0;
-}
diff --git a/src/gmxlib/selection/evaluate.c b/src/gmxlib/selection/evaluate.c
deleted file mode 100644 (file)
index 9fbe3c0..0000000
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in evaluate.h.
- *
- * \todo
- * One of the major bottlenecks for selection performance is that all the
- * evaluation is carried out for atoms.
- * There are several cases when the evaluation could be done for residues
- * or molecules instead, including keywords that select by residue and
- * cases where residue centers are used as reference positions.
- * Implementing this would require a mechanism for recognizing whether
- * something can be evaluated by residue/molecule instead by atom, and
- * converting selections by residue/molecule into selections by atom
- * when necessary.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <maths.h>
-#include <smalloc.h>
-#include <vec.h>
-
-#include <indexutil.h>
-#include <poscalc.h>
-#include <selection.h>
-#include <selmethod.h>
-
-#include "evaluate.h"
-#include "mempool.h"
-#include "selcollection.h"
-#include "selelem.h"
-
-/*!
- * \param[in] fp       File handle to receive the output.
- * \param[in] evalfunc Function pointer to print.
- */
-void
-_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc)
-{
-    if (!evalfunc)
-        fprintf(fp, "none");
-    else if (evalfunc == &_gmx_sel_evaluate_root)
-        fprintf(fp, "root");
-    else if (evalfunc == &_gmx_sel_evaluate_static)
-        fprintf(fp, "static");
-    else if (evalfunc == &_gmx_sel_evaluate_subexpr_simple)
-        fprintf(fp, "subexpr_simple");
-    else if (evalfunc == &_gmx_sel_evaluate_subexpr_staticeval)
-        fprintf(fp, "subexpr_staticeval");
-    else if (evalfunc == &_gmx_sel_evaluate_subexpr)
-        fprintf(fp, "subexpr");
-    else if (evalfunc == &_gmx_sel_evaluate_subexprref_simple)
-        fprintf(fp, "ref_simple");
-    else if (evalfunc == &_gmx_sel_evaluate_subexprref)
-        fprintf(fp, "ref");
-    else if (evalfunc == &_gmx_sel_evaluate_method)
-        fprintf(fp, "method");
-    else if (evalfunc == &_gmx_sel_evaluate_modifier)
-        fprintf(fp, "mod");
-    else if (evalfunc == &_gmx_sel_evaluate_not)
-        fprintf(fp, "not");
-    else if (evalfunc == &_gmx_sel_evaluate_and)
-        fprintf(fp, "and");
-    else if (evalfunc == &_gmx_sel_evaluate_or)
-        fprintf(fp, "or");
-    else if (evalfunc == &_gmx_sel_evaluate_arithmetic)
-        fprintf(fp, "arithmetic");
-    else
-        fprintf(fp, "%p", (void*)(evalfunc));
-}
-
-/*!
- * \param[out] data Evaluation data structure to initialize.
- * \param[in]  mp   Memory pool for intermediate evaluation values.
- * \param[in]  gall Index group with all the atoms.
- * \param[in]  top  Topology structure for evaluation.
- * \param[in]  fr   New frame for evaluation.
- * \param[in]  pbc  New PBC information for evaluation.
- */
-void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
-                       gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
-                       t_topology *top, t_trxframe *fr, t_pbc *pbc)
-{
-    data->mp   = mp;
-    data->gall = gall;
-    data->top  = top;
-    data->fr   = fr;
-    data->pbc  = pbc;
-}
-
-/*! \brief
- * Recursively initializes the flags for evaluation.
- *
- * \param[in,out] sel Selection element to clear.
- *
- * The \ref SEL_INITFRAME flag is set for \ref SEL_EXPRESSION elements whose
- * method defines the \p init_frame callback (see sel_framefunc()), and
- * cleared for other elements.
- *
- * The \ref SEL_EVALFRAME flag is cleared for all elements.
- */
-static void
-init_frame_eval(t_selelem *sel)
-{
-    while (sel)
-    {
-        sel->flags &= ~(SEL_INITFRAME | SEL_EVALFRAME);
-        if (sel->type == SEL_EXPRESSION)
-        {
-            if (sel->u.expr.method && sel->u.expr.method->init_frame)
-            {
-                sel->flags |= SEL_INITFRAME;
-            }
-        }
-        if (sel->child && sel->type != SEL_SUBEXPRREF)
-        {
-            init_frame_eval(sel->child);
-        }
-        sel = sel->next;
-    }
-}
-
-/*!
- * \param[in,out] sc  The selection collection to evaluate.
- * \param[in] fr  Frame for which the evaluation should be carried out.
- * \param[in] pbc PBC data, or NULL if no PBC should be used.
- * \returns   0 on successful evaluation, a non-zero error code on error.
- *
- * This functions sets the global variables for topology, frame and PBC,
- * clears some information in the selection to initialize the evaluation
- * for a new frame, and evaluates \p sel and all the selections pointed by
- * the \p next pointers of \p sel.
- *
- * This is the only function that user code should call if they want to
- * evaluate a selection for a new frame.
- */
-int
-gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
-                               t_trxframe *fr, t_pbc *pbc)
-{
-    gmx_sel_evaluate_t  data;
-    t_selelem          *sel;
-    int                 g, i;
-    int                 rc;
-
-    _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
-    init_frame_eval(sc->root);
-    sel = sc->root;
-    while (sel)
-    {
-        /* Clear the evaluation group of subexpressions */
-        if (sel->child && sel->child->type == SEL_SUBEXPR)
-        {
-            sel->child->u.cgrp.isize = 0;
-            /* Not strictly necessary, because the value will be overwritten
-             * during first evaluation of the subexpression anyways, but we
-             * clear the group for clarity. Note that this is _not_ done during
-             * compilation because of some additional complexities involved
-             * (see compiler.c), so it should not be relied upon in
-             * _gmx_sel_evaluate_subexpr(). */
-            if (sel->child->v.type == GROUP_VALUE)
-            {
-                sel->child->v.u.g->isize = 0;
-            }
-        }
-        if (sel->evaluate)
-        {
-            rc = sel->evaluate(&data, sel, NULL);
-            if (rc != 0)
-            {
-                return rc;
-            }
-        }
-        sel = sel->next;
-    }
-    /* Update selection information */
-    for (g = 0; g < sc->nr; ++g)
-    {
-        gmx_ana_selection_t *sel = sc->sel[g];
-
-        if (sel->m != sel->orgm)
-        {
-            for (i = 0; i < sel->p.nr; ++i)
-            {
-                sel->m[i] = sel->orgm[sel->p.m.refid[i]];
-                sel->q[i] = sel->orgq[sel->p.m.refid[i]];
-            }
-        }
-        if (sel->bCFracDyn)
-        {
-            sel->cfrac = _gmx_selelem_estimate_coverfrac(sel->selelem);
-            sel->avecfrac += sel->cfrac;
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in,out] sc  The selection collection to evaluate.
- * \param[in]     nframes Total number of frames.
- * \returns       0 on successful evaluation, a non-zero error code on error.
- */
-int
-gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes)
-{
-    t_selelem          *sel;
-    int                 g;
-
-    for (g = 0; g < sc->nr; ++g)
-    {
-        sel = sc->sel[g]->selelem;
-        if (sc->sel[g]->bDynamic)
-        {
-            gmx_ana_index_copy(sc->sel[g]->g, sel->v.u.g, FALSE);
-            sc->sel[g]->g->name = NULL;
-            gmx_ana_indexmap_update(&sc->sel[g]->p.m, sc->sel[g]->g, sc->bMaskOnly);
-            sc->sel[g]->p.nr = sc->sel[g]->p.m.nr;
-        }
-
-        if (sc->sel[g]->bCFracDyn)
-        {
-            sc->sel[g]->avecfrac /= nframes;
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel  Selection element being evaluated.
- * \param[in] g    Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates each child of \p sel in \p g.
- */
-int
-_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel,
-                           gmx_ana_index_t *g)
-{
-    t_selelem  *child;
-    int         rc;
-
-    child = sel->child;
-    while (child)
-    {
-        if (child->evaluate)
-        {
-            rc = child->evaluate(data, child, g);
-            if (rc != 0)
-            {
-                return rc;
-            }
-        }
-        child = child->next;
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated
- *   (not used, can be NULL).
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates the first child element in the group defined by \p sel->u.cgrp.
- * If \p sel->u.cgrp is empty, nothing is done.
- * The value of \p sel is not touched (root elements do not evaluate to
- * values).
- *
- * This function can be used as \c t_selelem::evaluate for \ref SEL_ROOT
- * elements.
- */
-int
-_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int        rc;
-
-    if (sel->u.cgrp.isize == 0 || !sel->child->evaluate)
-    {
-        return 0;
-    }
-
-    rc = sel->child->evaluate(data, sel->child,
-                              sel->u.cgrp.isize < 0 ? NULL : &sel->u.cgrp);
-
-    return rc;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 for success.
- *
- * Sets the value of \p sel to the intersection of \p g and \p sel->u.cgrp.
- *
- * This function can be used as \c t_selelem::evaluate for \ref SEL_CONST
- * elements with value type \ref GROUP_VALUE.
- */
-int
-_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    gmx_ana_index_intersection(sel->v.u.g, &sel->u.cgrp, g);
-    return 0;
-}
-
-
-/*********************************************************************
- * SUBEXPRESSION EVALUATION
- *********************************************************************/
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel  Selection element being evaluated.
- * \param[in] g    Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates the child element (there should be exactly one) in \p g.
- * The compiler has taken care that the child actually stores the evaluated
- * value in the value pointer of this element.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
- * elements that are used only once, and hence do not need full subexpression
- * handling.
- */
-int
-_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int        rc;
-
-    if (sel->child->evaluate)
-    {
-        rc = sel->child->evaluate(data, sel->child, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    sel->v.nr = sel->child->v.nr;
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel  Selection element being evaluated.
- * \param[in] g    Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * If this is the first call for this frame, evaluates the child element
- * there should be exactly one in \p g.
- * The compiler has taken care that the child actually stores the evaluated
- * value in the value pointer of this element.
- * Assumes that \p g is persistent for the duration of the whole evaluation.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
- * elements that have a static evaluation group, and hence do not need full
- * subexpression handling.
- */
-int
-_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    if (sel->u.cgrp.isize == 0)
-    {
-        int  rc;
-
-        rc = sel->child->evaluate(data, sel->child, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        sel->v.nr = sel->child->v.nr;
-        gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, sel->u.cgrp.name, 0);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  data  Data for the current frame.
- * \param[in]  sel   Selection element being evaluated.
- * \param[in]  g     Group for which \p sel should be evaluated.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Finds the part of \p g for which the subexpression
- * has not yet been evaluated by comparing \p g to \p sel->u.cgrp.
- * If the part is not empty, the child expression is evaluated for this
- * part, and the results merged to the old values of the child.
- * The value of \p sel itself is undefined after the call.
- *
- * \todo
- * The call to gmx_ana_index_difference() can take quite a lot of unnecessary
- * time if the subexpression is evaluated either several times for the same
- * group or for completely distinct groups.
- * However, in the majority of cases, these situations occur when
- * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a
- * major problem.
- */
-int
-_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    gmx_ana_index_t  gmiss;
-    int              rc;
-
-    if (sel->u.cgrp.isize == 0)
-    {
-        char *name;
-        void *old_ptr    = sel->child->v.u.ptr;
-        int   old_nalloc = sel->child->v.nalloc;
-        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
-        rc = sel->child->evaluate(data, sel->child, g);
-        _gmx_selvalue_setstore_alloc(&sel->child->v, old_ptr, old_nalloc);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        /* We need to keep the name for the cgrp across the copy to avoid
-         * problems if g has a name set. */
-        name = sel->u.cgrp.name;
-        gmx_ana_index_copy(&sel->u.cgrp, g, FALSE);
-        sel->u.cgrp.name = name;
-        gmiss.isize = 0;
-    }
-    else
-    {
-        /* We allocate some extra memory here to avoid some computation. */
-        rc = _gmx_sel_mempool_alloc_group(data->mp, &gmiss, g->isize);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
-        if (gmiss.isize == 0)
-        {
-            _gmx_sel_mempool_free_group(data->mp, &gmiss);
-        }
-    }
-    if (gmiss.isize > 0)
-    {
-        rc = _gmx_selelem_mempool_reserve(sel->child, gmiss.isize);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        /* Evaluate the missing values for the child */
-        rc = sel->child->evaluate(data, sel->child, &gmiss);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        /* Merge the missing values to the existing ones. */
-        if (sel->v.type == GROUP_VALUE)
-        {
-            gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g);
-        }
-        else
-        {
-            int  i, j, k;
-
-            i = sel->u.cgrp.isize - 1;
-            j = gmiss.isize - 1;
-            /* TODO: This switch is kind of ugly, but it may be difficult to
-             * do this portably without C++ templates. */
-            switch (sel->v.type)
-            {
-                case INT_VALUE:
-                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
-                    {
-                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
-                        {
-                            sel->v.u.i[k] = sel->v.u.i[j--];
-                        }
-                        else
-                        {
-                            sel->v.u.i[k] = sel->child->v.u.i[i--];
-                        }
-                    }
-                    break;
-
-                case REAL_VALUE:
-                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
-                    {
-                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
-                        {
-                            sel->v.u.r[k] = sel->v.u.r[j--];
-                        }
-                        else
-                        {
-                            sel->v.u.r[k] = sel->child->v.u.r[i--];
-                        }
-                    }
-                    break;
-
-                case STR_VALUE:
-                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
-                    {
-                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
-                        {
-                            sel->v.u.s[k] = sel->v.u.s[j--];
-                        }
-                        else
-                        {
-                            sel->v.u.s[k] = sel->child->v.u.s[i--];
-                        }
-                    }
-                    break;
-
-                case POS_VALUE:
-                    /* TODO: Implement this */
-                    gmx_impl("position subexpressions not implemented properly");
-                    return -1;
-
-                case NO_VALUE:
-                case GROUP_VALUE:
-                    gmx_bug("internal error");
-                    return -1;
-            }
-        }
-        gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
-        _gmx_selelem_mempool_release(sel->child);
-        _gmx_sel_mempool_free_group(data->mp, &gmiss);
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 for success.
- *
- * Sets the value pointers of the child and its child to point to the same
- * memory as the value pointer of this element to avoid copying, and then
- * evaluates evaluates the child.
- *
- * This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
- * elements for which the \ref SEL_SUBEXPR does not have other references.
- */
-int
-_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    if (g)
-    {
-        int rc;
-
-        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
-        _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
-                                     sel->child->child->v.nalloc);
-        rc = sel->child->evaluate(data, sel->child, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    sel->v.nr = sel->child->v.nr;
-    if (sel->u.param)
-    {
-        sel->u.param->val.nr = sel->v.nr;
-        if (sel->u.param->nvalptr)
-        {
-            *sel->u.param->nvalptr = sel->u.param->val.nr;
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * If the value type is \ref POS_VALUE, the value of the child is simply
- * copied to set the value of \p sel (the child subexpression should
- * already have been evaluated by its root).
- * If the value type is something else, the child is evaluated for the
- * group \p g, and the value of the child is then copied.
- * There should be only one child element.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPRREF
- * elements.
- */
-int
-_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    t_selelem *expr;
-    int        i, j;
-
-    if (g)
-    {
-        int rc;
-
-        rc = sel->child->evaluate(data, sel->child, g);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    expr = sel->child;
-    switch (sel->v.type)
-    {
-        case INT_VALUE:
-            if (!g)
-            {
-                sel->v.nr = expr->v.nr;
-                memcpy(sel->v.u.i, expr->v.u.i, sel->v.nr*sizeof(*sel->v.u.i));
-            }
-            else
-            {
-                sel->v.nr = g->isize;
-                /* Extract the values corresponding to g */
-                for (i = j = 0; i < g->isize; ++i, ++j)
-                {
-                    while (sel->child->u.cgrp.index[j] < g->index[i])
-                    {
-                        ++j;
-                    }
-                    sel->v.u.i[i] = expr->v.u.i[j];
-                }
-            }
-            break;
-
-        case REAL_VALUE:
-            if (!g)
-            {
-                sel->v.nr = expr->v.nr;
-                memcpy(sel->v.u.r, expr->v.u.r, sel->v.nr*sizeof(*sel->v.u.r));
-            }
-            else
-            {
-                sel->v.nr = g->isize;
-                /* Extract the values corresponding to g */
-                for (i = j = 0; i < g->isize; ++i, ++j)
-                {
-                    while (sel->child->u.cgrp.index[j] < g->index[i])
-                    {
-                        ++j;
-                    }
-                    sel->v.u.r[i] = expr->v.u.r[j];
-                }
-            }
-            break;
-
-        case STR_VALUE:
-            if (!g)
-            {
-                sel->v.nr = expr->v.nr;
-                memcpy(sel->v.u.s, expr->v.u.s, sel->v.nr*sizeof(*sel->v.u.s));
-            }
-            else
-            {
-                sel->v.nr = g->isize;
-                /* Extract the values corresponding to g */
-                for (i = j = 0; i < g->isize; ++i, ++j)
-                {
-                    while (sel->child->u.cgrp.index[j] < g->index[i])
-                    {
-                        ++j;
-                    }
-                    sel->v.u.s[i] = expr->v.u.s[j];
-                }
-            }
-            break;
-
-        case POS_VALUE:
-            /* Currently, there is no need to do anything fancy here,
-             * but some future extensions may need a more flexible
-             * implementation. */
-            gmx_ana_pos_copy(sel->v.u.p, expr->v.u.p, FALSE);
-            break;
-
-        case GROUP_VALUE:
-            if (!g)
-            {
-                gmx_ana_index_copy(sel->v.u.g, expr->v.u.g, FALSE);
-            }
-            else
-            {
-                gmx_ana_index_intersection(sel->v.u.g, expr->v.u.g, g);
-            }
-            break;
-
-        default: /* should not be reached */
-            gmx_bug("invalid subexpression reference type");
-            return -1;
-    }
-    /* Store the number of values if needed */
-    if (sel->u.param)
-    {
-        sel->u.param->val.nr = sel->v.nr;
-        if (sel->u.param->nvalptr)
-        {
-            *sel->u.param->nvalptr = sel->u.param->val.nr;
-        }
-    }
-    return 0;
-}
-
-/********************************************************************
- * METHOD EXPRESSION EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates each child of a \ref SEL_EXPRESSION element.
- * The value of \p sel is not touched.
- *
- * This function is not used as \c t_selelem::evaluate,
- * but is used internally.
- */
-int
-_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    t_selelem *child;
-    int        rc;
-
-    child = sel->child;
-    while (child)
-    {
-        if (child->evaluate && !(child->flags & SEL_EVALFRAME))
-        {
-            if (child->flags & SEL_ATOMVAL)
-            {
-                rc = child->evaluate(data, child, g);
-            }
-            else
-            {
-                rc = child->evaluate(data, child, NULL);
-                child->flags |= SEL_EVALFRAME;
-            }
-            if (rc != 0)
-            {
-                return rc;
-            }
-        }
-        child = child->next;
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
- * to evaluate any parameter values.
- * If this is the first time this expression is evaluated for
- * the frame, sel_framefunc() callback is called if one is provided.
- * If a reference position calculation has been initialized for this element,
- * the positions are also updated, and sel_updatefunc_pos() is used to
- * evaluate the value. Otherwise, sel_updatefunc() is used.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_EXPRESSION
- * elements.
- */
-int
-_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int rc;
-
-    rc = _gmx_sel_evaluate_method_params(data, sel, g);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    if (sel->flags & SEL_INITFRAME)
-    {
-        rc = sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
-                                            sel->u.expr.mdata);
-        sel->flags &= ~SEL_INITFRAME;
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    if (sel->u.expr.pc)
-    {
-        gmx_ana_poscalc_update(sel->u.expr.pc, sel->u.expr.pos, g,
-                               data->fr, data->pbc);
-        rc = sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
-                                         sel->u.expr.pos, &sel->v,
-                                         sel->u.expr.mdata);
-    }
-    else
-    {
-        rc = sel->u.expr.method->update(data->top, data->fr, data->pbc, g,
-                                        &sel->v, sel->u.expr.mdata);
-    }
-    return rc;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
- * to evaluate any parameter values.
- * If this is the first time this expression is evaluated for
- * the frame, sel_framefunc() callback is called if one is provided.
- * The modifier is then evaluated using sel_updatefunc_pos().
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_MODIFIER
- * elements.
- */
-int
-_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int rc;
-
-    rc = _gmx_sel_evaluate_method_params(data, sel, g);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    if (sel->flags & SEL_INITFRAME)
-    {
-        rc = sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
-                                            sel->u.expr.mdata);
-        sel->flags &= ~SEL_INITFRAME;
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    if (sel->child->v.type != POS_VALUE)
-    {
-        gmx_bug("non-position valued modifiers not implemented");
-        return -1;
-    }
-    rc = sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
-                                    sel->child->v.u.p,
-                                    &sel->v, sel->u.expr.mdata);
-    return rc;
-}
-
-
-/********************************************************************
- * BOOLEAN EXPRESSION EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Evaluates the child element (there should be only one) in the group
- * \p g, and then sets the value of \p sel to the complement of the 
- * child value.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_NOT.
- */
-int
-_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int rc;
-
-    rc = _gmx_selelem_mempool_reserve(sel->child, g->isize);
-    if (rc == 0)
-    {
-        rc = sel->child->evaluate(data, sel->child, g);
-    }
-    if (rc != 0)
-    {
-        return rc;
-    }
-    gmx_ana_index_difference(sel->v.u.g, g, sel->child->v.u.g);
-    _gmx_selelem_mempool_release(sel->child);
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Short-circuiting evaluation of logical AND expressions.
- *
- * Starts by evaluating the first child element in the group \p g.
- * The each following child element is evaluated in the intersection
- * of all the previous values until all children have been evaluated
- * or the intersection becomes empty.
- * The value of \p sel is set to the intersection of all the (evaluated)
- * child values.
- *
- * If the first child does not have an evaluation function, it is skipped
- * and the evaluation is started at the second child.
- * This happens if the first child is a constant expression and during
- * compilation it was detected that the evaluation group is always a subset
- * of the constant group
- * (currently, the compiler never detects this).
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_AND.
- */
-int
-_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    t_selelem *child;
-    int        rc;
-
-    child = sel->child;
-    /* Skip the first child if it does not have an evaluation function. */
-    if (!child->evaluate)
-    {
-        child = child->next;
-    }
-    rc = _gmx_selelem_mempool_reserve(child, g->isize);
-    if (rc == 0)
-    {
-        rc = child->evaluate(data, child, g);
-    }
-    if (rc != 0)
-    {
-        return rc;
-    }
-    gmx_ana_index_copy(sel->v.u.g, child->v.u.g, FALSE);
-    _gmx_selelem_mempool_release(child);
-    child = child->next;
-    while (child && sel->v.u.g->isize > 0)
-    {
-        rc = _gmx_selelem_mempool_reserve(child, sel->v.u.g->isize);
-        if (rc == 0)
-        {
-            rc = child->evaluate(data, child, sel->v.u.g);
-        }
-        if (rc != 0)
-        {
-            return rc;
-        }
-        gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
-        _gmx_selelem_mempool_release(child);
-        child = child->next;
-    }
-    return 0;
-}
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel Selection element being evaluated.
- * \param[in] g   Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- *
- * Short-circuiting evaluation of logical OR expressions.
- *
- * Starts by evaluating the first child element in the group \p g.
- * For each subsequent child, finds the part of \p g that is not
- * included the value of any previous child, and evaluates the child
- * in that group until the last child is evaluated or all of \p g
- * is included in some child value.
- * The value of \p sel is set to the union of all the (evaluated)
- * child values.
- *
- * If the first child does not have an evaluation function, its value is
- * used without evaluation.
- * This happens if the first child is a constant expression, the selection
- * has been compiled, and the evaluation group is the same for each frame.
- * In this case, the compiler has taken care of that the child value is a
- * subset of \p g, making it unnecessary to evaluate it.
- *
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_OR.
- */
-int
-_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    t_selelem     *child;
-    gmx_ana_index_t  tmp, tmp2;
-    int              rc;
-
-    child = sel->child;
-    if (child->evaluate)
-    {
-        rc = _gmx_selelem_mempool_reserve(child, g->isize);
-        if (rc == 0)
-        {
-            rc = child->evaluate(data, child, g);
-        }
-        if (rc != 0)
-        {
-            return rc;
-        }
-        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
-        _gmx_selelem_mempool_release(child);
-    }
-    else
-    {
-        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
-    }
-    child = child->next;
-    while (child && tmp.isize > 0)
-    {
-        tmp.name = NULL;
-        rc = _gmx_selelem_mempool_reserve(child, tmp.isize);
-        if (rc == 0)
-        {
-            rc = child->evaluate(data, child, &tmp);
-        }
-        if (rc != 0)
-        {
-            return rc;
-        }
-        gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
-        _gmx_selelem_mempool_release(child);
-        sel->v.u.g->isize += tmp.isize;
-        tmp.isize = tmp2.isize;
-        tmp.index = tmp2.index;
-        child = child->next;
-    }
-    gmx_ana_index_sort(sel->v.u.g);
-    return 0;
-}
-
-
-/********************************************************************
- * ARITHMETIC EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] data Data for the current frame.
- * \param[in] sel  Selection element being evaluated.
- * \param[in] g    Group for which \p sel should be evaluated.
- * \returns   0 on success, a non-zero error code on error.
- */
-int
-_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel,
-                             gmx_ana_index_t *g)
-{
-    t_selelem  *left, *right;
-    int         n, i, i1, i2;
-    real        lval, rval=0., val=0.;
-    int         rc;
-
-    left  = sel->child;
-    right = left->next;
-
-    if (left->mempool)
-    {
-        _gmx_selvalue_setstore(&left->v, sel->v.u.ptr);
-        if (right)
-        {
-            rc = _gmx_selelem_mempool_reserve(right, g->isize);
-            if (rc != 0)
-            {
-                return rc;
-            }
-        }
-    }
-    else if (right && right->mempool)
-    {
-        _gmx_selvalue_setstore(&right->v, sel->v.u.ptr);
-    }
-    rc = _gmx_sel_evaluate_children(data, sel, g);
-
-    n = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
-    sel->v.nr = n;
-    for (i = i1 = i2 = 0; i < n; ++i)
-    {
-        lval = left->v.u.r[i1];
-        if (sel->u.arith.type != ARITH_NEG)
-        {
-            rval = right->v.u.r[i2];
-        }
-        switch (sel->u.arith.type)
-        {
-            case ARITH_PLUS:    val = lval + rval;     break;
-            case ARITH_MINUS:   val = lval - rval;     break;
-            case ARITH_NEG:     val = -lval;           break;
-            case ARITH_MULT:    val = lval * rval;     break;
-            case ARITH_DIV:     val = lval / rval;     break;
-            case ARITH_EXP:     val = pow(lval, rval); break;
-        }
-        sel->v.u.r[i] = val;
-        if (!(left->flags & SEL_SINGLEVAL))
-        {
-            ++i1;
-        }
-        if (sel->u.arith.type != ARITH_NEG && !(right->flags & SEL_SINGLEVAL))
-        {
-            ++i2;
-        }
-    }
-
-    if (left->mempool)
-    {
-        _gmx_selvalue_setstore(&left->v, NULL);
-        if (right)
-        {
-            _gmx_selelem_mempool_release(right);
-        }
-    }
-    else if (right && right->mempool)
-    {
-        _gmx_selvalue_setstore(&right->v, NULL);
-    }
-    return 0;
-}
diff --git a/src/gmxlib/selection/evaluate.h b/src/gmxlib/selection/evaluate.h
deleted file mode 100644 (file)
index 99c15c7..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Evaluation functions for sel_evalfunc().
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- * Users should only use gmx_ana_selcollection_evaluate() declared in
- * \ref selection.h to evaluate selections.
- *
- * The functions defined in this header file are all the possible values
- * for the \c t_selelem::evaluate field (in addition to NULL).
- */
-#ifndef SELECTION_EVALUATE_H
-#define SELECTION_EVALUATE_H
-
-#include <typedefs.h>
-
-#include <indexutil.h>
-
-#include "selelem.h"
-
-struct gmx_sel_mempool_t;
-
-/*! \internal \brief
- * Data structure for passing information required during evaluation.
- */
-typedef struct gmx_sel_evaluate_t
-{
-    /** Memory pool for intermediate values. */
-    struct gmx_sel_mempool_t *mp;
-    /** Index group that contains all the atoms. */
-    gmx_ana_index_t         *gall;
-    /** Topology information. */
-    t_topology              *top;
-    /** Current frame. */
-    t_trxframe              *fr;
-    /** PBC data. */
-    t_pbc                   *pbc;
-} gmx_sel_evaluate_t;
-
-/*! \name Utility functions
- */
-/*@{*/
-/** Initializes an evaluation data structure. */
-void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
-                       struct gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
-                       t_topology *top, t_trxframe *fr, t_pbc *pbc);
-/** Evaluates the children of a general selection element. */
-int
-_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates the children of a \ref SEL_EXPRESSION element. */
-int
-_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Misc. evaluation functions
- */
-/*@{*/
-/** Evaluates a root selection element. */
-int
-_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a static group selection element. */
-int
-_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates an arithmetic expression element. */
-int
-_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Subexpression evaluation functions
- */
-/*@{*/
-/** Evaluates a subexpression when there is only one reference. */
-int
-_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression when the evaluation group is static. */
-int
-_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression. */
-int
-_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression reference when there are no other references. */
-int
-_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression reference. */
-int
-_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Method evaluation functions
- */
-/*@{*/
-
-/** Evaluates a method expression. */
-int
-_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a modifier expression. */
-int
-_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/*@}*/
-
-/*! \name Boolean evaluation functions
- */
-/*@{*/
-/** Evaluates a boolean NOT element. */
-int
-_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a boolean AND element with short-circuiting. */
-int
-_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a boolean OR element with short-circuiting. */
-int
-_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/*@}*/
-
-#endif
diff --git a/src/gmxlib/selection/keywords.h b/src/gmxlib/selection/keywords.h
deleted file mode 100644 (file)
index f28f2aa..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Definitions of generic keyword evaluation structures.
- * 
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_KEYWORDS_H
-#define SELECTION_KEYWORDS_H
-
-struct gmx_ana_selmethod_t;
-struct t_selelem;
-struct t_selexpr_param;
-
-/** Selection method data for comparison expression evaluation. */
-extern struct gmx_ana_selmethod_t sm_compare;
-
-/** Selection method data for integer keyword evaluation. */
-extern struct gmx_ana_selmethod_t sm_keyword_int;
-/** Selection method data for real keyword evaluation. */
-extern struct gmx_ana_selmethod_t sm_keyword_real;
-/** Selection method data for string keyword evaluation. */
-extern struct gmx_ana_selmethod_t sm_keyword_str;
-/** Selection method data for position keyword evaluation. */
-extern struct gmx_ana_selmethod_t sm_keyword_pos;
-
-/** Prints information about a comparison expression. */
-void
-_gmx_selelem_print_compare_info(FILE *fp, void *data);
-
-/** Sets the position type for position keyword evaluation. */
-void
-_gmx_selelem_set_kwpos_type(struct t_selelem *sel, const char *type);
-/** Sets the flags for position keyword evaluation. */
-void
-_gmx_selelem_set_kwpos_flags(struct t_selelem *sel, int flags);
-
-/** Does custom processing for parameters of the \c same selection method. */
-int
-_gmx_selelem_custom_init_same(struct gmx_ana_selmethod_t **method,
-                              struct t_selexpr_param *params, void *scanner);
-
-/** Initializes a selection element for evaluating a keyword in a given group. */
-int
-_gmx_sel_init_keyword_evaluator(struct t_selelem **sel,
-                                struct gmx_ana_selmethod_t *method,
-                                struct t_selexpr_param *param, void *scanner);
-
-#endif
diff --git a/src/gmxlib/selection/mempool.c b/src/gmxlib/selection/mempool.c
deleted file mode 100644 (file)
index 32d8aa0..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Memory pooling for selection evaluation.
- *
- * \todo
- * Document these functions.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include <gmx_fatal.h>
-#include <smalloc.h>
-
-#include <indexutil.h>
-
-#include "mempool.h"
-
-#define ALIGN_STEP 8
-
-typedef struct gmx_sel_mempool_block_t
-{
-    void                       *ptr;
-    size_t                      size;
-} gmx_sel_mempool_block_t;
-
-struct gmx_sel_mempool_t
-{
-    size_t                      currsize;
-    size_t                      freesize;
-    char                       *buffer;
-    char                       *freeptr;
-    int                         nblocks;
-    gmx_sel_mempool_block_t    *blockstack;
-    int                         blockstack_nalloc;
-    size_t                      maxsize;
-};
-
-int
-_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp)
-{
-    gmx_sel_mempool_t *mp;
-
-    snew(mp, 1);
-    mp->currsize          = 0;
-    mp->freesize          = 0;
-    mp->buffer            = NULL;
-    mp->freeptr           = NULL;
-    mp->nblocks           = 0;
-    mp->blockstack        = NULL;
-    mp->blockstack_nalloc = 0;
-    mp->maxsize           = 0;
-    *mpp = mp;
-    return 0;
-}
-
-void
-_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp)
-{
-    if (!mp->buffer)
-    {
-        int  i;
-
-        for (i = 0; i < mp->nblocks; ++i)
-        {
-            sfree(mp->blockstack[i].ptr);
-        }
-    }
-    sfree(mp->buffer);
-    sfree(mp->blockstack);
-    sfree(mp);
-}
-
-int
-_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size)
-{
-    void   *ptr = NULL;
-    size_t  size_walign;
-
-    *ptrp = NULL;
-    size_walign = ((size + ALIGN_STEP - 1) / ALIGN_STEP) * ALIGN_STEP;
-    if (mp->buffer)
-    {
-        if (mp->freesize < size)
-        {
-            gmx_bug("out of memory pool memory");
-            return ENOMEM;
-        }
-        ptr = mp->freeptr;
-        mp->freeptr  += size_walign;
-        mp->freesize -= size_walign;
-        mp->currsize += size_walign;
-    }
-    else
-    {
-        ptr = malloc(size);
-        if (!ptr)
-        {
-            gmx_mem("out of memory");
-            return ENOMEM;
-        }
-        mp->currsize += size_walign;
-        if (mp->currsize > mp->maxsize)
-        {
-            mp->maxsize = mp->currsize;
-        }
-    }
-
-    if (mp->nblocks >= mp->blockstack_nalloc)
-    {
-        mp->blockstack_nalloc = mp->nblocks + 10;
-        srenew(mp->blockstack, mp->blockstack_nalloc);
-    }
-    mp->blockstack[mp->nblocks].ptr  = ptr;
-    mp->blockstack[mp->nblocks].size = size_walign;
-    mp->nblocks++;
-
-    *ptrp = ptr;
-    return 0;
-}
-
-void
-_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr)
-{
-    int size;
-
-    if (ptr == NULL)
-    {
-        return;
-    }
-    assert(mp->nblocks > 0 && mp->blockstack[mp->nblocks - 1].ptr == ptr);
-    mp->nblocks--;
-    size = mp->blockstack[mp->nblocks].size;
-    mp->currsize -= size;
-    if (mp->buffer)
-    {
-        mp->freeptr = (char *)ptr;
-        mp->freesize += size;
-    }
-    else
-    {
-        sfree(ptr);
-    }
-}
-
-int
-_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size)
-{
-    assert(mp->nblocks == 0 && !mp->buffer);
-    if (size == 0)
-    {
-        size = mp->maxsize;
-    }
-    mp->buffer = (char *)malloc(size);
-    if (!mp->buffer)
-    {
-        gmx_mem("out of memory");
-        return ENOMEM;
-    }
-    mp->freesize = size;
-    mp->freeptr  = mp->buffer;
-    return 0;
-}
-
-int
-_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g,
-                             int isize)
-{
-    return _gmx_sel_mempool_alloc(mp, (void **)&g->index,
-                                  sizeof(*g->index)*isize);
-}
-
-void
-_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g)
-{
-    _gmx_sel_mempool_free(mp, g->index);
-    g->index = NULL;
-}
diff --git a/src/gmxlib/selection/mempool.h b/src/gmxlib/selection/mempool.h
deleted file mode 100644 (file)
index ca6abba..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Declarations for memory pooling functions.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef GMX_SELECTION_MEMPOOL_H
-#define GMX_SELECTION_MEMPOOL_H
-
-struct gmx_ana_index_t;
-
-typedef struct gmx_sel_mempool_t gmx_sel_mempool_t;
-
-/** Create an empty memory pool. */
-int
-_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp);
-/** Destroy a memory pool. */
-void
-_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp);
-
-/** Allocate memory from a memory pool. */
-int
-_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size);
-/** Release memory allocated from a memory pool. */
-void
-_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr);
-/** Set the size of a memory pool. */
-int
-_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size);
-
-/** Convenience function for allocating an index group from a memory pool. */
-int
-_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g,
-                             int isize);
-/** Convenience function for freeing an index group from a memory pool. */
-void
-_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g);
-
-#endif
diff --git a/src/gmxlib/selection/params.c b/src/gmxlib/selection/params.c
deleted file mode 100644 (file)
index 94a59ff..0000000
+++ /dev/null
@@ -1,1250 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief
- * Implementation of functions in selparam.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <smalloc.h>
-#include <string2.h>
-#include <vec.h>
-
-#include <position.h>
-#include <selmethod.h>
-#include <selparam.h>
-
-#include "parsetree.h"
-#include "position.h"
-#include "selelem.h"
-
-/*!
- * \param[in] name   Name of the parameter to search.
- * \param[in] nparam Number of parameters in the \p param array.
- * \param[in] param  Parameter array to search.
- * \returns   Pointer to the parameter in the \p param
- *   or NULL if no parameter with name \p name was found.
- *
- * The comparison is case-sensitive.
- */
-gmx_ana_selparam_t *
-gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param)
-{
-    int                i;
-
-    if (nparam == 0)
-    {
-        return NULL;
-    }
-    /* Find the first non-null parameter */
-    i = 0;
-    while (i < nparam && param[i].name == NULL)
-    {
-        ++i;
-    }
-    /* Process the special case of a NULL parameter */
-    if (name == NULL)
-    {
-        return (i == 0) ? NULL : &param[i-1];
-    }
-    for ( ; i < nparam; ++i)
-    {
-        if (!strcmp(param[i].name, name))
-        {
-            return &param[i];
-        }
-        /* Check for 'no' prefix on gmx_boolean parameters */
-        if (param[i].val.type == NO_VALUE
-            && strlen(name) > 2 && name[0] == 'n' && name[1] == 'o'
-            && !strcmp(param[i].name, name+2))
-        {
-            return &param[i];
-        }
-    }
-    return NULL;
-}
-
-/*! \brief
- * Does a type conversion on a \c t_selexpr_value.
- *
- * \param[in,out] value    Value to convert.
- * \param[in]     type     Type to convert to.
- * \param[in]     scanner  Scanner data structure.
- * \returns       0 on success, a non-zero value on error.
- */
-static int
-convert_value(t_selexpr_value *value, e_selvalue_t type, void *scanner)
-{
-    if (value->type == type || type == NO_VALUE)
-    {
-        return 0;
-    }
-    if (value->bExpr)
-    {
-        /* Conversion from atom selection to position using default
-         * reference positions. */
-        if (value->type == GROUP_VALUE && type == POS_VALUE)
-        {
-            value->u.expr =
-                _gmx_sel_init_position(value->u.expr, NULL, scanner);
-            if (value->u.expr == NULL)
-            {
-                return -1;
-            }
-            value->type = type;
-            return 0;
-        }
-        return -1;
-    }
-    else
-    {
-        /* Integers to floating point are easy */
-        if (value->type == INT_VALUE && type == REAL_VALUE)
-        {
-            real r1 = (real)value->u.i.i1;
-            real r2 = (real)value->u.i.i2;
-            value->u.r.r1 = r1;
-            value->u.r.r2 = r2;
-            value->type = type;
-            return 0;
-        }
-        /* Reals that are integer-valued can also be converted */
-        if (value->type == REAL_VALUE && type == INT_VALUE
-            && gmx_within_tol(value->u.r.r1, (int)value->u.r.r1, GMX_REAL_EPS)
-            && gmx_within_tol(value->u.r.r2, (int)value->u.r.r2, GMX_REAL_EPS))
-        {
-            int i1 = (int)value->u.r.r1;
-            int i2 = (int)value->u.r.r2;
-            value->u.i.i1 = i1;
-            value->u.i.i2 = i2;
-            value->type = type;
-            return 0;
-        }
-    }
-    return -1;
-}
-
-/*! \brief
- * Does a type conversion on a list of values.
- *
- * \param[in,out] values   Values to convert.
- * \param[in]     type     Type to convert to.
- * \param[in]     scanner  Scanner data structure.
- * \returns       0 on success, a non-zero value on error.
- */
-static int
-convert_values(t_selexpr_value *values, e_selvalue_t type, void *scanner)
-{
-    t_selexpr_value *value;
-    int              rc, rc1;
-
-    rc = 0;
-    value = values;
-    while (value)
-    {
-        rc1 = convert_value(value, type, scanner);
-        if (rc1 != 0 && rc == 0)
-        {
-            rc = rc1;
-        }
-        value = value->next;
-    }
-    /* FIXME: More informative error messages */
-    return rc;
-}
-
-/*! \brief
- * Adds a child element for a parameter, keeping the parameter order.
- *
- * \param[in,out] root  Root element to which the child is added.
- * \param[in]     child Child to add.
- * \param[in]     param Parameter for which this child is a value.
- *
- * Puts \p child in the child list of \p root such that the list remains
- * in the same order as the corresponding parameters.
- */
-static void
-place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
-{
-    gmx_ana_selparam_t *ps;
-    int                 n;
-
-    ps = root->u.expr.method->param;
-    n  = param - ps;
-    /* Put the child element in the correct place */
-    if (!root->child || n < root->child->u.param - ps)
-    {
-        child->next = root->child;
-        root->child = child;
-    }
-    else
-    {
-        t_selelem *prev;
-
-        prev = root->child;
-        while (prev->next && prev->next->u.param - ps >= n)
-        {
-            prev = prev->next;
-        }
-        child->next = prev->next;
-        prev->next  = child;
-    }
-}
-
-/*! \brief
- * Comparison function for sorting integer ranges.
- * 
- * \param[in] a Pointer to the first range.
- * \param[in] b Pointer to the second range.
- * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
- *
- * The ranges are primarily sorted based on their starting point, and
- * secondarily based on length (longer ranges come first).
- */
-static int
-cmp_int_range(const void *a, const void *b)
-{
-    if (((int *)a)[0] < ((int *)b)[0])
-    {
-        return -1;
-    }
-    if (((int *)a)[0] > ((int *)b)[0])
-    {
-        return 1;
-    }
-    if (((int *)a)[1] > ((int *)b)[1])
-    {
-        return -1;
-    }
-    return 0;
-}
-
-/*! \brief
- * Comparison function for sorting real ranges.
- *
- * \param[in] a Pointer to the first range.
- * \param[in] b Pointer to the second range.
- * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
- *
- * The ranges are primarily sorted based on their starting point, and
- * secondarily based on length (longer ranges come first).
- */
-static int
-cmp_real_range(const void *a, const void *b)
-{
-    if (((real *)a)[0] < ((real *)b)[0])
-    {
-        return -1;
-    }
-    if (((real *)a)[0] > ((real *)b)[0])
-    {
-        return 1;
-    }
-    if (((real *)a)[1] > ((real *)b)[1])
-    {
-        return -1;
-    }
-    return 0;
-}
-
-/*! \brief
- * Parses the values for a parameter that takes integer or real ranges.
- * 
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- */
-static gmx_bool
-parse_values_range(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
-{
-    t_selexpr_value    *value;
-    int                *idata;
-    real               *rdata;
-    int                 i, j, n;
-
-    param->flags &= ~SPAR_DYNAMIC;
-    if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE)
-    {
-        gmx_bug("internal error");
-        return FALSE;
-    }
-    idata = NULL;
-    rdata = NULL;
-    if (param->val.type == INT_VALUE)
-    {
-        snew(idata, nval*2);
-    }
-    else
-    {
-        snew(rdata, nval*2);
-    }
-    value = values;
-    i = 0;
-    while (value)
-    {
-        if (value->bExpr)
-        {
-            _gmx_selparser_error("expressions not supported within range parameters");
-            return FALSE;
-        }
-        if (value->type != param->val.type)
-        {
-            gmx_bug("internal error");
-            return FALSE;
-        }
-        if (param->val.type == INT_VALUE)
-        {
-            /* Make sure the input range is in increasing order */
-            if (value->u.i.i1 > value->u.i.i2)
-            {
-                int tmp       = value->u.i.i1;
-                value->u.i.i1 = value->u.i.i2;
-                value->u.i.i2 = tmp;
-            }
-            /* Check if the new range overlaps or extends the previous one */
-            if (i > 0 && value->u.i.i1 <= idata[i-1]+1 && value->u.i.i2 >= idata[i-2]-1)
-            {
-                idata[i-2] = min(idata[i-2], value->u.i.i1);
-                idata[i-1] = max(idata[i-1], value->u.i.i2);
-            }
-            else
-            {
-                idata[i++] = value->u.i.i1;
-                idata[i++] = value->u.i.i2;
-            }
-        }
-        else
-        {
-            /* Make sure the input range is in increasing order */
-            if (value->u.r.r1 > value->u.r.r2)
-            {
-                real tmp      = value->u.r.r1;
-                value->u.r.r1 = value->u.r.r2;
-                value->u.r.r2 = tmp;
-            }
-            /* Check if the new range overlaps or extends the previous one */
-            if (i > 0 && value->u.r.r1 <= rdata[i-1] && value->u.r.r2 >= rdata[i-2])
-            {
-                rdata[i-2] = min(rdata[i-2], value->u.r.r1);
-                rdata[i-1] = max(rdata[i-1], value->u.r.r2);
-            }
-            else
-            {
-                rdata[i++] = value->u.r.r1;
-                rdata[i++] = value->u.r.r2;
-            }
-        }
-        value = value->next;
-    }
-    n = i/2;
-    /* Sort the ranges and merge consequent ones */
-    if (param->val.type == INT_VALUE)
-    {
-        qsort(idata, n, 2*sizeof(int), &cmp_int_range);
-        for (i = j = 2; i < 2*n; i += 2)
-        {
-            if (idata[j-1]+1 >= idata[i])
-            {
-                if (idata[i+1] > idata[j-1])
-                {
-                    idata[j-1] = idata[i+1];
-                }
-            }
-            else
-            {
-                idata[j]   = idata[i];
-                idata[j+1] = idata[i+1];
-                j += 2;
-            }
-        }
-    }
-    else
-    {
-        qsort(rdata, n, 2*sizeof(real), &cmp_real_range);
-        for (i = j = 2; i < 2*n; i += 2)
-        {
-            if (rdata[j-1]+1 >= rdata[i])
-            {
-                if (rdata[i+1] > rdata[j-1])
-                {
-                    rdata[j-1] = rdata[i+1];
-                }
-            }
-            else
-            {
-                rdata[j]   = rdata[i];
-                rdata[j+1] = rdata[i+1];
-                j += 2;
-            }
-        }
-    }
-    n = j/2;
-    /* Store the values */
-    if (param->flags & SPAR_VARNUM)
-    {
-        param->val.nr  = n;
-        if (param->val.type == INT_VALUE)
-        {
-            srenew(idata, j);
-            _gmx_selvalue_setstore_alloc(&param->val, idata, j);
-        }
-        else
-        {
-            srenew(rdata, j);
-            _gmx_selvalue_setstore_alloc(&param->val, rdata, j);
-        }
-    }
-    else
-    {
-        if (n != param->val.nr)
-        {
-            _gmx_selparser_error("the value of parameter '%s' should consist of exactly one range",
-                                 param->name);       
-            sfree(idata);
-            sfree(rdata);
-            return FALSE;
-        }
-        if (param->val.type == INT_VALUE)
-        {
-            memcpy(param->val.u.i, idata, 2*n*sizeof(int));
-            sfree(idata);
-        }
-        else
-        {
-            memcpy(param->val.u.r, rdata, 2*n*sizeof(real));
-            sfree(rdata);
-        }
-    }
-    if (param->nvalptr)
-    {
-        *param->nvalptr = param->val.nr;
-    }
-    param->nvalptr = NULL;
-
-    return TRUE;
-}
-
-/*! \brief
- * Parses the values for a parameter that takes a variable number of values.
- * 
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \param     root   Selection element to which child expressions are added.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- *
- * For integer ranges, the sequence of numbers from the first to second value
- * is stored, each as a separate value.
- */
-static gmx_bool
-parse_values_varnum(int nval, t_selexpr_value *values,
-                    gmx_ana_selparam_t *param, t_selelem *root)
-{
-    t_selexpr_value    *value;
-    int                 i, j;
-
-    param->flags &= ~SPAR_DYNAMIC;
-    /* Update nval if there are integer ranges. */
-    if (param->val.type == INT_VALUE)
-    {
-        value = values;
-        while (value)
-        {
-            if (value->type == INT_VALUE && !value->bExpr)
-            {
-                nval += abs(value->u.i.i2 - value->u.i.i1);
-            }
-            value = value->next;
-        }
-    }
-
-    /* Check that the value type is actually implemented */
-    if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE
-        && param->val.type != STR_VALUE && param->val.type != POS_VALUE)
-    {
-        gmx_bug("internal error");
-        return FALSE;
-    }
-
-    /* Reserve appropriate amount of memory */
-    if (param->val.type == POS_VALUE)
-    {
-        gmx_ana_pos_reserve(param->val.u.p, nval, 0);
-        gmx_ana_pos_set_nr(param->val.u.p, nval);
-        gmx_ana_indexmap_init(&param->val.u.p->m, NULL, NULL, INDEX_UNKNOWN);
-    }
-    else
-    {
-        _gmx_selvalue_reserve(&param->val, nval);
-    }
-
-    value = values;
-    i     = 0;
-    while (value)
-    {
-        if (value->bExpr)
-        {
-            _gmx_selparser_error("expressions not supported within value lists");
-            return FALSE;
-        }
-        if (value->type != param->val.type)
-        {
-            gmx_bug("internal error");
-            return FALSE;
-        }
-        switch (param->val.type)
-        {
-            case INT_VALUE:
-                if (value->u.i.i1 <= value->u.i.i2)
-                {
-                    for (j = value->u.i.i1; j <= value->u.i.i2; ++j)
-                    {
-                        param->val.u.i[i++] = j;
-                    }
-                }
-                else
-                {
-                    for (j = value->u.i.i1; j >= value->u.i.i2; --j)
-                    {
-                        param->val.u.i[i++] = j;
-                    }
-                }
-                break;
-            case REAL_VALUE:
-                if (value->u.r.r1 != value->u.r.r2)
-                {
-                    _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name);
-                    return FALSE;
-                }
-                param->val.u.r[i++] = value->u.r.r1;
-                break;
-            case STR_VALUE:  param->val.u.s[i++] = strdup(value->u.s); break;
-            case POS_VALUE:  copy_rvec(value->u.x, param->val.u.p->x[i++]); break;
-            default: /* Should not be reached */
-                gmx_bug("internal error");
-                return FALSE;
-        }
-        value = value->next;
-    }
-    param->val.nr = i;
-    if (param->nvalptr)
-    {
-        *param->nvalptr = param->val.nr;
-    }
-    param->nvalptr = NULL;
-    /* Create a dummy child element to store the string values.
-     * This element is responsible for freeing the values, but carries no
-     * other function. */
-    if (param->val.type == STR_VALUE)
-    {
-        t_selelem *child;
-
-        child = _gmx_selelem_create(SEL_CONST);
-        _gmx_selelem_set_vtype(child, STR_VALUE);
-        child->name = param->name;
-        child->flags &= ~SEL_ALLOCVAL;
-        child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
-        child->v.nr = param->val.nr;
-        _gmx_selvalue_setstore(&child->v, param->val.u.s);
-        /* Because the child is not group-valued, the u union is not used
-         * for anything, so we can abuse it by storing the parameter value
-         * as place_child() expects, but this is really ugly... */
-        child->u.param = param;
-        place_child(root, child, param);
-    }
-
-    return TRUE;
-}
-
-/*! \brief
- * Adds a new subexpression reference to a selection element.
- *
- * \param[in,out] root  Root element to which the subexpression is added.
- * \param[in]     param Parameter for which this expression is a value.
- * \param[in]     expr  Expression to add.
- * \returns       The created child element.
- *
- * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
- * list of \p root.
- * If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
- * \ref SEL_ALLOCVAL is cleared for the returned element.
- */
-static t_selelem *
-add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
-{
-    t_selelem          *child;
-    int                 rc;
-
-    if (root->type != SEL_EXPRESSION && root->type != SEL_MODIFIER)
-    {
-        gmx_bug("unsupported root element for selection parameter parser");
-        return NULL;
-    }
-    /* Create a subexpression reference element if necessary */
-    if (expr->type == SEL_SUBEXPRREF)
-    {
-        child = expr;
-    }
-    else
-    {
-        child = _gmx_selelem_create(SEL_SUBEXPRREF);
-        if (!child)
-        {
-            return NULL;
-        }
-        _gmx_selelem_set_vtype(child, expr->v.type);
-        child->child  = expr;
-    }
-    /* Setup the child element */
-    child->flags &= ~SEL_ALLOCVAL;
-    child->u.param = param;
-    if (child->v.type != param->val.type)
-    {
-        _gmx_selparser_error("invalid expression value for parameter '%s'",
-                             param->name);
-        goto on_error;
-    }
-    rc = _gmx_selelem_update_flags(child);
-    if (rc != 0)
-    {
-        goto on_error;
-    }
-    if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
-    {
-        _gmx_selparser_error("parameter '%s' does not support dynamic values",
-                             param->name);
-        goto on_error;
-    }
-    if (!(child->flags & SEL_DYNAMIC))
-    {
-        param->flags &= ~SPAR_DYNAMIC;
-    }
-    /* Put the child element in the correct place */
-    place_child(root, child, param);
-    return child;
-
-on_error:
-    if (child != expr)
-    {
-        _gmx_selelem_free(child);
-    }
-    return NULL;
-}
-
-/*! \brief
- * Parses an expression value for a parameter that takes a variable number of values.
- * 
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \param     root   Selection element to which child expressions are added.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- */
-static gmx_bool
-parse_values_varnum_expr(int nval, t_selexpr_value *values,
-                         gmx_ana_selparam_t *param, t_selelem *root)
-{
-    t_selexpr_value    *value;
-    t_selelem          *child;
-    t_selelem          *expr;
-
-    if (nval != 1 || !values->bExpr)
-    {
-        gmx_bug("internal error");
-        return FALSE;
-    }
-
-    value = values;
-    child = add_child(root, param, value->u.expr);
-    value->u.expr = NULL;
-    if (!child)
-    {
-        return FALSE;
-    }
-
-    /* Process single-valued expressions */
-    /* TODO: We should also handle SEL_SINGLEVAL expressions here */
-    if (child->v.type == POS_VALUE || child->v.type == GROUP_VALUE)
-    {
-        /* Set the value storage */
-        _gmx_selvalue_setstore(&child->v, param->val.u.ptr);
-        param->val.nr = 1;
-        if (param->nvalptr)
-        {
-            *param->nvalptr = param->val.nr;
-        }
-        param->nvalptr = NULL;
-        return TRUE;
-    }
-
-    if (!(child->flags & SEL_VARNUMVAL))
-    {
-        _gmx_selparser_error("invalid expression value for parameter '%s'",
-                             param->name);
-        return FALSE;
-    }
-
-    child->flags   |= SEL_ALLOCVAL;
-    param->val.nr   = -1;
-    *param->nvalptr = param->val.nr;
-    /* Rest of the initialization is done during compilation in
-     * init_method(). */
-
-    return TRUE;
-}
-
-/*! \brief
- * Initializes the storage of an expression value.
- *
- * \param[in,out] sel   Selection element that evaluates the value.
- * \param[in]     param Parameter to receive the value.
- * \param[in]     i     The value of \p sel evaluates the value \p i for
- *   \p param.
- *
- * Initializes the data pointer of \p sel such that the result is stored
- * as the value \p i of \p param.
- * This function is used internally by parse_values_std().
- */
-static gmx_bool
-set_expr_value_store(t_selelem *sel, gmx_ana_selparam_t *param, int i)
-{
-    if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
-    {
-        _gmx_selparser_error("invalid expression value for parameter '%s'",
-                             param->name);
-        return FALSE;
-    }
-    switch (sel->v.type)
-    {
-        case INT_VALUE:   sel->v.u.i = &param->val.u.i[i]; break;
-        case REAL_VALUE:  sel->v.u.r = &param->val.u.r[i]; break;
-        case STR_VALUE:   sel->v.u.s = &param->val.u.s[i]; break;
-        case POS_VALUE:   sel->v.u.p = &param->val.u.p[i]; break;
-        case GROUP_VALUE: sel->v.u.g = &param->val.u.g[i]; break;
-        default: /* Error */
-            gmx_bug("internal error");
-            return FALSE;
-    }
-    sel->v.nr = 1;
-    sel->v.nalloc = -1;
-    return TRUE;
-}
-
-/*! \brief
- * Parses the values for a parameter that takes a constant number of values.
- * 
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \param     root   Selection element to which child expressions are added.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- *
- * For integer ranges, the sequence of numbers from the first to second value
- * is stored, each as a separate value.
- */
-static gmx_bool
-parse_values_std(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
-                 t_selelem *root)
-{
-    t_selexpr_value   *value;
-    t_selelem         *child;
-    int                i, j;
-    gmx_bool               bDynamic;
-
-    /* Handle atom-valued parameters */
-    if (param->flags & SPAR_ATOMVAL)
-    {
-        if (nval > 1)
-        {
-            _gmx_selparser_error("extra values for parameter '%s'", param->name);
-            return FALSE;
-        }
-        value = values;
-        if (value->bExpr)
-        {
-            child = add_child(root, param, value->u.expr);
-            value->u.expr = NULL;
-            if (!child)
-            {
-                return FALSE;
-            }
-            child->flags |= SEL_ALLOCVAL;
-            if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
-            {
-                /* Rest of the initialization is done during compilation in
-                 * init_method(). */
-                /* TODO: Positions are not correctly handled */
-                param->val.nr = -1;
-                if (param->nvalptr)
-                {
-                    *param->nvalptr = -1;
-                }
-                return TRUE;
-            }
-            param->flags  &= ~SPAR_ATOMVAL;
-            param->val.nr  = 1;
-            if (param->nvalptr)
-            {
-                *param->nvalptr = 1;
-            }
-            param->nvalptr = NULL;
-            if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
-                || param->val.type == STR_VALUE)
-            {
-                _gmx_selvalue_reserve(&param->val, 1);
-            }
-            return set_expr_value_store(child, param, 0);
-        }
-        /* If we reach here, proceed with normal parameter handling */
-        param->val.nr = 1;
-        if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
-            || param->val.type == STR_VALUE)
-        {
-            _gmx_selvalue_reserve(&param->val, 1);
-        }
-        param->flags &= ~SPAR_ATOMVAL;
-        param->flags &= ~SPAR_DYNAMIC;
-    }
-
-    value = values;
-    i = 0;
-    bDynamic = FALSE;
-    while (value && i < param->val.nr)
-    {
-        if (value->type != param->val.type)
-        {
-            _gmx_selparser_error("incorrect value for parameter '%s' skipped", param->name);
-            value = value->next;
-            continue;
-        }
-        if (value->bExpr)
-        {
-            child = add_child(root, param, value->u.expr);
-            /* Clear the expression from the value once it is stored */
-            value->u.expr = NULL;
-            /* Check that the expression is valid */
-            if (!child)
-            {
-                return FALSE;
-            }
-            if (!set_expr_value_store(child, param, i))
-            {
-                return FALSE;
-            }
-            if (child->flags & SEL_DYNAMIC)
-            {
-                bDynamic = TRUE;
-            }
-        }
-        else
-        {
-            /* Value is not an expression */
-            switch (value->type)
-            {
-                case INT_VALUE:
-                    if (value->u.i.i1 <= value->u.i.i2)
-                    {
-                        for (j = value->u.i.i1; j <= value->u.i.i2 && i < param->val.nr; ++j)
-                        {
-                            param->val.u.i[i++] = j;
-                        }
-                        if (j != value->u.i.i2 + 1)
-                        {
-                            _gmx_selparser_error("extra values for parameter '%s' skipped", param->name);
-                        }
-                    }
-                    else
-                    {
-                        for (j = value->u.i.i1; j >= value->u.i.i2 && i < param->val.nr; --j)
-                        {
-                            param->val.u.i[i++] = j;
-                        }
-                        if (j != value->u.i.i2 - 1)
-                        {
-                            _gmx_selparser_error("extra values for parameter '%s' skipped", param->name);
-                        }
-                    }
-                    --i;
-                    break;
-                case REAL_VALUE:
-                    if (value->u.r.r1 != value->u.r.r2)
-                    {
-                        _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name);
-                        return FALSE;
-                    }
-                    param->val.u.r[i] = value->u.r.r1;
-                    break;
-                case STR_VALUE:
-                    param->val.u.s[i] = strdup(value->u.s);
-                    break;
-                case POS_VALUE:
-                    gmx_ana_pos_init_const(&param->val.u.p[i], value->u.x);
-                    break;
-                case NO_VALUE:
-                case GROUP_VALUE:
-                    gmx_bug("internal error");
-                    return FALSE;
-            }
-        }
-        ++i;
-        value = value->next;
-    }
-    if (value)
-    {
-        _gmx_selparser_error("extra values for parameter '%s'", param->name);
-        return FALSE;
-    }
-    if (i < param->val.nr)
-    {
-        _gmx_selparser_error("not enough values for parameter '%s'", param->name);
-        return FALSE;
-    }
-    if (!bDynamic)
-    {
-        param->flags &= ~SPAR_DYNAMIC;
-    }
-    if (param->nvalptr)
-    {
-        *param->nvalptr = param->val.nr;
-    }
-    param->nvalptr = NULL;
-
-    return TRUE;
-}
-
-/*! \brief
- * Parses the values for a gmx_boolean parameter.
- *
- * \param[in] name   Name by which the parameter was given.
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- */
-static gmx_bool
-parse_values_gmx_bool(const char *name, int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
-{
-    gmx_bool bSetNo;
-    int  len;
-
-    if (param->val.type != NO_VALUE)
-    {
-        gmx_bug("internal error");
-        return FALSE;
-    }
-    if (nval > 1 || (values && values->type != INT_VALUE))
-    {
-        _gmx_selparser_error("gmx_boolean parameter '%s' takes only a yes/no/on/off/0/1 value", param->name);
-        return FALSE;
-    }
-
-    bSetNo = FALSE;
-    /* Check if the parameter name is given with a 'no' prefix */
-    len = strlen(name);
-    if (len > 2 && name[0] == 'n' && name[1] == 'o'
-        && strncmp(name+2, param->name, len-2) == 0)
-    {
-        bSetNo = TRUE;
-    }
-    if (bSetNo && nval > 0)
-    {
-        _gmx_selparser_error("gmx_boolean parameter 'no%s' should not have a value", param->name);
-        return FALSE;
-    }
-    if (values && values->u.i.i1 == 0)
-    {
-        bSetNo = TRUE;
-    }
-
-    *param->val.u.b = bSetNo ? FALSE : TRUE;
-    return TRUE;
-}
-
-/*! \brief
- * Parses the values for an enumeration parameter.
- *
- * \param[in] nval   Number of values in \p values.
- * \param[in] values Pointer to the list of values.
- * \param     param  Parameter to parse.
- * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
- */
-static gmx_bool
-parse_values_enum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
-{
-    int  i, len, match;
-
-    if (nval != 1)
-    {
-        _gmx_selparser_error("a single value is required for parameter '%s'", param->name);
-        return FALSE;
-    }
-    if (values->type != STR_VALUE || param->val.type != STR_VALUE)
-    {
-        gmx_bug("internal error");
-        return FALSE;
-    }
-    if (values->bExpr)
-    {
-        _gmx_selparser_error("expression value for enumerated parameter '%s' not supported", param->name);
-        return FALSE;
-    }
-
-    len = strlen(values->u.s);
-    i = 1;
-    match = 0;
-    while (param->val.u.s[i] != NULL)
-    {
-        if (strncmp(values->u.s, param->val.u.s[i], len) == 0)
-        {
-            /* Check if there is a duplicate match */
-            if (match > 0)
-            {
-                _gmx_selparser_error("ambiguous value for parameter '%s'", param->name);
-                return FALSE;
-            }
-            match = i;
-        }
-        ++i;
-    }
-    if (match == 0)
-    {
-        _gmx_selparser_error("invalid value for parameter '%s'", param->name);
-        return FALSE;
-    }
-    param->val.u.s[0] = param->val.u.s[match];
-    return TRUE;
-}
-
-/*! \brief
- * Replaces constant expressions with their values.
- *
- * \param[in,out] values First element in the value list to process.
- */
-static void
-convert_const_values(t_selexpr_value *values)
-{
-    t_selexpr_value *val;
-
-    val = values;
-    while (val)
-    {
-        if (val->bExpr && val->u.expr->v.type != GROUP_VALUE &&
-            val->u.expr->type == SEL_CONST)
-        {
-            t_selelem *expr = val->u.expr;
-            val->bExpr = FALSE;
-            switch (expr->v.type)
-            {
-                case INT_VALUE:
-                    val->u.i.i1 = val->u.i.i2 = expr->v.u.i[0];
-                    break;
-                case REAL_VALUE:
-                    val->u.r.r1 = val->u.r.r2 = expr->v.u.r[0];
-                    break;
-                case STR_VALUE:
-                    val->u.s = expr->v.u.s[0];
-                    break;
-                case POS_VALUE:
-                    copy_rvec(expr->v.u.p->x[0], val->u.x);
-                    break;
-                default:
-                    gmx_bug("internal error");
-                    break;
-            }
-            _gmx_selelem_free(expr);
-        }
-        val = val->next;
-    }
-}
-
-/*!
- * \param     pparams List of parameters from the selection parser.
- * \param[in] nparam  Number of parameters in \p params.
- * \param     params  Array of parameters to parse.
- * \param     root    Selection element to which child expressions are added.
- * \param[in] scanner Scanner data structure.
- * \returns   TRUE if the parameters were parsed successfully, FALSE otherwise.
- *
- * Initializes the \p params array based on the parameters in \p pparams.
- * See the documentation of \c gmx_ana_selparam_t for different options
- * available for parsing.
- *
- * The list \p pparams and any associated values are freed after the parameters
- * have been processed, no matter is there was an error or not.
- */
-gmx_bool
-_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *params,
-                      t_selelem *root, void *scanner)
-{
-    t_selexpr_param    *pparam;
-    gmx_ana_selparam_t *oparam;
-    gmx_bool                bOk, rc;
-    int                 i;
-
-    /* Check that the value pointers of SPAR_VARNUM parameters are NULL and
-     * that they are not NULL for other parameters */
-    bOk = TRUE;
-    for (i = 0; i < nparam; ++i)
-    {
-        if (params[i].val.type != POS_VALUE && (params[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
-        {
-            if (params[i].val.u.ptr != NULL)
-            {
-                _gmx_selparser_error("warning: value pointer of parameter '%s' is not NULL\n"
-                                     "         although it should be for SPAR_VARNUM and SPAR_ATOMVAL parameters\n",
-                                     params[i].name);
-            }
-            if ((params[i].flags & SPAR_VARNUM)
-                && (params[i].flags & SPAR_DYNAMIC) && !params[i].nvalptr)
-            {
-                _gmx_selparser_error("error: nvalptr of parameter '%s' is NULL\n"
-                                     "       but both SPAR_VARNUM and SPAR_DYNAMIC are specified\n",
-                                     params[i].name);
-                bOk = FALSE;
-            }
-        }
-        else
-        {
-            if (params[i].val.u.ptr == NULL)
-            {
-                _gmx_selparser_error("error: value pointer of parameter '%s' is NULL\n",
-                                     params[i].name);
-                bOk = FALSE;
-            }
-        }
-    }
-    if (!bOk)
-    {
-        _gmx_selexpr_free_params(pparams);
-        return FALSE;
-    }
-    /* Parse the parameters */
-    pparam = pparams;
-    i      = 0;
-    while (pparam)
-    {
-        /* Find the parameter and make some checks */
-        if (pparam->name != NULL)
-        {
-            i = -1;
-            oparam = gmx_ana_selparam_find(pparam->name, nparam, params);
-        }
-        else if (i >= 0)
-        {
-            oparam = &params[i];
-            if (oparam->name != NULL)
-            {
-                oparam = NULL;
-                _gmx_selparser_error("too many NULL parameters provided");
-                bOk = FALSE;
-                goto next_param;
-            }
-            ++i;
-        }
-        else
-        {
-            _gmx_selparser_error("all NULL parameters should appear in the beginning of the list");
-            bOk = FALSE;
-            pparam = pparam->next;
-            continue;
-        }
-        if (!oparam)
-        {
-            _gmx_selparser_error("unknown parameter '%s' skipped", pparam->name);
-            bOk = FALSE;
-            goto next_param;
-        }
-        if (oparam->flags & SPAR_SET)
-        {
-            _gmx_selparser_error("parameter '%s' set multiple times, extra values skipped", pparam->name);
-            bOk = FALSE;
-            goto next_param;
-        }
-        oparam->flags |= SPAR_SET;
-        /* Process the values for the parameter */
-        convert_const_values(pparam->value);
-        if (convert_values(pparam->value, oparam->val.type, scanner) != 0)
-        {
-            _gmx_selparser_error("invalid value for parameter '%s'", pparam->name);
-            bOk = FALSE;
-            goto next_param;
-        }
-        if (oparam->val.type == NO_VALUE)
-        {
-            rc = parse_values_gmx_bool(pparam->name, pparam->nval, pparam->value, oparam);
-        }
-        else if (oparam->flags & SPAR_RANGES)
-        {
-            rc = parse_values_range(pparam->nval, pparam->value, oparam);
-        }
-        else if (oparam->flags & SPAR_VARNUM)
-        {
-            if (pparam->nval == 1 && pparam->value->bExpr)
-            {
-                rc = parse_values_varnum_expr(pparam->nval, pparam->value, oparam, root);
-            }
-            else
-            {
-                rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root);
-            }
-        }
-        else if (oparam->flags & SPAR_ENUMVAL)
-        {
-            rc = parse_values_enum(pparam->nval, pparam->value, oparam);
-        }
-        else
-        {
-            rc = parse_values_std(pparam->nval, pparam->value, oparam, root);
-        }
-        if (!rc)
-        {
-            bOk = FALSE;
-        }
-        /* Advance to the next parameter */
-next_param:
-        pparam = pparam->next;
-    }
-    /* Check that all required parameters are present */
-    for (i = 0; i < nparam; ++i)
-    {
-        if (!(params[i].flags & SPAR_OPTIONAL) && !(params[i].flags & SPAR_SET))
-        {
-            _gmx_selparser_error("required parameter '%s' not specified", params[i].name);
-            bOk = FALSE;
-        }
-    }
-    
-    _gmx_selexpr_free_params(pparams);
-    return bOk;
-}
diff --git a/src/gmxlib/selection/parser.c b/src/gmxlib/selection/parser.c
deleted file mode 100644 (file)
index 3e57a98..0000000
+++ /dev/null
@@ -1,2580 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   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, 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.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names.  */
-#define yyparse _gmx_sel_yybparse
-#define yylex   _gmx_sel_yyblex
-#define yyerror _gmx_sel_yyberror
-#define yylval  _gmx_sel_yyblval
-#define yychar  _gmx_sel_yybchar
-#define yydebug _gmx_sel_yybdebug
-#define yynerrs _gmx_sel_yybnerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     INVALID = 258,
-     HELP = 259,
-     HELP_TOPIC = 260,
-     TOK_INT = 261,
-     TOK_REAL = 262,
-     STR = 263,
-     IDENTIFIER = 264,
-     CMD_SEP = 265,
-     GROUP = 266,
-     TO = 267,
-     VARIABLE_NUMERIC = 268,
-     VARIABLE_GROUP = 269,
-     VARIABLE_POS = 270,
-     KEYWORD_NUMERIC = 271,
-     KEYWORD_STR = 272,
-     KEYWORD_POS = 273,
-     KEYWORD_GROUP = 274,
-     METHOD_NUMERIC = 275,
-     METHOD_GROUP = 276,
-     METHOD_POS = 277,
-     MODIFIER = 278,
-     EMPTY_POSMOD = 279,
-     PARAM = 280,
-     END_OF_METHOD = 281,
-     OF = 282,
-     CMP_OP = 283,
-     PARAM_REDUCT = 284,
-     XOR = 285,
-     OR = 286,
-     AND = 287,
-     NOT = 288,
-     UNARY_NEG = 289,
-     NUM_REDUCT = 290
-   };
-#endif
-/* Tokens.  */
-#define INVALID 258
-#define HELP 259
-#define HELP_TOPIC 260
-#define TOK_INT 261
-#define TOK_REAL 262
-#define STR 263
-#define IDENTIFIER 264
-#define CMD_SEP 265
-#define GROUP 266
-#define TO 267
-#define VARIABLE_NUMERIC 268
-#define VARIABLE_GROUP 269
-#define VARIABLE_POS 270
-#define KEYWORD_NUMERIC 271
-#define KEYWORD_STR 272
-#define KEYWORD_POS 273
-#define KEYWORD_GROUP 274
-#define METHOD_NUMERIC 275
-#define METHOD_GROUP 276
-#define METHOD_POS 277
-#define MODIFIER 278
-#define EMPTY_POSMOD 279
-#define PARAM 280
-#define END_OF_METHOD 281
-#define OF 282
-#define CMP_OP 283
-#define PARAM_REDUCT 284
-#define XOR 285
-#define OR 286
-#define AND 287
-#define NOT 288
-#define UNARY_NEG 289
-#define NUM_REDUCT 290
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 34 "parser.y"
-
-/*! \internal \file parser.c
- * \brief Generated (from parser.y by Bison) parser for the selection language.
- */
-/*! \internal \file parser.h
- * \brief Generated (from parser.y by Bison) parser include file.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <string2.h>
-
-#include "parsetree.h"
-#include "selelem.h"
-
-#include "scanner.h"
-
-static t_selexpr_value *
-process_value_list(t_selexpr_value *values, int *nr);
-static t_selexpr_param *
-process_param_list(t_selexpr_param *params);
-
-static void
-yyerror(yyscan_t, char const *s);
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 62 "parser.y"
-{
-    int                         i;
-    real                        r;
-    char                       *str;
-    struct gmx_ana_selmethod_t *meth;
-
-    struct t_selelem           *sel;
-
-    struct t_selexpr_value     *val;
-    struct t_selexpr_param     *param;
-}
-/* Line 187 of yacc.c.  */
-#line 214 "parser.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 227 "parser.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   417
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  49
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  26
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  91
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  150
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   290
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      42,    43,    36,    34,    45,    35,     2,    37,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    41,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    44,     2,    46,    39,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    47,     2,    48,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    38,
-      40
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     7,    10,    13,    14,    16,    18,
-      20,    22,    25,    29,    33,    37,    39,    41,    44,    47,
-      49,    51,    55,    59,    61,    64,    66,    69,    71,    73,
-      75,    77,    80,    84,    88,    92,    96,    99,   102,   104,
-     106,   109,   113,   117,   121,   123,   125,   128,   132,   136,
-     140,   144,   148,   151,   155,   159,   161,   164,   172,   176,
-     179,   183,   185,   187,   189,   191,   194,   195,   198,   201,
-     202,   204,   208,   210,   213,   217,   219,   223,   225,   228,
-     232,   234,   236,   238,   240,   242,   244,   246,   248,   250,
-     254,   258
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      50,     0,    -1,    -1,    50,    51,    -1,    52,    10,    -1,
-       1,    10,    -1,    -1,    53,    -1,     6,    -1,    59,    -1,
-      55,    -1,    59,    55,    -1,     9,    41,    60,    -1,     9,
-      41,    62,    -1,     9,    41,    64,    -1,     4,    -1,    54,
-      -1,     4,     5,    -1,    54,     5,    -1,    64,    -1,    60,
-      -1,    42,    55,    43,    -1,    55,    23,    65,    -1,     6,
-      -1,    35,     6,    -1,     7,    -1,    35,     7,    -1,    56,
-      -1,    57,    -1,     8,    -1,     9,    -1,    33,    60,    -1,
-      60,    32,    60,    -1,    60,    31,    60,    -1,    42,    60,
-      43,    -1,    62,    28,    62,    -1,    11,    59,    -1,    11,
-       6,    -1,    24,    -1,    18,    -1,    61,    19,    -1,    61,
-      17,    70,    -1,    61,    16,    70,    -1,    61,    21,    65,
-      -1,     6,    -1,     7,    -1,    61,    16,    -1,    61,    20,
-      65,    -1,    62,    34,    62,    -1,    62,    35,    62,    -1,
-      62,    36,    62,    -1,    62,    37,    62,    -1,    35,    62,
-      -1,    62,    39,    62,    -1,    42,    62,    43,    -1,    59,
-      -1,    61,    17,    -1,    44,    58,    45,    58,    45,    58,
-      46,    -1,    42,    64,    43,    -1,    22,    65,    -1,    18,
-      27,    60,    -1,    14,    -1,    13,    -1,    15,    -1,    66,
-      -1,    66,    26,    -1,    -1,    66,    67,    -1,    25,    68,
-      -1,    -1,    69,    -1,    47,    69,    48,    -1,    72,    -1,
-      69,    72,    -1,    69,    45,    72,    -1,    71,    -1,    47,
-      71,    48,    -1,    73,    -1,    71,    73,    -1,    71,    45,
-      73,    -1,    60,    -1,    64,    -1,    62,    -1,    63,    -1,
-      74,    -1,    56,    -1,    57,    -1,    59,    -1,    74,    -1,
-      56,    12,    56,    -1,    56,    12,    57,    -1,    57,    12,
-      58,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,   182,   182,   183,   192,   193,   213,   217,   218,   227,
-     237,   239,   241,   243,   245,   251,   252,   255,   256,   260,
-     261,   266,   267,   279,   280,   284,   285,   288,   289,   292,
-     293,   301,   307,   313,   325,   329,   337,   343,   351,   352,
-     356,   361,   366,   374,   386,   393,   403,   408,   416,   418,
-     420,   422,   424,   426,   428,   435,   442,   454,   459,   463,
-     471,   482,   486,   490,   499,   501,   506,   507,   512,   519,
-     520,   521,   525,   526,   528,   533,   534,   538,   539,   541,
-     545,   547,   549,   551,   553,   557,   562,   567,   572,   576,
-     581,   586
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "INVALID", "HELP", "HELP_TOPIC",
-  "TOK_INT", "TOK_REAL", "STR", "IDENTIFIER", "CMD_SEP", "GROUP", "TO",
-  "VARIABLE_NUMERIC", "VARIABLE_GROUP", "VARIABLE_POS", "KEYWORD_NUMERIC",
-  "KEYWORD_STR", "KEYWORD_POS", "KEYWORD_GROUP", "METHOD_NUMERIC",
-  "METHOD_GROUP", "METHOD_POS", "MODIFIER", "EMPTY_POSMOD", "PARAM",
-  "END_OF_METHOD", "OF", "CMP_OP", "PARAM_REDUCT", "XOR", "OR", "AND",
-  "NOT", "'+'", "'-'", "'*'", "'/'", "UNARY_NEG", "'^'", "NUM_REDUCT",
-  "'='", "'('", "')'", "'['", "','", "']'", "'{'", "'}'", "$accept",
-  "commands", "command", "cmd_plain", "help_request", "help_topic",
-  "selection", "integer_number", "real_number", "number", "string",
-  "sel_expr", "pos_mod", "num_expr", "str_expr", "pos_expr",
-  "method_params", "method_param_list", "method_param", "value_list",
-  "value_list_contents", "basic_value_list", "basic_value_list_contents",
-  "value_item", "basic_value_item", "value_item_range", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,    43,    45,    42,    47,   289,    94,
-     290,    61,    40,    41,    91,    44,    93,   123,   125
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    49,    50,    50,    51,    51,    52,    52,    52,    52,
-      52,    52,    52,    52,    52,    53,    53,    54,    54,    55,
-      55,    55,    55,    56,    56,    57,    57,    58,    58,    59,
-      59,    60,    60,    60,    60,    60,    60,    60,    61,    61,
-      60,    60,    60,    60,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    63,    63,    64,    64,    64,
-      64,    60,    62,    64,    65,    65,    66,    66,    67,    68,
-      68,    68,    69,    69,    69,    70,    70,    71,    71,    71,
-      72,    72,    72,    72,    72,    73,    73,    73,    73,    74,
-      74,    74
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     2,     2,     2,     0,     1,     1,     1,
-       1,     2,     3,     3,     3,     1,     1,     2,     2,     1,
-       1,     3,     3,     1,     2,     1,     2,     1,     1,     1,
-       1,     2,     3,     3,     3,     3,     2,     2,     1,     1,
-       2,     3,     3,     3,     1,     1,     2,     3,     3,     3,
-       3,     3,     2,     3,     3,     1,     2,     7,     3,     2,
-       3,     1,     1,     1,     1,     2,     0,     2,     2,     0,
-       1,     3,     1,     2,     3,     1,     3,     1,     2,     3,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
-       3,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     0,     1,     0,    15,    44,    45,    29,    30,     0,
-      62,    61,    63,    39,    66,    38,     0,     0,     0,     0,
-       3,     0,     7,    16,    10,     9,    20,     0,     0,    19,
-       5,    17,     0,    37,    30,    36,     0,    59,    64,    44,
-      39,     0,    31,     0,     0,    52,     0,    20,     0,    19,
-      23,    25,     0,    27,    28,     0,     4,    18,    66,    11,
-       0,     0,    46,     0,    40,    66,    66,     0,     0,     0,
-       0,     0,     0,     0,    12,    13,    14,    60,    69,    65,
-      67,     0,     0,    46,    21,    34,    54,    58,    24,    26,
-       0,    22,    33,    32,     0,    85,    86,    87,    42,    75,
-      77,    88,    41,    47,    43,    35,    48,    49,    50,    51,
-      53,     0,    44,    45,     0,     0,     0,     0,    55,    80,
-       0,    82,    83,    81,    68,    70,    72,    84,     0,     0,
-       0,     0,     0,    78,    44,    45,     0,    56,     0,    73,
-       0,    76,    89,    90,    91,    79,    71,    74,     0,    57
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     1,    20,    21,    22,    23,    24,    95,    96,    55,
-      97,   119,    27,    28,   122,   123,    37,    38,    80,   124,
-     125,   102,    99,   126,   100,   101
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -93
-static const yytype_int16 yypact[] =
-{
-     -93,   155,   -93,    10,    19,    26,   -93,   -93,    -3,    73,
-     -93,   -93,   -93,    22,   -93,   -93,   356,   372,   317,    11,
-     -93,    79,   -93,    86,    70,   317,    29,   384,   180,   -93,
-     -93,   -93,   342,   -93,   -93,   -93,   356,   -93,     6,   -93,
-     -93,   356,   -93,   372,   -10,    57,   -20,   -17,   256,    54,
-     -93,   -93,    88,   -93,   -93,    55,   -93,   -93,   -93,    70,
-     356,   356,   197,   174,   -93,   -93,   -93,   372,   372,   372,
-     372,   372,   372,   342,    29,   180,   -93,    29,   221,   -93,
-     -93,   -17,   223,   -93,   -93,   -93,   -93,   -93,   -93,   -93,
-      11,   -93,    69,   -93,    78,    90,    94,   -93,   -93,   244,
-     -93,   -93,   -93,   -93,   -93,   267,    36,    36,    57,    57,
-      57,    54,    95,    96,   375,   303,    90,    94,   -93,    29,
-     392,   267,   -93,   -93,   -93,   263,   -93,   -93,    71,    35,
-      11,    11,    78,   -93,   105,   106,   178,   174,   303,   -93,
-      11,   -93,   -93,   -93,   -93,   -93,   -93,   -93,    80,   -93
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-     -93,   -93,   -93,   -93,   -93,   -93,   -13,     0,    14,   -81,
-      -1,    87,    -4,   -16,   -93,     3,   -36,   -93,   -93,   -93,
-      12,    81,    39,   -91,   -92,   -67
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -27
-static const yytype_int16 yytable[] =
-{
-      25,    45,    48,    58,    29,    46,    83,   133,    35,   128,
-      65,   127,    59,    44,    60,    61,    75,    50,    51,    53,
-      30,    49,    91,    84,    31,    48,    85,    82,    29,   103,
-     104,    78,    79,    54,   139,    76,    -8,   133,    32,    44,
-     145,    50,    51,     7,    34,   139,    52,   147,   127,    36,
-     144,   105,   106,   107,   108,   109,   110,    48,   127,   148,
-      60,    61,   121,    44,    44,    44,    44,    44,    44,   127,
-      52,   127,    70,    71,   120,    72,   111,   118,   116,    33,
-     132,     7,    34,   141,    50,    51,     7,    34,    26,    56,
-      53,    57,   117,    58,    88,    89,    72,    87,    45,   121,
-      90,    61,   130,    42,    54,    47,   131,   -23,   -25,   121,
-      44,   120,    26,    52,   118,   116,   140,   -24,   -26,    74,
-     121,   120,   121,    77,   118,   116,   149,   136,    81,   117,
-     142,    53,   120,   129,   120,   118,   116,   118,   116,   117,
-      53,     0,     0,    98,   143,    54,     0,    92,    93,     0,
-     117,     0,   117,     0,    54,     2,     3,     0,     0,     4,
-      81,     5,     6,     7,     8,    -6,     9,     0,    10,    11,
-      12,     0,     0,    13,     0,     0,     0,    14,     0,    15,
-      50,    51,     7,    34,   112,   113,     7,    34,    16,     9,
-      17,    10,    11,    12,     0,     0,    13,    18,     0,    19,
-      14,     0,    15,    50,    51,     7,    34,     0,    67,    52,
-       0,    16,     0,   114,    68,    69,    70,    71,     0,    72,
-      73,    94,    19,   138,     0,     0,   146,   112,   113,     7,
-      34,     0,     9,     0,    10,    11,    12,     0,     0,    13,
-       0,     0,     0,    14,    94,    15,     0,     0,     0,     0,
-      50,    51,     7,    34,    16,     0,   114,    68,    69,    70,
-      71,     0,    72,    73,     0,    19,    86,     0,   115,   112,
-     113,     7,    34,     0,     9,     0,    10,    11,    12,    52,
-       0,    13,     0,     0,    67,    14,     0,    15,     0,   132,
-      68,    69,    70,    71,     0,    72,    16,     0,   114,    86,
-       0,    68,    69,    70,    71,    73,    72,    19,   138,   112,
-     113,     7,    34,     0,     9,     0,    10,    11,    12,     0,
-       0,    13,     0,    39,     6,    14,     0,    15,     9,     0,
-      10,    11,    12,     0,     0,    13,    16,     0,   114,    14,
-       0,    15,     0,     0,     0,    73,     0,    19,    39,     6,
-      16,     0,    17,     9,     0,    10,    11,    12,     0,    18,
-      13,    19,    39,     6,    14,     0,    15,     9,     0,    10,
-      11,     0,     0,     0,    40,    16,     0,    17,    39,     6,
-      15,   134,   135,     0,    73,    10,    19,     0,    10,    16,
-      40,    17,     0,    40,     0,     0,    15,     0,    41,    15,
-      62,    63,     0,    64,    65,    66,     0,    17,    62,   137,
-      17,    64,    65,    66,    43,     0,     0,    43
-};
-
-static const yytype_int16 yycheck[] =
-{
-       1,    17,    18,    23,     1,    18,    16,    99,     9,    90,
-      20,    78,    25,    17,    31,    32,    32,     6,     7,    19,
-      10,    18,    58,    43,     5,    41,    43,    43,    25,    65,
-      66,    25,    26,    19,   125,    32,    10,   129,    41,    43,
-     132,     6,     7,     8,     9,   136,    35,   138,   115,    27,
-     131,    67,    68,    69,    70,    71,    72,    73,   125,   140,
-      31,    32,    78,    67,    68,    69,    70,    71,    72,   136,
-      35,   138,    36,    37,    78,    39,    73,    78,    78,     6,
-      45,     8,     9,    48,     6,     7,     8,     9,     1,    10,
-      90,     5,    78,    23,     6,     7,    39,    43,   114,   115,
-      45,    32,    12,    16,    90,    18,    12,    12,    12,   125,
-     114,   115,    25,    35,   115,   115,    45,    12,    12,    32,
-     136,   125,   138,    36,   125,   125,    46,   115,    41,   115,
-     130,   131,   136,    94,   138,   136,   136,   138,   138,   125,
-     140,    -1,    -1,    62,   130,   131,    -1,    60,    61,    -1,
-     136,    -1,   138,    -1,   140,     0,     1,    -1,    -1,     4,
-      73,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
-      15,    -1,    -1,    18,    -1,    -1,    -1,    22,    -1,    24,
-       6,     7,     8,     9,     6,     7,     8,     9,    33,    11,
-      35,    13,    14,    15,    -1,    -1,    18,    42,    -1,    44,
-      22,    -1,    24,     6,     7,     8,     9,    -1,    28,    35,
-      -1,    33,    -1,    35,    34,    35,    36,    37,    -1,    39,
-      42,    47,    44,    45,    -1,    -1,    48,     6,     7,     8,
-       9,    -1,    11,    -1,    13,    14,    15,    -1,    -1,    18,
-      -1,    -1,    -1,    22,    47,    24,    -1,    -1,    -1,    -1,
-       6,     7,     8,     9,    33,    -1,    35,    34,    35,    36,
-      37,    -1,    39,    42,    -1,    44,    43,    -1,    47,     6,
-       7,     8,     9,    -1,    11,    -1,    13,    14,    15,    35,
-      -1,    18,    -1,    -1,    28,    22,    -1,    24,    -1,    45,
-      34,    35,    36,    37,    -1,    39,    33,    -1,    35,    43,
-      -1,    34,    35,    36,    37,    42,    39,    44,    45,     6,
-       7,     8,     9,    -1,    11,    -1,    13,    14,    15,    -1,
-      -1,    18,    -1,     6,     7,    22,    -1,    24,    11,    -1,
-      13,    14,    15,    -1,    -1,    18,    33,    -1,    35,    22,
-      -1,    24,    -1,    -1,    -1,    42,    -1,    44,     6,     7,
-      33,    -1,    35,    11,    -1,    13,    14,    15,    -1,    42,
-      18,    44,     6,     7,    22,    -1,    24,    11,    -1,    13,
-      14,    -1,    -1,    -1,    18,    33,    -1,    35,     6,     7,
-      24,     6,     7,    -1,    42,    13,    44,    -1,    13,    33,
-      18,    35,    -1,    18,    -1,    -1,    24,    -1,    42,    24,
-      16,    17,    -1,    19,    20,    21,    -1,    35,    16,    17,
-      35,    19,    20,    21,    42,    -1,    -1,    42
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    50,     0,     1,     4,     6,     7,     8,     9,    11,
-      13,    14,    15,    18,    22,    24,    33,    35,    42,    44,
-      51,    52,    53,    54,    55,    59,    60,    61,    62,    64,
-      10,     5,    41,     6,     9,    59,    27,    65,    66,     6,
-      18,    42,    60,    42,    61,    62,    55,    60,    62,    64,
-       6,     7,    35,    56,    57,    58,    10,     5,    23,    55,
-      31,    32,    16,    17,    19,    20,    21,    28,    34,    35,
-      36,    37,    39,    42,    60,    62,    64,    60,    25,    26,
-      67,    60,    62,    16,    43,    43,    43,    43,     6,     7,
-      45,    65,    60,    60,    47,    56,    57,    59,    70,    71,
-      73,    74,    70,    65,    65,    62,    62,    62,    62,    62,
-      62,    64,     6,     7,    35,    47,    56,    57,    59,    60,
-      61,    62,    63,    64,    68,    69,    72,    74,    58,    71,
-      12,    12,    45,    73,     6,     7,    69,    17,    45,    72,
-      45,    48,    56,    57,    58,    73,    48,    72,    58,    46
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (scanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, scanner)
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value, scanner); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t                 scanner)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    yyscan_t                 scanner;
-#endif
-{
-  if (!yyvaluep)
-    return;
-  YYUSE (scanner);
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t                 scanner)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, scanner)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-    yyscan_t                 scanner;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule, yyscan_t                 scanner)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule, scanner)
-    YYSTYPE *yyvsp;
-    int yyrule;
-    yyscan_t                 scanner;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      , scanner);
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule, scanner); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t                 scanner)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, scanner)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-    yyscan_t                 scanner;
-#endif
-{
-  YYUSE (yyvaluep);
-  YYUSE (scanner);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-      case 5: /* "HELP_TOPIC" */
-#line 161 "parser.y"
-       { free((yyvaluep->str));                     };
-#line 1317 "parser.c"
-       break;
-      case 8: /* "STR" */
-#line 161 "parser.y"
-       { free((yyvaluep->str));                     };
-#line 1322 "parser.c"
-       break;
-      case 9: /* "IDENTIFIER" */
-#line 161 "parser.y"
-       { free((yyvaluep->str));                     };
-#line 1327 "parser.c"
-       break;
-      case 25: /* "PARAM" */
-#line 162 "parser.y"
-       { if((yyvaluep->str)) free((yyvaluep->str));              };
-#line 1332 "parser.c"
-       break;
-      case 28: /* "CMP_OP" */
-#line 161 "parser.y"
-       { free((yyvaluep->str));                     };
-#line 1337 "parser.c"
-       break;
-      case 51: /* "command" */
-#line 163 "parser.y"
-       { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1342 "parser.c"
-       break;
-      case 52: /* "cmd_plain" */
-#line 163 "parser.y"
-       { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1347 "parser.c"
-       break;
-      case 55: /* "selection" */
-#line 164 "parser.y"
-       { _gmx_selelem_free_chain((yyvaluep->sel));  };
-#line 1352 "parser.c"
-       break;
-      case 59: /* "string" */
-#line 161 "parser.y"
-       { free((yyvaluep->str));                     };
-#line 1357 "parser.c"
-       break;
-      case 60: /* "sel_expr" */
-#line 165 "parser.y"
-       { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1362 "parser.c"
-       break;
-      case 62: /* "num_expr" */
-#line 165 "parser.y"
-       { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1367 "parser.c"
-       break;
-      case 63: /* "str_expr" */
-#line 165 "parser.y"
-       { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1372 "parser.c"
-       break;
-      case 64: /* "pos_expr" */
-#line 165 "parser.y"
-       { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1377 "parser.c"
-       break;
-      case 65: /* "method_params" */
-#line 166 "parser.y"
-       { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1382 "parser.c"
-       break;
-      case 66: /* "method_param_list" */
-#line 166 "parser.y"
-       { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1387 "parser.c"
-       break;
-      case 67: /* "method_param" */
-#line 166 "parser.y"
-       { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1392 "parser.c"
-       break;
-      case 68: /* "value_list" */
-#line 167 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1397 "parser.c"
-       break;
-      case 69: /* "value_list_contents" */
-#line 167 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1402 "parser.c"
-       break;
-      case 70: /* "basic_value_list" */
-#line 168 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1407 "parser.c"
-       break;
-      case 71: /* "basic_value_list_contents" */
-#line 168 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1412 "parser.c"
-       break;
-      case 72: /* "value_item" */
-#line 167 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1417 "parser.c"
-       break;
-      case 73: /* "basic_value_item" */
-#line 168 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1422 "parser.c"
-       break;
-      case 74: /* "value_item_range" */
-#line 167 "parser.y"
-       { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1427 "parser.c"
-       break;
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (yyscan_t                 scanner);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (yyscan_t                 scanner)
-#else
-int
-yyparse (scanner)
-    yyscan_t                 scanner;
-#endif
-#endif
-{
-  /* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 182 "parser.y"
-    { (yyval.sel) = NULL ;}
-    break;
-
-  case 3:
-#line 184 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
-                 if (_gmx_sel_parser_should_finish(scanner))
-                     YYACCEPT;
-             ;}
-    break;
-
-  case 4:
-#line 192 "parser.y"
-    { (yyval.sel) = (yyvsp[(1) - (2)].sel); ;}
-    break;
-
-  case 5:
-#line 194 "parser.y"
-    {
-                 (yyval.sel) = NULL;
-                 _gmx_selparser_error("invalid selection '%s'",
-                                      _gmx_sel_lexer_pselstr(scanner));
-                 _gmx_sel_lexer_clear_method_stack(scanner);
-                 if (_gmx_sel_is_lexer_interactive(scanner))
-                 {
-                     _gmx_sel_lexer_clear_pselstr(scanner);
-                     yyerrok;
-                 }
-                 else
-                 {
-                     YYABORT;
-                 }
-             ;}
-    break;
-
-  case 6:
-#line 213 "parser.y"
-    {
-                 (yyval.sel) = NULL;
-                 _gmx_sel_handle_empty_cmd(scanner);
-             ;}
-    break;
-
-  case 7:
-#line 217 "parser.y"
-    { (yyval.sel) = NULL; ;}
-    break;
-
-  case 8:
-#line 219 "parser.y"
-    {
-                 t_selelem *s, *p;
-                 s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
-                 if (s == NULL) YYERROR;
-                 p = _gmx_sel_init_position(s, NULL, scanner);
-                 if (p == NULL) YYERROR;
-                 (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
-             ;}
-    break;
-
-  case 9:
-#line 228 "parser.y"
-    {
-                 t_selelem *s, *p;
-                 s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
-                 free((yyvsp[(1) - (1)].str));
-                 if (s == NULL) YYERROR;
-                 p = _gmx_sel_init_position(s, NULL, scanner);
-                 if (p == NULL) YYERROR;
-                 (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
-             ;}
-    break;
-
-  case 10:
-#line 238 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner); ;}
-    break;
-
-  case 11:
-#line 240 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);   ;}
-    break;
-
-  case 12:
-#line 242 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
-    break;
-
-  case 13:
-#line 244 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
-    break;
-
-  case 14:
-#line 246 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
-    break;
-
-  case 15:
-#line 251 "parser.y"
-    { _gmx_sel_handle_help_cmd(NULL, scanner); ;}
-    break;
-
-  case 17:
-#line 255 "parser.y"
-    { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
-    break;
-
-  case 18:
-#line 256 "parser.y"
-    { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
-    break;
-
-  case 19:
-#line 260 "parser.y"
-    { (yyval.sel) = (yyvsp[(1) - (1)].sel); ;}
-    break;
-
-  case 20:
-#line 262 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 21:
-#line 266 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
-    break;
-
-  case 22:
-#line 268 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 23:
-#line 279 "parser.y"
-    { (yyval.r) = (yyvsp[(1) - (1)].i); ;}
-    break;
-
-  case 24:
-#line 280 "parser.y"
-    { (yyval.r) = -(yyvsp[(2) - (2)].i); ;}
-    break;
-
-  case 25:
-#line 284 "parser.y"
-    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
-    break;
-
-  case 26:
-#line 285 "parser.y"
-    { (yyval.r) = -(yyvsp[(2) - (2)].r); ;}
-    break;
-
-  case 27:
-#line 288 "parser.y"
-    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
-    break;
-
-  case 28:
-#line 289 "parser.y"
-    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
-    break;
-
-  case 29:
-#line 292 "parser.y"
-    { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
-    break;
-
-  case 30:
-#line 293 "parser.y"
-    { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
-    break;
-
-  case 31:
-#line 302 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
-                 (yyval.sel)->u.boolt = BOOL_NOT;
-                 (yyval.sel)->child = (yyvsp[(2) - (2)].sel);
-             ;}
-    break;
-
-  case 32:
-#line 308 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
-                 (yyval.sel)->u.boolt = BOOL_AND;
-                 (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
-             ;}
-    break;
-
-  case 33:
-#line 314 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
-                 (yyval.sel)->u.boolt = BOOL_OR;
-                 (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
-             ;}
-    break;
-
-  case 34:
-#line 325 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
-    break;
-
-  case 35:
-#line 330 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 36:
-#line 338 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
-                 free((yyvsp[(2) - (2)].str));
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 37:
-#line 344 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 38:
-#line 351 "parser.y"
-    { (yyval.str) = NULL; ;}
-    break;
-
-  case 39:
-#line 352 "parser.y"
-    { (yyval.str) = (yyvsp[(1) - (1)].str);   ;}
-    break;
-
-  case 40:
-#line 357 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 41:
-#line 362 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 42:
-#line 367 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 43:
-#line 375 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 44:
-#line 387 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
-                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
-                 (yyval.sel)->v.u.i[0] = (yyvsp[(1) - (1)].i);
-             ;}
-    break;
-
-  case 45:
-#line 394 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
-                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
-                 (yyval.sel)->v.u.r[0] = (yyvsp[(1) - (1)].r);
-             ;}
-    break;
-
-  case 46:
-#line 404 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 47:
-#line 409 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 48:
-#line 417 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner); ;}
-    break;
-
-  case 49:
-#line 419 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner); ;}
-    break;
-
-  case 50:
-#line 421 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner); ;}
-    break;
-
-  case 51:
-#line 423 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner); ;}
-    break;
-
-  case 52:
-#line 425 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner); ;}
-    break;
-
-  case 53:
-#line 427 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner); ;}
-    break;
-
-  case 54:
-#line 428 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
-    break;
-
-  case 55:
-#line 436 "parser.y"
-    {
-                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
-                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
-                 (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
-             ;}
-    break;
-
-  case 56:
-#line 443 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 57:
-#line 455 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
-    break;
-
-  case 58:
-#line 459 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
-    break;
-
-  case 59:
-#line 464 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 60:
-#line 472 "parser.y"
-    {
-                 (yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
-                 if ((yyval.sel) == NULL) YYERROR;
-             ;}
-    break;
-
-  case 61:
-#line 483 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 62:
-#line 487 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 63:
-#line 491 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 64:
-#line 500 "parser.y"
-    { (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); ;}
-    break;
-
-  case 65:
-#line 502 "parser.y"
-    { (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); ;}
-    break;
-
-  case 66:
-#line 506 "parser.y"
-    { (yyval.param) = NULL;              ;}
-    break;
-
-  case 67:
-#line 508 "parser.y"
-    { (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); ;}
-    break;
-
-  case 68:
-#line 513 "parser.y"
-    {
-                 (yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
-                 (yyval.param)->value = process_value_list((yyvsp[(2) - (2)].val), &(yyval.param)->nval);
-             ;}
-    break;
-
-  case 69:
-#line 519 "parser.y"
-    { (yyval.val) = NULL; ;}
-    break;
-
-  case 70:
-#line 520 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val);   ;}
-    break;
-
-  case 71:
-#line 521 "parser.y"
-    { (yyval.val) = (yyvsp[(2) - (3)].val);   ;}
-    break;
-
-  case 72:
-#line 525 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
-    break;
-
-  case 73:
-#line 527 "parser.y"
-    { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
-    break;
-
-  case 74:
-#line 529 "parser.y"
-    { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
-    break;
-
-  case 75:
-#line 533 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
-    break;
-
-  case 76:
-#line 534 "parser.y"
-    { (yyval.val) = (yyvsp[(2) - (3)].val); ;}
-    break;
-
-  case 77:
-#line 538 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
-    break;
-
-  case 78:
-#line 540 "parser.y"
-    { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
-    break;
-
-  case 79:
-#line 542 "parser.y"
-    { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
-    break;
-
-  case 80:
-#line 546 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 81:
-#line 548 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 82:
-#line 550 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 83:
-#line 552 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
-    break;
-
-  case 84:
-#line 553 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
-    break;
-
-  case 85:
-#line 558 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
-                 (yyval.val)->u.i.i1 = (yyval.val)->u.i.i2 = (yyvsp[(1) - (1)].r);
-             ;}
-    break;
-
-  case 86:
-#line 563 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
-                 (yyval.val)->u.r.r1 = (yyval.val)->u.r.r2 = (yyvsp[(1) - (1)].r);
-             ;}
-    break;
-
-  case 87:
-#line 568 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
-                 (yyval.val)->u.s = (yyvsp[(1) - (1)].str);
-             ;}
-    break;
-
-  case 88:
-#line 572 "parser.y"
-    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
-    break;
-
-  case 89:
-#line 577 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
-                 (yyval.val)->u.i.i1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.i.i2 = (yyvsp[(3) - (3)].r);
-             ;}
-    break;
-
-  case 90:
-#line 582 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
-                 (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
-             ;}
-    break;
-
-  case 91:
-#line 587 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
-                 (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
-             ;}
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 2309 "parser.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (scanner, YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (scanner, yymsg);
-         }
-       else
-         {
-           yyerror (scanner, YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval, scanner);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp, scanner);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (scanner, YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval, scanner);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp, scanner);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 593 "parser.y"
-
-
-static t_selexpr_value *
-process_value_list(t_selexpr_value *values, int *nr)
-{
-    t_selexpr_value *val, *pval, *nval;
-
-    /* Count values (if needed) and reverse list */
-    if (nr)
-    {
-        *nr  = 0;
-    }
-    pval = NULL;
-    val  = values;
-    while (val)
-    {
-        if (nr)
-        {
-            ++*nr;
-        }
-        nval = val->next;
-        val->next = pval;
-        pval = val;
-        val = nval;
-    }
-    values = pval;
-
-    return values;
-}
-
-static t_selexpr_param *
-process_param_list(t_selexpr_param *params)
-{
-    t_selexpr_param *par, *ppar, *npar;
-
-    /* Reverse list */
-    ppar = NULL;
-    par  = params;
-    while (par)
-    {
-        npar = par->next;
-        par->next = ppar;
-        ppar = par;
-        par = npar;
-    }
-    params = ppar;
-
-    return params;
-}
-
-static void
-yyerror(yyscan_t scanner, char const *s)
-{
-    _gmx_selparser_error("%s", s);
-}
-
-
-
diff --git a/src/gmxlib/selection/parser.h b/src/gmxlib/selection/parser.h
deleted file mode 100644 (file)
index e240cb3..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   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, 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.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     INVALID = 258,
-     HELP = 259,
-     HELP_TOPIC = 260,
-     TOK_INT = 261,
-     TOK_REAL = 262,
-     STR = 263,
-     IDENTIFIER = 264,
-     CMD_SEP = 265,
-     GROUP = 266,
-     TO = 267,
-     VARIABLE_NUMERIC = 268,
-     VARIABLE_GROUP = 269,
-     VARIABLE_POS = 270,
-     KEYWORD_NUMERIC = 271,
-     KEYWORD_STR = 272,
-     KEYWORD_POS = 273,
-     KEYWORD_GROUP = 274,
-     METHOD_NUMERIC = 275,
-     METHOD_GROUP = 276,
-     METHOD_POS = 277,
-     MODIFIER = 278,
-     EMPTY_POSMOD = 279,
-     PARAM = 280,
-     END_OF_METHOD = 281,
-     OF = 282,
-     CMP_OP = 283,
-     PARAM_REDUCT = 284,
-     XOR = 285,
-     OR = 286,
-     AND = 287,
-     NOT = 288,
-     UNARY_NEG = 289,
-     NUM_REDUCT = 290
-   };
-#endif
-/* Tokens.  */
-#define INVALID 258
-#define HELP 259
-#define HELP_TOPIC 260
-#define TOK_INT 261
-#define TOK_REAL 262
-#define STR 263
-#define IDENTIFIER 264
-#define CMD_SEP 265
-#define GROUP 266
-#define TO 267
-#define VARIABLE_NUMERIC 268
-#define VARIABLE_GROUP 269
-#define VARIABLE_POS 270
-#define KEYWORD_NUMERIC 271
-#define KEYWORD_STR 272
-#define KEYWORD_POS 273
-#define KEYWORD_GROUP 274
-#define METHOD_NUMERIC 275
-#define METHOD_GROUP 276
-#define METHOD_POS 277
-#define MODIFIER 278
-#define EMPTY_POSMOD 279
-#define PARAM 280
-#define END_OF_METHOD 281
-#define OF 282
-#define CMP_OP 283
-#define PARAM_REDUCT 284
-#define XOR 285
-#define OR 286
-#define AND 287
-#define NOT 288
-#define UNARY_NEG 289
-#define NUM_REDUCT 290
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 62 "parser.y"
-{
-    int                         i;
-    real                        r;
-    char                       *str;
-    struct gmx_ana_selmethod_t *meth;
-
-    struct t_selelem           *sel;
-
-    struct t_selexpr_value     *val;
-    struct t_selexpr_param     *param;
-}
-/* Line 1489 of yacc.c.  */
-#line 131 "parser.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
diff --git a/src/gmxlib/selection/parser.y b/src/gmxlib/selection/parser.y
deleted file mode 100644 (file)
index 551e0cf..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Grammar description and parser for the selection language.
- */
-%{
-/*! \internal \file parser.c
- * \brief Generated (from parser.y by Bison) parser for the selection language.
- */
-/*! \internal \file parser.h
- * \brief Generated (from parser.y by Bison) parser include file.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <string2.h>
-
-#include "parsetree.h"
-#include "selelem.h"
-
-#include "scanner.h"
-
-static t_selexpr_value *
-process_value_list(t_selexpr_value *values, int *nr);
-static t_selexpr_param *
-process_param_list(t_selexpr_param *params);
-
-static void
-yyerror(yyscan_t, char const *s);
-%}
-
-%union{
-    int                         i;
-    real                        r;
-    char                       *str;
-    struct gmx_ana_selmethod_t *meth;
-
-    struct t_selelem           *sel;
-
-    struct t_selexpr_value     *val;
-    struct t_selexpr_param     *param;
-};
-/* NOTE: The Intel compiler seems to report warnings for the above line about
- * "definition at end of file not followed by a semicolon or a declarator".
- * This is due to the compiler misinterpreting #line directives in the
- * generated files parser.c/.h, and changing them would be more trouble than
- * it's worth. */
-
-/* Invalid token to report lexer errors */
-%token INVALID
-
-/* Tokens for help requests */
-%token         HELP
-%token <str>   HELP_TOPIC
-
-/* Simple input tokens */
-%token <i>     TOK_INT
-%token <r>     TOK_REAL
-%token <str>   STR
-%token <str>   IDENTIFIER
-%token         CMD_SEP
-
-/* Simple keyword tokens */
-%token         GROUP
-%token         TO
-
-/* Variable tokens */
-%token <sel>   VARIABLE_NUMERIC
-%token <sel>   VARIABLE_GROUP
-%token <sel>   VARIABLE_POS
-
-/* Selection method tokens */
-%token <meth>  KEYWORD_NUMERIC
-%token <meth>  KEYWORD_STR
-%token <str>   KEYWORD_POS
-%token <meth>  KEYWORD_GROUP
-%token <meth>  METHOD_NUMERIC
-%token <meth>  METHOD_GROUP
-%token <meth>  METHOD_POS
-%token <meth>  MODIFIER
-/* Empty token that should precede any non-position KEYWORD/METHOD token that
- * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
- * conflicts that appear when a lookahead token would require a reduction of
- * a rule with empty RHS before shifting, and there is an alternative reduction
- * available. Replacing the empty RHS with a dummy token makes these conflicts
- * only shift/reduce conflicts. Another alternative would be to remove the
- * pos_mod non-terminal completely and split each rule that uses it into two,
- * but this would require duplicating six rules in the grammar. */
-%token         EMPTY_POSMOD
-
-%token <str>   PARAM
-%token         END_OF_METHOD
-
-%token          OF
-/* Comparison operators have lower precedence than parameter reduction
- * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
- * parenthesis. */
-%nonassoc <str> CMP_OP
-/* A dummy token that determines the precedence of parameter reduction */
-%nonassoc       PARAM_REDUCT
-/* Boolean operator tokens */
-%left           OR XOR
-%left           AND
-%left           NOT
-/* Arithmetic operator tokens */
-%left           '+' '-'
-%left           '*' '/'
-%right          UNARY_NEG   /* Dummy token for unary negation precedence */
-%right          '^'
-%nonassoc       NUM_REDUCT  /* Dummy token for numerical keyword reduction precedence */
-
-/* Simple non-terminals */
-%type <r>     integer_number
-%type <r>     real_number number
-%type <str>   string
-%type <str>   pos_mod
-
-/* Expression non-terminals */
-%type <sel>   commands command cmd_plain
-%type <sel>   selection
-%type <sel>   sel_expr
-%type <sel>   num_expr
-%type <sel>   str_expr
-%type <sel>   pos_expr
-
-/* Parameter/value non-terminals */
-%type <param> method_params method_param_list method_param
-%type <val>   value_list value_list_contents value_item value_item_range
-%type <val>   basic_value_list basic_value_list_contents basic_value_item
-
-%destructor { free($$);                     } HELP_TOPIC STR IDENTIFIER CMP_OP string
-%destructor { if($$) free($$);              } PARAM
-%destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
-%destructor { _gmx_selelem_free_chain($$);  } selection
-%destructor { _gmx_selelem_free($$);        } sel_expr num_expr str_expr pos_expr
-%destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
-%destructor { _gmx_selexpr_free_values($$); } value_list value_list_contents value_item value_item_range
-%destructor { _gmx_selexpr_free_values($$); } basic_value_list basic_value_list_contents basic_value_item
-
-%expect 50
-%debug
-%pure-parser
-
-/* If you change these, you also need to update the prototype in parsetree.c. */
-%name-prefix="_gmx_sel_yyb"
-%parse-param { yyscan_t                 scanner }
-%lex-param   { yyscan_t                 scanner }
-
-%%
-
-/* The start rule: allow one or more commands */
-commands:    /* empty */        { $$ = NULL }
-           | commands command
-             {
-                 $$ = _gmx_sel_append_selection($2, $1, scanner);
-                 if (_gmx_sel_parser_should_finish(scanner))
-                     YYACCEPT;
-             }
-;
-
-/* A command is formed from an actual command and a separator */
-command:     cmd_plain CMD_SEP  { $$ = $1; }
-           | error CMD_SEP
-             {
-                 $$ = NULL;
-                 _gmx_selparser_error("invalid selection '%s'",
-                                      _gmx_sel_lexer_pselstr(scanner));
-                 _gmx_sel_lexer_clear_method_stack(scanner);
-                 if (_gmx_sel_is_lexer_interactive(scanner))
-                 {
-                     _gmx_sel_lexer_clear_pselstr(scanner);
-                     yyerrok;
-                 }
-                 else
-                 {
-                     YYABORT;
-                 }
-             }
-;
-
-/* Commands can be selections or variable assignments */
-cmd_plain:   /* empty */
-             {
-                 $$ = NULL;
-                 _gmx_sel_handle_empty_cmd(scanner);
-             }
-           | help_request       { $$ = NULL; }
-           | TOK_INT
-             {
-                 t_selelem *s, *p;
-                 s = _gmx_sel_init_group_by_id($1, scanner);
-                 if (s == NULL) YYERROR;
-                 p = _gmx_sel_init_position(s, NULL, scanner);
-                 if (p == NULL) YYERROR;
-                 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
-             }
-           | string
-             {
-                 t_selelem *s, *p;
-                 s = _gmx_sel_init_group_by_name($1, scanner);
-                 free($1);
-                 if (s == NULL) YYERROR;
-                 p = _gmx_sel_init_position(s, NULL, scanner);
-                 if (p == NULL) YYERROR;
-                 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
-             }
-           | selection
-             { $$ = _gmx_sel_init_selection(NULL, $1, scanner); }
-           | string selection
-             { $$ = _gmx_sel_init_selection($1, $2, scanner);   }
-           | IDENTIFIER '=' sel_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
-           | IDENTIFIER '=' num_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
-           | IDENTIFIER '=' pos_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
-;
-
-/* Help requests */
-help_request:
-             HELP                   { _gmx_sel_handle_help_cmd(NULL, scanner); }
-           | help_topic
-;
-
-help_topic:  HELP HELP_TOPIC        { _gmx_sel_handle_help_cmd($2, scanner); }
-           | help_topic HELP_TOPIC  { _gmx_sel_handle_help_cmd($2, scanner); }
-;
-
-/* Selection is made of an expression and zero or more modifiers */
-selection:   pos_expr           { $$ = $1; }
-           | sel_expr
-             {
-                 $$ = _gmx_sel_init_position($1, NULL, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-           | '(' selection ')'  { $$ = $2; }
-           | selection MODIFIER method_params
-             {
-                 $$ = _gmx_sel_init_modifier($2, $3, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/********************************************************************
- * BASIC NON-TERMINAL SYMBOLS
- ********************************************************************/
-
-integer_number:
-             TOK_INT            { $$ = $1; }
-           | '-' TOK_INT        { $$ = -$2; }
-;
-
-real_number:
-             TOK_REAL           { $$ = $1; }
-           | '-' TOK_REAL       { $$ = -$2; }
-;
-
-number:      integer_number     { $$ = $1; }
-           | real_number        { $$ = $1; }
-;
-
-string:      STR                { $$ = $1; }
-           | IDENTIFIER         { $$ = $1; }
-;
-
-/********************************************************************
- * ATOM SELECTION EXPRESSIONS
- ********************************************************************/
-
-/* Boolean expressions and grouping */
-sel_expr:    NOT sel_expr
-             {
-                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
-                 $$->u.boolt = BOOL_NOT;
-                 $$->child = $2;
-             }
-           | sel_expr AND sel_expr
-             {
-                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
-                 $$->u.boolt = BOOL_AND;
-                 $$->child = $1; $$->child->next = $3;
-             }
-           | sel_expr OR  sel_expr
-             {
-                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
-                 $$->u.boolt = BOOL_OR;
-                 $$->child = $1; $$->child->next = $3;
-             }
-/*           | sel_expr XOR sel_expr
-             {
-                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
-                 $$->u.boolt = BOOL_XOR;
-                 $$->child = $1; $$->child->next = $3;
-             }*/
-           | '(' sel_expr ')'   { $$ = $2; }
-;
-
-/* Numeric comparisons */
-sel_expr:    num_expr CMP_OP num_expr
-             {
-                 $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/* External groups */
-sel_expr:    GROUP string
-             {
-                 $$ = _gmx_sel_init_group_by_name($2, scanner);
-                 free($2);
-                 if ($$ == NULL) YYERROR;
-             }
-           | GROUP TOK_INT
-             {
-                 $$ = _gmx_sel_init_group_by_id($2, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/* Position modifiers for selection methods */
-pos_mod:     EMPTY_POSMOD       { $$ = NULL; }
-           | KEYWORD_POS        { $$ = $1;   }
-;
-
-/* Keyword selections */
-sel_expr:    pos_mod KEYWORD_GROUP
-             {
-                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-           | pos_mod KEYWORD_STR basic_value_list
-             {
-                 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-           | pos_mod KEYWORD_NUMERIC basic_value_list
-             {
-                 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/* Custom selection methods */
-sel_expr:    pos_mod METHOD_GROUP method_params
-             {
-                 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/********************************************************************
- * NUMERICAL EXPRESSIONS
- ********************************************************************/
-
-/* Basic numerical values */
-num_expr:    TOK_INT
-             {
-                 $$ = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype($$, INT_VALUE);
-                 _gmx_selvalue_reserve(&$$->v, 1);
-                 $$->v.u.i[0] = $1;
-             }
-           | TOK_REAL
-             {
-                 $$ = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype($$, REAL_VALUE);
-                 _gmx_selvalue_reserve(&$$->v, 1);
-                 $$->v.u.r[0] = $1;
-             }
-;
-
-/* Numeric selection methods */
-num_expr:    pos_mod KEYWORD_NUMERIC    %prec NUM_REDUCT
-             {
-                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-           | pos_mod METHOD_NUMERIC method_params
-             {
-                 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/* Arithmetic evaluation and grouping */
-num_expr:    num_expr '+' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
-           | num_expr '-' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
-           | num_expr '*' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
-           | num_expr '/' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
-           | '-' num_expr %prec UNARY_NEG
-             { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
-           | num_expr '^' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
-           | '(' num_expr ')'   { $$ = $2; }
-;
-
-/********************************************************************
- * STRING EXPRESSIONS
- ********************************************************************/
-
-str_expr:    string
-             {
-                 $$ = _gmx_selelem_create(SEL_CONST);
-                 _gmx_selelem_set_vtype($$, STR_VALUE);
-                 _gmx_selvalue_reserve(&$$->v, 1);
-                 $$->v.u.s[0] = $1;
-             }
-           | pos_mod KEYWORD_STR
-             {
-                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/********************************************************************
- * POSITION EXPRESSIONS
- ********************************************************************/
-
-/* Constant position expressions */
-pos_expr:    '[' number ',' number ',' number ']'
-             { $$ = _gmx_sel_init_const_position($2, $4, $6); }
-;
-
-/* Grouping of position expressions */
-pos_expr:    '(' pos_expr ')'   { $$ = $2; }
-;
-
-/* Expressions with a position value */
-pos_expr:    METHOD_POS method_params
-             {
-                 $$ = _gmx_sel_init_method($1, $2, NULL, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/* Evaluation of positions using a keyword */
-pos_expr:    KEYWORD_POS OF sel_expr    %prec PARAM_REDUCT
-             {
-                 $$ = _gmx_sel_init_position($3, $1, scanner);
-                 if ($$ == NULL) YYERROR;
-             }
-;
-
-/********************************************************************
- * VARIABLES
- ********************************************************************/
-
-sel_expr:    VARIABLE_GROUP
-             { $$ = _gmx_sel_init_variable_ref($1); }
-;
-
-num_expr:    VARIABLE_NUMERIC
-             { $$ = _gmx_sel_init_variable_ref($1); }
-;
-
-pos_expr:    VARIABLE_POS
-             { $$ = _gmx_sel_init_variable_ref($1); }
-;
-
-/********************************************************************
- * METHOD PARAMETERS
- ********************************************************************/
-
-method_params:
-             method_param_list
-             { $$ = process_param_list($1); }
-           | method_param_list END_OF_METHOD
-             { $$ = process_param_list($1); }
-;
-
-method_param_list:
-             /* empty */        { $$ = NULL;              }
-           | method_param_list method_param
-                                { $2->next = $1; $$ = $2; }
-;
-
-method_param:
-             PARAM value_list
-             {
-                 $$ = _gmx_selexpr_create_param($1);
-                 $$->value = process_value_list($2, &$$->nval);
-             }
-;
-
-value_list:  /* empty */                         { $$ = NULL; }
-           | value_list_contents                 { $$ = $1;   }
-           | '{' value_list_contents '}'         { $$ = $2;   }
-;
-
-value_list_contents:
-             value_item          { $$ = $1; }
-           | value_list_contents value_item
-                                 { $2->next = $1; $$ = $2; }
-           | value_list_contents ',' value_item
-                                 { $3->next = $1; $$ = $3; }
-;
-
-basic_value_list:
-             basic_value_list_contents           { $$ = $1; }
-           | '{' basic_value_list_contents '}'   { $$ = $2; }
-;
-
-basic_value_list_contents:
-             basic_value_item    { $$ = $1; }
-           | basic_value_list_contents basic_value_item
-                                 { $2->next = $1; $$ = $2; }
-           | basic_value_list_contents ',' basic_value_item
-                                 { $3->next = $1; $$ = $3; }
-;
-
-value_item:  sel_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
-           | pos_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
-           | num_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
-           | str_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
-           | value_item_range    { $$ = $1; }
-;
-
-basic_value_item:
-             integer_number      %prec PARAM_REDUCT
-             {
-                 $$ = _gmx_selexpr_create_value(INT_VALUE);
-                 $$->u.i.i1 = $$->u.i.i2 = $1;
-             }
-           | real_number         %prec PARAM_REDUCT
-             {
-                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
-                 $$->u.r.r1 = $$->u.r.r2 = $1;
-             }
-           | string              %prec PARAM_REDUCT
-             {
-                 $$ = _gmx_selexpr_create_value(STR_VALUE);
-                 $$->u.s = $1;
-             }
-           | value_item_range    { $$ = $1; }
-;
-
-value_item_range:
-             integer_number TO integer_number
-             {
-                 $$ = _gmx_selexpr_create_value(INT_VALUE);
-                 $$->u.i.i1 = $1; $$->u.i.i2 = $3;
-             }
-           | integer_number TO real_number
-             {
-                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
-                 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
-             }
-           | real_number TO number
-             {
-                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
-                 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
-             }
-;
-
-%%
-
-static t_selexpr_value *
-process_value_list(t_selexpr_value *values, int *nr)
-{
-    t_selexpr_value *val, *pval, *nval;
-
-    /* Count values (if needed) and reverse list */
-    if (nr)
-    {
-        *nr  = 0;
-    }
-    pval = NULL;
-    val  = values;
-    while (val)
-    {
-        if (nr)
-        {
-            ++*nr;
-        }
-        nval = val->next;
-        val->next = pval;
-        pval = val;
-        val = nval;
-    }
-    values = pval;
-
-    return values;
-}
-
-static t_selexpr_param *
-process_param_list(t_selexpr_param *params)
-{
-    t_selexpr_param *par, *ppar, *npar;
-
-    /* Reverse list */
-    ppar = NULL;
-    par  = params;
-    while (par)
-    {
-        npar = par->next;
-        par->next = ppar;
-        ppar = par;
-        par = npar;
-    }
-    params = ppar;
-
-    return params;
-}
-
-static void
-yyerror(yyscan_t scanner, char const *s)
-{
-    _gmx_selparser_error("%s", s);
-}
-
-
diff --git a/src/gmxlib/selection/parsetree.c b/src/gmxlib/selection/parsetree.c
deleted file mode 100644 (file)
index 2da5106..0000000
+++ /dev/null
@@ -1,1510 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions of in parsetree.h.
- */
-/*! \internal
- * \page selparser Selection parsing
- *
- * The selection parser is implemented in the following files:
- *  - scanner.l:
- *    Tokenizer implemented using Flex, splits the input into tokens
- *    (scanner.c and scanner_flex.h are generated from this file).
- *  - scanner.h, scanner_internal.h, scanner_internal.c:
- *    Helper functions for scanner.l and for interfacing between
- *    scanner.l and parser.y. Functions in scanner_internal.h are only
- *    used from scanner.l, while scanner.h is used from the parser.
- *  - symrec.h, symrec.c:
- *    Functions used by the tokenizer to handle the symbol table, i.e.,
- *    the recognized keywords. Some basic keywords are hardcoded into
- *    scanner.l, but all method and variable references go through the
- *    symbol table, as do position evaluation keywords.
- *  - parser.y:
- *    Semantic rules for parsing the grammar
- *    (parser.c and parser.h are generated from this file by Bison).
- *  - parsetree.h, parsetree.c:
- *    Functions called from actions in parser.y to construct the
- *    evaluation elements corresponding to different grammar elements.
- *    parsetree.c also defines the external interface of the parser,
- *    i.e., the \c gmx_ana_selcollection_parse_*() functions declared
- *    in selection.h.
- *  - params.c:
- *    Defines a function that processes the parameters of selection
- *    methods and initializes the children of the method element.
- *
- * The basic control flow in the parser is as follows: when a
- * fmx_ana_selcollection_parse_*() gets called, it performs some
- * initialization, and then calls the _gmx_sel_yyparse() function generated
- * by Bison. This function then calls _gmx_sel_yylex() to repeatedly read
- * tokens from the input (more complex tasks related to token recognition
- * and bookkeeping are done by functions in scanner_internal.c) and uses the
- * grammar rules to decide what to do with them. Whenever a grammar rule
- * matches, a corresponding function in parsetree.c is called to construct
- * either a temporary representation for the object or a \c t_selelem object
- * (some simple rules are handled internally in parser.y).
- * When a complete selection has been parsed, the functions in parsetree.c
- * also take care of updating the \c gmx_ana_selcollection_t structure
- * appropriately.
- *
- * The rest of this page describes the resulting \c t_selelem object tree.
- * Before the selections can be evaluated, this tree needs to be passed to
- * the selection compiler, which is described on a separate page:
- * \ref selcompiler
- *
- *
- * \section selparser_tree Element tree constructed by the parser
- *
- * The parser initializes the following fields in all selection elements:
- * \c t_selelem::name, \c t_selelem::type, \c t_selelem::v\c .type,
- * \c t_selelem::flags, \c t_selelem::child, \c t_selelem::next, and
- * \c t_selelem::refcount.
- * Some other fields are also initialized for particular element types as
- * discussed below.
- * Fields that are not initialized are set to zero, NULL, or other similar
- * value.
- *
- *
- * \subsection selparser_tree_root Root elements
- *
- * The parser creates a \ref SEL_ROOT selection element for each variable
- * assignment and each selection. However, there are two exceptions that do
- * not result in a \ref SEL_ROOT element (in these cases, only the symbol
- * table is modified):
- *  - Variable assignments that assign a variable to another variable.
- *  - Variable assignments that assign a non-group constant.
- *  .
- * The \ref SEL_ROOT elements are linked together in a chain in the same order
- * as in the input.
- *
- * The children of the \ref SEL_ROOT elements can be used to distinguish
- * the two types of root elements from each other:
- *  - For variable assignments, the first and only child is always
- *    a \ref SEL_SUBEXPR element.
- *  - For selections, the first child is a \ref SEL_EXPRESSION or a
- *    \ref SEL_MODIFIER element that evaluates the final positions (if the
- *    selection defines a constant position, the child is a \ref SEL_CONST).
- *    The rest of the children are \ref SEL_MODIFIER elements with
- *    \ref NO_VALUE, in the order given by the user.
- *  .
- * The name of the selection/variable is stored in \c t_selelem::cgrp\c .name.
- * It is set to either the name provided by the user or the selection string
- * for selections not explicitly named by the user.
- * \ref SEL_ROOT or \ref SEL_SUBEXPR elements do not appear anywhere else.
- *
- *
- * \subsection selparser_tree_const Constant elements
- *
- * \ref SEL_CONST elements are created for every constant that is required
- * for later evaluation.
- * Currently, \ref SEL_CONST elements can be present for
- *  - selections that consist of a constant position,
- *  - \ref GROUP_VALUE method parameters if provided using external index
- *    groups,
- *  .
- * For group-valued elements, the value is stored in \c t_selelem::cgrp;
- * other types of values are stored in \c t_selelem::v.
- * Constants that appear as parameters for selection methods are not present
- * in the selection tree unless they have \ref GROUP_VALUE.
- * \ref SEL_CONST elements have no children.
- *
- *
- * \subsection selparser_tree_method Method evaluation elements
- *
- * \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are treated very
- * similarly. The \c gmx_ana_selmethod_t structure corresponding to the
- * evaluation method is in \c t_selelem::method, and the method data in
- * \c t_selelem::mdata has been allocated using sel_datafunc().
- * If a non-standard reference position type was set, \c t_selelem::pc has
- * also been created, but only the type has been set.
- * All children of these elements are of the type \ref SEL_SUBEXPRREF, and
- * each describes a selection that needs to be evaluated to obtain a value
- * for one parameter of the method.
- * No children are present for parameters that were given a constant
- * non-\ref GROUP_VALUE value.
- * The children are sorted in the order in which the parameters appear in the
- * \ref gmx_ana_selmethod_t structure.
- *
- * In addition to actual selection keywords, \ref SEL_EXPRESSION elements
- * are used internally to implement numerical comparisons (e.g., "x < 5")
- * and keyword matching (e.g., "resnr 1 to 3" or "name CA").
- *
- *
- * \subsection selparser_tree_subexpr Subexpression elements
- *
- * \ref SEL_SUBEXPR elements only appear for variables, as described above.
- * \c t_selelem::name points to the name of the variable (from the
- * \ref SEL_ROOT element).
- * The element always has exactly one child, which represents the value of
- * the variable.
- * \ref SEL_SUBEXPR element is the only element type that can have
- * \c t_selelem::refcount different from 1.
- *
- * \ref SEL_SUBEXPRREF elements are used for two purposes:
- *  - Variable references that need to be evaluated (i.e., there is a
- *    \ref SEL_SUBEXPR element for the variable) are represented using
- *    \ref SEL_SUBEXPRREF elements.
- *    In this case, \c t_selelem::param is NULL, and the first and only
- *    child of the element is the \ref SEL_SUBEXPR element of the variable.
- *    Such references can appear anywhere where the variable value
- *    (the child of the \ref SEL_SUBEXPR element) would be valid.
- *  - Children of \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are
- *    always of this type. For these elements, \c t_selelem::param is
- *    initialized to point to the parameter that receives the value from
- *    the expression.
- *    Each such element has exactly one child, which can be of any type;
- *    the \ref SEL_SUBEXPR element of a variable is used if the value comes
- *    from a variable, otherwise the child type is not \ref SEL_SUBEXPR.
- *
- *
- * \subsection selparser_tree_gmx_bool Boolean elements
- *
- * One \ref SEL_BOOLEAN element is created for each gmx_boolean keyword in the
- * input, and the tree structure represents the evaluation order.
- * The \c t_selelem::boolt type gives the type of the operation.
- * Each element has exactly two children (one for \ref BOOL_NOT elements),
- * which are in the order given in the input.
- * The children always have \ref GROUP_VALUE, but different element types
- * are possible.
- *
- *
- * \subsection selparser_tree_arith Arithmetic elements
- *
- * One \ref SEL_ARITHMETIC element is created for each arithmetic operation in
- * the input, and the tree structure represents the evaluation order.
- * The \c t_selelem::optype type gives the name of the operation.
- * Each element has exactly two children (one for unary negation elements),
- * which are in the order given in the input.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <futil.h>
-#include <smalloc.h>
-#include <string2.h>
-#include <gmx_fatal.h>
-
-#include <poscalc.h>
-#include <selection.h>
-#include <selmethod.h>
-
-#include "keywords.h"
-#include "parsetree.h"
-#include "selcollection.h"
-#include "selelem.h"
-#include "selhelp.h"
-#include "symrec.h"
-
-#include "scanner.h"
-
-/* In parser.y */
-/*! \brief
- * Parser function generated by Bison.
- */
-int
-_gmx_sel_yybparse(void *scanner);
-
-/*!
- * It is a simple wrapper for fprintf(stderr, ...).
- */
-void
-_gmx_selparser_error(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    fprintf(stderr, "selection parser: ");
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    va_end(ap);
-}
-
-/*!
- * \param[in] type  Type for the new value.
- * \returns   Pointer to the newly allocated value.
- */
-t_selexpr_value *
-_gmx_selexpr_create_value(e_selvalue_t type)
-{
-    t_selexpr_value *value;
-    snew(value, 1);
-    value->type  = type;
-    value->bExpr = FALSE;
-    value->next  = NULL;
-    return value;
-}
-
-/*!
- * \param[in] expr  Expression for the value.
- * \returns   Pointer to the newly allocated value.
- */
-t_selexpr_value *
-_gmx_selexpr_create_value_expr(t_selelem *expr)
-{
-    t_selexpr_value *value;
-    snew(value, 1);
-    value->type   = expr->v.type;
-    value->bExpr  = TRUE;
-    value->u.expr = expr;
-    value->next   = NULL;
-    return value;
-}
-
-/*!
- * \param[in] name Name for the new parameter.
- * \returns   Pointer to the newly allocated parameter.
- *
- * No copy of \p name is made.
- */
-t_selexpr_param *
-_gmx_selexpr_create_param(char *name)
-{
-    t_selexpr_param *param;
-    snew(param, 1);
-    param->name = name;
-    param->next = NULL;
-    return param;
-}
-
-/*!
- * \param value Pointer to the beginning of the value list to free.
- *
- * The expressions referenced by the values are also freed
- * (to prevent this, set the expression to NULL before calling the function).
- */
-void
-_gmx_selexpr_free_values(t_selexpr_value *value)
-{
-    t_selexpr_value *old;
-
-    while (value)
-    {
-        if (value->bExpr)
-        {
-            if (value->u.expr)
-            {
-                _gmx_selelem_free(value->u.expr);
-            }
-        }
-        else if (value->type == STR_VALUE)
-        {
-            sfree(value->u.s);
-        }
-        old = value;
-        value = value->next;
-        sfree(old);
-    }
-}
-
-/*!
- * \param param Pointer the the beginning of the parameter list to free.
- *
- * The values of the parameters are freed with free_selexpr_values().
- */
-void
-_gmx_selexpr_free_params(t_selexpr_param *param)
-{
-    t_selexpr_param *old;
-
-    while (param)
-    {
-        _gmx_selexpr_free_values(param->value);
-        old = param;
-        param = param->next;
-        sfree(old->name);
-        sfree(old);
-    }
-}
-
-/*!
- * \param[in,out] sel  Root of the selection element tree to initialize.
- * \returns       0 on success, an error code on error.
- *
- * Propagates the \ref SEL_DYNAMIC flag from the children of \p sel to \p sel
- * (if any child of \p sel is dynamic, \p sel is also marked as such).
- * The \ref SEL_DYNAMIC flag is also set for \ref SEL_EXPRESSION elements with
- * a dynamic method.
- * Also, sets one of the \ref SEL_SINGLEVAL, \ref SEL_ATOMVAL, or
- * \ref SEL_VARNUMVAL flags, either based on the children or on the type of
- * the selection method.
- * If the types of the children conflict, an error is returned.
- *
- * The flags of the children of \p sel are also updated if not done earlier.
- * The flags are initialized only once for any element; if \ref SEL_FLAGSSET
- * is set for an element, the function returns immediately, and the recursive
- * operation does not descend beyond such elements.
- */
-int
-_gmx_selelem_update_flags(t_selelem *sel)
-{
-    t_selelem          *child;
-    int                 rc;
-    gmx_bool                bUseChildType=FALSE;
-    gmx_bool                bOnlySingleChildren;
-
-    /* Return if the flags have already been set */
-    if (sel->flags & SEL_FLAGSSET)
-    {
-        return 0;
-    }
-    /* Set the flags based on the current element type */
-    switch (sel->type)
-    {
-        case SEL_CONST:
-            sel->flags |= SEL_SINGLEVAL;
-            bUseChildType = FALSE;
-            break;
-
-        case SEL_EXPRESSION:
-            if (sel->u.expr.method->flags & SMETH_DYNAMIC)
-            {
-                sel->flags |= SEL_DYNAMIC;
-            }
-            if (sel->u.expr.method->flags & SMETH_SINGLEVAL)
-            {
-                sel->flags |= SEL_SINGLEVAL;
-            }
-            else if (sel->u.expr.method->flags & SMETH_VARNUMVAL)
-            {
-                sel->flags |= SEL_VARNUMVAL;
-            }
-            else
-            {
-                sel->flags |= SEL_ATOMVAL;
-            }
-            bUseChildType = FALSE;
-            break;
-
-        case SEL_ARITHMETIC:
-            sel->flags |= SEL_ATOMVAL;
-            bUseChildType = FALSE;
-            break;
-
-        case SEL_MODIFIER:
-            if (sel->v.type != NO_VALUE)
-            {
-                sel->flags |= SEL_VARNUMVAL;
-            }
-            bUseChildType = FALSE;
-            break;
-
-        case SEL_ROOT:
-            bUseChildType = FALSE;
-            break;
-
-        case SEL_BOOLEAN:
-        case SEL_SUBEXPR:
-        case SEL_SUBEXPRREF:
-            bUseChildType = TRUE;
-            break;
-    }
-    /* Loop through children to propagate their flags upwards */
-    bOnlySingleChildren = TRUE;
-    child = sel->child;
-    while (child)
-    {
-        /* Update the child */
-        rc = _gmx_selelem_update_flags(child);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        /* Propagate the dynamic flag */
-        sel->flags |= (child->flags & SEL_DYNAMIC);
-        /* Propagate the type flag if necessary and check for problems */
-        if (bUseChildType)
-        {
-            if ((sel->flags & SEL_VALTYPEMASK)
-                && !(sel->flags & child->flags & SEL_VALTYPEMASK))
-            {
-                _gmx_selparser_error("invalid combination of selection expressions");
-                return EINVAL;
-            }
-            sel->flags |= (child->flags & SEL_VALTYPEMASK);
-        }
-        if (!(child->flags & SEL_SINGLEVAL))
-        {
-            bOnlySingleChildren = FALSE;
-        }
-
-        child = child->next;
-    }
-    /* For arithmetic expressions consisting only of single values,
-     * the result is also a single value. */
-    if (sel->type == SEL_ARITHMETIC && bOnlySingleChildren)
-    {
-        sel->flags = (sel->flags & ~SEL_VALTYPEMASK) | SEL_SINGLEVAL;
-    }
-    /* For root elements, the type should be propagated here, after the
-     * children have been updated. */
-    if (sel->type == SEL_ROOT)
-    {
-        sel->flags |= (sel->child->flags & SEL_VALTYPEMASK);
-    }
-    /* Mark that the flags are set */
-    sel->flags |= SEL_FLAGSSET;
-    return 0;
-}
-
-/*!
- * \param[in,out] sel    Selection element to initialize.
- * \param[in]     scanner Scanner data structure.
- *
- * A deep copy of the parameters is made to allow several
- * expressions with the same method to coexist peacefully.
- * Calls sel_datafunc() if one is specified for the method.
- */
-void
-_gmx_selelem_init_method_params(t_selelem *sel, yyscan_t scanner)
-{
-    int                 nparams;
-    gmx_ana_selparam_t *orgparam;
-    gmx_ana_selparam_t *param;
-    int                 i;
-    void               *mdata;
-
-    nparams   = sel->u.expr.method->nparams;
-    orgparam  = sel->u.expr.method->param;
-    snew(param, nparams);
-    memcpy(param, orgparam, nparams*sizeof(gmx_ana_selparam_t));
-    for (i = 0; i < nparams; ++i)
-    {
-        param[i].flags &= ~SPAR_SET;
-        _gmx_selvalue_setstore(&param[i].val, NULL);
-        if (param[i].flags & SPAR_VARNUM)
-        {
-            param[i].val.nr = -1;
-        }
-        /* Duplicate the enum value array if it is given statically */
-        if ((param[i].flags & SPAR_ENUMVAL) && orgparam[i].val.u.ptr != NULL)
-        {
-            int n;
-
-            /* Count the values */
-            n = 1;
-            while (orgparam[i].val.u.s[n] != NULL)
-            {
-                ++n;
-            }
-            _gmx_selvalue_reserve(&param[i].val, n+1);
-            memcpy(param[i].val.u.s, orgparam[i].val.u.s,
-                   (n+1)*sizeof(param[i].val.u.s[0]));
-        }
-    }
-    mdata = NULL;
-    if (sel->u.expr.method->init_data)
-    {
-        mdata = sel->u.expr.method->init_data(nparams, param);
-        if (mdata == NULL)
-        {
-            gmx_fatal(FARGS, "Method data initialization failed");
-        }
-    }
-    if (sel->u.expr.method->set_poscoll)
-    {
-        gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-
-        sel->u.expr.method->set_poscoll(sc->pcc, mdata);
-    }
-    /* Store the values */
-    sel->u.expr.method->param = param;
-    sel->u.expr.mdata         = mdata;
-}
-
-/*!
- * \param[in,out] sel    Selection element to initialize.
- * \param[in]     method Selection method to set.
- * \param[in]     scanner Scanner data structure.
- *
- * Makes a copy of \p method and stores it in \p sel->u.expr.method,
- * and calls _gmx_selelem_init_method_params();
- */
-void
-_gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
-                        yyscan_t scanner)
-{
-    int      i;
-
-    _gmx_selelem_set_vtype(sel, method->type);
-    sel->name   = method->name;
-    snew(sel->u.expr.method, 1);
-    memcpy(sel->u.expr.method, method, sizeof(gmx_ana_selmethod_t));
-    _gmx_selelem_init_method_params(sel, scanner);
-}
-
-/*! \brief
- * Initializes the reference position calculation for a \ref SEL_EXPRESSION
- * element.
- *
- * \param[in,out] pcc    Position calculation collection to use.
- * \param[in,out] sel    Selection element to initialize.
- * \param[in]     rpost  Reference position type to use (NULL = default).
- * \returns       0 on success, a non-zero error code on error.
- */
-static int
-set_refpos_type(gmx_ana_poscalc_coll_t *pcc, t_selelem *sel, const char *rpost)
-{
-    int  rc;
-
-    if (!rpost)
-    {
-        return 0;
-    }
-
-    rc = 0;
-    if (sel->u.expr.method->pupdate)
-    {
-        /* By default, use whole residues/molecules. */
-        rc = gmx_ana_poscalc_create_enum(&sel->u.expr.pc, pcc, rpost,
-                                         POS_COMPLWHOLE);
-    }
-    else
-    {
-        _gmx_selparser_error("warning: '%s' modifier for '%s' ignored",
-                             rpost, sel->u.expr.method->name);
-    }
-    return rc;
-}
-
-/*!
- * \param[in]  left    Selection element for the left hand side.
- * \param[in]  right   Selection element for the right hand side.
- * \param[in]  op      String representation of the operator.
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * arithmetic expressions.
- */
-t_selelem *
-_gmx_sel_init_arithmetic(t_selelem *left, t_selelem *right, char op,
-                         yyscan_t scanner)
-{
-    t_selelem         *sel;
-    char               buf[2];
-
-    buf[0] = op;
-    buf[1] = 0;
-    sel = _gmx_selelem_create(SEL_ARITHMETIC);
-    sel->v.type        = REAL_VALUE;
-    switch(op)
-    {
-        case '+': sel->u.arith.type = ARITH_PLUS; break;
-        case '-': sel->u.arith.type = (right ? ARITH_MINUS : ARITH_NEG); break;
-        case '*': sel->u.arith.type = ARITH_MULT; break;
-        case '/': sel->u.arith.type = ARITH_DIV;  break;
-        case '^': sel->u.arith.type = ARITH_EXP;  break;
-    }
-    sel->u.arith.opstr = strdup(buf);
-    sel->name          = sel->u.arith.opstr;
-    sel->child         = left;
-    sel->child->next   = right;
-    return sel;
-}
-
-/*!
- * \param[in]  left   Selection element for the left hand side.
- * \param[in]  right  Selection element for the right hand side.
- * \param[in]  cmpop  String representation of the comparison operator.
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * comparison expressions.
- */
-t_selelem *
-_gmx_sel_init_comparison(t_selelem *left, t_selelem *right, char *cmpop,
-                         yyscan_t scanner)
-{
-    t_selelem         *sel;
-    t_selexpr_param   *params, *param;
-    const char        *name;
-    int                rc;
-
-    sel = _gmx_selelem_create(SEL_EXPRESSION);
-    _gmx_selelem_set_method(sel, &sm_compare, scanner);
-    /* Create the parameter for the left expression */
-    name               = left->v.type == INT_VALUE ? "int1" : "real1";
-    params = param     = _gmx_selexpr_create_param(strdup(name));
-    param->nval        = 1;
-    param->value       = _gmx_selexpr_create_value_expr(left);
-    /* Create the parameter for the right expression */
-    name               = right->v.type == INT_VALUE ? "int2" : "real2";
-    param              = _gmx_selexpr_create_param(strdup(name));
-    param->nval        = 1;
-    param->value       = _gmx_selexpr_create_value_expr(right);
-    params->next       = param;
-    /* Create the parameter for the operator */
-    param              = _gmx_selexpr_create_param(strdup("op"));
-    param->nval        = 1;
-    param->value       = _gmx_selexpr_create_value(STR_VALUE);
-    param->value->u.s  = cmpop;
-    params->next->next = param;
-    if (!_gmx_sel_parse_params(params, sel->u.expr.method->nparams,
-                               sel->u.expr.method->param, sel, scanner))
-    {
-        _gmx_selparser_error("error in comparison initialization");
-        _gmx_selelem_free(sel);
-        return NULL;
-    }
-
-    return sel;
-}
-
-/*!
- * \param[in]  method Method to use.
- * \param[in]  args   Pointer to the first argument.
- * \param[in]  rpost  Reference position type to use (NULL = default).
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * selection methods that do not take parameters.
- */
-t_selelem *
-_gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
-                      const char *rpost, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    t_selelem         *root, *child;
-    t_selexpr_param   *params, *param;
-    t_selexpr_value   *arg;
-    int                nargs;
-    int                rc;
-
-    if (method->nparams > 0)
-    {
-        gmx_bug("internal error");
-        return NULL;
-    }
-
-    root = _gmx_selelem_create(SEL_EXPRESSION);
-    child = root;
-    _gmx_selelem_set_method(child, method, scanner);
-
-    /* Initialize the evaluation of keyword matching if values are provided */
-    if (args)
-    {
-        gmx_ana_selmethod_t *kwmethod;
-        switch (method->type)
-        {
-            case INT_VALUE:  kwmethod = &sm_keyword_int;  break;
-            case REAL_VALUE: kwmethod = &sm_keyword_real; break;
-            case STR_VALUE:  kwmethod = &sm_keyword_str;  break;
-            default:
-                _gmx_selparser_error("unknown type for keyword selection");
-                _gmx_selexpr_free_values(args);
-                goto on_error;
-        }
-        /* Count the arguments */
-        nargs = 0;
-        arg   = args;
-        while (arg)
-        {
-            ++nargs;
-            arg = arg->next;
-        }
-        /* Initialize the selection element */
-        root = _gmx_selelem_create(SEL_EXPRESSION);
-        _gmx_selelem_set_method(root, kwmethod, scanner);
-        params = param = _gmx_selexpr_create_param(NULL);
-        param->nval    = 1;
-        param->value   = _gmx_selexpr_create_value_expr(child);
-        param          = _gmx_selexpr_create_param(NULL);
-        param->nval    = nargs;
-        param->value   = args;
-        params->next   = param;
-        if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
-                                   root->u.expr.method->param, root, scanner))
-        {
-            _gmx_selparser_error("error in keyword selection initialization");
-            goto on_error;
-        }
-    }
-    rc = set_refpos_type(sc->pcc, child, rpost);
-    if (rc != 0)
-    {
-        goto on_error;
-    }
-
-    return root;
-
-/* On error, free all memory and return NULL. */
-on_error:
-    _gmx_selelem_free(root);
-    return NULL;
-}
-
-/*!
- * \param[in]  method Method to use for initialization.
- * \param[in]  params Pointer to the first parameter.
- * \param[in]  rpost  Reference position type to use (NULL = default).
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * selection methods that take parameters.
- *
- * Part of the behavior of the \c same selection keyword is hardcoded into
- * this function (or rather, into _gmx_selelem_custom_init_same()) to allow the
- * use of any keyword in \c "same KEYWORD as" without requiring special
- * handling somewhere else (or sacrificing the simple syntax).
- */
-t_selelem *
-_gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
-                     const char *rpost, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    t_selelem       *root;
-    int              rc;
-
-    _gmx_sel_finish_method(scanner);
-    /* The "same" keyword needs some custom massaging of the parameters. */
-    rc = _gmx_selelem_custom_init_same(&method, params, scanner);
-    if (rc != 0)
-    {
-        _gmx_selexpr_free_params(params);
-        return NULL;
-    }
-    root = _gmx_selelem_create(SEL_EXPRESSION);
-    _gmx_selelem_set_method(root, method, scanner);
-    /* Process the parameters */
-    if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
-                               root->u.expr.method->param, root, scanner))
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-    rc = set_refpos_type(sc->pcc, root, rpost);
-    if (rc != 0)
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-
-    return root;
-}
-
-/*!
- * \param[in]  method Modifier to use for initialization.
- * \param[in]  params Pointer to the first parameter.
- * \param[in]  sel    Selection element that the modifier should act on.
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * selection modifiers.
- */
-t_selelem *
-_gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
-                       t_selelem *sel, yyscan_t scanner)
-{
-    t_selelem         *root;
-    t_selelem         *mod;
-    t_selexpr_param   *vparam;
-    int                i;
-
-    _gmx_sel_finish_method(scanner);
-    mod = _gmx_selelem_create(SEL_MODIFIER);
-    _gmx_selelem_set_method(mod, method, scanner);
-    if (method->type == NO_VALUE)
-    {
-        t_selelem *child;
-
-        child = sel;
-        while (child->next)
-        {
-            child = child->next;
-        }
-        child->next = mod;
-        root        = sel;
-    }
-    else
-    {
-        vparam        = _gmx_selexpr_create_param(NULL);
-        vparam->nval  = 1;
-        vparam->value = _gmx_selexpr_create_value_expr(sel);
-        vparam->next  = params;
-        params        = vparam;
-        root          = mod;
-    }
-    /* Process the parameters */
-    if (!_gmx_sel_parse_params(params, mod->u.expr.method->nparams,
-                               mod->u.expr.method->param, mod, scanner))
-    {
-        _gmx_selelem_free(mod);
-        return NULL;
-    }
-
-    return root;
-}
-
-/*!
- * \param[in]  expr    Input selection element for the position calculation.
- * \param[in]  type    Reference position type or NULL for default.
- * \param[in]  scanner Scanner data structure.
- * \returns    The created selection element.
- *
- * This function handles the creation of a \c t_selelem object for
- * evaluation of reference positions.
- */
-t_selelem *
-_gmx_sel_init_position(t_selelem *expr, const char *type, yyscan_t scanner)
-{
-    t_selelem       *root;
-    t_selexpr_param *params;
-
-    root = _gmx_selelem_create(SEL_EXPRESSION);
-    _gmx_selelem_set_method(root, &sm_keyword_pos, scanner);
-    _gmx_selelem_set_kwpos_type(root, type);
-    /* Create the parameters for the parameter parser. */
-    params        = _gmx_selexpr_create_param(NULL);
-    params->nval  = 1;
-    params->value = _gmx_selexpr_create_value_expr(expr);
-    /* Parse the parameters. */
-    if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
-                               root->u.expr.method->param, root, scanner))
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-
-    return root;
-}
-
-/*!
- * \param[in] x,y,z  Coordinates for the position.
- * \returns   The creates selection element.
- */
-t_selelem *
-_gmx_sel_init_const_position(real x, real y, real z)
-{
-    t_selelem *sel;
-    rvec       pos;
-
-    sel = _gmx_selelem_create(SEL_CONST);
-    _gmx_selelem_set_vtype(sel, POS_VALUE);
-    _gmx_selvalue_reserve(&sel->v, 1);
-    pos[XX] = x;
-    pos[YY] = y;
-    pos[ZZ] = z;
-    gmx_ana_pos_init_const(sel->v.u.p, pos);
-    return sel;
-}
-
-/*!
- * \param[in] name  Name of an index group to search for.
- * \param[in] scanner Scanner data structure.
- * \returns   The created constant selection element, or NULL if no matching
- *     index group found.
- *
- * See gmx_ana_indexgrps_find() for information on how \p name is matched
- * against the index groups.
- */
-t_selelem *
-_gmx_sel_init_group_by_name(const char *name, yyscan_t scanner)
-{
-    gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
-    t_selelem *sel;
-
-    if (!grps)
-    {
-        return NULL;
-    }
-    sel = _gmx_selelem_create(SEL_CONST);
-    _gmx_selelem_set_vtype(sel, GROUP_VALUE); 
-    /* FIXME: The constness should not be cast away */
-    if (!gmx_ana_indexgrps_find(&sel->u.cgrp, grps, (char *)name))
-    {
-        _gmx_selelem_free(sel);
-        return NULL;
-    }
-    sel->name = sel->u.cgrp.name;
-    return sel;
-}
-
-/*!
- * \param[in] id    Zero-based index number of the group to extract.
- * \param[in] scanner Scanner data structure.
- * \returns   The created constant selection element, or NULL if no matching
- *     index group found.
- */
-t_selelem *
-_gmx_sel_init_group_by_id(int id, yyscan_t scanner)
-{
-    gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
-    t_selelem *sel;
-
-    if (!grps)
-    {
-        return NULL;
-    }
-    sel = _gmx_selelem_create(SEL_CONST);
-    _gmx_selelem_set_vtype(sel, GROUP_VALUE);
-    if (!gmx_ana_indexgrps_extract(&sel->u.cgrp, grps, id))
-    {
-        _gmx_selelem_free(sel);
-        return NULL;
-    }
-    sel->name = sel->u.cgrp.name;
-    return sel;
-}
-
-/*!
- * \param[in,out] sel  Value of the variable.
- * \returns       The created selection element that references \p sel.
- *
- * The reference count of \p sel is updated, but no other modifications are
- * made.
- */
-t_selelem *
-_gmx_sel_init_variable_ref(t_selelem *sel)
-{
-    t_selelem *ref;
-
-    if (sel->v.type == POS_VALUE && sel->type == SEL_CONST)
-    {
-        ref = sel;
-    }
-    else
-    {
-        ref = _gmx_selelem_create(SEL_SUBEXPRREF);
-        _gmx_selelem_set_vtype(ref, sel->v.type);
-        ref->name  = sel->name;
-        ref->child = sel;
-    }
-    sel->refcount++;
-    return ref;
-}
-
-/*! \brief
- * Initializes default values for position keyword evaluation.
- *
- * \param[in,out] root       Root of the element tree to initialize.
- * \param[in]     sc         Selection collection to use defaults from.
- * \param[in]     bSelection Whether the element evaluates the positions for a
- *   selection.
- */
-static void
-init_pos_keyword_defaults(t_selelem *root, gmx_ana_selcollection_t *sc, gmx_bool bSelection)
-{
-    t_selelem               *child;
-    int                      flags;
-
-    /* Selections use largest static group by default, while
-     * reference positions use the whole residue/molecule. */
-    if (root->type == SEL_EXPRESSION)
-    {
-        flags = bSelection ? POS_COMPLMAX : POS_COMPLWHOLE;
-        if (bSelection && sc->bMaskOnly)
-        {
-            flags |= POS_MASKONLY;
-        }
-        if (bSelection && sc->bVelocities)
-        {
-            flags |= POS_VELOCITIES;
-        }
-        if (bSelection && sc->bForces)
-        {
-            flags |= POS_FORCES;
-        }
-        _gmx_selelem_set_kwpos_type(root, bSelection ? sc->spost : sc->rpost);
-        _gmx_selelem_set_kwpos_flags(root, flags);
-    }
-    /* Change the defaults once we are no longer processing modifiers */
-    if (root->type != SEL_ROOT && root->type != SEL_MODIFIER
-        && root->type != SEL_SUBEXPRREF && root->type != SEL_SUBEXPR)
-    {
-        bSelection = FALSE;
-    }
-    /* Recurse into children */
-    child = root->child;
-    while (child)
-    {
-        init_pos_keyword_defaults(child, sc, bSelection);
-        child = child->next;
-    }
-}
-
-/*!
- * \param[in]  name     Name for the selection
- *     (if NULL, a default name is constructed).
- * \param[in]  sel      The selection element that evaluates the selection.
- * \param      scanner  Scanner data structure.
- * \returns    The created root selection element.
- *
- * This function handles the creation of root (\ref SEL_ROOT) \c t_selelem
- * objects for selections.
- */
-t_selelem *
-_gmx_sel_init_selection(char *name, t_selelem *sel, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    t_selelem               *root;
-    int                      rc;
-
-    if (sel->v.type != POS_VALUE)
-    {
-        gmx_bug("each selection must evaluate to a position");
-        /* FIXME: Better handling of this error */
-        sfree(name);
-        return NULL;
-    }
-
-    root = _gmx_selelem_create(SEL_ROOT);
-    root->child = sel;
-    /* Assign the name (this is done here to free it automatically in the case
-     * of an error below). */
-    if (name)
-    {
-        root->name = root->u.cgrp.name = name;
-    }
-    /* Update the flags */
-    rc = _gmx_selelem_update_flags(root);
-    if (rc != 0)
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-    /* Initialize defaults for position keywords */
-    init_pos_keyword_defaults(sel, sc, TRUE);
-
-    /* If there is no name provided by the user, check whether the actual
-     * selection given was from an external group, and if so, use the name
-     * of the external group. */
-    if (!root->name)
-    {
-        t_selelem *child = root->child;
-        while (child->type == SEL_MODIFIER)
-        {
-            if (!child->child || child->child->type != SEL_SUBEXPRREF
-                || !child->child->child)
-            {
-                break;
-            }
-            child = child->child->child;
-        }
-        if (child->type == SEL_EXPRESSION
-            && child->child && child->child->type == SEL_SUBEXPRREF
-            && child->child->child
-            && child->child->child->type == SEL_CONST
-            && child->child->child->v.type == GROUP_VALUE)
-        {
-            root->name = root->u.cgrp.name =
-                strdup(child->child->child->u.cgrp.name);
-        }
-    }
-    /* If there still is no name, use the selection string */
-    if (!root->name)
-    {
-        root->name = root->u.cgrp.name
-            = strdup(_gmx_sel_lexer_pselstr(scanner));
-    }
-
-    /* Print out some information if the parser is interactive */
-    if (_gmx_sel_is_lexer_interactive(scanner))
-    {
-        fprintf(stderr, "Selection '%s' parsed\n",
-                _gmx_sel_lexer_pselstr(scanner));
-    }
-
-    return root;
-}
-
-
-/*!
- * \param[in]  name     Name of the variable (should not be freed after this
- *   function).
- * \param[in]  expr     The selection element that evaluates the variable.
- * \param      scanner  Scanner data structure.
- * \returns    The created root selection element.
- *
- * This function handles the creation of root \c t_selelem objects for
- * variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
- * element are both created.
- */
-t_selelem *
-_gmx_sel_assign_variable(char *name, t_selelem *expr, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    const char              *pselstr = _gmx_sel_lexer_pselstr(scanner);
-    t_selelem               *root = NULL;
-    int                      rc;
-
-    rc = _gmx_selelem_update_flags(expr);
-    if (rc != 0)
-    {
-        sfree(name);
-        _gmx_selelem_free(expr);
-        return NULL;
-    }
-    /* Check if this is a constant non-group value */
-    if (expr->type == SEL_CONST && expr->v.type != GROUP_VALUE)
-    {
-        /* If so, just assign the constant value to the variable */
-        if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr))
-        {
-            _gmx_selelem_free(expr);
-            sfree(name);
-            return NULL;
-        }
-        _gmx_selelem_free(expr);
-        sfree(name);
-        goto finish;
-    }
-    /* Check if we are assigning a variable to another variable */
-    if (expr->type == SEL_SUBEXPRREF)
-    {
-        /* If so, make a simple alias */
-        if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr->child))
-        {
-            _gmx_selelem_free(expr);
-            sfree(name);
-            return NULL;
-        }
-        _gmx_selelem_free(expr);
-        sfree(name);
-        goto finish;
-    }
-    /* Create the root element */
-    root = _gmx_selelem_create(SEL_ROOT);
-    root->name          = name;
-    root->u.cgrp.name   = name;
-    /* Create the subexpression element */
-    root->child = _gmx_selelem_create(SEL_SUBEXPR);
-    _gmx_selelem_set_vtype(root->child, expr->v.type);
-    root->child->name   = name;
-    root->child->child  = expr;
-    /* Update flags */
-    rc = _gmx_selelem_update_flags(root);
-    if (rc != 0)
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-    /* Add the variable to the symbol table */
-    if (!_gmx_sel_add_var_symbol(sc->symtab, name, root->child))
-    {
-        _gmx_selelem_free(root);
-        return NULL;
-    }
-finish:
-    srenew(sc->varstrs, sc->nvars + 1);
-    sc->varstrs[sc->nvars] = strdup(pselstr);
-    ++sc->nvars;
-    if (_gmx_sel_is_lexer_interactive(scanner))
-    {
-        fprintf(stderr, "Variable '%s' parsed\n", pselstr);
-    }
-    return root;
-}
-
-/*!
- * \param         sel   Selection to append (can be NULL, in which
- *   case nothing is done).
- * \param         last  Last selection, or NULL if not present or not known.
- * \param         scanner  Scanner data structure.
- * \returns       The last selection after the append.
- *
- * Appends \p sel after the last root element, and returns either \p sel
- * (if it was non-NULL) or the last element (if \p sel was NULL).
- */
-t_selelem *
-_gmx_sel_append_selection(t_selelem *sel, t_selelem *last, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-
-    /* Append sel after last, or the last element of sc if last is NULL */
-    if (last)
-    {
-        last->next = sel;
-    }
-    else
-    {
-        if (sc->root)
-        {
-            last = sc->root;
-            while (last->next)
-            {
-                last = last->next;
-            }
-            last->next = sel;
-        }
-        else
-        {
-            sc->root = sel;
-        }
-    }
-    /* Initialize a selection object if necessary */
-    if (sel)
-    {
-        last = sel;
-        /* Add the new selection to the collection if it is not a variable. */
-        if (sel->child->type != SEL_SUBEXPR)
-        {
-            int        i;
-
-            sc->nr++;
-            srenew(sc->sel, sc->nr);
-            i = sc->nr - 1;
-            snew(sc->sel[i], 1);
-            sc->sel[i]->name   = strdup(sel->name);
-            sc->sel[i]->selstr = strdup(_gmx_sel_lexer_pselstr(scanner));
-
-            if (sel->child->type == SEL_CONST)
-            {
-                gmx_ana_pos_copy(&sc->sel[i]->p, sel->child->v.u.p, TRUE);
-                sc->sel[i]->bDynamic = FALSE;
-            }
-            else
-            {
-                t_selelem *child;
-
-                child = sel->child;
-                child->flags     &= ~SEL_ALLOCVAL;
-                _gmx_selvalue_setstore(&child->v, &sc->sel[i]->p);
-                /* We should also skip any modifiers to determine the dynamic
-                 * status. */
-                while (child->type == SEL_MODIFIER)
-                {
-                    child = child->child;
-                    if (child->type == SEL_SUBEXPRREF)
-                    {
-                        child = child->child;
-                        /* Because most subexpression elements are created
-                         * during compilation, we need to check for them
-                         * explicitly here.
-                         */
-                        if (child->type == SEL_SUBEXPR)
-                        {
-                            child = child->child;
-                        }
-                    }
-                }
-                /* For variable references, we should skip the
-                 * SEL_SUBEXPRREF and SEL_SUBEXPR elements. */
-                if (child->type == SEL_SUBEXPRREF)
-                {
-                    child = child->child->child;
-                }
-                sc->sel[i]->bDynamic = (child->child->flags & SEL_DYNAMIC);
-            }
-            /* The group will be set after compilation */
-            sc->sel[i]->g        = NULL;
-            sc->sel[i]->selelem  = sel;
-            gmx_ana_selection_init_coverfrac(sc->sel[i], CFRAC_NONE);
-        }
-    }
-    /* Clear the selection string now that we've saved it */
-    _gmx_sel_lexer_clear_pselstr(scanner);
-    return last;
-}
-
-/*!
- * \param[in] scanner Scanner data structure.
- * \returns   TRUE if the parser should finish, FALSE if parsing should
- *   continue.
- *
- * This function is called always after _gmx_sel_append_selection() to
- * check whether a sufficient number of selections has already been provided.
- * This is used to terminate interactive parsers when the correct number of
- * selections has been provided.
- */
-gmx_bool
-_gmx_sel_parser_should_finish(yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    return sc->nr == _gmx_sel_lexer_exp_selcount(scanner);
-}
-
-/*!
- * \param[in] scanner Scanner data structure.
- */
-void
-_gmx_sel_handle_empty_cmd(yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    gmx_ana_indexgrps_t     *grps = _gmx_sel_lexer_indexgrps(scanner);
-    int                      i;
-
-    if (!_gmx_sel_is_lexer_interactive(scanner))
-        return;
-
-    if (grps)
-    {
-        fprintf(stderr, "Available index groups:\n");
-        gmx_ana_indexgrps_print(_gmx_sel_lexer_indexgrps(scanner), 0);
-    }
-    if (sc->nvars > 0 || sc->nr > 0)
-    {
-        fprintf(stderr, "Currently provided selections:\n");
-        for (i = 0; i < sc->nvars; ++i)
-        {
-            fprintf(stderr, "     %s\n", sc->varstrs[i]);
-        }
-        for (i = 0; i < sc->nr; ++i)
-        {
-            fprintf(stderr, " %2d. %s\n", i+1, sc->sel[i]->selstr);
-        }
-    }
-}
-
-/*!
- * \param[in] topic   Topic for which help was requested, or NULL for general
- *                    help.
- * \param[in] scanner Scanner data structure.
- *
- * \p topic is freed by this function.
- */
-void
-_gmx_sel_handle_help_cmd(char *topic, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-
-    _gmx_sel_print_help(sc, topic);
-    if (topic)
-    {
-        sfree(topic);
-    }
-}
-
-/*! \brief
- * Internal helper function used by gmx_ana_selcollection_parse_*() to do the actual work.
- *
- * \param[in]     maxnr   Maximum number of selections to parse
- *   (if -1, parse as many as provided by the user).
- * \param[in,out] scanner Scanner data structure.
- * \returns       0 on success, -1 on error.
- */
-static int
-run_parser(int maxnr, yyscan_t scanner)
-{
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
-    gmx_bool bOk;
-    int  nr;
-
-    nr  = sc->nr;
-    bOk = !_gmx_sel_yybparse(scanner);
-    _gmx_sel_free_lexer(scanner);
-    nr = sc->nr - nr;
-    if (maxnr > 0 && nr != maxnr)
-    {
-        return -1;
-    }
-    return bOk ? 0 : -1;
-}
-
-/*!
- * \param[in,out] sc    Selection collection to use for output.
- * \param[in]     nr    Number of selections to parse
- *   (if -1, parse as many as provided by the user).
- * \param[in]     grps  External index groups (can be NULL).
- * \param[in]     bInteractive Whether the parser should behave interactively.
- * \returns       0 on success, -1 on error.
- *
- * The number of selections parsed can be accessed with
- * gmx_ana_selcollection_get_count() (note that if you call the parser
- * multiple times, this function returns the total count).
- */
-int
-gmx_ana_selcollection_parse_stdin(gmx_ana_selcollection_t *sc, int nr,
-                                  gmx_ana_indexgrps_t *grps, gmx_bool bInteractive)
-{
-    yyscan_t scanner;
-    int      rc;
-
-    rc = _gmx_sel_init_lexer(&scanner, sc, bInteractive, nr, grps);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    /* We don't set the lexer input here, which causes it to use a special
-     * internal implementation for reading from stdin. */
-    return run_parser(nr, scanner);
-}
-
-/*!
- * \param[in,out] sc    Selection collection to use for output.
- * \param[in]     fnm   Name of the file to parse selections from.
- * \param[in]     grps  External index groups (can be NULL).
- * \returns       0 on success, -1 on error.
- *
- * The number of selections parsed can be accessed with
- * gmx_ana_selcollection_get_count() (note that if you call the parser
- * multiple times, this function returns the total count).
- */
-int
-gmx_ana_selcollection_parse_file(gmx_ana_selcollection_t *sc, const char *fnm,
-                                 gmx_ana_indexgrps_t *grps)
-{
-    yyscan_t scanner;
-    FILE *fp;
-    int   rc;
-
-    rc = _gmx_sel_init_lexer(&scanner, sc, FALSE, -1, grps);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    fp = ffopen(fnm, "r");
-    _gmx_sel_set_lex_input_file(scanner, fp);
-    rc = run_parser(-1, scanner);
-    ffclose(fp);
-    return rc;
-}
-
-/*!
- * \param[in,out] sc    Selection collection to use for output.
- * \param[in]     str   String to parse selections from.
- * \param[in]     grps  External index groups (can be NULL).
- * \returns       0 on success, -1 on error.
- *
- * The number of selections parsed can be accessed with
- * gmx_ana_selcollection_get_count() (note that if you call the parser
- * multiple times, this function returns the total count).
- */
-int
-gmx_ana_selcollection_parse_str(gmx_ana_selcollection_t *sc, const char *str,
-                                gmx_ana_indexgrps_t *grps)
-{
-    yyscan_t scanner;
-    int      rc;
-
-    rc = _gmx_sel_init_lexer(&scanner, sc, FALSE, -1, grps);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    _gmx_sel_set_lex_input_str(scanner, str);
-    return run_parser(-1, scanner);
-}
diff --git a/src/gmxlib/selection/parsetree.h b/src/gmxlib/selection/parsetree.h
deleted file mode 100644 (file)
index 8d97d15..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Handling of intermediate selection parser data.
- *
- * The data types declared in this header are used by the parser to store
- * intermediate data when constructing method expressions.
- * In particular, the parameters for the method are stored.
- * The intermediate data is freed once a \c t_selelem object can be
- * constructed.
- * 
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_PARSETREE_H
-#define SELECTION_PARSETREE_H
-
-/*#include <typedefs.h>*/
-#include <types/simple.h>
-
-
-#include <selvalue.h>
-
-struct t_selelem;
-struct gmx_ana_indexgrps_t;
-struct gmx_ana_selmethod_t;
-struct gmx_ana_selparam_t;
-
-/*! \internal \brief
- * Describes a parsed value, possibly resulting from expression evaluation.
- */
-typedef struct t_selexpr_value
-{
-    /** Type of the value. */
-    e_selvalue_t            type;
-    /** TRUE if the value is the result of an expression. */
-    gmx_bool                    bExpr;
-    union {
-        /** The integer value/range (\p type INT_VALUE); */
-        struct {
-            /** Beginning of the range. */
-            int             i1;
-            /** End of the range; equals \p i1 for a single integer. */
-            int             i2;
-        }                   i;
-        /** The real value/range (\p type REAL_VALUE); */
-        struct {
-            /** Beginning of the range. */
-            real            r1;
-            /** End of the range; equals \p r1 for a single number. */
-            real            r2;
-        }                   r;
-        /** The string value (\p type STR_VALUE); */
-        char               *s;
-        /** The position value (\p type POS_VALUE); */
-        rvec                x;
-        /** The expression if \p bExpr is TRUE. */
-        struct t_selelem   *expr;
-    }                       u;
-    /** Pointer to the next value. */
-    struct t_selexpr_value *next;
-} t_selexpr_value;
-
-/*! \internal \brief
- * Describes a parsed method parameter.
- */
-typedef struct t_selexpr_param
-{
-    /** Name of the parameter. */
-    char                   *name;
-    /** Number of values given for this parameter. */
-    int                     nval;
-    /** Pointer to the first value. */
-    struct t_selexpr_value *value;
-    /** Pointer to the next parameter. */
-    struct t_selexpr_param *next;
-} t_selexpr_param;
-
-/** Error reporting function for the selection parser. */
-void
-_gmx_selparser_error(const char *fmt, ...);
-
-/** Allocates and initializes a constant \c t_selexpr_value. */
-t_selexpr_value *
-_gmx_selexpr_create_value(e_selvalue_t type);
-/** Allocates and initializes an expression \c t_selexpr_value. */
-t_selexpr_value *
-_gmx_selexpr_create_value_expr(struct t_selelem *expr);
-/** Allocates and initializes a \c t_selexpr_param. */
-t_selexpr_param *
-_gmx_selexpr_create_param(char *name);
-
-/** Frees the memory allocated for a chain of values. */
-void
-_gmx_selexpr_free_values(t_selexpr_value *value);
-/** Frees the memory allocated for a chain of parameters. */
-void
-_gmx_selexpr_free_params(t_selexpr_param *param);
-
-/** Propagates the flags for selection elements. */
-int
-_gmx_selelem_update_flags(struct t_selelem *sel);
-
-/** Initializes the method parameter data of \ref SEL_EXPRESSION and
- * \ref SEL_MODIFIER elements. */
-void
-_gmx_selelem_init_method_params(struct t_selelem *sel, void *scanner);
-/** Initializes the method for a \ref SEL_EXPRESSION selection element. */
-void
-_gmx_selelem_set_method(struct t_selelem *sel,
-                        struct gmx_ana_selmethod_t *method, void *scanner);
-
-/** Creates a \c t_selelem for arithmetic expression evaluation. */
-struct t_selelem *
-_gmx_sel_init_arithmetic(struct t_selelem *left, struct t_selelem *right,
-                         char op, void *scanner);
-/** Creates a \c t_selelem for comparsion expression evaluation. */
-struct t_selelem *
-_gmx_sel_init_comparison(struct t_selelem *left, struct t_selelem *right,
-                         char *cmpop, void *scanner);
-/** Creates a \c t_selelem for a keyword expression from the parsed data. */
-struct t_selelem *
-_gmx_sel_init_keyword(struct gmx_ana_selmethod_t *method,
-                      t_selexpr_value *args, const char *rpost, void *scanner);
-/** Creates a \c t_selelem for a method expression from the parsed data. */
-struct t_selelem *
-_gmx_sel_init_method(struct gmx_ana_selmethod_t *method,
-                     t_selexpr_param *params, const char *rpost,
-                     void *scanner);
-/** Creates a \c t_selelem for a modifier expression from the parsed data. */
-struct t_selelem *
-_gmx_sel_init_modifier(struct gmx_ana_selmethod_t *mod, t_selexpr_param *params,
-                       struct t_selelem *sel, void *scanner);
-/** Creates a \c t_selelem for evaluation of reference positions. */
-struct t_selelem *
-_gmx_sel_init_position(struct t_selelem *expr, const char *type, void *scanner);
-
-/** Creates a \c t_selelem for a constant position. */
-struct t_selelem *
-_gmx_sel_init_const_position(real x, real y, real z);
-/** Creates a \c t_selelem for a index group expression using group name. */
-struct t_selelem *
-_gmx_sel_init_group_by_name(const char *name, void *scanner);
-/** Creates a \c t_selelem for a index group expression using group index. */
-struct t_selelem *
-_gmx_sel_init_group_by_id(int id, void *scanner);
-/** Creates a \c t_selelem for a variable reference */
-struct t_selelem *
-_gmx_sel_init_variable_ref(struct t_selelem *sel);
-
-/** Creates a root \c t_selelem for a selection. */
-struct t_selelem *
-_gmx_sel_init_selection(char *name, struct t_selelem *sel, void *scanner);
-/** Creates a root \c t_selelem elements for a variable assignment. */
-struct t_selelem *
-_gmx_sel_assign_variable(char *name, struct t_selelem *expr, void *scanner);
-/** Appends a root \c t_selelem to a selection collection. */
-struct t_selelem *
-_gmx_sel_append_selection(struct t_selelem *sel, struct t_selelem *last,
-                          void *scanner);
-/** Check whether the parser should finish. */
-gmx_bool
-_gmx_sel_parser_should_finish(void *scanner);
-
-/** Handle empty commands. */
-void
-_gmx_sel_handle_empty_cmd(void *scanner);
-/** Process help commands. */
-void
-_gmx_sel_handle_help_cmd(char *topic, void *scanner);
-
-/* In params.c */
-/** Initializes an array of parameters based on input from the selection parser. */
-gmx_bool
-_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam,
-                      struct gmx_ana_selparam_t *param, struct t_selelem *root,
-                      void *scanner);
-
-#endif
diff --git a/src/gmxlib/selection/regenerate_parser.sh b/src/gmxlib/selection/regenerate_parser.sh
deleted file mode 100755 (executable)
index 5b597dc..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# This script runs Bison and/or Flex to regenerate the files as follows:
-#   parser.y  -> parser.c, parser.h
-#   scanner.l -> scanner.c, scanner_flex.h
-# The commands are run only if the generated files are older than the
-# Bison/Flex input files, or if a '-f' flag is provided.
-
-FORCE=
-if [ "x$1" == "x-f" ] ; then
-    FORCE=1
-fi
-
-# For convenience, change to the directory where the files are located
-# if the script is run from the root of the source tree.
-dirname=src/gmxlib/selection
-if [[ -f $dirname/parser.y && -f $dirname/scanner.l ]] ; then
-    cd $dirname
-fi
-
-[[ $FORCE || parser.y  -nt parser.c ]]  && bison -d -t -o parser.c parser.y
-[[ $FORCE || scanner.l -nt scanner.c ]] && flex -o scanner.c scanner.l
diff --git a/src/gmxlib/selection/scanner.c b/src/gmxlib/selection/scanner.c
deleted file mode 100644 (file)
index de74a3d..0000000
+++ /dev/null
@@ -1,2215 +0,0 @@
-#line 2 "scanner.c"
-
-#line 4 "scanner.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else  /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE _gmx_sel_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-       do \
-               { \
-               /* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-               *yy_cp = yyg->yy_hold_char; \
-               YY_RESTORE_YY_MORE_OFFSET \
-               yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-               } \
-       while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-       {
-       FILE *yy_input_file;
-
-       char *yy_ch_buf;                /* input buffer */
-       char *yy_buf_pos;               /* current position in input buffer */
-
-       /* Size of input buffer in bytes, not including room for EOB
-        * characters.
-        */
-       yy_size_t yy_buf_size;
-
-       /* Number of characters read into yy_ch_buf, not including EOB
-        * characters.
-        */
-       int yy_n_chars;
-
-       /* Whether we "own" the buffer - i.e., we know we created it,
-        * and can realloc() it to grow it, and should free() it to
-        * delete it.
-        */
-       int yy_is_our_buffer;
-
-       /* Whether this is an "interactive" input source; if so, and
-        * if we're using stdio for input, then we want to use getc()
-        * instead of fread(), to make sure we stop fetching input after
-        * each newline.
-        */
-       int yy_is_interactive;
-
-       /* Whether we're considered to be at the beginning of a line.
-        * If so, '^' rules will be active on the next match, otherwise
-        * not.
-        */
-       int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-       /* Whether to try to fill the input buffer when we reach the
-        * end of it.
-        */
-       int yy_fill_buffer;
-
-       int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-       /* When an EOF's been seen but there's still some text to process
-        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-        * shouldn't try reading from the input source any more.  We might
-        * still have a bunch of tokens to match, though, because of
-        * possible backing-up.
-        *
-        * When we actually see the EOF, we change the status to "new"
-        * (via _gmx_sel_yyrestart()), so that the user can continue scanning by
-        * just pointing yyin at a new input file.
-        */
-#define YY_BUFFER_EOF_PENDING 2
-
-       };
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void _gmx_sel_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void _gmx_sel_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner );
-
-static void _gmx_sel_yyensure_buffer_stack (yyscan_t yyscanner );
-static void _gmx_sel_yy_load_buffer_state (yyscan_t yyscanner );
-static void _gmx_sel_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER _gmx_sel_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE _gmx_sel_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *_gmx_sel_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *_gmx_sel_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void _gmx_sel_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer _gmx_sel_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-       { \
-       if ( ! YY_CURRENT_BUFFER ){ \
-        _gmx_sel_yyensure_buffer_stack (yyscanner); \
-               YY_CURRENT_BUFFER_LVALUE =    \
-            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-       } \
-       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-       }
-
-#define yy_set_bol(at_bol) \
-       { \
-       if ( ! YY_CURRENT_BUFFER ){\
-        _gmx_sel_yyensure_buffer_stack (yyscanner); \
-               YY_CURRENT_BUFFER_LVALUE =    \
-            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-       } \
-       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-       }
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-#define _gmx_sel_yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-       yyg->yytext_ptr = yy_bp; \
-       yyleng = (size_t) (yy_cp - yy_bp); \
-       yyg->yy_hold_char = *yy_cp; \
-       *yy_cp = '\0'; \
-       yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 26
-#define YY_END_OF_BUFFER 27
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-       {
-       flex_int32_t yy_verify;
-       flex_int32_t yy_nxt;
-       };
-static yyconst flex_int16_t yy_accept[89] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       27,   25,   23,    6,   20,   25,    1,   25,   25,    2,
-        6,   21,   25,   22,   25,   24,   22,   22,   22,   22,
-       22,   22,   25,   22,   22,   22,   22,   22,   11,    8,
-       10,   10,    9,   23,   21,    0,    4,    0,    1,   17,
-        3,    3,    2,   24,   24,   22,    5,   22,   22,   22,
-       18,   15,   22,   18,   16,   13,   22,   12,   22,   22,
-        8,    9,    0,    0,    3,   17,   22,   20,   19,   13,
-       22,    0,    3,    3,   22,    7,   14,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    5,    6,    1,    1,    7,    1,    1,
-        1,    1,    8,    1,    8,    9,    1,   10,   10,   10,
-       10,   10,   10,   10,   10,   10,   10,    1,   11,   12,
-       13,   12,    1,    1,   14,   14,   14,   14,   15,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
-        1,   16,    1,    1,   17,    1,   18,   14,   14,   19,
-
-       20,   21,   22,   23,   14,   14,   14,   24,   14,   25,
-       26,   27,   14,   28,   29,   30,   31,   14,   14,   32,
-       33,   14,    1,   34,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[35] =
-    {   0,
-        1,    1,    2,    1,    1,    1,    1,    1,    3,    4,
-        1,    1,    1,    4,    4,    1,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[94] =
-    {   0,
-        0,    0,  131,  130,   10,   12,  132,  131,   45,    0,
-      153,  158,  150,  158,  138,   75,    0,  143,  139,   72,
-      158,  135,  134,    0,  143,  136,  119,  115,  116,  113,
-      114,  113,  104,   62,  111,   68,  116,  115,  158,  132,
-      158,  158,    0,  131,  158,   79,  158,  127,    0,  158,
-       84,   87,   91,  122,   31,    0,  158,  111,  103,   98,
-        0,    0,   99,  158,    0,   96,  104,    0,   95,   99,
-      120,    0,   34,  107,   76,    0,   82,    0,    0,    0,
-       83,   99,   98,   95,   76,    0,    0,  158,  111,  115,
-      117,   94,   84
-
-    } ;
-
-static yyconst flex_int16_t yy_def[94] =
-    {   0,
-       88,    1,    1,    1,    1,    1,    1,    1,   88,    9,
-       88,   88,   88,   88,   88,   89,   90,   88,   88,   91,
-       88,   88,   88,   92,   88,   91,   92,   92,   92,   92,
-       92,   92,   88,   92,   92,   92,   92,   92,   88,   88,
-       88,   88,   93,   88,   88,   89,   88,   88,   90,   88,
-       88,   88,   91,   91,   91,   92,   88,   92,   92,   92,
-       92,   92,   92,   88,   92,   92,   92,   92,   92,   92,
-       88,   93,   88,   88,   91,   92,   92,   92,   92,   92,
-       92,   88,   88,   88,   92,   92,   92,    0,   88,   88,
-       88,   88,   88
-
-    } ;
-
-static yyconst flex_int16_t yy_nxt[193] =
-    {   0,
-       12,   13,   14,   15,   16,   17,   18,   12,   19,   20,
-       21,   22,   23,   24,   24,   25,   26,   27,   24,   24,
-       24,   28,   24,   24,   29,   30,   24,   24,   24,   31,
-       24,   32,   24,   33,   35,   36,   35,   36,   74,   88,
-       75,   82,   37,   83,   37,   39,   40,   41,   39,   39,
-       39,   39,   39,   39,   39,   42,   39,   39,   43,   43,
-       39,   39,   43,   43,   43,   43,   43,   43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,   39,   47,
-       52,   53,   65,   47,   88,   75,   55,   72,   67,   61,
-       48,   55,   68,   51,   48,   61,   51,   56,   73,   52,
-
-       53,   73,   87,   73,   84,   55,   73,   83,   83,   86,
-       55,   46,   85,   46,   46,   49,   84,   49,   49,   54,
-       54,   71,   81,   68,   80,   78,   79,   78,   77,   76,
-       88,   46,   44,   71,   70,   69,   66,   64,   63,   62,
-       61,   60,   59,   58,   88,   57,   45,   45,   51,   50,
-       45,   44,   88,   38,   38,   34,   34,   11,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88
-
-    } ;
-
-static yyconst flex_int16_t yy_chk[193] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    5,    5,    6,    6,   55,   55,
-       55,   73,    5,   73,    6,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,   16,
-       20,   20,   34,   46,   75,   75,   20,   93,   36,   34,
-       16,   20,   36,   51,   46,   36,   52,   92,   51,   53,
-
-       53,   52,   85,   51,   84,   53,   52,   83,   82,   81,
-       53,   89,   77,   89,   89,   90,   74,   90,   90,   91,
-       91,   71,   70,   69,   67,   66,   63,   60,   59,   58,
-       54,   48,   44,   40,   38,   37,   35,   33,   32,   31,
-       30,   29,   28,   27,   26,   25,   23,   22,   19,   18,
-       15,   13,   11,    8,    7,    4,    3,   88,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
-       88,   88
-
-    } ;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "scanner.l"
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \cond \internal \file scanner.l
- * \brief
- * Tokenizer for the selection language.
- * \endcond
- */
-/*! \internal \file scanner.c
- * \brief
- * Generated (from scanner.l by Flex) tokenizer for the selection language.
- */
-#line 41 "scanner.l"
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string2.h>
-
-#include "parser.h"
-#include "scanner.h"
-#include "scanner_internal.h"
-
-/* This macro is here to make the actions a bit shorter, since nearly every
- * action needs this call. */
-#define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
-
-#define YY_NO_UNISTD_H 1
-
-
-
-
-#line 571 "scanner.c"
-
-#define INITIAL 0
-#define matchof 1
-#define matchbool 2
-#define cmdstart 3
-#define help 4
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    int yy_n_chars;
-    int yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-int _gmx_sel_yylex_init (yyscan_t* scanner);
-
-int _gmx_sel_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int _gmx_sel_yylex_destroy (yyscan_t yyscanner );
-
-int _gmx_sel_yyget_debug (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE _gmx_sel_yyget_extra (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *_gmx_sel_yyget_in (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *_gmx_sel_yyget_out (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
-
-int _gmx_sel_yyget_leng (yyscan_t yyscanner );
-
-char *_gmx_sel_yyget_text (yyscan_t yyscanner );
-
-int _gmx_sel_yyget_lineno (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int _gmx_sel_yywrap (yyscan_t yyscanner );
-#else
-extern int _gmx_sel_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-               { \
-               int c = '*'; \
-               size_t n; \
-               for ( n = 0; n < max_size && \
-                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-                       buf[n] = (char) c; \
-               if ( c == '\n' ) \
-                       buf[n++] = (char) c; \
-               if ( c == EOF && ferror( yyin ) ) \
-                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
-               result = n; \
-               } \
-       else \
-               { \
-               errno=0; \
-               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-                       { \
-                       if( errno != EINTR) \
-                               { \
-                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
-                               break; \
-                               } \
-                       errno=0; \
-                       clearerr(yyin); \
-                       } \
-               }\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int _gmx_sel_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int _gmx_sel_yylex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-       YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-       register yy_state_type yy_current_state;
-       register char *yy_cp, *yy_bp;
-       register int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-#line 80 "scanner.l"
-
-
-
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(yyscanner);
-    int              retval;
-    /* Return a token if one is pending */
-    retval = _gmx_sel_lexer_process_pending(yylval, state);
-    if (retval != 0)
-    {
-        return retval;
-    }
-    /* Handle the start conditions for 'of' matching */
-    if (state->bMatchOf)
-    {
-        BEGIN(matchof);
-        state->bMatchOf = FALSE;
-    }
-    else if (state->bMatchBool)
-    {
-        BEGIN(matchbool);
-        state->bMatchBool = FALSE;
-    }
-    else if (state->bCmdStart)
-    {
-        BEGIN(cmdstart);
-    }
-    else if (YYSTATE != help)
-    {
-        BEGIN(0);
-    }
-
-
-#line 834 "scanner.c"
-
-       if ( !yyg->yy_init )
-               {
-               yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-               YY_USER_INIT;
-#endif
-
-               if ( ! yyg->yy_start )
-                       yyg->yy_start = 1;      /* first start state */
-
-               if ( ! yyin )
-                       yyin = stdin;
-
-               if ( ! yyout )
-                       yyout = stdout;
-
-               if ( ! YY_CURRENT_BUFFER ) {
-                       _gmx_sel_yyensure_buffer_stack (yyscanner);
-                       YY_CURRENT_BUFFER_LVALUE =
-                               _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-               }
-
-               _gmx_sel_yy_load_buffer_state(yyscanner );
-               }
-
-       while ( 1 )             /* loops until end-of-file is reached */
-               {
-               yy_cp = yyg->yy_c_buf_p;
-
-               /* Support of yytext. */
-               *yy_cp = yyg->yy_hold_char;
-
-               /* yy_bp points to the position in yy_ch_buf of the start of
-                * the current run.
-                */
-               yy_bp = yy_cp;
-
-               yy_current_state = yyg->yy_start;
-yy_match:
-               do
-                       {
-                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-                       if ( yy_accept[yy_current_state] )
-                               {
-                               yyg->yy_last_accepting_state = yy_current_state;
-                               yyg->yy_last_accepting_cpos = yy_cp;
-                               }
-                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-                               {
-                               yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 89 )
-                                       yy_c = yy_meta[(unsigned int) yy_c];
-                               }
-                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-                       ++yy_cp;
-                       }
-               while ( yy_current_state != 88 );
-               yy_cp = yyg->yy_last_accepting_cpos;
-               yy_current_state = yyg->yy_last_accepting_state;
-
-yy_find_action:
-               yy_act = yy_accept[yy_current_state];
-
-               YY_DO_BEFORE_ACTION;
-
-do_action:     /* This label is used only to access EOF actions. */
-
-               switch ( yy_act )
-       { /* beginning of action switch */
-                       case 0: /* must back up */
-                       /* undo the effects of YY_DO_BEFORE_ACTION */
-                       *yy_cp = yyg->yy_hold_char;
-                       yy_cp = yyg->yy_last_accepting_cpos;
-                       yy_current_state = yyg->yy_last_accepting_state;
-                       goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 112 "scanner.l"
-
-       YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 113 "scanner.l"
-{ yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
-       YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 114 "scanner.l"
-{ yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
-       YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 115 "scanner.l"
-{ yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
-       YY_BREAK
-case 5:
-/* rule 5 can match eol */
-YY_RULE_SETUP
-#line 117 "scanner.l"
-{ _gmx_sel_lexer_add_token(" ", 1, state); }
-       YY_BREAK
-case 6:
-/* rule 6 can match eol */
-YY_RULE_SETUP
-#line 118 "scanner.l"
-{
-                    if (yytext[0] == ';' || state->bInteractive)
-                    {
-                        rtrim(state->pselstr);
-                        return CMD_SEP;
-                    }
-                    else
-                    {
-                        _gmx_sel_lexer_add_token(" ", 1, state);
-                    }
-                }
-       YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 130 "scanner.l"
-{ BEGIN(help); return HELP; }
-       YY_BREAK
-
-case 8:
-YY_RULE_SETUP
-#line 132 "scanner.l"
-
-       YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 133 "scanner.l"
-{ yylval->str = gmx_strndup(yytext, yyleng); return HELP_TOPIC; }
-       YY_BREAK
-case 10:
-/* rule 10 can match eol */
-YY_RULE_SETUP
-#line 134 "scanner.l"
-{ return CMD_SEP; }
-       YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 135 "scanner.l"
-{ return INVALID; }
-       YY_BREAK
-
-
-case 12:
-YY_RULE_SETUP
-#line 139 "scanner.l"
-{ ADD_TOKEN; yylval->i = 1; return TOK_INT; }
-       YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 140 "scanner.l"
-{ ADD_TOKEN; yylval->i = 0; return TOK_INT; }
-       YY_BREAK
-
-case 14:
-YY_RULE_SETUP
-#line 142 "scanner.l"
-{ ADD_TOKEN; return GROUP; }
-       YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 143 "scanner.l"
-{ ADD_TOKEN; return TO; }
-       YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 144 "scanner.l"
-{ ADD_TOKEN; BEGIN(0); return OF; }
-       YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 145 "scanner.l"
-{ ADD_TOKEN; return AND; }
-       YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 146 "scanner.l"
-{ ADD_TOKEN; return OR; }
-       YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 147 "scanner.l"
-{ ADD_TOKEN; return XOR; }
-       YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 148 "scanner.l"
-{ ADD_TOKEN; return NOT; }
-       YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 149 "scanner.l"
-{ yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return CMP_OP; }
-       YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 151 "scanner.l"
-{ return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
-       YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 153 "scanner.l"
-{ _gmx_sel_lexer_add_token(" ", 1, state); }
-       YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 154 "scanner.l"
-{ yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
-       YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 155 "scanner.l"
-{ ADD_TOKEN; return yytext[0]; }
-       YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 156 "scanner.l"
-YY_FATAL_ERROR( "flex scanner jammed" );
-       YY_BREAK
-#line 1060 "scanner.c"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(matchof):
-case YY_STATE_EOF(matchbool):
-case YY_STATE_EOF(cmdstart):
-case YY_STATE_EOF(help):
-       yyterminate();
-
-       case YY_END_OF_BUFFER:
-               {
-               /* Amount of text matched not including the EOB char. */
-               int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-               /* Undo the effects of YY_DO_BEFORE_ACTION. */
-               *yy_cp = yyg->yy_hold_char;
-               YY_RESTORE_YY_MORE_OFFSET
-
-               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-                       {
-                       /* We're scanning a new file or input source.  It's
-                        * possible that this happened because the user
-                        * just pointed yyin at a new source and called
-                        * _gmx_sel_yylex().  If so, then we have to assure
-                        * consistency between YY_CURRENT_BUFFER and our
-                        * globals.  Here is the right place to do so, because
-                        * this is the first action (other than possibly a
-                        * back-up) that will match for the new input source.
-                        */
-                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-                       }
-
-               /* Note that here we test for yy_c_buf_p "<=" to the position
-                * of the first EOB in the buffer, since yy_c_buf_p will
-                * already have been incremented past the NUL character
-                * (since all states make transitions on EOB to the
-                * end-of-buffer state).  Contrast this with the test
-                * in input().
-                */
-               if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-                       { /* This was really a NUL. */
-                       yy_state_type yy_next_state;
-
-                       yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-                       yy_current_state = yy_get_previous_state( yyscanner );
-
-                       /* Okay, we're now positioned to make the NUL
-                        * transition.  We couldn't have
-                        * yy_get_previous_state() go ahead and do it
-                        * for us because it doesn't know how to deal
-                        * with the possibility of jamming (and we don't
-                        * want to build jamming into it because then it
-                        * will run more slowly).
-                        */
-
-                       yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-                       yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-                       if ( yy_next_state )
-                               {
-                               /* Consume the NUL. */
-                               yy_cp = ++yyg->yy_c_buf_p;
-                               yy_current_state = yy_next_state;
-                               goto yy_match;
-                               }
-
-                       else
-                               {
-                               yy_cp = yyg->yy_last_accepting_cpos;
-                               yy_current_state = yyg->yy_last_accepting_state;
-                               goto yy_find_action;
-                               }
-                       }
-
-               else switch ( yy_get_next_buffer( yyscanner ) )
-                       {
-                       case EOB_ACT_END_OF_FILE:
-                               {
-                               yyg->yy_did_buffer_switch_on_eof = 0;
-
-                               if ( _gmx_sel_yywrap(yyscanner ) )
-                                       {
-                                       /* Note: because we've taken care in
-                                        * yy_get_next_buffer() to have set up
-                                        * yytext, we can now set up
-                                        * yy_c_buf_p so that if some total
-                                        * hoser (like flex itself) wants to
-                                        * call the scanner after we return the
-                                        * YY_NULL, it'll still work - another
-                                        * YY_NULL will get returned.
-                                        */
-                                       yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-                                       yy_act = YY_STATE_EOF(YY_START);
-                                       goto do_action;
-                                       }
-
-                               else
-                                       {
-                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
-                                               YY_NEW_FILE;
-                                       }
-                               break;
-                               }
-
-                       case EOB_ACT_CONTINUE_SCAN:
-                               yyg->yy_c_buf_p =
-                                       yyg->yytext_ptr + yy_amount_of_matched_text;
-
-                               yy_current_state = yy_get_previous_state( yyscanner );
-
-                               yy_cp = yyg->yy_c_buf_p;
-                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-                               goto yy_match;
-
-                       case EOB_ACT_LAST_MATCH:
-                               yyg->yy_c_buf_p =
-                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-                               yy_current_state = yy_get_previous_state( yyscanner );
-
-                               yy_cp = yyg->yy_c_buf_p;
-                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-                               goto yy_find_action;
-                       }
-               break;
-               }
-
-       default:
-               YY_FATAL_ERROR(
-                       "fatal flex scanner internal error--no action found" );
-       } /* end of action switch */
-               } /* end of scanning one token */
-} /* end of _gmx_sel_yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *     EOB_ACT_LAST_MATCH -
- *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *     EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-       register char *source = yyg->yytext_ptr;
-       register int number_to_move, i;
-       int ret_val;
-
-       if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-               YY_FATAL_ERROR(
-               "fatal flex scanner internal error--end of buffer missed" );
-
-       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-               { /* Don't try to fill the buffer, so this is an EOF. */
-               if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-                       {
-                       /* We matched a single character, the EOB, so
-                        * treat this as a final EOF.
-                        */
-                       return EOB_ACT_END_OF_FILE;
-                       }
-
-               else
-                       {
-                       /* We matched some text prior to the EOB, first
-                        * process it.
-                        */
-                       return EOB_ACT_LAST_MATCH;
-                       }
-               }
-
-       /* Try to read more data. */
-
-       /* First move last chars to start of buffer. */
-       number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-       for ( i = 0; i < number_to_move; ++i )
-               *(dest++) = *(source++);
-
-       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-               /* don't do the read, it's not guaranteed to return an EOF,
-                * just force an EOF
-                */
-               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-       else
-               {
-                       int num_to_read =
-                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-               while ( num_to_read <= 0 )
-                       { /* Not enough room in the buffer - grow it. */
-
-                       /* just a shorter name for the current buffer */
-                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-                       int yy_c_buf_p_offset =
-                               (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-                       if ( b->yy_is_our_buffer )
-                               {
-                               int new_size = b->yy_buf_size * 2;
-
-                               if ( new_size <= 0 )
-                                       b->yy_buf_size += b->yy_buf_size / 8;
-                               else
-                                       b->yy_buf_size *= 2;
-
-                               b->yy_ch_buf = (char *)
-                                       /* Include room in for 2 EOB chars. */
-                                       _gmx_sel_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-                               }
-                       else
-                               /* Can't grow it, we don't own it. */
-                               b->yy_ch_buf = 0;
-
-                       if ( ! b->yy_ch_buf )
-                               YY_FATAL_ERROR(
-                               "fatal error - scanner input buffer overflow" );
-
-                       yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-                                               number_to_move - 1;
-
-                       }
-
-               if ( num_to_read > YY_READ_BUF_SIZE )
-                       num_to_read = YY_READ_BUF_SIZE;
-
-               /* Read in more data. */
-               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-                       yyg->yy_n_chars, (size_t) num_to_read );
-
-               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-               }
-
-       if ( yyg->yy_n_chars == 0 )
-               {
-               if ( number_to_move == YY_MORE_ADJ )
-                       {
-                       ret_val = EOB_ACT_END_OF_FILE;
-                       _gmx_sel_yyrestart(yyin  ,yyscanner);
-                       }
-
-               else
-                       {
-                       ret_val = EOB_ACT_LAST_MATCH;
-                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-                               YY_BUFFER_EOF_PENDING;
-                       }
-               }
-
-       else
-               ret_val = EOB_ACT_CONTINUE_SCAN;
-
-       if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-               /* Extend the array by 50%, plus the number we really need. */
-               yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _gmx_sel_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-       }
-
-       yyg->yy_n_chars += number_to_move;
-       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-       yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-       return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-       register yy_state_type yy_current_state;
-       register char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       yy_current_state = yyg->yy_start;
-
-       for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-               {
-               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-               if ( yy_accept[yy_current_state] )
-                       {
-                       yyg->yy_last_accepting_state = yy_current_state;
-                       yyg->yy_last_accepting_cpos = yy_cp;
-                       }
-               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-                       {
-                       yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 89 )
-                               yy_c = yy_meta[(unsigned int) yy_c];
-                       }
-               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-               }
-
-       return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *     next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-       register int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-       register char *yy_cp = yyg->yy_c_buf_p;
-
-       register YY_CHAR yy_c = 1;
-       if ( yy_accept[yy_current_state] )
-               {
-               yyg->yy_last_accepting_state = yy_current_state;
-               yyg->yy_last_accepting_cpos = yy_cp;
-               }
-       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-               {
-               yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 89 )
-                       yy_c = yy_meta[(unsigned int) yy_c];
-               }
-       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 88);
-
-       return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
-{
-       register char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yy_cp = yyg->yy_c_buf_p;
-
-       /* undo effects of setting up yytext */
-       *yy_cp = yyg->yy_hold_char;
-
-       if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-               { /* need to shift things up to make room */
-               /* +2 for EOB chars. */
-               register int number_to_move = yyg->yy_n_chars + 2;
-               register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-                                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-               register char *source =
-                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-               while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-                       *--dest = *--source;
-
-               yy_cp += (int) (dest - source);
-               yy_bp += (int) (dest - source);
-               YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-               if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
-               }
-
-       *--yy_cp = (char) c;
-
-       yyg->yytext_ptr = yy_bp;
-       yyg->yy_hold_char = *yy_cp;
-       yyg->yy_c_buf_p = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-       int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       *yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-       if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-               {
-               /* yy_c_buf_p now points to the character we want to return.
-                * If this occurs *before* the EOB characters, then it's a
-                * valid NUL; if not, then we've hit the end of the buffer.
-                */
-               if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-                       /* This was really a NUL. */
-                       *yyg->yy_c_buf_p = '\0';
-
-               else
-                       { /* need more input */
-                       int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-                       ++yyg->yy_c_buf_p;
-
-                       switch ( yy_get_next_buffer( yyscanner ) )
-                               {
-                               case EOB_ACT_LAST_MATCH:
-                                       /* This happens because yy_g_n_b()
-                                        * sees that we've accumulated a
-                                        * token and flags that we need to
-                                        * try matching the token before
-                                        * proceeding.  But for input(),
-                                        * there's no matching to consider.
-                                        * So convert the EOB_ACT_LAST_MATCH
-                                        * to EOB_ACT_END_OF_FILE.
-                                        */
-
-                                       /* Reset buffer status. */
-                                       _gmx_sel_yyrestart(yyin ,yyscanner);
-
-                                       /*FALLTHROUGH*/
-
-                               case EOB_ACT_END_OF_FILE:
-                                       {
-                                       if ( _gmx_sel_yywrap(yyscanner ) )
-                                               return EOF;
-
-                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
-                                               YY_NEW_FILE;
-#ifdef __cplusplus
-                                       return yyinput(yyscanner);
-#else
-                                       return input(yyscanner);
-#endif
-                                       }
-
-                               case EOB_ACT_CONTINUE_SCAN:
-                                       yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-                                       break;
-                               }
-                       }
-               }
-
-       c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
-       *yyg->yy_c_buf_p = '\0';        /* preserve yytext */
-       yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-       return c;
-}
-#endif /* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void _gmx_sel_yyrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       if ( ! YY_CURRENT_BUFFER ){
-        _gmx_sel_yyensure_buffer_stack (yyscanner);
-               YY_CURRENT_BUFFER_LVALUE =
-            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-       }
-
-       _gmx_sel_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-       _gmx_sel_yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void _gmx_sel_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       /* TODO. We should be able to replace this entire function body
-        * with
-        *              _gmx_sel_yypop_buffer_state();
-        *              _gmx_sel_yypush_buffer_state(new_buffer);
-     */
-       _gmx_sel_yyensure_buffer_stack (yyscanner);
-       if ( YY_CURRENT_BUFFER == new_buffer )
-               return;
-
-       if ( YY_CURRENT_BUFFER )
-               {
-               /* Flush out information for old buffer. */
-               *yyg->yy_c_buf_p = yyg->yy_hold_char;
-               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-               }
-
-       YY_CURRENT_BUFFER_LVALUE = new_buffer;
-       _gmx_sel_yy_load_buffer_state(yyscanner );
-
-       /* We don't actually know whether we did this switch during
-        * EOF (_gmx_sel_yywrap()) processing, but the only time this flag
-        * is looked at is after _gmx_sel_yywrap() is called, so it's safe
-        * to go ahead and always set it.
-        */
-       yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void _gmx_sel_yy_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-       yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-       yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE _gmx_sel_yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-       YY_BUFFER_STATE b;
-    
-       b = (YY_BUFFER_STATE) _gmx_sel_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-       if ( ! b )
-               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_create_buffer()" );
-
-       b->yy_buf_size = size;
-
-       /* yy_ch_buf has to be 2 characters longer than the size given because
-        * we need to put in 2 end-of-buffer characters.
-        */
-       b->yy_ch_buf = (char *) _gmx_sel_yyalloc(b->yy_buf_size + 2 ,yyscanner );
-       if ( ! b->yy_ch_buf )
-               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_create_buffer()" );
-
-       b->yy_is_our_buffer = 1;
-
-       _gmx_sel_yy_init_buffer(b,file ,yyscanner);
-
-       return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with _gmx_sel_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       if ( ! b )
-               return;
-
-       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-       if ( b->yy_is_our_buffer )
-               _gmx_sel_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
-       _gmx_sel_yyfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a _gmx_sel_yyrestart() or at EOF.
- */
-    static void _gmx_sel_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-       int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       _gmx_sel_yy_flush_buffer(b ,yyscanner);
-
-       b->yy_input_file = file;
-       b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then _gmx_sel_yy_init_buffer was _probably_
-     * called from _gmx_sel_yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-       errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-       if ( ! b )
-               return;
-
-       b->yy_n_chars = 0;
-
-       /* We always need two end-of-buffer characters.  The first causes
-        * a transition to the end-of-buffer state.  The second causes
-        * a jam in that state.
-        */
-       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-       b->yy_buf_pos = &b->yy_ch_buf[0];
-
-       b->yy_at_bol = 1;
-       b->yy_buffer_status = YY_BUFFER_NEW;
-
-       if ( b == YY_CURRENT_BUFFER )
-               _gmx_sel_yy_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-       if (new_buffer == NULL)
-               return;
-
-       _gmx_sel_yyensure_buffer_stack(yyscanner);
-
-       /* This block is copied from _gmx_sel_yy_switch_to_buffer. */
-       if ( YY_CURRENT_BUFFER )
-               {
-               /* Flush out information for old buffer. */
-               *yyg->yy_c_buf_p = yyg->yy_hold_char;
-               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-               }
-
-       /* Only push if top exists. Otherwise, replace top. */
-       if (YY_CURRENT_BUFFER)
-               yyg->yy_buffer_stack_top++;
-       YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-       /* copied from _gmx_sel_yy_switch_to_buffer. */
-       _gmx_sel_yy_load_buffer_state(yyscanner );
-       yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-       if (!YY_CURRENT_BUFFER)
-               return;
-
-       _gmx_sel_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-       YY_CURRENT_BUFFER_LVALUE = NULL;
-       if (yyg->yy_buffer_stack_top > 0)
-               --yyg->yy_buffer_stack_top;
-
-       if (YY_CURRENT_BUFFER) {
-               _gmx_sel_yy_load_buffer_state(yyscanner );
-               yyg->yy_did_buffer_switch_on_eof = 1;
-       }
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void _gmx_sel_yyensure_buffer_stack (yyscan_t yyscanner)
-{
-       int num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-       if (!yyg->yy_buffer_stack) {
-
-               /* First allocation is just for 2 elements, since we don't know if this
-                * scanner will even need a stack. We use 2 instead of 1 to avoid an
-                * immediate realloc on the next call.
-         */
-               num_to_alloc = 1;
-               yyg->yy_buffer_stack = (struct yy_buffer_state**)_gmx_sel_yyalloc
-                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
-                                                               , yyscanner);
-               if ( ! yyg->yy_buffer_stack )
-                       YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yyensure_buffer_stack()" );
-                                                                 
-               memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-                               
-               yyg->yy_buffer_stack_max = num_to_alloc;
-               yyg->yy_buffer_stack_top = 0;
-               return;
-       }
-
-       if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-               /* Increase the buffer to prepare for a possible push. */
-               int grow_size = 8 /* arbitrary grow size */;
-
-               num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-               yyg->yy_buffer_stack = (struct yy_buffer_state**)_gmx_sel_yyrealloc
-                                                               (yyg->yy_buffer_stack,
-                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
-                                                               , yyscanner);
-               if ( ! yyg->yy_buffer_stack )
-                       YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yyensure_buffer_stack()" );
-
-               /* zero only the new slots.*/
-               memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-               yyg->yy_buffer_stack_max = num_to_alloc;
-       }
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE _gmx_sel_yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-       YY_BUFFER_STATE b;
-    
-       if ( size < 2 ||
-            base[size-2] != YY_END_OF_BUFFER_CHAR ||
-            base[size-1] != YY_END_OF_BUFFER_CHAR )
-               /* They forgot to leave room for the EOB's. */
-               return 0;
-
-       b = (YY_BUFFER_STATE) _gmx_sel_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-       if ( ! b )
-               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_scan_buffer()" );
-
-       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
-       b->yy_buf_pos = b->yy_ch_buf = base;
-       b->yy_is_our_buffer = 0;
-       b->yy_input_file = 0;
-       b->yy_n_chars = b->yy_buf_size;
-       b->yy_is_interactive = 0;
-       b->yy_at_bol = 1;
-       b->yy_fill_buffer = 0;
-       b->yy_buffer_status = YY_BUFFER_NEW;
-
-       _gmx_sel_yy_switch_to_buffer(b ,yyscanner );
-
-       return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to _gmx_sel_yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       _gmx_sel_yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-    
-       return _gmx_sel_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to _gmx_sel_yylex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE _gmx_sel_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-{
-       YY_BUFFER_STATE b;
-       char *buf;
-       yy_size_t n;
-       int i;
-    
-       /* Get memory for full buffer, including space for trailing EOB's. */
-       n = _yybytes_len + 2;
-       buf = (char *) _gmx_sel_yyalloc(n ,yyscanner );
-       if ( ! buf )
-               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_scan_bytes()" );
-
-       for ( i = 0; i < _yybytes_len; ++i )
-               buf[i] = yybytes[i];
-
-       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-       b = _gmx_sel_yy_scan_buffer(buf,n ,yyscanner);
-       if ( ! b )
-               YY_FATAL_ERROR( "bad buffer in _gmx_sel_yy_scan_bytes()" );
-
-       /* It's okay to grow etc. this buffer, and we should throw it
-        * away when we're done.
-        */
-       b->yy_is_our_buffer = 1;
-
-       return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-       (void) fprintf( stderr, "%s\n", msg );
-       exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-       do \
-               { \
-               /* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-               yytext[yyleng] = yyg->yy_hold_char; \
-               yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-               yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-               *yyg->yy_c_buf_p = '\0'; \
-               yyleng = yyless_macro_arg; \
-               } \
-       while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE _gmx_sel_yyget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int _gmx_sel_yyget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int _gmx_sel_yyget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-    
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *_gmx_sel_yyget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *_gmx_sel_yyget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int _gmx_sel_yyget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *_gmx_sel_yyget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void _gmx_sel_yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void _gmx_sel_yyset_lineno (int  line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "_gmx_sel_yyset_lineno called with no buffer" , yyscanner); 
-    
-    yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void _gmx_sel_yyset_column (int  column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           yy_fatal_error( "_gmx_sel_yyset_column called with no buffer" , yyscanner); 
-    
-    yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see _gmx_sel_yy_switch_to_buffer
- */
-void _gmx_sel_yyset_in (FILE *  in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = in_str ;
-}
-
-void _gmx_sel_yyset_out (FILE *  out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = out_str ;
-}
-
-int _gmx_sel_yyget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void _gmx_sel_yyset_debug (int  bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* _gmx_sel_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int _gmx_sel_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) _gmx_sel_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* _gmx_sel_yylex_init_extra has the same functionality as _gmx_sel_yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to _gmx_sel_yyalloc in
- * the yyextra field.
- */
-
-int _gmx_sel_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    _gmx_sel_yyset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-       
-    *ptr_yy_globals = (yyscan_t) _gmx_sel_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-       
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-    
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-    
-    _gmx_sel_yyset_extra (yy_user_defined, *ptr_yy_globals);
-    
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from _gmx_sel_yylex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = 0;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = (char *) 0;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * _gmx_sel_yylex_init()
-     */
-    return 0;
-}
-
-/* _gmx_sel_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int _gmx_sel_yylex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-       while(YY_CURRENT_BUFFER){
-               _gmx_sel_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-               YY_CURRENT_BUFFER_LVALUE = NULL;
-               _gmx_sel_yypop_buffer_state(yyscanner);
-       }
-
-       /* Destroy the stack itself. */
-       _gmx_sel_yyfree(yyg->yy_buffer_stack ,yyscanner);
-       yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        _gmx_sel_yyfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * _gmx_sel_yylex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    _gmx_sel_yyfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-       register int i;
-       for ( i = 0; i < n; ++i )
-               s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-       register int n;
-       for ( n = 0; s[n]; ++n )
-               ;
-
-       return n;
-}
-#endif
-
-void *_gmx_sel_yyalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-       return (void *) malloc( size );
-}
-
-void *_gmx_sel_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-       /* The cast to (char *) in the following accommodates both
-        * implementations that use char* generic pointers, and those
-        * that use void* generic pointers.  It works with the latter
-        * because both ANSI C and C++ allow castless assignment from
-        * any pointer type to void*, and deal with argument conversions
-        * as though doing an assignment.
-        */
-       return (void *) realloc( (char *) ptr, size );
-}
-
-void _gmx_sel_yyfree (void * ptr , yyscan_t yyscanner)
-{
-       free( (char *) ptr );   /* see _gmx_sel_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 156 "scanner.l"
diff --git a/src/gmxlib/selection/scanner.h b/src/gmxlib/selection/scanner.h
deleted file mode 100644 (file)
index 4486038..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief
- * Parser/scanner interaction functions.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_SCANNER_H
-#define SELECTION_SCANNER_H
-
-#include "parser.h"
-
-struct gmx_ana_indexgrps_t;
-struct gmx_ana_selcollection_t;
-
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void *yyscan_t;
-#endif
-
-/** Initializes the selection scanner. */
-int
-_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
-                    gmx_bool bInteractive, int maxnr,
-                    struct gmx_ana_indexgrps_t *grps);
-/** Frees memory allocated for the selection scanner. */
-void
-_gmx_sel_free_lexer(yyscan_t scanner);
-
-/** Returns TRUE if the scanner is interactive. */
-gmx_bool
-_gmx_sel_is_lexer_interactive(yyscan_t scanner);
-/** Returns the selection collection for the scanner. */
-struct gmx_ana_selcollection_t *
-_gmx_sel_lexer_selcollection(yyscan_t scanner);
-/** Returns the external index groups for the scanner. */
-struct gmx_ana_indexgrps_t *
-_gmx_sel_lexer_indexgrps(yyscan_t scanner);
-/** Returns the number of selections after which the parser should stop. */
-int
-_gmx_sel_lexer_exp_selcount(yyscan_t scanner);
-
-/** Returns a pretty string of the current selection.  */
-const char *
-_gmx_sel_lexer_pselstr(yyscan_t scanner);
-/** Clears the current selection string.  */
-void
-_gmx_sel_lexer_clear_pselstr(yyscan_t scanner);
-/** Clears the method stack in the scanner in error situations. */
-void
-_gmx_sel_lexer_clear_method_stack(yyscan_t scanner);
-/** Notifies the scanner that a complete method expression has been parsed. */
-void
-_gmx_sel_finish_method(yyscan_t scanner);
-/** Initializes the scanner to scan a file. */
-void
-_gmx_sel_set_lex_input_file(yyscan_t scanner, FILE *fp);
-/** Initializes the scanner to scan a string. */
-void
-_gmx_sel_set_lex_input_str(yyscan_t scanner, const char *str);
-
-/** A wrapper for the actual scanner, used by the Bison parser. */
-int
-_gmx_sel_yyblex(YYSTYPE *yylval, yyscan_t yyscanner);
-
-#endif
diff --git a/src/gmxlib/selection/scanner.l b/src/gmxlib/selection/scanner.l
deleted file mode 100644 (file)
index b23b2b3..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \cond \internal \file scanner.l
- * \brief
- * Tokenizer for the selection language.
- * \endcond
- */
-/*! \internal \file scanner.c
- * \brief
- * Generated (from scanner.l by Flex) tokenizer for the selection language.
- */
-%{
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string2.h>
-
-#include "parser.h"
-#include "scanner.h"
-#include "scanner_internal.h"
-
-/* This macro is here to make the actions a bit shorter, since nearly every
- * action needs this call. */
-#define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
-
-%}
-
-INTEGER    [[:digit:]]+
-DSEQ       ([[:digit:]]+)
-FRAC       (([[:digit:]]*"."{DSEQ})|{DSEQ}".")
-EXP        ([eE][+-]?{DSEQ})
-REAL       (({FRAC}{EXP}?)|({DSEQ}{EXP}))
-STRING     (\"([^\"\\\n]|(\\\"))*\")
-IDENTIFIER ([[:alpha:]][_[:alnum:]]*)
-CMPOP      (([<>]=?)|([!=]=))
-COMMENT    (#.*)
-
-%option nodefault
-%option noyywrap
-%option reentrant
-%option prefix="_gmx_sel_yy"
-%option header-file="scanner_flex.h"
-%option nounistd
-%option never-interactive
-
-%s matchof
-%s matchbool
-%s cmdstart
-%x help
-
-%%
-
-%{
-    gmx_sel_lexer_t *state = yyget_extra(yyscanner);
-    int              retval;
-    /* Return a token if one is pending */
-    retval = _gmx_sel_lexer_process_pending(yylval, state);
-    if (retval != 0)
-    {
-        return retval;
-    }
-    /* Handle the start conditions for 'of' matching */
-    if (state->bMatchOf)
-    {
-        BEGIN(matchof);
-        state->bMatchOf = FALSE;
-    }
-    else if (state->bMatchBool)
-    {
-        BEGIN(matchbool);
-        state->bMatchBool = FALSE;
-    }
-    else if (state->bCmdStart)
-    {
-        BEGIN(cmdstart);
-    }
-    else if (YYSTATE != help)
-    {
-        BEGIN(0);
-    }
-%}
-
-{COMMENT}
-{INTEGER}       { yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
-{REAL}          { yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
-{STRING}        { yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
-
-\\\n            { _gmx_sel_lexer_add_token(" ", 1, state); }
-";"|\n          {
-                    if (yytext[0] == ';' || state->bInteractive)
-                    {
-                        rtrim(state->pselstr);
-                        return CMD_SEP;
-                    }
-                    else
-                    {
-                        _gmx_sel_lexer_add_token(" ", 1, state);
-                    }
-                }
-
-<cmdstart>help  { BEGIN(help); return HELP; }
-<help>{
-[[:blank:]]+
-{IDENTIFIER}    { yylval->str = gmx_strndup(yytext, yyleng); return HELP_TOPIC; }
-";"|\n          { return CMD_SEP; }
-.               { return INVALID; }
-}
-
-<matchbool>{
-yes|on          { ADD_TOKEN; yylval->i = 1; return TOK_INT; }
-no|off          { ADD_TOKEN; yylval->i = 0; return TOK_INT; }
-}
-group           { ADD_TOKEN; return GROUP; }
-to              { ADD_TOKEN; return TO; }
-<matchof>of     { ADD_TOKEN; BEGIN(0); return OF; }
-and|"&&"        { ADD_TOKEN; return AND; }
-or|"||"         { ADD_TOKEN; return OR; }
-xor             { ADD_TOKEN; return XOR; }
-not|"!"         { ADD_TOKEN; return NOT; }
-{CMPOP}         { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return CMP_OP; }
-
-{IDENTIFIER}    { return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
-
-[[:blank:]]+    { _gmx_sel_lexer_add_token(" ", 1, state); }
-[_[:alnum:]]+   { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
-.               { ADD_TOKEN; return yytext[0]; }
diff --git a/src/gmxlib/selection/scanner_flex.h b/src/gmxlib/selection/scanner_flex.h
deleted file mode 100644 (file)
index 0a89dc9..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-#ifndef _gmx_sel_yyHEADER_H
-#define _gmx_sel_yyHEADER_H 1
-#define _gmx_sel_yyIN_HEADER 1
-
-#line 6 "scanner_flex.h"
-
-#line 8 "scanner_flex.h"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else  /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-       {
-       FILE *yy_input_file;
-
-       char *yy_ch_buf;                /* input buffer */
-       char *yy_buf_pos;               /* current position in input buffer */
-
-       /* Size of input buffer in bytes, not including room for EOB
-        * characters.
-        */
-       yy_size_t yy_buf_size;
-
-       /* Number of characters read into yy_ch_buf, not including EOB
-        * characters.
-        */
-       int yy_n_chars;
-
-       /* Whether we "own" the buffer - i.e., we know we created it,
-        * and can realloc() it to grow it, and should free() it to
-        * delete it.
-        */
-       int yy_is_our_buffer;
-
-       /* Whether this is an "interactive" input source; if so, and
-        * if we're using stdio for input, then we want to use getc()
-        * instead of fread(), to make sure we stop fetching input after
-        * each newline.
-        */
-       int yy_is_interactive;
-
-       /* Whether we're considered to be at the beginning of a line.
-        * If so, '^' rules will be active on the next match, otherwise
-        * not.
-        */
-       int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-       /* Whether to try to fill the input buffer when we reach the
-        * end of it.
-        */
-       int yy_fill_buffer;
-
-       int yy_buffer_status;
-
-       };
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-void _gmx_sel_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void _gmx_sel_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner );
-
-YY_BUFFER_STATE _gmx_sel_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE _gmx_sel_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *_gmx_sel_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *_gmx_sel_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void _gmx_sel_yyfree (void * ,yyscan_t yyscanner );
-
-#define _gmx_sel_yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-#define yytext_ptr yytext_r
-
-#ifdef YY_HEADER_EXPORT_START_CONDITIONS
-#define INITIAL 0
-#define matchof 1
-#define matchbool 2
-#define cmdstart 3
-#define help 4
-
-#endif
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-int _gmx_sel_yylex_init (yyscan_t* scanner);
-
-int _gmx_sel_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int _gmx_sel_yylex_destroy (yyscan_t yyscanner );
-
-int _gmx_sel_yyget_debug (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE _gmx_sel_yyget_extra (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *_gmx_sel_yyget_in (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *_gmx_sel_yyget_out (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
-
-int _gmx_sel_yyget_leng (yyscan_t yyscanner );
-
-char *_gmx_sel_yyget_text (yyscan_t yyscanner );
-
-int _gmx_sel_yyget_lineno (yyscan_t yyscanner );
-
-void _gmx_sel_yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int _gmx_sel_yywrap (yyscan_t yyscanner );
-#else
-extern int _gmx_sel_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int _gmx_sel_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int _gmx_sel_yylex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-
-#line 156 "scanner.l"
-
-#line 349 "scanner_flex.h"
-#undef _gmx_sel_yyIN_HEADER
-#endif /* _gmx_sel_yyHEADER_H */
diff --git a/src/gmxlib/selection/scanner_internal.c b/src/gmxlib/selection/scanner_internal.c
deleted file mode 100644 (file)
index 1e7e4f7..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Helper functions for the selection tokenizer.
- *
- * This file implements the functions in the headers scanner.h and
- * scanner_internal.h.
- */
-/*! \internal file scanner_flex.h
- * \brief Generated (from scanner.l) header file by Flex.
- *
- * This file contains definitions of functions that are needed in
- * scanner_internal.c.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <typedefs.h>
-#include <smalloc.h>
-#include <string.h>
-
-#include "string2.h"
-#include "gmx_fatal.h"
-
-#include <selmethod.h>
-
-#include "parsetree.h"
-#include "selcollection.h"
-#include "selelem.h"
-#include "symrec.h"
-
-#include "parser.h"
-#include "scanner.h"
-#include "scanner_internal.h"
-
-#define STRSTORE_ALLOCSTEP 1000
-
-/* These are defined as macros in the generated scanner_flex.h.
- * We undefine them here to have them as variable names in the subroutines.
- * There are other ways of doing this, but this is probably the easiest. */
-#undef yylval
-#undef yytext
-#undef yyleng
-
-static gmx_bool
-read_stdin_line(gmx_sel_lexer_t *state)
-{
-    char *ptr     = state->inputstr;
-    int   max_len = state->nalloc_input;
-    int   totlen = 0;
-
-    if (feof(stdin))
-    {
-        return FALSE;
-    }
-    if (state->bInteractive)
-    {
-        fprintf(stderr, "> ");
-    }
-    /* For some reason (at least on my Linux), fgets() doesn't return until
-     * the user presses Ctrl-D _twice_ at the end of a non-empty line.
-     * This can be a bit confusing for users, but there's not much we can
-     * do, and the chances of a normal user noticing this are not very big. */
-    while (fgets(ptr, max_len, stdin))
-    {
-        int len = strlen(ptr);
-
-        totlen += len;
-        if (len >= 2 && ptr[len - 1] == '\n' && ptr[len - 2] == '\\')
-        {
-            if (state->bInteractive)
-            {
-                fprintf(stderr, "... ");
-            }
-        }
-        else if (len >= 1 && ptr[len - 1] == '\n')
-        {
-            break;
-        }
-        else if (len < max_len - 1)
-        {
-            if (state->bInteractive)
-            {
-                fprintf(stderr, "\n");
-            }
-            break;
-        }
-        ptr     += len;
-        max_len -= len;
-        if (max_len <= 2)
-        {
-            max_len += state->nalloc_input;
-            state->nalloc_input *= 2;
-            len = ptr - state->inputstr;
-            srenew(state->inputstr, state->nalloc_input);
-            ptr = state->inputstr + len;
-        }
-    }
-    if (ferror(stdin))
-    {
-        gmx_input("selection reading failed");
-    }
-    return totlen > 0;
-}
-
-int
-_gmx_sel_yyblex(YYSTYPE *yylval, yyscan_t yyscanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(yyscanner);
-    gmx_bool bCmdStart;
-    int token;
-
-    if (!state->bBuffer && !state->inputstr)
-    {
-        state->nalloc_input = 1024;
-        snew(state->inputstr, state->nalloc_input);
-        read_stdin_line(state);
-        _gmx_sel_set_lex_input_str(yyscanner, state->inputstr);
-    }
-    bCmdStart = state->bCmdStart;
-    token = _gmx_sel_yylex(yylval, yyscanner);
-    while (state->inputstr && token == 0 && read_stdin_line(state))
-    {
-        _gmx_sel_set_lex_input_str(yyscanner, state->inputstr);
-        token = _gmx_sel_yylex(yylval, yyscanner);
-    }
-    if (token == 0 && !bCmdStart)
-    {
-        token = CMD_SEP;
-        rtrim(state->pselstr);
-    }
-    state->bCmdStart = (token == CMD_SEP);
-    return token;
-}
-
-static int
-init_param_token(YYSTYPE *yylval, gmx_ana_selparam_t *param, gmx_bool bBoolNo)
-{
-    if (bBoolNo)
-    {
-        snew(yylval->str, strlen(param->name) + 3);
-        yylval->str[0] = 'n';
-        yylval->str[1] = 'o';
-        strcpy(yylval->str+2, param->name);
-    }
-    else
-    {
-        yylval->str = param->name ? strdup(param->name) : NULL;
-    }
-    return PARAM;
-}
-
-static int
-init_method_token(YYSTYPE *yylval, gmx_ana_selmethod_t *method, gmx_bool bPosMod,
-                  gmx_sel_lexer_t *state)
-{
-    /* If the previous token was not KEYWORD_POS, return EMPTY_POSMOD
-     * before the actual method to work around a limitation in Bison. */
-    if (!bPosMod && method->type != POS_VALUE)
-    {
-        state->nextmethod = method;
-        return EMPTY_POSMOD;
-    }
-    yylval->meth = method;
-    if (!(method->flags & SMETH_MODIFIER) && method->nparams == 0)
-    {
-        /* Keyword */
-        switch (method->type)
-        {
-            case INT_VALUE:   return KEYWORD_NUMERIC;
-            case REAL_VALUE:  return KEYWORD_NUMERIC;
-            case STR_VALUE:   return KEYWORD_STR;
-            case GROUP_VALUE: return KEYWORD_GROUP;
-            default:          return INVALID;
-        }
-    } else {
-        /* Method with parameters or a modifier */
-        if (method->flags & SMETH_MODIFIER)
-        {
-            /* Remove all methods from the stack */
-            state->msp = -1;
-            if (method->param[1].name == NULL)
-            {
-                state->nextparam = &method->param[1];
-            }
-        }
-        else
-        {
-            if (method->param[0].name == NULL)
-            {
-                state->nextparam = &method->param[0];
-            }
-        }
-        ++state->msp;
-        if (state->msp >= state->mstack_alloc)
-        {
-            state->mstack_alloc += 10;
-            srenew(state->mstack, state->mstack_alloc);
-        }
-        state->mstack[state->msp] = method;
-        if (method->flags & SMETH_MODIFIER)
-        {
-            return MODIFIER;
-        }
-        switch (method->type)
-        {
-            case INT_VALUE:   return METHOD_NUMERIC;
-            case REAL_VALUE:  return METHOD_NUMERIC;
-            case POS_VALUE:   return METHOD_POS;
-            case GROUP_VALUE: return METHOD_GROUP;
-            default:
-                --state->msp;
-                return INVALID;
-        }
-    }
-    return INVALID; /* Should not be reached */
-}
-
-int
-_gmx_sel_lexer_process_pending(YYSTYPE *yylval, gmx_sel_lexer_t *state)
-{
-    if (state->nextparam)
-    {
-        gmx_ana_selparam_t *param = state->nextparam;
-        gmx_bool                bBoolNo = state->bBoolNo;
-
-        if (state->neom > 0)
-        {
-            --state->neom;
-            return END_OF_METHOD;
-        }
-        state->nextparam = NULL;
-        state->bBoolNo   = FALSE;
-        _gmx_sel_lexer_add_token(param->name, -1, state);
-        return init_param_token(yylval, param, bBoolNo);
-    }
-    if (state->prev_pos_kw > 0)
-    {
-        --state->prev_pos_kw;
-    }
-    if (state->nextmethod)
-    {
-        gmx_ana_selmethod_t *method = state->nextmethod;
-
-        state->nextmethod = NULL;
-        return init_method_token(yylval, method, TRUE, state);
-    }
-    return 0;
-}
-
-int
-_gmx_sel_lexer_process_identifier(YYSTYPE *yylval, char *yytext, size_t yyleng,
-                                  gmx_sel_lexer_t *state)
-{
-    gmx_sel_symrec_t *symbol;
-    e_symbol_t        symtype;
-
-    /* Check if the identifier matches with a parameter name */
-    if (state->msp >= 0)
-    {
-        gmx_ana_selparam_t *param = NULL;
-        gmx_bool                bBoolNo = FALSE;
-        int                 sp = state->msp;
-        while (!param && sp >= 0)
-        {
-            int             i;
-            for (i = 0; i < state->mstack[sp]->nparams; ++i)
-            {
-                /* Skip NULL parameters and too long parameters */
-                if (state->mstack[sp]->param[i].name == NULL
-                    || strlen(state->mstack[sp]->param[i].name) > yyleng)
-                {
-                    continue;
-                }
-                if (!strncmp(state->mstack[sp]->param[i].name, yytext, yyleng))
-                {
-                    param = &state->mstack[sp]->param[i];
-                    break;
-                }
-                /* Check separately for a 'no' prefix on gmx_boolean parameters */
-                if (state->mstack[sp]->param[i].val.type == NO_VALUE
-                    && yyleng > 2 && yytext[0] == 'n' && yytext[1] == 'o'
-                    && !strncmp(state->mstack[sp]->param[i].name, yytext+2, yyleng-2))
-                {
-                    param = &state->mstack[sp]->param[i];
-                    bBoolNo = TRUE;
-                    break;
-                }
-            }
-            if (!param)
-            {
-                --sp;
-            }
-        }
-        if (param)
-        {
-            if (param->val.type == NO_VALUE && !bBoolNo)
-            {
-                state->bMatchBool = TRUE;
-            }
-            if (sp < state->msp)
-            {
-                state->neom = state->msp - sp - 1;
-                state->nextparam = param;
-                state->bBoolNo   = bBoolNo;
-                return END_OF_METHOD;
-            }
-            _gmx_sel_lexer_add_token(param->name, -1, state);
-            return init_param_token(yylval, param, bBoolNo);
-        }
-    }
-
-    /* Check if the identifier matches with a symbol */
-    symbol = _gmx_sel_find_symbol_len(state->sc->symtab, yytext, yyleng, FALSE);
-    /* If there is no match, return the token as a string */
-    if (!symbol)
-    {
-        yylval->str = gmx_strndup(yytext, yyleng);
-        _gmx_sel_lexer_add_token(yytext, yyleng, state);
-        return IDENTIFIER;
-    }
-    _gmx_sel_lexer_add_token(_gmx_sel_sym_name(symbol), -1, state);
-    symtype = _gmx_sel_sym_type(symbol);
-    /* Reserved symbols should have been caught earlier */
-    if (symtype == SYMBOL_RESERVED)
-    {
-        return INVALID;
-    }
-    /* For variable symbols, return the type of the variable value */
-    if (symtype == SYMBOL_VARIABLE)
-    {
-        t_selelem *var;
-
-        var = _gmx_sel_sym_value_var(symbol);
-        /* Return simple tokens for constant variables */
-        if (var->type == SEL_CONST)
-        {
-            switch (var->v.type)
-            {
-                case INT_VALUE:
-                    yylval->i = var->v.u.i[0];
-                    return TOK_INT;
-                case REAL_VALUE:
-                    yylval->r = var->v.u.r[0];
-                    return TOK_REAL;
-                case POS_VALUE:
-                    break;
-                default:
-                    return INVALID;
-            }
-        }
-        yylval->sel = var;
-        switch (var->v.type)
-        {
-            case INT_VALUE:   return VARIABLE_NUMERIC;
-            case REAL_VALUE:  return VARIABLE_NUMERIC;
-            case POS_VALUE:   return VARIABLE_POS;
-            case GROUP_VALUE: return VARIABLE_GROUP;
-            default:          return INVALID;
-        }
-        return INVALID;
-    }
-    /* For method symbols, return the correct type */
-    if (symtype == SYMBOL_METHOD)
-    {
-        gmx_ana_selmethod_t *method;
-
-        method = _gmx_sel_sym_value_method(symbol);
-        return init_method_token(yylval, method, state->prev_pos_kw > 0, state);
-    }
-    /* For position symbols, we need to return KEYWORD_POS, but we also need
-     * some additional handling. */
-    if (symtype == SYMBOL_POS)
-    {
-        state->bMatchOf = TRUE;
-        yylval->str = _gmx_sel_sym_name(symbol);
-        state->prev_pos_kw = 2;
-        return KEYWORD_POS;
-    }
-    /* Should not be reached */
-    return INVALID;
-}
-
-void
-_gmx_sel_lexer_add_token(const char *str, int len, gmx_sel_lexer_t *state)
-{
-    /* Do nothing if the string is empty, or if it is a space and there is
-     * no other text yet, or if there already is a space. */
-    if (!str || len == 0 || strlen(str) == 0
-        || (str[0] == ' ' && str[1] == 0
-            && (state->pslen == 0 || state->pselstr[state->pslen - 1] == ' ')))
-    {
-        return;
-    }
-    if (len < 0)
-    {
-        len = strlen(str);
-    }
-    /* Allocate more memory if necessary */
-    if (state->nalloc_psel - state->pslen < len)
-    {
-        int incr = STRSTORE_ALLOCSTEP < len ? len : STRSTORE_ALLOCSTEP;
-        state->nalloc_psel += incr;
-        srenew(state->pselstr, state->nalloc_psel);
-    }
-    /* Append the token to the stored string */
-    strncpy(state->pselstr + state->pslen, str, len);
-    state->pslen += len;
-    state->pselstr[state->pslen] = 0;
-}
-
-int
-_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
-                    gmx_bool bInteractive, int maxnr,
-                    struct gmx_ana_indexgrps_t *grps)
-{
-    gmx_sel_lexer_t *state;
-    int              rc;
-
-    rc = _gmx_sel_yylex_init(scannerp);
-    if (rc != 0)
-    {
-        return rc;
-    }
-
-    snew(state, 1);
-    state->sc        = sc;
-    state->grps      = grps;
-    state->nexpsel   = (maxnr > 0 ? sc->nr + maxnr : -1);
-
-    state->bInteractive = bInteractive;
-    state->nalloc_input = 0;
-    state->inputstr     = NULL;
-
-    snew(state->pselstr, STRSTORE_ALLOCSTEP);
-    state->pselstr[0]   = 0;
-    state->pslen        = 0;
-    state->nalloc_psel  = STRSTORE_ALLOCSTEP;
-
-    snew(state->mstack, 20);
-    state->mstack_alloc = 20;
-    state->msp          = -1;
-    state->neom         = 0;
-    state->nextparam    = NULL;
-    state->nextmethod   = NULL;
-    state->prev_pos_kw  = 0;
-    state->bBoolNo      = FALSE;
-    state->bMatchOf     = FALSE;
-    state->bMatchBool   = FALSE;
-    state->bCmdStart    = TRUE;
-    state->bBuffer      = FALSE;
-
-    _gmx_sel_yyset_extra(state, *scannerp);
-    return 0;
-}
-
-void
-_gmx_sel_free_lexer(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-
-    sfree(state->inputstr);
-    sfree(state->pselstr);
-    sfree(state->mstack);
-    if (state->bBuffer)
-    {
-        _gmx_sel_yy_delete_buffer(state->buffer, scanner);
-    }
-    sfree(state);
-    _gmx_sel_yylex_destroy(scanner);
-}
-
-gmx_bool
-_gmx_sel_is_lexer_interactive(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    return state->bInteractive;
-}
-
-struct gmx_ana_selcollection_t *
-_gmx_sel_lexer_selcollection(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    return state->sc;
-}
-
-struct gmx_ana_indexgrps_t *
-_gmx_sel_lexer_indexgrps(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    return state->grps;
-}
-
-int
-_gmx_sel_lexer_exp_selcount(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    return state->nexpsel;
-}
-
-const char *
-_gmx_sel_lexer_pselstr(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    return state->pselstr;
-}
-
-void
-_gmx_sel_lexer_clear_pselstr(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-    state->pselstr[0] = 0;
-    state->pslen      = 0;
-}
-
-void
-_gmx_sel_lexer_clear_method_stack(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-
-    state->msp = -1;
-}
-
-void
-_gmx_sel_finish_method(yyscan_t scanner)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-
-    if (state->msp >= 0)
-    {
-        --state->msp;
-    }
-}
-
-void
-_gmx_sel_set_lex_input_file(yyscan_t scanner, FILE *fp)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-
-    state->bBuffer = TRUE;
-    state->buffer  = _gmx_sel_yy_create_buffer(fp, YY_BUF_SIZE, scanner);
-    _gmx_sel_yy_switch_to_buffer(state->buffer, scanner);
-}
-
-void
-_gmx_sel_set_lex_input_str(yyscan_t scanner, const char *str)
-{
-    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
-
-    if (state->bBuffer)
-    {
-        _gmx_sel_yy_delete_buffer(state->buffer, scanner);
-    }
-    state->bBuffer = TRUE;
-    state->buffer  = _gmx_sel_yy_scan_string(str, scanner);
-}
diff --git a/src/gmxlib/selection/scanner_internal.h b/src/gmxlib/selection/scanner_internal.h
deleted file mode 100644 (file)
index 802c8f7..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Internal header file used by the selection tokenizer.
- */
-#ifndef SELECTION_SCANNER_INTERNAL_H
-#define SELECTION_SCANNER_INTERNAL_H
-
-#include "parser.h"
-
-/** The scanning function generated by Flex. */
-#define YY_DECL int _gmx_sel_yylex(YYSTYPE *yylval, yyscan_t yyscanner)
-YY_DECL;
-
-/* These need to be defined before including scanner_flex.h, because it
- * uses YY_EXTRA_TYPE. But we also need to include it before defining
- * gmx_sel_lexer_t; hence the forward declaration. */
-struct gmx_sel_lexer_t;
-#define YY_EXTRA_TYPE struct gmx_sel_lexer_t *
-
-/* We cannot include scanner_flex.h from the scanner itself, because it
- * seems to break everything. */
-/* And we need to define YY_NO_UNISTD_H here as well, otherwise unistd.h
- * gets included in other files than scanner.c... */
-#ifndef FLEX_SCANNER
-#define YY_NO_UNISTD_H
-#include "scanner_flex.h"
-#endif
-
-/*! \brief
- * Internal data structure for the selection tokenizer state.
- */
-typedef struct gmx_sel_lexer_t
-{
-    struct gmx_ana_selcollection_t  *sc;
-    struct gmx_ana_indexgrps_t      *grps;
-    int                              nexpsel;
-
-    gmx_bool                             bInteractive;
-    char                            *inputstr;
-    int                              nalloc_input;
-
-    char                            *pselstr;
-    int                              pslen;
-    int                              nalloc_psel;
-
-    struct gmx_ana_selmethod_t     **mstack;
-    int                              msp;
-    int                              mstack_alloc;
-
-    int                              neom;
-    struct gmx_ana_selparam_t       *nextparam;
-    gmx_bool                             bBoolNo;
-    struct gmx_ana_selmethod_t      *nextmethod;
-    int                              prev_pos_kw;
-
-    gmx_bool                             bMatchOf;
-    gmx_bool                             bMatchBool;
-    gmx_bool                             bCmdStart;
-
-    gmx_bool                             bBuffer;
-    YY_BUFFER_STATE                  buffer;
-} gmx_sel_lexer_t;
-
-/* Because Flex defines yylval, yytext, and yyleng as macros,
- * and this file is included from scanner.l,
- * we cannot have them here as parameter names... */
-/** Internal function for cases where several tokens need to be returned. */
-int
-_gmx_sel_lexer_process_pending(YYSTYPE *, gmx_sel_lexer_t *state);
-/** Internal function that processes identifier tokens. */
-int
-_gmx_sel_lexer_process_identifier(YYSTYPE *, char *, size_t,
-                                  gmx_sel_lexer_t *state);
-/** Internal function to add a token to the pretty-printed selection text. */
-void
-_gmx_sel_lexer_add_token(const char *str, int len, gmx_sel_lexer_t *state);
-
-#endif
diff --git a/src/gmxlib/selection/selcollection.h b/src/gmxlib/selection/selcollection.h
deleted file mode 100644 (file)
index 909c878..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Definition of \c gmx_ana_selcollection_t.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_COLLECTION_H
-#define SELECTION_COLLECTION_H
-
-#include <typedefs.h>
-
-#include <indexutil.h>
-
-/*! \internal
- * \brief
- * Information for a collection of selections.
- *
- * The functions to deal with the structure are defined in selection.h.
- * The structure is allocated with gmx_ana_selcollection_create() and
- * freed with gmx_ana_selcollection_free().
- * Some default values must then be set with
- * gmx_ana_selcollection_set_refpostype() and
- * gmx_ana_selcollection_set_outpostype().
- *
- * After setting the default values, one or more selections can be parsed
- * with gmx_ana_selcollection_parse_*().
- * At latest at this point, the topology must be set with
- * gmx_ana_selcollection_set_topology() unless
- * gmx_ana_selcollection_requires_top() returns FALSE.
- * Once all selections are parsed, they must be compiled all at once using
- * gmx_ana_selcollection_compile().
- * After these calls, gmx_ana_selcollection_get_count() and 
- * gmx_ana_selcollection_get_selections() can be used
- * to get the compiled selections.
- * gmx_ana_selcollection_evaluate() can be used to update the selections for a
- * new frame.
- * gmx_ana_selcollection_evaluate_fin() can be called after all the frames have
- * been processed to restore the selection values back to the ones they were
- * after gmx_ana_selcollection_compile(), i.e., dynamic selections have the
- * maximal index group as their value.
- *
- * At any point, gmx_ana_selcollection_requires_top() can be called to see
- * whether the information provided so far requires loading the topology.
- * gmx_ana_selcollection_print_tree() can be used to print the internal
- * representation of the selections (mostly useful for debugging).
- */
-struct gmx_ana_selcollection_t
-{
-    /** Default reference position type for selections. */
-    const char                 *rpost;
-    /** Default output position type for selections. */
-    const char                 *spost;
-    /** TRUE if \ref POS_MASKONLY should be used for output position evaluation. */
-    gmx_bool                        bMaskOnly;
-    /** TRUE if velocities should be evaluated for output positions. */
-    gmx_bool                        bVelocities;
-    /** TRUE if forces should be evaluated for output positions. */
-    gmx_bool                        bForces;
-    /** TRUE if debugging output should be printed during compilation. */
-    gmx_bool                        bDebugCompile;
-
-    /** Root of the selection element tree. */
-    struct t_selelem           *root;
-    /** Number of selections in \p sel. */
-    int                         nr;
-    /** Array of compiled selections. */
-    struct gmx_ana_selection_t **sel;
-    /** Number of variables defined. */
-    int                            nvars;
-    /** Selection strings for variables. */
-    char                         **varstrs;
-
-    /** Topology for the collection. */
-    t_topology                    *top;
-    /** Index group that contains all the atoms. */
-    struct gmx_ana_index_t         gall;
-    /** Position calculation collection used for selection position evaluation. */
-    struct gmx_ana_poscalc_coll_t *pcc;
-    /** Memory pool used for selection evaluation. */
-    struct gmx_sel_mempool_t      *mempool;
-    /** Parser symbol table. */
-    struct gmx_sel_symtab_t     *symtab;
-};
-
-/** Clears the symbol table in the collection */
-void
-_gmx_selcollection_clear_symtab(struct gmx_ana_selcollection_t *sc);
-
-#endif
diff --git a/src/gmxlib/selection/selection.c b/src/gmxlib/selection/selection.c
deleted file mode 100644 (file)
index 17a9cf7..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief
- * Implementation of functions in selection.h.
- */
-/*! \internal \dir src/gmxlib/selection
- * \brief
- * Source code for selection-related routines.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <smalloc.h>
-#include <statutil.h>
-#include <string2.h>
-#include <xvgr.h>
-#include <gmx_fatal.h>
-
-#include <poscalc.h>
-#include <selection.h>
-#include <selmethod.h>
-
-#include "mempool.h"
-#include "selcollection.h"
-#include "selelem.h"
-#include "symrec.h"
-
-/*!
- * \param[out] scp Pointer to a newly allocated empty selection collection.
- * \param[in]  pcc Position calculation data structure to use for selection
- *   position evaluation.
- * \returns    0 on success.
- */
-int
-gmx_ana_selcollection_create(gmx_ana_selcollection_t **scp,
-                             gmx_ana_poscalc_coll_t *pcc)
-{
-    gmx_ana_selcollection_t *sc;
-    
-    snew(sc, 1);
-    sc->rpost     = NULL;
-    sc->spost     = NULL;
-    sc->bMaskOnly = FALSE;
-    sc->bVelocities = FALSE;
-    sc->bForces   = FALSE;
-    sc->bDebugCompile = FALSE;
-    sc->root      = NULL;
-    sc->nr        = 0;
-    sc->sel       = NULL;
-    sc->nvars     = 0;
-    sc->varstrs   = NULL;
-    sc->top       = NULL;
-    gmx_ana_index_clear(&sc->gall);
-    sc->pcc       = pcc;
-    sc->mempool   = NULL;
-    _gmx_sel_symtab_create(&sc->symtab);
-    *scp = sc;
-    return 0;
-}
-
-/*!
- * \param[in,out] sc Selection collection to free.
- *
- * The pointer \p sc is invalid after the call.
- */
-void
-gmx_ana_selcollection_free(gmx_ana_selcollection_t *sc)
-{
-    int  i;
-
-    _gmx_selelem_free_chain(sc->root);
-    if (sc->sel)
-    {
-        for (i = 0; i < sc->nr; ++i)
-        {
-            gmx_ana_selection_free(sc->sel[i]);
-        }
-    }
-    sfree(sc->sel);
-    for (i = 0; i < sc->nvars; ++i)
-    {
-        sfree(sc->varstrs[i]);
-    }
-    sfree(sc->varstrs);
-    gmx_ana_index_deinit(&sc->gall);
-    if (sc->mempool)
-    {
-        _gmx_sel_mempool_destroy(sc->mempool);
-    }
-    _gmx_selcollection_clear_symtab(sc);
-    sfree(sc);
-}
-
-/*!
- * \param[in,out] sc Selection collection.
- */
-void
-_gmx_selcollection_clear_symtab(gmx_ana_selcollection_t *sc)
-{
-    if (sc->symtab)
-    {
-        _gmx_sel_symtab_free(sc->symtab);
-        sc->symtab = NULL;
-    }
-}
-
-/*!
- * \param[in,out] sc        Selection collection to modify.
- * \param[in]     type      Default selection reference position type
- *   (one of the strings acceptable for gmx_ana_poscalc_type_from_enum()).
- *
- * Should be called before calling gmx_ana_selcollection_requires_top() or
- * gmx_ana_selcollection_parse_*().
- */
-void
-gmx_ana_selcollection_set_refpostype(gmx_ana_selcollection_t *sc,
-                                     const char *type)
-{
-    sc->rpost     = type;
-}
-
-/*!
- * \param[in,out] sc        Selection collection to modify.
- * \param[in]     type      Default selection output position type
- *   (one of the strings acceptable for gmx_ana_poslcalc_type_from_enum()).
- * \param[in]     bMaskOnly If TRUE, the output positions are initialized
- *   using \ref POS_MASKONLY.
- *
- * If \p type is NULL, the default type is not modified.
- * Should be called before calling gmx_ana_selcollection_requires_top() or
- * gmx_ana_selcollection_parse_*().
- */
-void
-gmx_ana_selcollection_set_outpostype(gmx_ana_selcollection_t *sc,
-                                     const char *type, gmx_bool bMaskOnly)
-{
-    if (type)
-    {
-        sc->spost     = type;
-    }
-    sc->bMaskOnly = bMaskOnly;
-}
-
-/*!
- * \param[in,out] sc        Selection collection to modify.
- * \param[in]     bVelOut   If TRUE, selections will also evaluate
- *      velocities.
- */
-void
-gmx_ana_selcollection_set_veloutput(gmx_ana_selcollection_t *sc,
-                                    gmx_bool bVelOut)
-{
-    sc->bVelocities = bVelOut;
-}
-
-/*!
- * \param[in,out] sc        Selection collection to modify.
- * \param[in]     bForceOut If TRUE, selections will also evaluate
- *      forces.
- */
-void
-gmx_ana_selcollection_set_forceoutput(gmx_ana_selcollection_t *sc,
-                                      gmx_bool bForceOut)
-{
-    sc->bForces = bForceOut;
-}
-
-/*!
- * \param[in,out] sc        Selection collection to set the topology for.
- * \param[in]     top       Topology data.
- * \param[in]     natoms    Number of atoms. If <=0, the number of atoms in the
- *   topology is used.
- * \returns       0 on success, EINVAL if \p top is NULL and \p natoms <= 0.
- *
- * The topology is also set for the position calculation collection
- * associated with \p sc.
- *
- * \p natoms determines the largest atom index that can be selected by the
- * selection: even if the topology contains more atoms, they will not be
- * selected.
- */
-int
-gmx_ana_selcollection_set_topology(gmx_ana_selcollection_t *sc, t_topology *top,
-                                   int natoms)
-{
-    gmx_ana_poscalc_coll_set_topology(sc->pcc, top);
-    sc->top = top;
-
-    /* Get the number of atoms from the topology if it is not given */
-    if (natoms <= 0)
-    {
-        if (!sc->top)
-        {
-            gmx_incons("selections need either the topology or the number of atoms");
-            return EINVAL;
-        }
-        natoms = sc->top->atoms.nr;
-    }
-    gmx_ana_index_init_simple(&sc->gall, natoms, NULL);
-    return 0;
-}
-
-/*!
- * \param[in]  sc  Selection collection to query.
- * \returns    Number of selections in \p sc.
- *
- * If gmx_ana_selcollection_parse_*() has not been called, returns 0.
- *
- * \see gmx_ana_selcollection_get_selection()
- */
-int
-gmx_ana_selcollection_get_count(gmx_ana_selcollection_t *sc)
-{
-    return sc->nr;
-}
-
-/*!
- * \param[in]  sc  Selection collection to query.
- * \param[in]  i   Number of the selection.
- * \returns    Pointer to the \p i'th selection in \p sc,
- *   or NULL if there is no such selection.
- *
- * \p i should be between 0 and the value returned by
- * gmx_ana_selcollection_get_count().
- * The returned pointer should not be freed.
- * If gmx_ana_selcollection_compile() has not been called, the returned
- * selection is not completely initialized (but the returned pointer will be
- * valid even after compilation, and will point to the initialized selection).
- *
- * \see gmx_ana_selcollection_get_count()
- */
-gmx_ana_selection_t *
-gmx_ana_selcollection_get_selection(gmx_ana_selcollection_t *sc, int i)
-{
-    if (i < 0 || i >= sc->nr || !sc->sel)
-        return NULL;
-    return sc->sel[i];
-}
-
-/*!
- * \param[in]  sc  Selection collection to query.
- * \returns    TRUE if any selection in \p sc requires topology information,
- *   FALSE otherwise.
- *
- * Before gmx_ana_selcollection_parse_*(), the return value is based just on
- * the position types set.
- * After gmx_ana_selcollection_parse_*(), the return value also takes into account the
- * selection keywords used.
- */
-gmx_bool
-gmx_ana_selcollection_requires_top(gmx_ana_selcollection_t *sc)
-{
-    t_selelem   *sel;
-    e_poscalc_t  type;
-    int          flags;
-    int          rc;
-
-    if (sc->rpost)
-    {
-        flags = 0;
-        rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &type, &flags);
-        if (rc == 0 && type != POS_ATOM)
-        {
-            return TRUE;
-        }
-    }
-    if (sc->spost)
-    {
-        flags = 0;
-        rc = gmx_ana_poscalc_type_from_enum(sc->spost, &type, &flags);
-        if (rc == 0 && type != POS_ATOM)
-        {
-            return TRUE;
-        }
-    }
-
-    sel = sc->root;
-    while (sel)
-    {
-        if (_gmx_selelem_requires_top(sel))
-        {
-            return TRUE;
-        }
-        sel = sel->next;
-    }
-    return FALSE;
-}
-
-/*!
- * \param[in] fp      File handle to receive the output.
- * \param[in] sc      Selection collection to print.
- * \param[in] bValues If TRUE, the evaluated values of selection elements
- *   are printed as well.
- */
-void
-gmx_ana_selcollection_print_tree(FILE *fp, gmx_ana_selcollection_t *sc, gmx_bool bValues)
-{
-    t_selelem *sel;
-
-    sel = sc->root;
-    while (sel)
-    {
-        _gmx_selelem_print_tree(fp, sel, bValues, 0);
-        sel = sel->next;
-    }
-}
-
-/*!
- * \param[in] sel  Selection to free.
- *
- * After the call, the pointer \p sel is invalid.
- */
-void
-gmx_ana_selection_free(gmx_ana_selection_t *sel)
-{
-    sfree(sel->name);
-    sfree(sel->selstr);
-    gmx_ana_pos_deinit(&sel->p);
-    if (sel->m != sel->orgm)
-    {
-        sfree(sel->m);
-    }
-    if (sel->q != sel->orgq)
-    {
-        sfree(sel->q);
-    }
-    sfree(sel->orgm);
-    sfree(sel->orgq);
-    sfree(sel);
-}
-
-/*!
- * \param[in] sel  Selection whose name is needed.
- * \returns   Pointer to the name of the selection.
- *
- * The return value should not be freed by the caller.
- */
-char *
-gmx_ana_selection_name(gmx_ana_selection_t *sel)
-{
-    return sel->name;
-}
-
-/*!
- * \param[in] sel  Selection for which information should be printed.
- */
-void
-gmx_ana_selection_print_info(gmx_ana_selection_t *sel)
-{
-    fprintf(stderr, "\"%s\" (%d position%s, %d atom%s%s)", sel->name,
-            sel->p.nr,     sel->p.nr     == 1 ? "" : "s",
-            sel->g->isize, sel->g->isize == 1 ? "" : "s",
-            sel->bDynamic ? ", dynamic" : "");
-    fprintf(stderr, "\n");
-}
-
-/*!
- * \param[in] sel  Selection to initialize.
- * \param[in] type Type of covered fraction required.
- * \returns   TRUE if the covered fraction can be calculated for the selection,
- *   FALSE otherwise.    
- */
-gmx_bool
-gmx_ana_selection_init_coverfrac(gmx_ana_selection_t *sel, e_coverfrac_t type)
-{
-    sel->cfractype = type;
-    if (type == CFRAC_NONE || !sel->selelem)
-    {
-        sel->bCFracDyn = FALSE;
-    }
-    else if (!_gmx_selelem_can_estimate_cover(sel->selelem))
-    {
-        sel->cfractype = CFRAC_NONE;
-        sel->bCFracDyn = FALSE;
-    }
-    else
-    {
-        sel->bCFracDyn = TRUE;
-    }
-    sel->cfrac     = sel->bCFracDyn ? 0.0 : 1.0;
-    sel->avecfrac  = sel->cfrac;
-    return type == CFRAC_NONE || sel->cfractype != CFRAC_NONE;
-}
-
-/*!
- * \param[in] out  Output file.
- * \param[in] sc   Selection collection which should be written.
- * \param[in] oenv Output options structure.
- */
-void xvgr_selcollection(FILE *out, gmx_ana_selcollection_t *sc,
-                        const output_env_t oenv)
-{
-    int  i;
-
-    if (output_env_get_xvg_format(oenv) != exvgNONE && sc)
-    {
-        fprintf(out, "# Selections:\n");
-        for (i = 0; i < sc->nvars; ++i)
-        {
-            fprintf(out, "#   %s\n", sc->varstrs[i]);
-        }
-        for (i = 0; i < sc->nr; ++i)
-        {
-            fprintf(out, "#   %s\n", sc->sel[i]->selstr);
-        }
-        fprintf(out, "#\n");
-    }
-}
diff --git a/src/gmxlib/selection/selelem.c b/src/gmxlib/selection/selelem.c
deleted file mode 100644 (file)
index 09971c0..0000000
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in selelem.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <smalloc.h>
-#include <gmx_fatal.h>
-
-#include <indexutil.h>
-#include <poscalc.h>
-#include <position.h>
-#include <selmethod.h>
-
-#include "keywords.h"
-#include "mempool.h"
-#include "selelem.h"
-
-/*!
- * \param[in] sel Selection for which the string is requested
- * \returns   Pointer to a string that corresponds to \p sel->type.
- *
- * The return value points to a string constant and should not be \p free'd.
- * 
- * The function returns NULL if \p sel->type is not one of the valid values.
- */
-const char *
-_gmx_selelem_type_str(t_selelem *sel)
-{
-    switch (sel->type)
-    {
-        case SEL_CONST:      return "CONST";
-        case SEL_EXPRESSION: return "EXPR";
-        case SEL_BOOLEAN:    return "BOOL";
-        case SEL_ARITHMETIC: return "ARITH";
-        case SEL_ROOT:       return "ROOT";
-        case SEL_SUBEXPR:    return "SUBEXPR";
-        case SEL_SUBEXPRREF: return "REF";
-        case SEL_MODIFIER:   return "MODIFIER";
-    }
-    return NULL;
-}
-
-/*!
- * \param[in] val Value structore for which the string is requested.
- * \returns   Pointer to a string that corresponds to \p val->type,
- *   NULL if the type value is invalid.
- *
- * The return value points to a string constant and should not be \p free'd.
- */
-const char *
-_gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
-{
-    switch (val->type)
-    {
-        case NO_VALUE:       return "NONE";
-        case INT_VALUE:      return "INT";
-        case REAL_VALUE:     return "REAL";
-        case STR_VALUE:      return "STR";
-        case POS_VALUE:      return "VEC";
-        case GROUP_VALUE:    return "GROUP";
-    }
-    return NULL;
-}
-
-/*! \copydoc _gmx_selelem_type_str() */
-const char *
-_gmx_selelem_gmx_boolean_type_str(t_selelem *sel)
-{
-    switch (sel->u.boolt)
-    {
-        case BOOL_NOT:  return "NOT"; break;
-        case BOOL_AND:  return "AND"; break;
-        case BOOL_OR:   return "OR";  break;
-        case BOOL_XOR:  return "XOR"; break;
-    }
-    return NULL;
-}
-
-/*!
- * \param[in] type Type of selection element to allocate.
- * \returns   Pointer to the newly allocated and initialized element.
- *
- * \c t_selelem::type is set to \p type,
- * \c t_selelem::v::type is set to \ref GROUP_VALUE for gmx_boolean and comparison
- * expressions and \ref NO_VALUE for others,
- * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
- * set for \ref SEL_BOOLEAN elements),
- * and \c t_selelem::refcount is set to one.
- * All the pointers are set to NULL.
- */
-t_selelem *
-_gmx_selelem_create(e_selelem_t type)
-{
-    t_selelem *sel;
-
-    snew(sel, 1);
-    sel->name       = NULL;
-    sel->type       = type;
-    sel->flags      = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
-    if (type == SEL_BOOLEAN)
-    {
-        sel->v.type = GROUP_VALUE;
-        sel->flags |= SEL_ALLOCDATA;
-    }
-    else
-    {
-        sel->v.type = NO_VALUE;
-    }
-    _gmx_selvalue_clear(&sel->v);
-    sel->evaluate   = NULL;
-    sel->mempool    = NULL;
-    sel->child      = NULL;
-    sel->next       = NULL;
-    sel->refcount   = 1;
-
-    return sel;
-}
-
-/*!
- * \param[in,out] sel   Selection element to set the type for.
- * \param[in]     vtype Value type for the selection element.
- * \returns       0 on success, EINVAL if the value type is invalid.
- *
- * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
- * \ref SEL_ALLOCDATA flag is also set.
- *
- * This function should only be called at most once for each element,
- * preferably right after calling _gmx_selelem_create().
- */
-int
-_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
-{
-    if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
-    {
-        gmx_bug("internal error");
-        return EINVAL;
-    }
-    if (sel->v.type != NO_VALUE && vtype != sel->v.type)
-    {
-        gmx_call("_gmx_selelem_set_vtype() called more than once");
-        return EINVAL;
-    }
-    sel->v.type = vtype;
-    if (vtype == GROUP_VALUE || vtype == POS_VALUE)
-    {
-        sel->flags |= SEL_ALLOCDATA;
-    }
-    return 0;
-}
-
-/*!
- * \param[in,out] sel   Selection element to reserve.
- * \param[in]     count Number of values to reserve memory for.
- * \returns       0 on success or if no memory pool, non-zero on error.
- *
- * Reserves memory for the values of \p sel from the \p sel->mempool
- * memory pool. If no memory pool is set, nothing is done.
- */
-int
-_gmx_selelem_mempool_reserve(t_selelem *sel, int count)
-{
-    int rc = 0;
-
-    if (!sel->mempool)
-    {
-        return 0;
-    }
-    switch (sel->v.type)
-    {
-        case INT_VALUE:
-            rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.i,
-                                        sizeof(*sel->v.u.i)*count);
-            break;
-
-        case REAL_VALUE:
-            rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.r,
-                                        sizeof(*sel->v.u.r)*count);
-            break;
-
-        case GROUP_VALUE:
-            rc = _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
-            break;
-
-        default:
-            gmx_incons("mem pooling not implemented for requested type");
-            return -1;
-    }
-    return rc;
-}
-
-/*!
- * \param[in,out] sel   Selection element to release.
- *
- * Releases the memory allocated for the values of \p sel from the
- * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
- */
-void
-_gmx_selelem_mempool_release(t_selelem *sel)
-{
-    if (!sel->mempool)
-    {
-        return;
-    }
-    switch (sel->v.type)
-    {
-        case INT_VALUE:
-        case REAL_VALUE:
-            _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
-            _gmx_selvalue_setstore(&sel->v, NULL);
-            break;
-
-        case GROUP_VALUE:
-            if (sel->v.u.g)
-            {
-                _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
-            }
-            break;
-
-        default:
-            gmx_incons("mem pooling not implemented for requested type");
-            break;
-    }
-}
-
-/*!
- * \param[in] sel Selection to free.
- */
-void
-_gmx_selelem_free_values(t_selelem *sel)
-{
-    int   i, n;
-
-    _gmx_selelem_mempool_release(sel);
-    if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
-    {
-        /* The number of position/group structures is constant, so the
-         * backup of using sel->v.nr should work for them.
-         * For strings, we report an error if we don't know the allocation
-         * size here. */
-        n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
-        switch (sel->v.type)
-        {
-            case STR_VALUE:
-                if (sel->v.nalloc == 0)
-                {
-                    gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
-                    break;
-                }
-                for (i = 0; i < n; ++i)
-                {
-                    sfree(sel->v.u.s[i]);
-                }
-                break;
-            case POS_VALUE:
-                for (i = 0; i < n; ++i)
-                {
-                    gmx_ana_pos_deinit(&sel->v.u.p[i]);
-                }
-                break;
-            case GROUP_VALUE:
-                for (i = 0; i < n; ++i)
-                {
-                    gmx_ana_index_deinit(&sel->v.u.g[i]);
-                }
-                break;
-            default: /* No special handling for other types */
-                break;
-        }
-    }
-    if (sel->flags & SEL_ALLOCVAL)
-    {
-        sfree(sel->v.u.ptr);
-    }
-    _gmx_selvalue_setstore(&sel->v, NULL);
-    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
-    {
-        sel->u.param->val.u.ptr = NULL;
-    }
-}
-
-/*!
- * \param[in] method Method to free.
- * \param[in] mdata  Method data to free.
- */
-void
-_gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
-{
-    sel_freefunc free_func = NULL;
-
-    /* Save the pointer to the free function. */
-    if (method && method->free)
-    {
-        free_func = method->free;
-    }
-
-    /* Free the method itself.
-     * Has to be done before freeing the method data, because parameter
-     * values are typically stored in the method data, and here we may
-     * access them. */
-    if (method)
-    {
-        int  i, j;
-
-        /* Free the memory allocated for the parameters that are not managed
-         * by the selection method itself. */
-        for (i = 0; i < method->nparams; ++i)
-        {
-            gmx_ana_selparam_t *param = &method->param[i];
-
-            if (param->val.u.ptr)
-            {
-                if (param->val.type == GROUP_VALUE)
-                {
-                    for (j = 0; j < param->val.nr; ++j)
-                    {
-                        gmx_ana_index_deinit(&param->val.u.g[j]);
-                    }
-                }
-                else if (param->val.type == POS_VALUE)
-                {
-                    for (j = 0; j < param->val.nr; ++j)
-                    {
-                        gmx_ana_pos_deinit(&param->val.u.p[j]);
-                    }
-                }
-
-                if (param->val.nalloc > 0)
-                {
-                    sfree(param->val.u.ptr);
-                }
-            }
-        }
-        sfree(method->param);
-        sfree(method);
-    }
-    /* Free method data. */
-    if (mdata)
-    {
-        if (free_func)
-        {
-            free_func(mdata);
-        }
-        sfree(mdata);
-    }
-}
-
-/*!
- * \param[in] sel Selection to free.
- */
-void
-_gmx_selelem_free_exprdata(t_selelem *sel)
-{
-    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
-    {
-        _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
-        sel->u.expr.mdata = NULL;
-        sel->u.expr.method = NULL;
-        /* Free position data */
-        if (sel->u.expr.pos)
-        {
-            gmx_ana_pos_free(sel->u.expr.pos);
-            sel->u.expr.pos = NULL;
-        }
-        /* Free position calculation data */
-        if (sel->u.expr.pc)
-        {
-            gmx_ana_poscalc_free(sel->u.expr.pc);
-            sel->u.expr.pc = NULL;
-        }
-    }
-    if (sel->type == SEL_ARITHMETIC)
-    {
-        sfree(sel->u.arith.opstr);
-        sel->u.arith.opstr = NULL;
-    }
-    if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
-        || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
-    {
-        gmx_ana_index_deinit(&sel->u.cgrp);
-    }
-}
-
-/*!
- * \param[in] sel Selection to free.
- *
- * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
- * memory allocated for \p sel and all its children if the reference count
- * reaches zero.
- */
-void
-_gmx_selelem_free(t_selelem *sel)
-{
-    /* Decrement the reference counter and do nothing if references remain */
-    sel->refcount--;
-    if (sel->refcount > 0)
-    {
-        return;
-    }
-
-    /* Free the children.
-     * Must be done before freeing other data, because the children may hold
-     * references to data in this element. */
-    _gmx_selelem_free_chain(sel->child);
-
-    /* Free value storage */
-    _gmx_selelem_free_values(sel);
-
-    /* Free other storage */
-    _gmx_selelem_free_exprdata(sel);
-
-    /* Free temporary compiler data if present */
-    _gmx_selelem_free_compiler_data(sel);
-
-    sfree(sel);
-}
-
-/*!
- * \param[in] first First selection to free.
- *
- * Frees \p first and all selections accessible through the
- * \ref t_selelem::next "first->next" pointer.
- */
-void
-_gmx_selelem_free_chain(t_selelem *first)
-{
-    t_selelem *child, *prev;
-
-    child = first;
-    while (child)
-    {
-        prev = child;
-        child = child->next;
-        _gmx_selelem_free(prev);
-    }
-}
-
-/*!
- * \param[in] fp      File handle to receive the output.
- * \param[in] sel     Root of the selection subtree to print.
- * \param[in] bValues If TRUE, the evaluated values of selection elements
- *   are printed as well.
- * \param[in] level   Indentation level, starting from zero.
- */
-void
-_gmx_selelem_print_tree(FILE *fp, t_selelem *sel, gmx_bool bValues, int level)
-{
-    t_selelem *child;
-    int          i;
-
-    fprintf(fp, "%*c %s %s", level*2+1, '*',
-            _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
-    if (sel->name)
-    {
-        fprintf(fp, " \"%s\"", sel->name);
-    }
-    fprintf(fp, " flg=");
-    if (sel->flags & SEL_FLAGSSET)
-    {
-        fprintf(fp, "s");
-    }
-    if (sel->flags & SEL_SINGLEVAL)
-    {
-        fprintf(fp, "S");
-    }
-    if (sel->flags & SEL_ATOMVAL)
-    {
-        fprintf(fp, "A");
-    }
-    if (sel->flags & SEL_VARNUMVAL)
-    {
-        fprintf(fp, "V");
-    }
-    if (sel->flags & SEL_DYNAMIC)
-    {
-        fprintf(fp, "D");
-    }
-    if (!(sel->flags & SEL_VALFLAGMASK))
-    {
-        fprintf(fp, "0");
-    }
-    if (sel->mempool)
-    {
-        fprintf(fp, "P");
-    }
-    if (sel->type == SEL_CONST)
-    {
-        if (sel->v.type == INT_VALUE)
-        {
-            fprintf(fp, " %d", sel->v.u.i[0]);
-        }
-        else if (sel->v.type == REAL_VALUE)
-        {
-            fprintf(fp, " %f", sel->v.u.r[0]);
-        }
-        else if (sel->v.type == GROUP_VALUE)
-        {
-            gmx_ana_index_t *g = sel->v.u.g;
-            if (!g || g->isize == 0)
-                g = &sel->u.cgrp;
-            fprintf(fp, " (%d atoms)", g->isize);
-        }
-    }
-    else if (sel->type == SEL_BOOLEAN)
-    {
-        fprintf(fp, " %s", _gmx_selelem_gmx_boolean_type_str(sel));
-    }
-    else if (sel->type == SEL_EXPRESSION
-             && sel->u.expr.method->name == sm_compare.name)
-    {
-        _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
-    }
-    if (sel->evaluate)
-    {
-        fprintf(fp, " eval=");
-        _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
-    }
-    if (sel->refcount > 1)
-    {
-        fprintf(fp, " refc=%d", sel->refcount);
-    }
-    if (!(sel->flags & SEL_ALLOCVAL))
-    {
-        fprintf(fp, " (ext. output)");
-    }
-    fprintf(fp, "\n");
-
-    if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
-    {
-        gmx_ana_index_t *g = sel->v.u.g;
-        if (!g || g->isize == 0 || sel->evaluate != NULL)
-        {
-            g = &sel->u.cgrp;
-        }
-        if (g->isize < 0)
-        {
-            fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
-        }
-        else if (g->isize > 0)
-        {
-            fprintf(fp, "%*c group:", level*2+1, ' ');
-            if (g->isize <= 20)
-            {
-                for (i = 0; i < g->isize; ++i)
-                {
-                    fprintf(fp, " %d", g->index[i] + 1);
-                }
-            }
-            else
-            {
-                fprintf(fp, " %d atoms", g->isize);
-            }
-            fprintf(fp, "\n");
-        }
-    }
-    else if (sel->type == SEL_EXPRESSION)
-    {
-        if (sel->u.expr.pc)
-        {
-            fprintf(fp, "%*c COM", level*2+3, '*');
-            fprintf(fp, "\n");
-        }
-    }
-
-    if (sel->cdata)
-    {
-        _gmx_selelem_print_compiler_info(fp, sel, level);
-    }
-
-    if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
-    {
-        fprintf(fp, "%*c value: ", level*2+1, ' ');
-        switch (sel->v.type)
-        {
-            case POS_VALUE:
-                /* In normal use, the pointer should never be NULL, but it's
-                 * useful to have the check for debugging to avoid accidental
-                 * segfaults when printing the selection tree. */
-                if (sel->v.u.p->x)
-                {
-                    fprintf(fp, "(%f, %f, %f)",
-                            sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
-                            sel->v.u.p->x[0][ZZ]);
-                }
-                else
-                {
-                    fprintf(fp, "(null)");
-                }
-                break;
-            case GROUP_VALUE:
-                fprintf(fp, "%d atoms", sel->v.u.g->isize);
-                if (sel->v.u.g->isize < 20)
-                {
-                    if (sel->v.u.g->isize > 0)
-                    {
-                        fprintf(fp, ":");
-                    }
-                    for (i = 0; i < sel->v.u.g->isize; ++i)
-                    {
-                        fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
-                    }
-                }
-                break;
-            default:
-                fprintf(fp, "???");
-                break;
-        }
-        fprintf(fp, "\n");
-    }
-
-    /* Print the subexpressions with one more level of indentation */
-    child = sel->child;
-    while (child)
-    {
-        if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
-        {
-            _gmx_selelem_print_tree(fp, child, bValues, level+1);
-        }
-        child = child->next;
-    }
-}
-
-/*!
- * \param[in] root Root of the subtree to query.
- * \returns TRUE if \p root or any any of its elements require topology
- *   information, FALSE otherwise.
- */
-gmx_bool
-_gmx_selelem_requires_top(t_selelem *root)
-{
-    t_selelem *child;
-
-    if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
-    {
-        if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
-        {
-            return TRUE;
-        }
-        if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
-        {
-            return TRUE;
-        }
-    }
-    child = root->child;
-    while (child)
-    {
-        if (_gmx_selelem_requires_top(child))
-        {
-            return TRUE;
-        }
-        child = child->next;
-    }
-    return FALSE;
-}
diff --git a/src/gmxlib/selection/selelem.h b/src/gmxlib/selection/selelem.h
deleted file mode 100644 (file)
index 571d8a1..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Definition of \c t_selelem and related things.
- *
- * The selection element trees constructed by the parser and the compiler
- * are described on the respective pages:
- * \ref selparser and \ref selcompiler.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_ELEMENT_H
-#define SELECTION_ELEMENT_H
-
-#include <types/simple.h>
-
-#include <indexutil.h>
-#include <selvalue.h>
-
-struct gmx_ana_poscalc_t;
-struct gmx_ana_selparam_t;
-struct gmx_ana_selmethod_t;
-
-struct gmx_sel_evaluate_t;
-struct gmx_sel_mempool_t;
-struct t_selelem;
-
-/********************************************************************/
-/*! \name Enumerations for expression types
- ********************************************************************/
-/*@{*/
-
-/** Defines the type of a \c t_selelem object. */
-typedef enum
-{
-    /** Constant-valued expression. */
-    SEL_CONST,
-    /** Method expression that requires evaluation. */
-    SEL_EXPRESSION,
-    /** Boolean expression. */
-    SEL_BOOLEAN,
-    /** Arithmetic expression. */
-    SEL_ARITHMETIC,
-    /** Root node of the evaluation tree. */
-    SEL_ROOT,
-    /** Subexpression that may be referenced several times. */
-    SEL_SUBEXPR,
-    /** Reference to a subexpression. */
-    SEL_SUBEXPRREF,
-    /** Post-processing of selection value. */
-    SEL_MODIFIER
-} e_selelem_t;
-
-/** Defines the gmx_boolean operation of \c t_selelem objects with type \ref SEL_BOOLEAN. */
-typedef enum
-{
-    BOOL_NOT,           /**< Not */
-    BOOL_AND,           /**< And */
-    BOOL_OR,            /**< Or */
-    BOOL_XOR            /**< Xor (not implemented). */
-} e_boolean_t;
-
-/** Defines the arithmetic operation of \c t_selelem objects with type \ref SEL_ARITHMETIC. */
-typedef enum
-{
-    ARITH_PLUS,         /**< + */
-    ARITH_MINUS,        /**< - */
-    ARITH_NEG,          /**< Unary - */
-    ARITH_MULT,         /**< * */
-    ARITH_DIV,          /**< / */
-    ARITH_EXP           /**< ^ (to power) */
-} e_arithmetic_t;
-
-/** Returns a string representation of the type of a \c t_selelem. */
-extern const char *
-_gmx_selelem_type_str(struct t_selelem *sel);
-/** Returns a string representation of the gmx_boolean type of a \ref SEL_BOOLEAN \c t_selelem. */
-extern const char *
-_gmx_selelem_gmx_boolean_type_str(struct t_selelem *sel);
-/** Returns a string representation of the type of a \c gmx_ana_selvalue_t. */
-extern const char *
-_gmx_sel_value_type_str(gmx_ana_selvalue_t *val);
-
-/*@}*/
-
-
-/********************************************************************/
-/*! \name Selection expression flags
- * \anchor selelem_flags
- ********************************************************************/
-/*@{*/
-/*! \brief
- * Selection value flags are set.
- *
- * If this flag is set, the flags covered by \ref SEL_VALFLAGMASK
- * have been set properly for the element.
- */
-#define SEL_FLAGSSET    1
-/*! \brief
- * The element evaluates to a single value.
- *
- * This flag is always set for \ref GROUP_VALUE elements.
- */
-#define SEL_SINGLEVAL   2
-/*! \brief
- * The element evaluates to one value for each input atom.
- */
-#define SEL_ATOMVAL     4
-/*! \brief
- * The element evaluates to an arbitrary number of values.
- */
-#define SEL_VARNUMVAL   8
-/*! \brief
- * The element (or one of its children) is dynamic.
- */
-#define SEL_DYNAMIC     16
-/*! \brief
- * Mask that covers the flags that describe the number of values.
- */
-#define SEL_VALTYPEMASK (SEL_SINGLEVAL | SEL_ATOMVAL | SEL_VARNUMVAL)
-/*! \brief
- * Mask that covers the flags that describe the value type.
- */
-#define SEL_VALFLAGMASK (SEL_FLAGSSET | SEL_VALTYPEMASK | SEL_DYNAMIC)
-/*! \brief
- * Data has been allocated for the \p v.u union.
- *
- * If not set, the \p v.u.ptr points to data allocated externally.
- * This is the case if the value of the element is used as a parameter
- * for a selection method or if the element evaluates the final value of
- * a selection.
- *
- * Even if the flag is set, \p v.u.ptr can be NULL during initialization.
- *
- * \todo
- * This flag overlaps with the function of \p v.nalloc field, and could
- * probably be removed, making memory management simpler. Currently, the
- * \p v.nalloc field is not kept up-to-date in all cases when this flag
- * is changed and is used in places where this flag is not, so this would
- * require a careful investigation of the selection code.
- */
-#define SEL_ALLOCVAL    (1<<8)
-/*! \brief
- * Data has been allocated for the group/position structure.
- *
- * If not set, the memory allocated for fields in \p v.u.g or \p v.u.p is
- * managed externally.
- *
- * This field has no effect if the value type is not \ref GROUP_VALUE or
- * \ref POS_VALUE, but should not be set.
- */
-#define SEL_ALLOCDATA   (1<<9)
-/*! \brief
- * \p method->init_frame should be called for the frame.
- */
-#define SEL_INITFRAME   (1<<10)
-/*! \brief
- * Parameter has been evaluated for the current frame.
- *
- * This flag is set for children of \ref SEL_EXPRESSION elements (which
- * describe method parameters) after the element has been evaluated for the
- * current frame.
- * It is not set for \ref SEL_ATOMVAL elements, because they may need to
- * be evaluated multiple times.
- */
-#define SEL_EVALFRAME   (1<<11)
-/*! \brief
- * \p method->init has been called.
- */
-#define SEL_METHODINIT  (1<<12)
-/*! \brief
- * \p method->outinit has been called.
- *
- * This flag is also used for \ref SEL_SUBEXPRREF elements.
- */
-#define SEL_OUTINIT     (1<<13)
-/*@}*/
-
-
-/********************************************************************/
-/*! \name Selection expression data structures and functions
- ********************************************************************/
-/*@{*/
-
-struct t_selelem;
-
-/*! \brief
- * Function pointer for evaluating a \c t_selelem.
- */
-typedef int (*sel_evalfunc)(struct gmx_sel_evaluate_t *data,
-                            struct t_selelem *sel, gmx_ana_index_t *g);
-
-/*! \internal \brief
- * Represents an element of a selection expression.
- */
-typedef struct t_selelem
-{
-    /*! \brief Name of the element.
-     *
-     * This field is only used for informative purposes.
-     * It is always either NULL or a pointer to a string.
-     * Memory is never allocated for it directly.
-     */
-    const char                         *name;
-    /** Type of the element. */
-    e_selelem_t                         type;
-    /*! \brief
-     * Value storage of the element.
-     *
-     * This field contains the evaluated value of the element, as well as
-     * the output value type.
-     */
-    gmx_ana_selvalue_t                  v;
-    /*! \brief
-     * Evaluation function for the element.
-     *
-     * Can be either NULL (if the expression is a constant and does not require
-     * evaluation) or point to one of the functions defined in evaluate.h.
-     */
-    sel_evalfunc                        evaluate;
-    /*! \brief
-     * Information flags about the element.
-     *
-     * Allowed flags are listed here:
-     * \ref selelem_flags "flags for \c t_selelem".
-     */
-    int                                 flags;
-    /** Data required by the evaluation function. */
-    union {
-        /*! \brief Index group data for several element types.
-         *
-         *  - \ref SEL_CONST : if the value type is \ref GROUP_VALUE,
-         *    this field holds the unprocessed group value.
-         *  - \ref SEL_ROOT : holds the group value for which the
-         *    selection subtree should be evaluated.
-         *  - \ref SEL_SUBEXPR : holds the group for which the subexpression
-         *    has been evaluated.
-         */
-        gmx_ana_index_t                 cgrp;
-        /** Data for \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements. */
-        struct {
-            /** Pointer the the method used in this expression. */
-            struct gmx_ana_selmethod_t *method;
-            /** Pointer to the data allocated by the method's \p init_data (see sel_datafunc()). */
-            void                       *mdata;
-            /** Pointer to the position data passed to the method. */
-            struct gmx_ana_pos_t       *pos;
-            /** Pointer to the evaluation data for \p pos. */
-            struct gmx_ana_poscalc_t   *pc;
-        }                               expr;
-        /** Operation type for \ref SEL_BOOLEAN elements. */
-        e_boolean_t                     boolt;
-        /** Operation type for \ref SEL_ARITHMETIC elements. */
-        struct {
-            /** Operation type. */
-            e_arithmetic_t              type;
-            /** String representation. */
-            char                       *opstr;
-        }                               arith;
-        /** Associated selection parameter for \ref SEL_SUBEXPRREF elements. */
-        struct gmx_ana_selparam_t      *param;
-    }                                   u;
-    /** Memory pool to use for values, or NULL if standard memory handling. */
-    struct gmx_sel_mempool_t           *mempool;
-    /** Internal data for the selection compiler. */
-    struct t_compiler_data             *cdata;
-    
-    /*! \brief The first child element.
-     *
-     * Other children can be accessed through the \p next field of \p child.
-     */
-    struct t_selelem                    *child;
-    /** The next sibling element. */
-    struct t_selelem                    *next;
-    /*! \brief Number of references to this element.
-     *
-     * Should be larger than one only for \ref SEL_SUBEXPR elements.
-     */
-    int                                  refcount;
-} t_selelem;
-
-/* In evaluate.c */
-/** Writes out a human-readable name for an evaluation function. */
-extern void
-_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc);
-
-/** Allocates memory and performs some common initialization for a \c t_selelem. */
-extern t_selelem *
-_gmx_selelem_create(e_selelem_t type);
-/** Sets the value type of a \c t_selelem. */
-extern int
-_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype);
-/** Reserves memory for value of a \c t_selelem from a memory pool. */
-extern int
-_gmx_selelem_mempool_reserve(t_selelem *sel, int count);
-/** Releases memory pool used for value of a \c t_selelem. */
-extern void
-_gmx_selelem_mempool_release(t_selelem *sel);
-/** Frees the memory allocated for a \c t_selelem structure and all its children. */
-extern void
-_gmx_selelem_free(t_selelem *sel);
-/** Frees the memory allocated for a \c t_selelem structure, all its children, and also all structures referenced through t_selelem::next fields. */
-extern void
-_gmx_selelem_free_chain(t_selelem *first);
-
-/** Frees the memory allocated for the \c t_selelem::d union. */
-extern void
-_gmx_selelem_free_values(t_selelem *sel);
-/** Frees the memory allocated for a selection method. */
-extern void
-_gmx_selelem_free_method(struct gmx_ana_selmethod_t *method, void *mdata);
-/** Frees the memory allocated for the \c t_selelem::u field. */
-extern void
-_gmx_selelem_free_exprdata(t_selelem *sel);
-/* In compiler.c */
-/** Frees the memory allocated for the selection compiler. */
-extern void
-_gmx_selelem_free_compiler_data(t_selelem *sel);
-
-/** Prints a human-readable version of a selection element subtree. */
-extern void
-_gmx_selelem_print_tree(FILE *fp, t_selelem *root, gmx_bool bValues, int level);
-/* In compile.c */
-/** Prints a human-readable version of the internal compiler data structure. */
-extern void
-_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level);
-
-/** Returns TRUE if the selection element subtree requires topology information for evaluation. */
-extern gmx_bool
-_gmx_selelem_requires_top(t_selelem *root);
-
-/* In sm_insolidangle.c */
-/** Returns TRUE if the covered fraction of the selection can be calculated. */
-extern gmx_bool
-_gmx_selelem_can_estimate_cover(t_selelem *sel);
-/** Returns the covered fraction of the selection for the current frame. */
-extern real
-_gmx_selelem_estimate_coverfrac(t_selelem *sel);
-
-/*@}*/
-
-#endif
diff --git a/src/gmxlib/selection/selhelp.c b/src/gmxlib/selection/selhelp.c
deleted file mode 100644 (file)
index 0bbe59f..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in selhelp.c.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <string2.h>
-#include <wman.h>
-
-#include "selcollection.h"
-#include "selmethod.h"
-#include "selhelp.h"
-#include "symrec.h"
-
-typedef struct {
-    const char  *topic;
-    int          nl;
-    const char **text;
-} t_selection_help_item;
-
-static const char *help_common[] = {
-    "SELECTION HELP[PAR]",
-
-    "This program supports selections in addition to traditional index files.",
-    "Please read the subtopic pages (available through \"help topic\") for",
-    "more information.",
-    "Explanation of command-line arguments for specifying selections can be",
-    "found under the \"cmdline\" subtopic, and general selection syntax is",
-    "described under \"syntax\". Available keywords can be found under",
-    "\"keywords\", and concrete examples under \"examples\".",
-    "Other subtopics give more details on certain aspects.",
-    "\"help all\" prints the help for all subtopics.",
-};
-
-static const char *help_arithmetic[] = {
-    "ARITHMETIC EXPRESSIONS IN SELECTIONS[PAR]",
-
-    "Basic arithmetic evaluation is supported for numeric expressions.",
-    "Supported operations are addition, subtraction, negation, multiplication,",
-    "division, and exponentiation (using ^).",
-    "Result of a division by zero or other illegal operations is undefined.",
-};
-
-static const char *help_cmdline[] = {
-    "SELECTION COMMAND-LINE ARGUMENTS[PAR]",
-
-    "There are two alternative command-line arguments for specifying",
-    "selections:[BR]",
-    "1. [TT]-select[tt] can be used to specify the complete selection as a",
-    "string on the command line.[BR]",
-    "2. [TT]-sf[tt] can be used to specify a file name from which the",
-    "selection is read.[BR]",
-    "If both options are specified, [TT]-select[tt] takes precedence.",
-    "If neither of the above is present, the user is prompted to type the",
-    "selection on the standard input (a pipe can also be used to provide",
-    "the selections in this case).",
-    "This is also done if an empty string is passed to [TT]-select[tt].[PAR]",
-
-    "Option [TT]-n[tt] can be used to provide an index file.",
-    "If no index file is provided, default groups are generated.",
-    "In both cases, the user can also select an index group instead of",
-    "writing a full selection.",
-    "The default groups are generated by reading selections from a file",
-    "[TT]defselection.dat[tt]. If such a file is found in the current",
-    "directory, it is used instead of the one provided by default.[PAR]",
-
-    "Depending on the tool, two additional command-line arguments may be",
-    "available to control the behavior:[BR]",
-    "1. [TT]-seltype[tt] can be used to specify the default type of",
-    "positions to calculate for each selection.[BR]",
-    "2. [TT]-selrpos[tt] can be used to specify the default type of",
-    "positions used in selecting atoms by coordinates.[BR]",
-    "See \"help positions\" for more information on these options.",
-};
-
-static const char *help_eval[] = {
-    "SELECTION EVALUATION AND OPTIMIZATION[PAR]",
-
-    "Boolean evaluation proceeds from left to right and is short-circuiting",
-    "i.e., as soon as it is known whether an atom will be selected, the",
-    "remaining expressions are not evaluated at all.",
-    "This can be used to optimize the selections: you should write the",
-    "most restrictive and/or the most inexpensive expressions first in",
-    "boolean expressions.",
-    "The relative ordering between dynamic and static expressions does not",
-    "matter: all static expressions are evaluated only once, before the first",
-    "frame, and the result becomes the leftmost expression.[PAR]",
-
-    "Another point for optimization is in common subexpressions: they are not",
-    "automatically recognized, but can be manually optimized by the use of",
-    "variables. This can have a big impact on the performance of complex",
-    "selections, in particular if you define several index groups like this:",
-    "  [TT]rdist = distance from com of resnr 1 to 5;[tt][BR]",
-    "  [TT]resname RES and rdist < 2;[tt][BR]",
-    "  [TT]resname RES and rdist < 4;[tt][BR]",
-    "  [TT]resname RES and rdist < 6;[tt][BR]",
-    "Without the variable assignment, the distances would be evaluated three",
-    "times, although they are exactly the same within each selection.",
-    "Anything assigned into a variable becomes a common subexpression that",
-    "is evaluated only once during a frame.",
-    "Currently, in some cases the use of variables can actually lead to a small",
-    "performance loss because of the checks necessary to determine for which",
-    "atoms the expression has already been evaluated, but this should not be",
-    "a major problem.",
-};
-
-static const char *help_examples[] = {
-    "SELECTION EXAMPLES[PAR]",
-
-    "Below, examples of increasingly complex selections are given.[PAR]",
-
-    "Selection of all water oxygens:[BR]",
-    "  resname SOL and name OW",
-    "[PAR]",
-
-    "Centers of mass of residues 1 to 5 and 10:[BR]",
-    "  res_com of resnr 1 to 5 10",
-    "[PAR]",
-
-    "All atoms farther than 1 nm of a fixed position:[BR]",
-    "  not within 1 of (1.2, 3.1, 2.4)",
-    "[PAR]",
-
-    "All atoms of a residue LIG within 0.5 nm of a protein (with a custom name):[BR]",
-    "  \"Close to protein\" resname LIG and within 0.5 of group \"Protein\"",
-    "[PAR]",
-
-    "All protein residues that have at least one atom within 0.5 nm of a residue LIG:[BR]",
-    "  group \"Protein\" and same residue as within 0.5 of resname LIG",
-    "[PAR]",
-
-    "All RES residues whose COM is between 2 and 4 nm from the COM of all of them:[BR]",
-    "  rdist = res_com distance from com of resname RES[BR]",
-    "  resname RES and rdist >= 2 and rdist <= 4",
-    "[PAR]",
-
-    "Selection like C1 C2 C2 C3 C3 C4 ... C8 C9 (e.g., for g_bond):[BR]",
-    "  name \"C[1-8]\" merge name \"C[2-9]\"",
-};
-
-static const char *help_keywords[] = {
-    "SELECTION KEYWORDS[PAR]",
-
-    "The following selection keywords are currently available.",
-    "For keywords marked with a star, additional help is available through",
-    "\"help KEYWORD\", where KEYWORD is the name of the keyword.",
-};
-
-static const char *help_limits[] = {
-    "SELECTION LIMITATIONS[PAR]",
-
-    "Some analysis programs may require a special structure for the input",
-    "selections (e.g., [TT]g_angle[tt] requires the index group to be made",
-    "of groups of three or four atoms).",
-    "For such programs, it is up to the user to provide a proper selection",
-    "expression that always returns such positions.",
-    "[PAR]",
-
-    "Due to technical reasons, having a negative value as the first value in",
-    "expressions like[BR]",
-    "[TT]charge -1 to -0.7[tt][BR]",
-    "result in a syntax error. A workaround is to write[BR]",
-    "[TT]charge {-1 to -0.7}[tt][BR]",
-    "instead.",
-};
-
-static const char *help_positions[] = {
-    "SPECIFYING POSITIONS[PAR]",
-
-    "Possible ways of specifying positions in selections are:[PAR]",
-
-    "1. A constant position can be defined as [TT][XX, YY, ZZ][tt], where",
-    "[TT]XX[tt], [TT]YY[tt] and [TT]ZZ[tt] are real numbers.[PAR]",
-
-    "2. [TT]com of ATOM_EXPR [pbc][tt] or [TT]cog of ATOM_EXPR [pbc][tt]",
-    "calculate the center of mass/geometry of [TT]ATOM_EXPR[tt]. If",
-    "[TT]pbc[tt] is specified, the center is calculated iteratively to try",
-    "to deal with cases where [TT]ATOM_EXPR[tt] wraps around periodic",
-    "boundary conditions.[PAR]",
-
-    "3. [TT]POSTYPE of ATOM_EXPR[tt] calculates the specified positions for",
-    "the atoms in [TT]ATOM_EXPR[tt].",
-    "[TT]POSTYPE[tt] can be [TT]atom[tt], [TT]res_com[tt], [TT]res_cog[tt],",
-    "[TT]mol_com[tt] or [TT]mol_cog[tt], with an optional prefix [TT]whole_[tt]",
-    "[TT]part_[tt] or [TT]dyn_[tt].",
-    "[TT]whole_[tt] calculates the centers for the whole residue/molecule,",
-    "even if only part of it is selected.",
-    "[TT]part_[tt] prefix calculates the centers for the selected atoms, but",
-    "uses always the same atoms for the same residue/molecule. The used atoms",
-    "are determined from the the largest group allowed by the selection.",
-    "[TT]dyn_[tt] calculates the centers strictly only for the selected atoms.",
-    "If no prefix is specified, whole selections default to [TT]part_[tt] and",
-    "other places default to [TT]whole_[tt].",
-    "The latter is often desirable to select the same molecules in different",
-    "tools, while the first is a compromise between speed ([TT]dyn_[tt]",
-    "positions can be slower to evaluate than [TT]part_[tt]) and intuitive",
-    "behavior.[PAR]",
-
-    "4. [TT]ATOM_EXPR[tt], when given for whole selections, is handled as 3.",
-    "above, using the position type from the command-line argument",
-    "[TT]-seltype[tt].[PAR]",
-
-    "Selection keywords that select atoms based on their positions, such as",
-    "[TT]dist from[tt], use by default the positions defined by the",
-    "[TT]-selrpos[tt] command-line option.",
-    "This can be overridden by prepending a [TT]POSTYPE[tt] specifier to the",
-    "keyword. For example, [TT]res_com dist from POS[tt] evaluates the",
-    "residue center of mass distances. In the example, all atoms of a residue",
-    "are either selected or not, based on the single distance calculated.",
-};
-
-static const char *help_syntax[] = {
-    "SELECTION SYNTAX[PAR]",
-
-    "A set of selections consists of one or more selections, separated by",
-    "semicolons. Each selection defines a set of positions for the analysis.",
-    "Each selection can also be preceded by a string that gives a name for",
-    "the selection for use in, e.g., graph legends.",
-    "If no name is provided, the string used for the selection is used",
-    "automatically as the name.[PAR]",
-
-    "For interactive input, the syntax is slightly altered: line breaks can",
-    "also be used to separate selections. \\ followed by a line break can",
-    "be used to continue a line if necessary.",
-    "Notice that the above only applies to real interactive input,",
-    "not if you provide the selections, e.g., from a pipe.[PAR]",
-
-    "It is possible to use variables to store selection expressions.",
-    "A variable is defined with the following syntax:[BR]",
-    "[TT]VARNAME = EXPR ;[tt][BR]",
-    "where [TT]EXPR[tt] is any valid selection expression.",
-    "After this, [TT]VARNAME[tt] can be used anywhere where [TT]EXPR[tt]",
-    "would be valid.[PAR]",
-
-    "Selections are composed of three main types of expressions, those that",
-    "define atoms ([TT]ATOM_EXPR[tt]s), those that define positions",
-    "([TT]POS_EXPR[tt]s), and those that evaluate to numeric values",
-    "([TT]NUM_EXPR[tt]s). Each selection should be a [TT]POS_EXPR[tt]",
-    "or a [TT]ATOM_EXPR[tt] (the latter is automatically converted to",
-    "positions). The basic rules are as follows:[BR]",
-    "1. An expression like [TT]NUM_EXPR1 < NUM_EXPR2[tt] evaluates to an",
-    "[TT]ATOM_EXPR[tt] that selects all the atoms for which the comparison",
-    "is true.[BR]",
-    "2. Atom expressions can be combined with gmx_boolean operations such as",
-    "[TT]not ATOM_EXPR[tt], [TT]ATOM_EXPR and ATOM_EXPR[tt], or",
-    "[TT]ATOM_EXPR or ATOM_EXPR[tt]. Parentheses can be used to alter the",
-    "evaluation order.[BR]",
-    "3. [TT]ATOM_EXPR[tt] expressions can be converted into [TT]POS_EXPR[tt]",
-    "expressions in various ways, see \"help positions\" for more details.[PAR]",
-
-    "Some keywords select atoms based on string values such as the atom name.",
-    "For these keywords, it is possible to use wildcards ([TT]name \"C*\"[tt])",
-    "or regular expressions (e.g., [TT]resname \"R[AB]\"[tt]).",
-    "The match type is automatically guessed from the string: if it contains",
-    "other characters than letters, numbers, '*', or '?', it is interpreted",
-    "as a regular expression.",
-    "Strings that contain non-alphanumeric characters should be enclosed in",
-    "double quotes as in the examples. For other strings, the quotes are",
-    "optional, but if the value conflicts with a reserved keyword, a syntax",
-    "error will occur. If your strings contain uppercase letters, this should",
-    "not happen.[PAR]",
-
-    "Index groups provided with the [TT]-n[tt] command-line option or",
-    "generated by default can be accessed with [TT]group NR[tt] or",
-    "[TT]group NAME[tt], where [TT]NR[tt] is a zero-based index of the group",
-    "and [TT]NAME[tt] is part of the name of the desired group.",
-    "The keyword [TT]group[tt] is optional if the whole selection is",
-    "provided from an index group.",
-    "To see a list of available groups in the interactive mode, press enter",
-    "in the beginning of a line.",
-};
-
-static const t_selection_help_item helpitems[] = {
-    {NULL,          asize(help_common),     help_common},
-    {"cmdline",     asize(help_cmdline),    help_cmdline},
-    {"syntax",      asize(help_syntax),     help_syntax},
-    {"positions",   asize(help_positions),  help_positions},
-    {"arithmetic",  asize(help_arithmetic), help_arithmetic},
-    {"keywords",    asize(help_keywords),   help_keywords},
-    {"evaluation",  asize(help_eval),       help_eval},
-    {"limitations", asize(help_limits),     help_limits},
-    {"examples",    asize(help_examples),   help_examples},
-};
-
-/*! \brief
- * Prints a brief list of keywords (selection methods) available.
- *
- * \param[in] sc    Selection collection for which the list should be printed.
- * \param[in] type  Only methods that return this type are printed.
- * \param[in] bMod  If FALSE, \ref SMETH_MODIFIER methods are excluded, otherwise
- *     only them are printed.
- */
-static void
-print_keyword_list(struct gmx_ana_selcollection_t *sc, e_selvalue_t type,
-                   gmx_bool bMod)
-{
-    gmx_sel_symrec_t *symbol;
-
-    symbol = _gmx_sel_first_symbol(sc->symtab, SYMBOL_METHOD);
-    while (symbol)
-    {
-        gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
-        gmx_bool                 bShow;
-        bShow = (method->type == type)
-            && ((bMod && (method->flags & SMETH_MODIFIER))
-                || (!bMod && !(method->flags & SMETH_MODIFIER)));
-        if (bShow)
-        {
-            fprintf(stderr, " %c ",
-                    (method->help.nlhelp > 0 && method->help.help) ? '*' : ' ');
-            if (method->help.syntax)
-            {
-                fprintf(stderr, "%s\n", method->help.syntax);
-            }
-            else
-            {
-                const char *symname = _gmx_sel_sym_name(symbol);
-
-                fprintf(stderr, "%s", symname);
-                if (strcmp(symname, method->name) != 0)
-                {
-                    fprintf(stderr, " (synonym for %s)", method->name);
-                }
-                fprintf(stderr, "\n");
-            }
-        }
-        symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
-    }
-}
-
-/*!
- * \param[in]  sc    Selection collection for which help should be printed.
- * \param[in]  topic Topic to print help on, or NULL for general help.
- *
- * \p sc is used to get information on which keywords are available in the
- * present context.
- */
-void
-_gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
-{
-    const t_selection_help_item *item = NULL;
-    size_t i;
-
-    /* Find the item for the topic */
-    if (!topic)
-    {
-        item = &helpitems[0];
-    }
-    else if (strcmp(topic, "all") == 0)
-    {
-        for (i = 0; i < asize(helpitems); ++i)
-        {
-            item = &helpitems[i];
-            _gmx_sel_print_help(sc, item->topic);
-            if (i != asize(helpitems) - 1)
-            {
-                fprintf(stderr, "\n\n");
-            }
-        }
-        return;
-    }
-    else
-    {
-        for (i = 1; i < asize(helpitems); ++i)
-        {
-            if (strncmp(helpitems[i].topic, topic, strlen(topic)) == 0)
-            {
-                item = &helpitems[i];
-                break;
-            }
-        }
-    }
-    /* If the topic is not found, check the available methods.
-     * If they don't provide any help either, tell the user and exit. */
-    if (!item)
-    {
-        gmx_sel_symrec_t *symbol;
-
-        symbol = _gmx_sel_first_symbol(sc->symtab, SYMBOL_METHOD);
-        while (symbol)
-        {
-            gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
-            if (method->help.nlhelp > 0 && method->help.help
-                && strncmp(method->name, topic, strlen(topic)) == 0)
-            {
-                print_tty_formatted(stderr, method->help.nlhelp,
-                        method->help.help, 0, NULL, NULL, FALSE);
-                return;
-            }
-            symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
-        }
-
-        fprintf(stderr, "No help available for '%s'.\n", topic);
-        return;
-    }
-    /* Print the help */
-    print_tty_formatted(stderr, item->nl, item->text, 0, NULL, NULL, FALSE);
-    /* Special handling of certain pages */
-    if (!topic)
-    {
-        int len = 0;
-
-        /* Print the subtopics on the main page */
-        fprintf(stderr, "\nAvailable subtopics:\n");
-        for (i = 1; i < asize(helpitems); ++i)
-        {
-            int len1 = strlen(helpitems[i].topic) + 2;
-
-            len += len1;
-            if (len > 79)
-            {
-                fprintf(stderr, "\n");
-                len = len1;
-            }
-            fprintf(stderr, "  %s", helpitems[i].topic);
-        }
-        fprintf(stderr, "\n");
-    }
-    else if (strcmp(item->topic, "keywords") == 0)
-    {
-        /* Print the list of keywords */
-        fprintf(stderr, "\nKeywords that select atoms by an integer property:\n");
-        fprintf(stderr, "(use in expressions or like \"atomnr 1 to 5 7 9\")\n");
-        print_keyword_list(sc, INT_VALUE, FALSE);
-
-        fprintf(stderr, "\nKeywords that select atoms by a numeric property:\n");
-        fprintf(stderr, "(use in expressions or like \"occupancy 0.5 to 1\")\n");
-        print_keyword_list(sc, REAL_VALUE, FALSE);
-
-        fprintf(stderr, "\nKeywords that select atoms by a string property:\n");
-        fprintf(stderr, "(use like \"name PATTERN [PATTERN] ...\")\n");
-        print_keyword_list(sc, STR_VALUE, FALSE);
-
-        fprintf(stderr, "\nAdditional keywords that directly select atoms:\n");
-        print_keyword_list(sc, GROUP_VALUE, FALSE);
-
-        fprintf(stderr, "\nKeywords that directly evaluate to positions:\n");
-        fprintf(stderr, "(see also \"help positions\")\n");
-        print_keyword_list(sc, POS_VALUE, FALSE);
-
-        fprintf(stderr, "\nAdditional keywords:\n");
-        print_keyword_list(sc, POS_VALUE, TRUE);
-        print_keyword_list(sc, NO_VALUE, TRUE);
-    }
-}
diff --git a/src/gmxlib/selection/selhelp.h b/src/gmxlib/selection/selhelp.h
deleted file mode 100644 (file)
index 54acb1b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Functions for printing help for selections.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_HELP_H
-#define SELECTION_HELP_H
-
-struct gmx_ana_selcollection_t;
-
-/** Prints help for writing selections. */
-void
-_gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic);
-
-#endif
diff --git a/src/gmxlib/selection/selmethod.c b/src/gmxlib/selection/selmethod.c
deleted file mode 100644 (file)
index 982eaed..0000000
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in selmethod.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <stdarg.h>
-
-#include <macros.h>
-#include <string2.h>
-
-#include <selmethod.h>
-
-#include "selcollection.h"
-#include "symrec.h"
-
-/*
- * These global variables cannot be const because gmx_ana_selmethod_register()
- * modifies them to set some defaults. This is a small price to pay for the
- * convenience of not having to remember exactly how the selection compiler
- * expects the structures to be filled, and even more so if the expectations
- * change. Also, even if the gmx_ana_selmethod_t structures were made const,
- * the parameters could not be without typecasts somewhere, because the param
- * field in gmx_ana_selmethod_t cannot be declared const.
- *
- * Even though the variables may be modified, this should be thread-safe as
- * modifications are done only in gmx_ana_selmethod_register(), and it should
- * work even if called more than once for the same structure, and even if
- * called concurrently from multiple threads (as long as the selection
- * collection is not the same).
- *
- * All of these problems should go away if/when the selection methods are
- * implemented as C++ classes.
- */
-
-/* From sm_com.c */
-extern gmx_ana_selmethod_t sm_cog;
-extern gmx_ana_selmethod_t sm_com;
-/* From sm_simple.c */
-extern gmx_ana_selmethod_t sm_all;
-extern gmx_ana_selmethod_t sm_none;
-extern gmx_ana_selmethod_t sm_atomnr;
-extern gmx_ana_selmethod_t sm_resnr;
-extern gmx_ana_selmethod_t sm_resindex;
-extern gmx_ana_selmethod_t sm_molindex;
-extern gmx_ana_selmethod_t sm_atomname;
-extern gmx_ana_selmethod_t sm_atomtype;
-extern gmx_ana_selmethod_t sm_resname;
-extern gmx_ana_selmethod_t sm_insertcode;
-extern gmx_ana_selmethod_t sm_chain;
-extern gmx_ana_selmethod_t sm_mass;
-extern gmx_ana_selmethod_t sm_charge;
-extern gmx_ana_selmethod_t sm_altloc;
-extern gmx_ana_selmethod_t sm_occupancy;
-extern gmx_ana_selmethod_t sm_betafactor;
-extern gmx_ana_selmethod_t sm_x;
-extern gmx_ana_selmethod_t sm_y;
-extern gmx_ana_selmethod_t sm_z;
-/* From sm_distance.c */
-extern gmx_ana_selmethod_t sm_distance;
-extern gmx_ana_selmethod_t sm_mindistance;
-extern gmx_ana_selmethod_t sm_within;
-/* From sm_insolidangle.c */
-extern gmx_ana_selmethod_t sm_insolidangle;
-/* From sm_same.c */
-extern gmx_ana_selmethod_t sm_same;
-
-/* From sm_merge.c */
-extern gmx_ana_selmethod_t sm_merge;
-extern gmx_ana_selmethod_t sm_plus;
-/* From sm_permute.c */
-extern gmx_ana_selmethod_t sm_permute;
-
-/*! \brief
- * Helper structure for defining selection methods.
- */
-typedef struct {
-    /*! \brief
-     * Name to register the method under.
-     *
-     * If NULL, use the actual name of the method.
-     * This field is used for defining synonyms.
-     */
-    const char            *name;
-    /** Method data structure to register. */
-    gmx_ana_selmethod_t   *method;
-} t_register_method;
-
-/** Array of selection methods defined in the library. */
-static const t_register_method smtable_def[] = {
-    {NULL,         &sm_cog},
-    {NULL,         &sm_com},
-
-    {NULL,         &sm_all},
-    {NULL,         &sm_none},
-    {NULL,         &sm_atomnr},
-    {NULL,         &sm_resnr},
-    {"resid",      &sm_resnr},
-    {NULL,         &sm_resindex},
-    {"residue",    &sm_resindex},
-    {NULL,         &sm_molindex},
-    {"mol",        &sm_molindex},
-    {"molecule",   &sm_molindex},
-    {NULL,         &sm_atomname},
-    {NULL,         &sm_atomtype},
-    {NULL,         &sm_resname},
-    {NULL,         &sm_insertcode},
-    {NULL,         &sm_chain},
-    {NULL,         &sm_mass},
-    {NULL,         &sm_charge},
-    {NULL,         &sm_altloc},
-    {NULL,         &sm_occupancy},
-    {NULL,         &sm_betafactor},
-    {NULL,         &sm_x},
-    {NULL,         &sm_y},
-    {NULL,         &sm_z},
-
-    {NULL,         &sm_distance},
-    {NULL,         &sm_mindistance},
-    {NULL,         &sm_within},
-    {NULL,         &sm_insolidangle},
-    {NULL,         &sm_same},
-
-    {NULL,         &sm_merge},
-    {NULL,         &sm_plus},
-    {NULL,         &sm_permute},
-};
-
-/*! \brief
- * Convenience function for reporting errors found in selection methods.
- */
-static void
-report_error(FILE *fp, const char *name, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    if (fp)
-    {
-        fprintf(fp, "selection method '%s': ", name);
-        vfprintf(fp, fmt, ap);
-        fprintf(fp, "\n");
-    }
-    va_end(ap);
-}
-
-/*! \brief
- * Convenience function for reporting errors found in selection method parameters.
- */
-static void
-report_param_error(FILE *fp, const char *mname, const char *pname,
-                   const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    if (fp)
-    {
-        fprintf(fp, "selection method '%s': parameter '%s': ", mname, pname);
-        vfprintf(fp, fmt, ap);
-        fprintf(fp, "\n");
-    }
-    va_end(ap);
-}
-
-/*! \brief
- * Checks the validity of parameters.
- *
- * \param[in]     fp      File handle to use for diagnostic messages
- *   (can be NULL).
- * \param[in]     name    Name of the method (used for error messages).
- * \param[in]     nparams Number of parameters in \p param.
- * \param[in,out] param   Parameter array
- *   (only the \c flags field of gmx_boolean parameters may be modified).
- * \param[in]     symtab  Symbol table (used for checking overlaps).
- * \returns       TRUE if there are no problems with the parameters,
- *   FALSE otherwise.
- *
- * This function performs some checks common to both check_method() and
- * check_modifier().
- * The purpose of these checks is to ensure that the selection parser does not
- * need to check for the validity of the parameters at each turn, and to
- * report programming errors as early as possible.
- * If you remove a check, make sure that the parameter parser can handle the
- * resulting parameters.
- */
-static gmx_bool
-check_params(FILE *fp, const char *name, int nparams, gmx_ana_selparam_t param[],
-             gmx_sel_symtab_t *symtab)
-{
-    gmx_bool              bOk = TRUE;
-    gmx_sel_symrec_t *sym;
-    int               i, j;
-
-    if (nparams > 0 && !param)
-    {
-        report_error(fp, name, "error: missing parameter data");
-        bOk = FALSE;
-        return FALSE;
-    }
-    if (nparams == 0 && param)
-    {
-        report_error(fp, name, "warning: parameter data unused because nparams=0");
-    }
-    /* Check each parameter */
-    for (i = 0; i < nparams; ++i)
-    {
-        /* Check that there is at most one NULL name, in the beginning */
-        if (param[i].name == NULL && i > 0)
-        {
-            report_error(fp, name, "error: NULL parameter should be the first one");
-            bOk = FALSE;
-            continue;
-        }
-        /* Check for duplicates */
-        for (j = 0; j < i; ++j)
-        {
-            if (param[j].name == NULL)
-            {
-                continue;
-            }
-            if (!gmx_strcasecmp(param[i].name, param[j].name))
-            {
-                report_error(fp, name, "error: duplicate parameter name '%s'", param[i].name);
-                bOk = FALSE;
-                break;
-            }
-        }
-        /* Check flags */
-        if (param[i].flags & SPAR_SET)
-        {
-            report_param_error(fp, name, param[i].name, "warning: flag SPAR_SET is set");
-            param[i].flags &= ~SPAR_SET;
-        }
-        if (param[i].flags & SPAR_RANGES)
-        {
-            if (param[i].val.type != INT_VALUE && param[i].val.type != REAL_VALUE)
-            {
-                report_param_error(fp, name, param[i].name, "error: SPAR_RANGES cannot be set for a non-numeric parameter");
-                bOk = FALSE;
-            }
-            if (param[i].flags & SPAR_DYNAMIC)
-            {
-                report_param_error(fp, name, param[i].name, "warning: SPAR_DYNAMIC does not have effect with SPAR_RANGES");
-                param[i].flags &= ~SPAR_DYNAMIC;
-            }
-            if (!(param[i].flags & SPAR_VARNUM) && param[i].val.nr != 1)
-            {
-                report_param_error(fp, name, param[i].name, "error: range should take either one or an arbitrary number of values");
-                bOk = FALSE;
-            }
-            if (param[i].flags & SPAR_ATOMVAL)
-            {
-                report_param_error(fp, name, param[i].name, "error: SPAR_RANGES and SPAR_ATOMVAL both set");
-                bOk = FALSE;
-            }
-        }
-        if ((param[i].flags & SPAR_VARNUM) && (param[i].flags & SPAR_ATOMVAL))
-        {
-            report_param_error(fp, name, param[i].name, "error: SPAR_VARNUM and SPAR_ATOMVAL both set");
-            bOk = FALSE;
-        }
-        if (param[i].flags & SPAR_ENUMVAL)
-        {
-            if (param[i].val.type != STR_VALUE)
-            {
-                report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL can only be set for string parameters");
-                bOk = FALSE;
-            }
-            if (param[i].val.nr != 1)
-            {
-                report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL parameters should take exactly one value");
-                bOk = FALSE;
-            }
-            if (param[i].flags & (SPAR_DYNAMIC | SPAR_VARNUM | SPAR_ATOMVAL))
-            {
-                report_param_error(fp, name, param[i].name, "error: only SPAR_OPTIONAL supported with SPAR_ENUMVAL");
-                bOk = FALSE;
-            }
-        }
-        /* Check gmx_boolean parameters */
-        if (param[i].val.type == NO_VALUE)
-        {
-            if (param[i].val.nr != 0)
-            {
-                report_param_error(fp, name, param[i].name, "error: number of values should be zero for gmx_boolean parameters");
-                bOk = FALSE;
-            }
-            /* The gmx_boolean parameters should always be optional, so set the
-             * flag for convenience. */
-            param[i].flags |= SPAR_OPTIONAL;
-            /* Any other flags should not be specified */
-            if (param[i].flags & ~SPAR_OPTIONAL)
-            {
-                report_param_error(fp, name, param[i].name, "error: gmx_boolean parameter should not have any flags set");
-                bOk = FALSE;
-            }
-        }
-        /* Check val.nr */
-        if (param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL))
-        {
-            if (param[i].val.nr != -1)
-            {
-                report_param_error(fp, name, param[i].name, "warning: val.nr is not -1 although SPAR_VARNUM/SPAR_ATOMVAL is set");
-            }
-            param[i].val.nr = -1;
-        }
-        else if (param[i].val.type != NO_VALUE)
-        {
-            if (param[i].val.nr <= 0)
-            {
-                report_param_error(fp, name, param[i].name, "error: val.nr <= 0");
-                bOk = FALSE;
-            }
-        }
-        /* Check that the value pointer is NULL */
-        if (param[i].nvalptr != NULL)
-        {
-            report_param_error(fp, name, param[i].name, "warning: nvalptr is set");
-        }
-        if (param[i].val.u.ptr != NULL && !(param[i].flags & SPAR_ENUMVAL))
-        {
-            report_param_error(fp, name, param[i].name, "warning: value pointer is set");
-        }
-        /* Check that the name contains only valid characters */
-        if (param[i].name == NULL)
-        {
-            continue;
-        }
-        if (!isalpha(param[i].name[0]))
-        {
-            report_param_error(fp, name, param[i].name, "error: name does not begin with a letter");
-            bOk = FALSE;
-            continue;
-        }
-        for (j = 1; param[i].name[j] != 0; ++j)
-        {
-            if (param[i].name[j] != '_' && !isalnum(param[i].name[j]))
-            {
-                report_param_error(fp, name, param[i].name, "error: name contains non-alphanumeric characters");
-                bOk = FALSE;
-                break;
-            }
-        }
-        if (param[i].name[j] != 0)
-        {
-            continue;
-        }
-        /* Check that the name does not conflict with a method */
-        if (_gmx_sel_find_symbol(symtab, param[i].name, TRUE))
-        {
-            report_param_error(fp, name, param[i].name, "error: name conflicts with another method or a keyword");
-            bOk = FALSE;
-        }
-    } /* End of parameter loop */
-    /* Check parameters of existing methods */
-    sym = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
-    while (sym)
-    {
-        gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(sym);
-        gmx_ana_selparam_t  *param =
-            gmx_ana_selmethod_find_param(name, method);
-        if (param)
-        {
-            report_param_error(fp, method->name, param->name, "error: name conflicts with another method or a keyword");
-            bOk = FALSE;
-        }
-        sym = _gmx_sel_next_symbol(sym, SYMBOL_METHOD);
-    }
-    return bOk;
-}
-
-/*! \brief
- * Checks the validity of selection method callback functions.
- *
- * \param[in] fp        File handle to use for diagnostic messages
- *   (can be NULL).
- * \param[in] method    The method to check.
- * \returns   TRUE if there are no problems, FALSE otherwise.
- *
- * This function performs some checks common to both check_method() and
- * check_modifier().
- * This function checks that all the required callbacks are defined, i.e.,
- * not NULL, to find programming errors.
- */
-static gmx_bool
-check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
-{
-    gmx_bool         bOk = TRUE;
-    gmx_bool         bNeedInit;
-    int          i;
-
-    /* Make some checks on init_data and free */
-    if (method->nparams > 0 && !method->init_data)
-    {
-        report_error(fp, method->name, "error: init_data should be provided because the method has parameters");
-        bOk = FALSE;
-    }
-    if (method->free && !method->init_data)
-    {
-        report_error(fp, method->name, "warning: free is not used because of missing init_data");
-    }
-    /* Check presence of outinit for position-valued methods */
-    if (method->type == POS_VALUE && !method->outinit)
-    {
-        report_error(fp, method->name, "error: outinit should be provided because the method has POS_VALUE");
-        bOk = FALSE;
-    }
-    /* Warn of dynamic callbacks in static methods */
-    if (!(method->flags & SMETH_MODIFIER))
-    {
-        if (method->pupdate && !(method->flags & SMETH_DYNAMIC))
-        {
-            report_error(fp, method->name, "warning: pupdate not used because the method is static");
-            method->pupdate = NULL;
-        }
-    }
-    /* Check that there is an evaluation function */
-    if (method->type != NO_VALUE && !method->update && !method->pupdate)
-    {
-        report_error(fp, method->name, "error: evaluation function missing");
-        bOk = FALSE;
-    }
-    /* Loop through the parameters to determine if initialization callbacks
-     * are needed. */
-    bNeedInit = FALSE;
-    for (i = 0; i < method->nparams; ++i)
-    {
-        if (method->param[i].val.type != POS_VALUE
-            && (method->param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
-        {
-            bNeedInit = TRUE;
-        }
-    }
-    /* Check that the callbacks required by the parameters are present */
-    if (bNeedInit && !method->init)
-    {
-        report_error(fp, method->name, "error: init should be provided");
-        bOk = FALSE;
-    }
-    return bOk;
-}
-
-/*!
- * Checks the validity of a selection method.
- *
- * \param[in]     fp     File handle to use for diagnostic messages
- *   (can be NULL).
- * \param[in,out] method Method to check.
- * \param[in]     symtab Symbol table (used for checking overlaps).
- *
- * Checks the validity of the given selection method data structure
- * that does not have \ref SMETH_MODIFIER set.
- * If you remove a check, please make sure that the selection parser,
- * compiler, and evaluation functions can deal with the method.
- */
-static gmx_bool
-check_method(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
-{
-    gmx_bool         bOk = TRUE;
-
-    /* Check the type */
-    if (method->type == NO_VALUE)
-    {
-        report_error(fp, method->name, "error: no value type specified");
-        bOk = FALSE;
-    }
-    if (method->type == STR_VALUE && method->nparams > 0)
-    {
-        report_error(fp, method->name, "error: evaluates to a string but is not a keyword");
-        bOk = FALSE;
-    }
-    /* Check flags */
-    if (method->type == GROUP_VALUE)
-    {
-        /* Group methods should always have SMETH_SINGLEVAL,
-         * so set it for convenience. */
-        method->flags |= SMETH_SINGLEVAL;
-        /* Check that conflicting flags are not present. */
-        if (method->flags & SMETH_VARNUMVAL)
-        {
-            report_error(fp, method->name, "error: SMETH_VARNUMVAL cannot be set for group-valued methods");
-            bOk = FALSE;
-        }
-    }
-    else
-    {
-        if ((method->flags & SMETH_SINGLEVAL)
-            && (method->flags & SMETH_VARNUMVAL))
-        {
-            report_error(fp, method->name, "error: SMETH_SINGLEVAL and SMETH_VARNUMVAL both set");
-            bOk = FALSE;
-        }
-    }
-    if ((method->flags & SMETH_CHARVAL) && method->type != STR_VALUE)
-    {
-        report_error(fp, method->name, "error: SMETH_CHARVAL can only be specified for STR_VALUE methods");
-        bOk = FALSE;
-    }
-    /* Check the parameters */
-    if (!check_params(fp, method->name, method->nparams, method->param, symtab))
-    {
-        bOk = FALSE;
-    }
-    /* Check the callback pointers */
-    if (!check_callbacks(fp, method))
-    {
-        bOk = FALSE;
-    }
-
-    return bOk;
-}
-
-/*!
- * Checks the validity of a selection modifier method.
- *
- * \param[in]     fp     File handle to use for diagnostic messages
- *   (can be NULL).
- * \param[in,out] method Method to check.
- * \param[in]     symtab Symbol table (used for checking overlaps).
- *
- * Checks the validity of the given selection method data structure
- * that has \ref SMETH_MODIFIER set.
- * If you remove a check, please make sure that the selection parser,
- * compiler, and evaluation functions can deal with the method.
- */
-static gmx_bool
-check_modifier(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
-{
-    gmx_bool         bOk = TRUE;
-
-    /* Check the type */
-    if (method->type != NO_VALUE && method->type != POS_VALUE)
-    {
-        report_error(fp, method->name, "error: modifier should have type POS_VALUE or NO_VALUE");
-        bOk = FALSE;
-    }
-    /* Check flags */
-    if (method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
-    {
-        report_error(fp, method->name, "error: modifier should not have SMETH_SINGLEVAL or SMETH_VARNUMVAL set");
-        bOk = FALSE;
-    }
-    /* Check the parameters */
-    /* The first parameter is skipped */
-    if (!check_params(fp, method->name, method->nparams-1, method->param+1, symtab))
-    {
-        bOk = FALSE;
-    }
-    /* Check the callback pointers */
-    if (!check_callbacks(fp, method))
-    {
-        bOk = FALSE;
-    }
-    if (method->update)
-    {
-        report_error(fp, method->name, "error: modifier should not have update");
-        bOk = FALSE;
-    }
-    if (method->type == POS_VALUE && !method->pupdate)
-    {
-        report_error(fp, method->name, "error: evaluation function missing");
-        bOk = FALSE;
-    }
-
-    return bOk;
-}
-
-/*!
- * \param[in,out] sc     Selection collection to registered the method to.
- * \param[in]     name   Name under which the method should be registered.
- * \param[in]     method Method to register.
- * \returns       0 on success, EINVAL if there was something wrong with the
- *   method.
- *
- * \p name does not need to match the name of the method, and the same
- * method can be registered multiple times under different names.
- * If \p name equals some previously registered name,
- * an error message is printed and the method is not registered.
- *
- * The function also performs some sanity checking on the input method,
- * and refuses to register it if there are problems.
- * Some problems only generate warnings.
- * All problems are described to \p stderr.
- */
-int
-gmx_ana_selmethod_register(struct gmx_ana_selcollection_t *sc,
-                           const char *name, gmx_ana_selmethod_t *method)
-{
-    gmx_bool bOk;
-
-    /* Check the method */
-    if (method->flags & SMETH_MODIFIER)
-    {
-        bOk = check_modifier(stderr, method, sc->symtab);
-    }
-    else
-    {
-        bOk = check_method(stderr, method, sc->symtab);
-    }
-    /* Try to register the method if everything is ok */
-    if (bOk) 
-    {
-        if (!_gmx_sel_add_method_symbol(sc->symtab, name, method))
-        {
-            bOk = FALSE;
-        }
-    }
-    if (!bOk)
-    {
-        report_error(stderr, name, "warning: not registered");
-        return EINVAL;
-    }
-    return 0;
-}
-
-/*!
- * \param[in,out] sc     Selection collection to registered the methods to.
- * \returns       0 on success, -1 if any of the default methods could not be
- *   registered.
- */
-int
-gmx_ana_selmethod_register_defaults(struct gmx_ana_selcollection_t *sc)
-{
-    size_t i;
-    int  rc;
-    gmx_bool bOk;
-
-    bOk = TRUE;
-    for (i = 0; i < asize(smtable_def); ++i)
-    {
-        gmx_ana_selmethod_t *method = smtable_def[i].method;
-
-        if (smtable_def[i].name == NULL)
-        {
-            rc = gmx_ana_selmethod_register(sc, method->name, method);
-        }
-        else
-        {
-            rc = gmx_ana_selmethod_register(sc, smtable_def[i].name, method);
-        }
-        if (rc != 0)
-        {
-            bOk = FALSE;
-        }
-    }
-    return bOk ? 0 : -1;
-}
-
-/*!
- * \param[in] name   Name of the parameter to search.
- * \param[in] method Method to search for the parameter.
- * \returns   Pointer to the parameter in the
- *   \ref gmx_ana_selmethod_t::param "method->param" array,
- *   or NULL if no parameter with name \p name was found.
- *
- * This is a simple wrapper for gmx_ana_selparam_find().
- */
-gmx_ana_selparam_t *
-gmx_ana_selmethod_find_param(const char *name, gmx_ana_selmethod_t *method)
-{
-    return gmx_ana_selparam_find(name, method->nparams, method->param);
-}
diff --git a/src/gmxlib/selection/selvalue.c b/src/gmxlib/selection/selvalue.c
deleted file mode 100644 (file)
index 769bfa5..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in selvalue.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <smalloc.h>
-
-#include <indexutil.h>
-#include <position.h>
-#include <selvalue.h>
-
-/*!
- * \param[out] val  Output structure
- *
- * The type of \p val is not touched.
- * Any contents of \p val are discarded without freeing.
- */
-void
-_gmx_selvalue_clear(gmx_ana_selvalue_t *val)
-{
-    val->nr     = 0;
-    val->u.ptr  = NULL;
-    val->nalloc = 0;
-}
-
-/*!
- * \param[in,out] val  Value structure to allocate.
- * \param[in]     n    Maximum number of values needed.
- * \returns       Zero on success.
- *
- * Reserves memory for the values within \p val to store at least \p n values,
- * of the type specified in the \p val structure.
- *
- * If the type is \ref POS_VALUE or \ref GROUP_VALUE, memory is reserved for
- * the data structures, but no memory is reserved inside these newly allocated
- * data structures.
- * Similarly, for \ref STR_VALUE values, the pointers are set to NULL.
- * For other values, the memory is uninitialized.
- */
-int
-_gmx_selvalue_reserve(gmx_ana_selvalue_t *val, int n)
-{
-    int  i;
-
-    if (val->nalloc == -1)
-    {
-        return 0;
-    }
-
-    if (!val->u.ptr || val->nalloc < n)
-    {
-        switch (val->type)
-        {
-            case INT_VALUE:   srenew(val->u.i, n); break;
-            case REAL_VALUE:  srenew(val->u.r, n); break;
-            case STR_VALUE:
-                srenew(val->u.s, n);
-                for (i = val->nalloc; i < n; ++i)
-                {
-                    val->u.s[i] = NULL;
-                }
-                break;
-            case POS_VALUE:
-                srenew(val->u.p, n);
-                for (i = val->nalloc; i < n; ++i)
-                {
-                    gmx_ana_pos_clear(&val->u.p[i]);
-                }
-                break;
-            case GROUP_VALUE:
-                srenew(val->u.g, n);
-                for (i = val->nalloc; i < n; ++i)
-                {
-                    gmx_ana_index_clear(&val->u.g[i]);
-                }
-                break;
-            case NO_VALUE:    break;
-        }
-        val->nalloc = n;
-    }
-    return 0;
-}
-
-/*!
- * \param[in,out] val    Value structure to allocate.
- * \param[in]     ptr    Pointer where the values should be stored.
- * \returns       Zero on success.
- *
- * Automatic memory management is disabled for \p ptr, unless \p ptr is NULL.
- */
-int
-_gmx_selvalue_setstore(gmx_ana_selvalue_t *val, void *ptr)
-{
-    val->u.ptr  = ptr;
-    val->nalloc = (ptr ? -1 : 0);
-    return 0;
-}
-
-/*!
- * \param[in,out] val    Value structure to allocate.
- * \param[in]     ptr    Pointer where the values should be stored.
- * \param[in]     nalloc Number of values allocated for \p ptr.
- * \returns       Zero on success.
- */
-int
-_gmx_selvalue_setstore_alloc(gmx_ana_selvalue_t *val, void *ptr, int nalloc)
-{
-    val->u.ptr  = ptr;
-    val->nalloc = nalloc;
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_compare.c b/src/gmxlib/selection/sm_compare.c
deleted file mode 100644 (file)
index 103eb9e..0000000
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief
- * Implementation of internal selection method for comparison expressions.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <maths.h>
-#include <macros.h>
-#include <smalloc.h>
-#include <gmx_fatal.h>
-
-#include <selmethod.h>
-
-/** Defines the comparison operator for comparison expressions. */
-typedef enum
-{
-    CMP_INVALID,        /**< Indicates an error */
-    CMP_LESS,           /**< '<' */
-    CMP_LEQ,            /**< '<=' */
-    CMP_GTR,            /**< '>' */
-    CMP_GEQ,            /**< '>=' */
-    CMP_EQUAL,          /**< '==' */
-    CMP_NEQ             /**< '!=' */
-} e_comparison_t;
-
-/** The operand has a single value. */
-#define CMP_SINGLEVAL  1
-/** The operand value is dynamic. */
-#define CMP_DYNAMICVAL 2
-/** The value is real. */
-#define CMP_REALVAL    4
-/** The integer array is allocated. */
-#define CMP_ALLOCINT   16
-/** The real array is allocated. */
-#define CMP_ALLOCREAL  32
-
-/*! \internal \brief
- * Data structure for comparison expression operand values.
- */
-typedef struct
-{
-    /** Flags that describe the type of the operand. */
-    int             flags;
-    /** (Array of) integer value(s). */
-    int        *i;
-    /** (Array of) real value(s). */
-    real       *r;
-} t_compare_value;
-
-/*! \internal \brief
- * Data structure for comparison expression evaluation.
- */
-typedef struct
-{
-    /** Comparison operator as a string. */
-    char            *cmpop;
-    /** Comparison operator type. */
-    e_comparison_t   cmpt;
-    /** Left value. */
-    t_compare_value  left;
-    /** Right value. */
-    t_compare_value  right;
-} t_methoddata_compare;
-
-/** Allocates data for comparison expression evaluation. */
-static void *
-init_data_compare(int npar, gmx_ana_selparam_t *param);
-/** Initializes data for comparison expression evaluation. */
-static int
-init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the memory allocated for comparison expression evaluation. */
-static void
-free_data_compare(void *data);
-/** Evaluates comparison expressions. */
-static int
-evaluate_compare(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for comparison expression evaluation. */
-static gmx_ana_selparam_t smparams_compare[] = {
-    {"int1",  {INT_VALUE,  -1, {NULL}}, NULL,
-     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
-    {"real1", {REAL_VALUE, -1, {NULL}}, NULL,
-     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
-    {"op",    {STR_VALUE,   1, {NULL}}, NULL, 0},
-    {"int2",  {INT_VALUE,  -1, {NULL}}, NULL,
-     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
-    {"real2", {REAL_VALUE, -1, {NULL}}, NULL,
-     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
-};
-
-/** \internal Selection method data for comparison expression evaluation. */
-gmx_ana_selmethod_t sm_compare = {
-    "cmp", GROUP_VALUE, SMETH_SINGLEVAL,
-    asize(smparams_compare), smparams_compare,
-    &init_data_compare,
-    NULL,
-    &init_compare,
-    NULL,
-    &free_data_compare,
-    NULL,
-    &evaluate_compare,
-    NULL,
-    {NULL, 0, NULL},
-};
-
-/*! \brief
- * Returns a \c e_comparison_t value corresponding to an operator.
- *
- * \param[in] str  String to process.
- * \returns   The comparison type corresponding to the first one or two
- *   characters of \p str.
- *
- * \p str can contain any number of characters; only the first two
- * are used.
- * If the beginning of \p str does not match any of the recognized types,
- * \ref CMP_INVALID is returned.
- */
-static e_comparison_t
-comparison_type(char *str)
-{
-    switch (str[0])
-    {
-        case '<': return (str[1] == '=') ? CMP_LEQ   : CMP_LESS;
-        case '>': return (str[1] == '=') ? CMP_GEQ   : CMP_GTR;
-        case '=': return (str[1] == '=') ? CMP_EQUAL : CMP_INVALID;
-        case '!': return (str[1] == '=') ? CMP_NEQ   : CMP_INVALID;
-    }
-    return CMP_INVALID;
-}
-
-/*! \brief
- * Returns a string corresponding to a \c e_comparison_t value.
- *
- * \param[in] cmpt  Comparison type to convert.
- * \returns   Pointer to a string that corresponds to \p cmpt.
- *
- * The return value points to a string constant and should not be \p free'd.
- * 
- * The function returns NULL if \p cmpt is not one of the valid values.
- */
-static const char *
-comparison_type_str(e_comparison_t cmpt)
-{
-    switch (cmpt)
-    {
-        case CMP_INVALID: return "INVALID"; break;
-        case CMP_LESS:    return "<";  break;
-        case CMP_LEQ:     return "<="; break;
-        case CMP_GTR:     return ">";  break;
-        case CMP_GEQ:     return ">="; break;
-        case CMP_EQUAL:   return "=="; break;
-        case CMP_NEQ:     return "!="; break;
-    }
-    return NULL;
-}
-
-/*!
- * \param[in] fp    File to receive the output.
- * \param[in] data  Should point to a \c t_methoddata_compare.
- */
-void
-_gmx_selelem_print_compare_info(FILE *fp, void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-
-    fprintf(fp, " \"");
-    /* Print the left value */
-    if ((d->left.flags & CMP_SINGLEVAL) && !(d->left.flags & CMP_DYNAMICVAL))
-    {
-        if (d->left.flags & CMP_REALVAL)
-        {
-            fprintf(fp, "%f ", d->left.r[0]);
-        }
-        else
-        {
-            fprintf(fp, "%d ", d->left.i[0]);
-        }
-    }
-    /* Print the operator */
-    if (d->cmpt != CMP_INVALID)
-    {
-        fprintf(fp, "%s", comparison_type_str(d->cmpt));
-    }
-    else
-    {
-        fprintf(fp, "%s", d->cmpop);
-    }
-    /* Print the right value */
-    if ((d->right.flags & CMP_SINGLEVAL) && !(d->right.flags & CMP_DYNAMICVAL))
-    {
-        if (d->right.flags & CMP_REALVAL)
-        {
-            fprintf(fp, " %f", d->right.r[0]);
-        }
-        else
-        {
-            fprintf(fp, " %d", d->right.i[0]);
-        }
-    }
-    fprintf(fp, "\"");
-}
-
-/*!
- * \param[in]     npar  Not used (should be 5).
- * \param[in,out] param Method parameters (should point to a copy of
- *   \ref smparams_compare).
- * \returns       Pointer to the allocated data (\c t_methoddata_compare).
- *
- * Allocates memory for a \c t_methoddata_compare structure.
- */
-static void *
-init_data_compare(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_compare *data;
-
-    snew(data, 1);
-    param[2].val.u.s = &data->cmpop;
-    return data;
-}
-
-/* \brief
- * Reverses a comparison operator.
- *
- * \param[in] type  Comparison operator to reverse.
- * \returns   The correct comparison operator that equals \p type when the
- *   left and right sides are interchanged.
- */
-static e_comparison_t
-reverse_comparison_type(e_comparison_t type)
-{
-    switch (type)
-    {
-        case CMP_LESS: return CMP_GTR;
-        case CMP_LEQ:  return CMP_GEQ;
-        case CMP_GTR:  return CMP_LESS;
-        case CMP_GEQ:  return CMP_LEQ;
-        default:       break;
-    }
-    return type;
-}
-
-/*! \brief
- * Initializes the value storage for comparison expression.
- *
- * \param[out] val   Value structure to initialize.
- * \param[in]  param Parameters to use for initialization.
- * \returns    The number of values provided for the value, 0 on error.
- */
-static int
-init_comparison_value(t_compare_value *val, gmx_ana_selparam_t param[2])
-{
-    int  n;
-
-    val->flags = 0;
-    if (param[0].flags & SPAR_SET)
-    {
-        val->flags |=  (param[0].flags & SPAR_DYNAMIC) ? CMP_DYNAMICVAL : 0;
-        val->flags |= !(param[0].flags & SPAR_ATOMVAL) ? CMP_SINGLEVAL  : 0;
-        n           = param[0].val.nr;
-        val->i      = param[0].val.u.i;
-    }
-    else if (param[1].flags & SPAR_SET)
-    {
-        val->flags |=  (param[1].flags & SPAR_DYNAMIC) ? CMP_DYNAMICVAL : 0;
-        val->flags |= !(param[1].flags & SPAR_ATOMVAL) ? CMP_SINGLEVAL  : 0;
-        val->flags |= CMP_REALVAL;
-        n           = param[1].val.nr;
-        val->r      = param[1].val.u.r;
-    }
-    else
-    {
-        n           = 0;
-        val->i      = NULL;
-        val->r      = NULL;
-    }
-    return n;
-}
-
-/* \brief
- * Converts an integer value to floating point.
- *
- * \param[in]     n   Number of values in the \p val->u array.
- * \param[in,out] val Value to convert.
- */
-static void
-convert_int_real(int n, t_compare_value *val)
-{
-    int   i;
-    real *rv;
-
-    snew(rv, n);
-    for (i = 0; i < n; ++i)
-    {
-        rv[i] = (real)val->i[i];
-    }
-    /* Free the previous value if one is present. */
-    sfree(val->r);
-    val->r      = rv;
-    val->flags |= CMP_REALVAL | CMP_ALLOCREAL;
-}
-
-/* \brief
- * Converts a floating point value to integer.
- *
- * \param[in]     n      Number of values in the \p val->u array.
- * \param[in,out] val    Value to convert.
- * \param[in]     cmpt   Comparison operator type.
- * \param[in]     bRight TRUE if \p val appears on the right hand size of
- *   \p cmpt.
- * \returns       0 on success, EINVAL on error.
- *
- * The values are rounded such that the same comparison operator can be used.
- */
-static int
-convert_real_int(int n, t_compare_value *val, e_comparison_t cmpt, gmx_bool bRight)
-{
-    int   i;
-    int  *iv;
-
-    if (!bRight)
-    {
-        cmpt = reverse_comparison_type(cmpt);
-    }
-    snew(iv, n);
-    /* Round according to the comparison type */
-    for (i = 0; i < n; ++i)
-    {
-        switch (cmpt)
-        {
-            case CMP_LESS:
-            case CMP_GEQ:
-                iv[i] = (int)ceil(val->r[i]);
-                break;
-            case CMP_GTR:
-            case CMP_LEQ:
-                iv[i] = (int)floor(val->r[i]);
-                break;
-            case CMP_EQUAL:
-            case CMP_NEQ:
-                fprintf(stderr, "comparing equality an integer expression and a real value\n");
-                sfree(iv);
-                return EINVAL;
-            case CMP_INVALID: /* Should not be reached */
-                gmx_bug("internal error");
-                sfree(iv);
-                return EINVAL;
-        }
-    }
-    /* Free the previous value if one is present. */
-    sfree(val->i);
-    val->i      = iv;
-    val->flags &= ~CMP_REALVAL;
-    val->flags |= CMP_ALLOCINT;
-    return 0;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 5).
- * \param[in] param Method parameters (should point to \ref smparams_compare).
- * \param[in] data  Should point to a \c t_methoddata_compare.
- * \returns   0 if the input data is valid, -1 on error.
- */
-static int
-init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-    int                   n1, n2;
-
-    /* Store the values */
-    n1 = init_comparison_value(&d->left, &param[0]);
-    n2 = init_comparison_value(&d->right, &param[3]);
-    if (n1 == 0 || n2 == 0)
-    {
-        gmx_bug("one of the values for comparison missing");
-        return -1;
-    }
-    /* Store the comparison type */
-    d->cmpt = comparison_type(d->cmpop);
-    if (d->cmpt == CMP_INVALID)
-    {
-        gmx_bug("invalid comparison type");
-        return -1;
-    }
-    /* Convert the values to the same type */
-    if ((d->left.flags & CMP_REALVAL) && !(d->right.flags & CMP_REALVAL))
-    {
-        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
-        {
-            /* Nothing can be done */
-        }
-        else if (!(d->right.flags & CMP_DYNAMICVAL))
-        {
-            convert_int_real(n2, &d->right);
-        }
-        else /* d->left is static */
-        {
-            if (convert_real_int(n1, &d->left, d->cmpt, FALSE))
-            {
-                return -1;
-            }
-        }
-    }
-    else if (!(d->left.flags & CMP_REALVAL) && (d->right.flags & CMP_REALVAL))
-    {
-        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
-        {
-            /* Reverse the sides to place the integer on the right */
-            int    flags;
-            d->left.r  = d->right.r;
-            d->right.r = NULL;
-            d->right.i = d->left.i;
-            d->left.i  = NULL;
-            flags          = d->left.flags;
-            d->left.flags  = d->right.flags;
-            d->right.flags = flags;
-            d->cmpt = reverse_comparison_type(d->cmpt);
-        }
-        else if (!(d->left.flags & CMP_DYNAMICVAL))
-        {
-            convert_int_real(n1, &d->left);
-        }
-        else /* d->right is static */
-        {
-            if (convert_real_int(n2, &d->right, d->cmpt, TRUE))
-            {
-                return -1;
-            }
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \c t_methoddata_compare).
- *
- * Frees the memory allocated for \c t_methoddata_compare.
- */
-static void
-free_data_compare(void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-
-    sfree(d->cmpop);
-    if (d->left.flags & CMP_ALLOCINT)
-    {
-        sfree(d->left.i);
-    }
-    if (d->left.flags & CMP_ALLOCREAL)
-    {
-        sfree(d->left.r);
-    }
-    if (d->right.flags & CMP_ALLOCINT)
-    {
-        sfree(d->right.i);
-    }
-    if (d->right.flags & CMP_ALLOCREAL)
-    {
-        sfree(d->right.r);
-    }
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  g     Evaluation index group.
- * \param[out] out   Output data structure (\p out->u.g is used).
- * \param[in]  data  Should point to a \c t_methoddata_compare.
- * \returns    0 for success.
- */
-static int
-evaluate_compare_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-    int                   i, i1, i2, ig;
-    int                   a, b;
-    gmx_bool                  bAccept;
-
-    for (i = i1 = i2 = ig = 0; i < g->isize; ++i)
-    {
-        a = d->left.i[i1];
-        b = d->right.i[i2];
-        bAccept = FALSE;
-        switch (d->cmpt)
-        {
-            case CMP_INVALID: break;
-            case CMP_LESS:    bAccept = a <  b; break;
-            case CMP_LEQ:     bAccept = a <= b; break;
-            case CMP_GTR:     bAccept = a >  b; break;
-            case CMP_GEQ:     bAccept = a >= b; break;
-            case CMP_EQUAL:   bAccept = a == b; break;
-            case CMP_NEQ:     bAccept = a != b; break;
-        }
-        if (bAccept)
-        {
-            out->u.g->index[ig++] = g->index[i];
-        }
-        if (!(d->left.flags & CMP_SINGLEVAL))
-        {
-            ++i1;
-        }
-        if (!(d->right.flags & CMP_SINGLEVAL))
-        {
-            ++i2;
-        }
-    }
-    out->u.g->isize = ig;
-    return 0;
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  g     Evaluation index group.
- * \param[out] out   Output data structure (\p out->u.g is used).
- * \param[in]  data  Should point to a \c t_methoddata_compare.
- * \returns    0 for success.
- */
-static int
-evaluate_compare_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-    int                   i, i1, i2, ig;
-    real                  a, b;
-    gmx_bool                  bAccept;
-
-    for (i = i1 = i2 = ig = 0; i < g->isize; ++i)
-    {
-        a = d->left.r[i1];
-        b = (d->right.flags & CMP_REALVAL) ? d->right.r[i2] : d->right.i[i2];
-        bAccept = FALSE;
-        switch (d->cmpt)
-        {
-            case CMP_INVALID: break;
-            case CMP_LESS:    bAccept = a <  b; break;
-            case CMP_LEQ:     bAccept = a <= b; break;
-            case CMP_GTR:     bAccept = a >  b; break;
-            case CMP_GEQ:     bAccept = a >= b; break;
-            case CMP_EQUAL:   bAccept =  gmx_within_tol(a, b, GMX_REAL_EPS); break;
-            case CMP_NEQ:     bAccept = !gmx_within_tol(a, b, GMX_REAL_EPS); break;
-        }
-        if (bAccept)
-        {
-            out->u.g->index[ig++] = g->index[i];
-        }
-        if (!(d->left.flags & CMP_SINGLEVAL))
-        {
-            ++i1;
-        }
-        if (!(d->right.flags & CMP_SINGLEVAL))
-        {
-            ++i2;
-        }
-    }
-    out->u.g->isize = ig;
-    return 0;
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  g     Evaluation index group.
- * \param[out] out   Output data structure (\p out->u.g is used).
- * \param[in]  data  Should point to a \c t_methoddata_compare.
- * \returns    0 for success.
- */
-static int
-evaluate_compare(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_compare *d = (t_methoddata_compare *)data;
-
-    if (!((d->left.flags | d->right.flags) & CMP_REALVAL))
-    {
-        return evaluate_compare_int(top, fr, pbc, g, out, data);
-    }
-    else
-    {
-        return evaluate_compare_real(top, fr, pbc, g, out, data);
-    }
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_distance.c b/src/gmxlib/selection/sm_distance.c
deleted file mode 100644 (file)
index 61ee58e..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of distance-based selection methods.
- *
- * This file implements the \p distance, \p mindistance and \p within
- * selection methods.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <pbc.h>
-#include <smalloc.h>
-#include <vec.h>
-
-#include <nbsearch.h>
-#include <position.h>
-#include <selmethod.h>
-
-/*! \internal \brief
- * Data structure for distance-based selection method.
- *
- * The same data structure is used by all the distance-based methods.
- */
-typedef struct
-{
-    /** Cutoff distance. */
-    real                cutoff;
-    /** Positions of the reference points. */
-    gmx_ana_pos_t       p;
-    /** Neighborhood search data. */
-    gmx_ana_nbsearch_t *nb;
-} t_methoddata_distance;
-
-/** Allocates data for distance-based selection methods. */
-static void *
-init_data_common(int npar, gmx_ana_selparam_t *param);
-/** Initializes a distance-based selection method. */
-static int
-init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the data allocated for a distance-based selection method. */
-static void
-free_data_common(void *data);
-/** Initializes the evaluation of a distance-based within selection method for a frame. */
-static int
-init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/** Evaluates the \p distance selection method. */
-static int
-evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p within selection method. */
-static int
-evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for the \p distance selection method. */
-static gmx_ana_selparam_t smparams_distance[] = {
-    {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
-    {"from",   {POS_VALUE,  1, {NULL}}, NULL, SPAR_DYNAMIC},
-};
-
-/** Parameters for the \p mindistance selection method. */
-static gmx_ana_selparam_t smparams_mindistance[] = {
-    {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
-    {"from",   {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-};
-
-/** Parameters for the \p within selection method. */
-static gmx_ana_selparam_t smparams_within[] = {
-    {NULL, {REAL_VALUE,  1, {NULL}}, NULL, 0},
-    {"of", {POS_VALUE,  -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-};
-
-/** Help text for the distance selection methods. */
-static const char *help_distance[] = {
-    "DISTANCE-BASED SELECTION KEYWORDS[PAR]",
-
-    "[TT]distance from POS [cutoff REAL][tt][BR]",
-    "[TT]mindistance from POS_EXPR [cutoff REAL][tt][BR]",
-    "[TT]within REAL of POS_EXPR[tt][PAR]",
-
-    "[TT]distance[tt] and [TT]mindistance[tt] calculate the distance from the",
-    "given position(s), the only difference being in that [TT]distance[tt]",
-    "only accepts a single position, while any number of positions can be",
-    "given for [TT]mindistance[tt], which then calculates the distance to the",
-    "closest position.",
-    "[TT]within[tt] directly selects atoms that are within [TT]REAL[tt] of",
-    "[TT]POS_EXPR[tt].[PAR]",
-
-    "For the first two keywords, it is possible to specify a cutoff to speed",
-    "up the evaluation: all distances above the specified cutoff are",
-    "returned as equal to the cutoff.",
-    "Currently, this does nothing, but in the future, it allows the use of",
-    "grid-based neighborhood search techniques.",
-};
-
-/** \internal Selection method data for the \p distance method. */
-gmx_ana_selmethod_t sm_distance = {
-    "distance", REAL_VALUE, SMETH_DYNAMIC,
-    asize(smparams_distance), smparams_distance,
-    &init_data_common,
-    NULL,
-    &init_common,
-    NULL,
-    &free_data_common,
-    &init_frame_common,
-    NULL,
-    &evaluate_distance,
-    {"distance from POS [cutoff REAL]", asize(help_distance), help_distance},
-};
-
-/** \internal Selection method data for the \p distance method. */
-gmx_ana_selmethod_t sm_mindistance = {
-    "mindistance", REAL_VALUE, SMETH_DYNAMIC,
-    asize(smparams_mindistance), smparams_mindistance,
-    &init_data_common,
-    NULL,
-    &init_common,
-    NULL,
-    &free_data_common,
-    &init_frame_common,
-    NULL,
-    &evaluate_distance,
-    {"mindistance from POS_EXPR [cutoff REAL]", asize(help_distance), help_distance},
-};
-
-/** \internal Selection method data for the \p within method. */
-gmx_ana_selmethod_t sm_within = {
-    "within", GROUP_VALUE, SMETH_DYNAMIC,
-    asize(smparams_within), smparams_within,
-    &init_data_common,
-    NULL,
-    &init_common,
-    NULL,
-    &free_data_common,
-    &init_frame_common,
-    NULL,
-    &evaluate_within,
-    {"within REAL of POS_EXPR", asize(help_distance), help_distance},
-};
-
-/*!
- * \param[in]     npar  Not used (should be 2).
- * \param[in,out] param Method parameters (should point to one of the distance
- *   parameter arrays).
- * \returns       Pointer to the allocated data (\c t_methoddata_distance).
- *
- * Allocates memory for a \c t_methoddata_distance structure and
- * initializes the parameter as follows:
- *  - the first parameter defines the value for
- *    \c t_methoddata_distance::cutoff.
- *  - the second parameter defines the reference positions and the value is
- *    stored in \c t_methoddata_distance::p.
- */
-static void *
-init_data_common(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_distance *data;
-
-    snew(data, 1);
-    data->cutoff     = -1;
-    param[0].val.u.r = &data->cutoff;
-    param[1].val.u.p = &data->p;
-    return data;
-}
-
-/*!
- * \param   top   Not used.
- * \param   npar  Not used (should be 2).
- * \param   param Method parameters (should point to one of the distance
- *   parameter arrays).
- * \param   data  Pointer to \c t_methoddata_distance to initialize.
- * \returns 0 on success, a non-zero error code on failure.
- *
- * Initializes the neighborhood search data structure
- * (\c t_methoddata_distance::nb).
- * Also checks that the cutoff is valid.
- */
-static int
-init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_distance *d = (t_methoddata_distance *)data;
-
-    if ((param[0].flags & SPAR_SET) && d->cutoff <= 0)
-    {
-        fprintf(stderr, "error: distance cutoff should be > 0");
-        return -1;
-    }
-    return gmx_ana_nbsearch_create(&d->nb, d->cutoff, d->p.nr);
-}
-
-/*!
- * \param data Data to free (should point to a \c t_methoddata_distance).
- *
- * Frees the memory allocated for \c t_methoddata_distance::xref and
- * \c t_methoddata_distance::nb.
- */
-static void
-free_data_common(void *data)
-{
-    t_methoddata_distance *d = (t_methoddata_distance *)data;
-
-    if (d->nb)
-    {
-        gmx_ana_nbsearch_free(d->nb);
-    }
-}
-
-/*!
- * \param[in]  top  Not used.
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  PBC structure.
- * \param      data Should point to a \c t_methoddata_distance.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Initializes the neighborhood search for the current frame.
- */
-static int
-init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
-{
-    t_methoddata_distance *d = (t_methoddata_distance *)data;
-
-    return gmx_ana_nbsearch_pos_init(d->nb, pbc, &d->p);
-}
-
-/*!
- * See sel_updatefunc_pos() for description of the parameters.
- * \p data should point to a \c t_methoddata_distance.
- *
- * Calculates the distance of each position from \c t_methoddata_distance::p
- * and puts them in \p out->u.r.
- */
-static int
-evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_distance *d = (t_methoddata_distance *)data;
-    int  b, i;
-    real n;
-
-    out->nr = pos->g->isize;
-    for (b = 0; b < pos->nr; ++b)
-    {
-        n = gmx_ana_nbsearch_pos_mindist(d->nb, pos, b);
-        for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
-        {
-            out->u.r[i] = n;
-        }
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_distance.
- *
- * Finds the atoms that are closer than the defined cutoff to
- * \c t_methoddata_distance::xref and puts them in \p out.g.
- */
-static int
-evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_distance *d = (t_methoddata_distance *)data;
-    int                    b;
-
-    out->u.g->isize = 0;
-    for (b = 0; b < pos->nr; ++b)
-    {
-        if (gmx_ana_nbsearch_pos_is_within(d->nb, pos, b))
-        {
-            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
-        }
-    }
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_insolidangle.c b/src/gmxlib/selection/sm_insolidangle.c
deleted file mode 100644 (file)
index 9ed4aaa..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \page sm_insolidangle Selection method: insolidangle
- *
- * This method selects a subset of particles that are located in a solid
- * angle defined by a center and a set of points.
- * The solid angle is constructed as a union of small cones whose axis
- * goes through the center and a point.
- * So there's such a cone for each position, and a
- * point is in the solid angle if it lies within any of these cones.
- * The width of the cones can be adjusted.
- *
- * \internal
- *
- * The method is implemented by partitioning the surface of the unit sphere
- * into bins using the polar coordinates \f$(\theta, \phi)\f$.
- * The partitioning is always uniform in the zenith angle \f$\theta\f$,
- * while the partitioning in the azimuthal angle \f$\phi\f$ varies.
- * For each reference point, the unit vector from the center to the point
- * is constructed, and it is stored in all the bins that overlap with the
- * cone defined by the point.
- * Bins that are completely covered by a single cone are marked as such.
- * Checking whether a point is in the solid angle is then straightforward
- * with this data structure: one finds the bin that corresponds to the point,
- * and checks whether the bin is completely covered. If it is not, one
- * additionally needs to check whether it is within the specified cutoff of
- * any of the stored points.
- *
- * The above construction gives quite a lot of flexibility for constructing
- * the bins without modifying the rest of the code.
- * The current (quite inefficient) implementation is discussed below, but
- * it should be optimized to get the most out of the code.
- *
- * The current way of constructing the bins constructs the boundaries
- * statically: the bin size in the zenith direction is set to approximately
- * half the angle cutoff, and the bins in the azimuthal direction have
- * sizes such that the shortest edge of the bin is approximately equal to
- * half the angle cutoff (for the regions close to the poles, a single bin
- * is used).
- * Each reference point is then added to the bins as follows:
- *  -# Find the zenith angle range that is spanned by the cone centered at the
- *     point (this is simple addition/subtraction).
- *  -# Calculate the maximal span of the cone in the azimuthal direction using
- *     the formula
- *     \f[\sin \Delta \phi_{max} = \frac{\sin \alpha}{\sin \theta}\f]
- *     (a sine formula in spherical coordinates),
- *     where \f$\alpha\f$ is the width of the cone and \f$\theta\f$ is the
- *     zenith angle of the cone center.
- *     Similarly, the zenith angle at which this extent is achieved is
- *     calculated using
- *     \f[\cos \theta_{max} = \frac{\cos \theta}{\cos \alpha}\f]
- *     (Pythagoras's theorem in spherical coordinates).
- *  -# For each zenith angle bin that is at least partially covered by the
- *     cone, calculate the span of the cone at the edges using
- *     \f[\sin^2 \frac{\Delta \phi}{2} = \frac{\sin^2 \frac{\alpha}{2} - \sin^2 \frac{\theta - \theta'}{2}}{\sin \theta \sin \theta'}\f]
- *     (distance in spherical geometry),
- *     where \f$\theta'\f$ is the zenith angle of the bin edge.
- *  -# Using the values calculated above, loop through the azimuthal bins that
- *     are partially or completely covered by the cone and update them.
- *
- * The total solid angle (for covered fraction calculations) is estimated by
- * taking the total area of completely covered bins plus
- * half the area of partially covered bins.
- * The second one is an approximation, but should give reasonable estimates
- * for the averages as well as in cases where the bin size is small.
- */
-/*! \internal \file
- * \brief Implementation of the \ref sm_insolidangle "insolidangle"
- *   selection method.
- *
- * \todo
- * The implementation could be optimized quite a bit.
- * 
- * \todo Move the covered fraction stuff somewhere else and make it more
- * generic (along the lines it is handled in selection.h and trajana.h).
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-
-#include <macros.h>
-#include <maths.h>
-#include <pbc.h>
-#include <physics.h>
-#include <smalloc.h>
-#include <vec.h>
-
-#include <indexutil.h>
-#include <position.h>
-#include <selection.h>
-#include <selmethod.h>
-
-#include "selelem.h"
-
-/*! \internal \brief
- * Internal data structure for the \p insolidangle selection method.
- *
- * \see \c t_partition
- */
-typedef struct
-{
-    /** Left edge of the partition. */
-    real                left;
-    /** Bin index corresponding to this partition. */
-    int                 bin;
-} t_partition_item;
-
-/*! \internal \brief
- * Internal data structure for the \p insolidangle selection method.
- *
- * Describes the surface partitioning within one slice along the zenith angle.
- * The slice from azimuthal angle \p p[i].left to \p p[i+1].left belongs to
- * bin \p p[i].bin.
- */
-typedef struct
-{
-    /** Number of partition items (\p p contains \p n+1 items). */
-    int                 n;
-    /** Array of partition edges and corresponding bins. */
-    t_partition_item   *p;
-} t_partition;
-
-/*! \internal \brief
- * Internal data structure for the \p insolidangle selection method.
- *
- * Contains the reference points that partially cover a certain region on the
- * surface of the unit sphere.
- * If \p n is -1, the whole region described by the bin is covered.
- */
-typedef struct
-{
-    /** Number of points in the array \p x, -1 if whole bin covered. */
-    int   n;
-    /** Number of elements allocated for \p x. */
-    int   n_alloc;
-    /** Array of points that partially cover the bin. */
-    rvec *x;
-} t_spheresurfacebin;
-
-/*! \internal \brief
- * Data structure for the \p insolidangle selection method.
- *
- * All angle values are in the units of radians.
- */
-typedef struct
-{
-    /** Center of the solid angle. */
-    gmx_ana_pos_t       center;
-    /** Positions that span the solid angle. */
-    gmx_ana_pos_t       span;
-    /** Cutoff angle. */
-    real                angcut;
-    /** Estimate of the covered fraction. */
-    real                cfrac;
-
-    /** Cutoff for the cosine (equals cos(angcut)). */
-    real                distccut;
-    /** Bin size to be used as the target bin size when constructing the bins. */
-    real                targetbinsize;
-
-    /** Number of bins in the \p tbin array. */
-    int                 ntbins;
-    /** Size of one bin in the zenith angle direction. */
-    real                tbinsize;
-    /** Array of zenith angle slices. */
-    t_partition        *tbin;
-    /** Number of elements allocated for the \p bin array. */
-    int                 maxbins;
-    /** Number of elements used in the \p bin array. */
-    int                 nbins;
-    /** Array of individual bins. */
-    t_spheresurfacebin *bin;
-} t_methoddata_insolidangle;
-
-/** Allocates data for the \p insolidangle selection method. */
-static void *
-init_data_insolidangle(int npar, gmx_ana_selparam_t *param);
-/** Initializes the \p insolidangle selection method. */
-static int
-init_insolidangle(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the data allocated for the \p insolidangle selection method. */
-static void
-free_data_insolidangle(void *data);
-/** Initializes the evaluation of the \p insolidangle selection method for a frame. */
-static int
-init_frame_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/** Internal helper function for evaluate_insolidangle(). */
-static gmx_bool
-accept_insolidangle(rvec x, t_pbc *pbc, void *data);
-/** Evaluates the \p insolidangle selection method. */
-static int
-evaluate_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                      gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-
-/** Calculates the distance between unit vectors. */
-static real
-sph_distc(rvec x1, rvec x2);
-/** Does a binary search on a \p t_partition to find a bin for a value. */
-static int
-find_partition_bin(t_partition *p, real value);
-/** Finds a bin that corresponds to a location on the unit sphere surface. */
-static int
-find_surface_bin(t_methoddata_insolidangle *surf, rvec x);
-/** Clears/initializes the bins on the unit sphere surface. */
-static void
-clear_surface_points(t_methoddata_insolidangle *surf);
-/** Frees memory allocated for storing the reference points in the surface bins. */
-static void
-free_surface_points(t_methoddata_insolidangle *surf);
-/** Adds a reference point to a given bin. */
-static void
-add_surface_point(t_methoddata_insolidangle *surf, int tbin, int pbin, rvec x);
-/** Marks a bin as completely covered. */
-static void
-mark_surface_covered(t_methoddata_insolidangle *surf, int tbin, int pbin);
-/** Helper function for store_surface_point() to update a single zenith angle bin. */
-static void
-update_surface_bin(t_methoddata_insolidangle *surf, int tbin,
-                   real phi, real pdelta1, real pdelta2, real pdeltamax,
-                   rvec x);
-/** Adds a single reference point and updates the surface bins. */
-static void
-store_surface_point(t_methoddata_insolidangle *surf, rvec x);
-/** Optimizes the surface bins for faster searching. */
-static void
-optimize_surface_points(t_methoddata_insolidangle *surf);
-/** Estimates the area covered by the reference cones. */
-static real
-estimate_covered_fraction(t_methoddata_insolidangle *surf);
-/** Checks whether a point lies within a solid angle. */
-static gmx_bool
-is_surface_covered(t_methoddata_insolidangle *surf, rvec x);
-
-/** Parameters for the \p insolidangle selection method. */
-static gmx_ana_selparam_t smparams_insolidangle[] = {
-    {"center", {POS_VALUE,   1, {NULL}}, NULL, SPAR_DYNAMIC},
-    {"span",   {POS_VALUE,  -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-    {"cutoff", {REAL_VALUE,  1, {NULL}}, NULL, SPAR_OPTIONAL},
-};
-
-/** Help text for the \p insolidangle selection method. */
-static const char *help_insolidangle[] = {
-    "SELECTING ATOMS IN A SOLID ANGLE[PAR]",
-
-    "[TT]insolidangle center POS span POS_EXPR [cutoff REAL][tt][PAR]",
-
-    "This keyword selects atoms that are within [TT]REAL[tt] degrees",
-    "(default=5) of any position in [TT]POS_EXPR[tt] as seen from [TT]POS[tt]",
-    "a position expression that evaluates to a single position), i.e., atoms",
-    "in the solid angle spanned by the positions in [TT]POS_EXPR[tt] and",
-    "centered at [TT]POS[tt].[PAR]"
-
-    "Technically, the solid angle is constructed as a union of small cones",
-    "whose tip is at [TT]POS[tt] and the axis goes through a point in",
-    "[TT]POS_EXPR[tt]. There is such a cone for each position in",
-    "[TT]POS_EXPR[tt], and point is in the solid angle if it lies within any",
-    "of these cones. The cutoff determines the width of the cones.",
-};
-
-/** \internal Selection method data for the \p insolidangle method. */
-gmx_ana_selmethod_t sm_insolidangle = {
-    "insolidangle", GROUP_VALUE, SMETH_DYNAMIC,
-    asize(smparams_insolidangle), smparams_insolidangle,
-    &init_data_insolidangle,
-    NULL,
-    &init_insolidangle,
-    NULL,
-    &free_data_insolidangle,
-    &init_frame_insolidangle,
-    NULL,
-    &evaluate_insolidangle,
-    {"insolidangle center POS span POS_EXPR [cutoff REAL]",
-     asize(help_insolidangle), help_insolidangle},
-};
-
-/*!
- * \param[in]     npar  Not used (should be 3).
- * \param[in,out] param Method parameters (should point to 
- *   \ref smparams_insolidangle).
- * \returns Pointer to the allocated data (\ref t_methoddata_insolidangle).
- *
- * Allocates memory for a \ref t_methoddata_insolidangle structure and
- * initializes the parameter as follows:
- *  - \p center defines the value for t_methoddata_insolidangle::center.
- *  - \p span   defines the value for t_methoddata_insolidangle::span.
- *  - \p cutoff defines the value for t_methoddata_insolidangle::angcut.
- */
-static void *
-init_data_insolidangle(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_insolidangle *data;
-
-    snew(data, 1);
-    data->angcut = 5.0;
-    param[0].val.u.p = &data->center;
-    param[1].val.u.p = &data->span;
-    param[2].val.u.r = &data->angcut;
-    return data;
-}
-
-/*!
- * \param   top  Not used.
- * \param   npar Not used.
- * \param   param Not used.
- * \param   data Pointer to \ref t_methoddata_insolidangle to initialize.
- * \returns 0 on success, -1 on failure.
- *
- * Converts t_methoddata_insolidangle::angcut to radians and allocates
- * and allocates memory for the bins used during the evaluation.
- */
-static int
-init_insolidangle(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_insolidangle *surf = (t_methoddata_insolidangle *)data;
-    int                        i, c;
-
-    if (surf->angcut <= 0)
-    {
-        fprintf(stderr, "error: angle cutoff should be > 0");
-        return -1;
-    }
-
-    surf->angcut *= DEG2RAD;
-
-    surf->distccut = -cos(surf->angcut);
-    surf->targetbinsize = surf->angcut / 2;
-    surf->ntbins = (int) (M_PI / surf->targetbinsize);
-    surf->tbinsize = (180.0 / surf->ntbins)*DEG2RAD;
-
-    snew(surf->tbin, (int)(M_PI/surf->tbinsize) + 1);
-    surf->maxbins = 0;
-    for (i = 0; i < surf->ntbins; ++i)
-    {
-        c = max(sin(surf->tbinsize*i), sin(surf->tbinsize*(i+1)))
-              * M_2PI / surf->targetbinsize + 1;
-        snew(surf->tbin[i].p, c+1);
-        surf->maxbins += c;
-    }
-    surf->nbins = 0;
-    snew(surf->bin, surf->maxbins);
-
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_insolidangle).
- *
- * Frees the memory allocated for \c t_methoddata_insolidangle::center and
- * \c t_methoddata_insolidangle::span, as well as the memory for the internal
- * bin structure.
- */
-static void
-free_data_insolidangle(void *data)
-{
-    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
-    int                        i;
-
-    if (d->tbin)
-    {
-        for (i = 0; i < d->ntbins; ++i)
-        {
-            sfree(d->tbin[i].p);
-        }
-        sfree(d->tbin);
-    }
-    free_surface_points(d);
-    sfree(d->bin);
-}
-
-/*!
- * \param[in]  top  Not used.
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  PBC structure.
- * \param      data Should point to a \ref t_methoddata_insolidangle.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Creates a lookup structure that enables fast queries of whether a point
- * is within the solid angle or not.
- */
-static int
-init_frame_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
-{
-    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
-    rvec                       dx;
-    int                        i;
-
-    free_surface_points(d);
-    clear_surface_points(d);
-    for (i = 0; i < d->span.nr; ++i)
-    {
-        if (pbc)
-        {
-            pbc_dx(pbc, d->span.x[i], d->center.x[0], dx);
-        }
-        else
-        {
-            rvec_sub(d->span.x[i], d->center.x[0], dx);
-        }
-        unitv(dx, dx);
-        store_surface_point(d, dx);
-    }
-    optimize_surface_points(d);
-    d->cfrac = -1;
-    return 0;
-}
-
-/*!
- * \param[in] x    Test point.
- * \param[in] pbc  PBC data (if NULL, no PBC are used).
- * \param[in] data Pointer to a \c t_methoddata_insolidangle data structure.
- * \returns   TRUE if \p x is within the solid angle, FALSE otherwise.
- */
-static gmx_bool
-accept_insolidangle(rvec x, t_pbc *pbc, void *data)
-{
-    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
-    rvec                       dx;
-
-    if (pbc)
-    {
-        pbc_dx(pbc, x, d->center.x[0], dx);
-    }
-    else
-    {
-        rvec_sub(x, d->center.x[0], dx);
-    }
-    unitv(dx, dx);
-    return is_surface_covered(d, dx);
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_insolidangle.
- *
- * Calculates which atoms in \p g are within the solid angle spanned by
- * \c t_methoddata_insolidangle::span and centered at
- * \c t_methoddata_insolidangle::center, and stores the result in \p out->u.g.
- */
-static int
-evaluate_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                      gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
-    int                        b;
-
-    out->u.g->isize = 0;
-    for (b = 0; b < pos->nr; ++b)
-    {
-        if (accept_insolidangle(pos->x[b], pbc, data))
-        {
-            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in] sel Selection element to query.
- * \returns   TRUE if the covered fraction can be estimated for \p sel with
- *   _gmx_selelem_estimate_coverfrac(), FALSE otherwise.
- */
-gmx_bool
-_gmx_selelem_can_estimate_cover(t_selelem *sel)
-{
-    t_selelem   *child;
-    gmx_bool         bFound;
-    gmx_bool         bDynFound;
-
-    if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_OR)
-    {
-        return FALSE;
-    }
-    bFound    = FALSE;
-    bDynFound = FALSE;
-    child     = sel->child;
-    while (child)
-    {
-        if (child->type == SEL_EXPRESSION)
-        {
-            if (child->u.expr.method->name == sm_insolidangle.name)
-            {
-                if (bFound || bDynFound)
-                {
-                    return FALSE;
-                }
-                bFound = TRUE;
-            }
-            else if (child->u.expr.method
-                     && (child->u.expr.method->flags & SMETH_DYNAMIC))
-            {
-                if (bFound)
-                {
-                    return FALSE;
-                }
-                bDynFound = TRUE;
-            }
-        }
-        else if (!_gmx_selelem_can_estimate_cover(child))
-        {
-            return FALSE;
-        }
-        child = child->next;
-    }
-    return TRUE;
-}
-
-/*!
- * \param[in] sel Selection for which the fraction should be calculated.
- * \returns Fraction of angles covered by the selection (between zero and one).
- *
- * The return value is undefined if _gmx_selelem_can_estimate_cover() returns
- * FALSE.
- * Should be called after gmx_ana_evaluate_selections() has been called for the
- * frame.
- */
-real
-_gmx_selelem_estimate_coverfrac(t_selelem *sel)
-{
-    t_selelem   *child;
-    real         cfrac;
-
-    if (sel->type == SEL_EXPRESSION && sel->u.expr.method->name == sm_insolidangle.name)
-    {
-        t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)sel->u.expr.mdata;
-        if (d->cfrac < 0)
-        {
-            d->cfrac = estimate_covered_fraction(d);        
-        }
-        return d->cfrac;
-    }
-    if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT)
-    {
-        cfrac = _gmx_selelem_estimate_coverfrac(sel->child);
-        if (cfrac < 1.0)
-        {
-            return 1 - cfrac;
-        }
-        return 1;
-    }
-
-    /* Here, we assume that the selection is simple enough */
-    child = sel->child;
-    while (child)
-    {
-        cfrac = _gmx_selelem_estimate_coverfrac(child); 
-        if (cfrac < 1.0)
-        {
-            return cfrac;
-        }
-        child = child->next;
-    }
-    return 1.0;
-}
-
-/*!
- * \param[in] x1  Unit vector 1.
- * \param[in] x2  Unit vector 2.
- * \returns   Minus the dot product of \p x1 and \p x2.
- *
- * This function is used internally to calculate the distance between the
- * unit vectors \p x1 and \p x2 to find out whether \p x2 is within the
- * cone centered at \p x1. Currently, the cosine of the angle is used
- * for efficiency, and the minus is there to make it behave like a normal
- * distance (larger values mean longer distances).
- */
-static real
-sph_distc(rvec x1, rvec x2)
-{
-    return -iprod(x1, x2);
-}
-
-/*!
- * \param[in] p     Partition to search.
- * \param[in] value Value to search for.
- * \returns   The partition index in \p p that contains \p value.
- *
- * If \p value is outside the range of \p p, the first/last index is returned.
- * Otherwise, the return value \c i satisfies \c p->p[i].left<=value and
- * \c p->p[i+1].left>value
- */
-static int
-find_partition_bin(t_partition *p, real value)
-{
-    int pmin, pmax, pbin;
-
-    /* Binary search the partition */
-    pmin = 0; pmax = p->n;
-    while (pmax > pmin + 1)
-    {
-        pbin = pmin + (pmax - pmin) / 2;
-        if (p->p[pbin].left <= value)
-        {
-            pmin = pbin;
-        }
-        else
-        {
-            pmax = pbin;
-        }
-    }
-    pbin = pmin;
-    return pbin;
-}
-
-/*!
- * \param[in] surf  Surface data structure to search.
- * \param[in] x     Unit vector to find.
- * \returns   The bin index that contains \p x.
- *
- * The return value is an index to the \p surf->bin array.
- */
-static int
-find_surface_bin(t_methoddata_insolidangle *surf, rvec x)
-{
-    real theta, phi;
-    int  tbin, pbin;
-    
-    theta = acos(x[ZZ]);
-    phi = atan2(x[YY], x[XX]);
-    tbin = floor(theta / surf->tbinsize);
-    if (tbin >= surf->ntbins)
-    {
-        tbin = surf->ntbins - 1;
-    }
-    pbin = find_partition_bin(&surf->tbin[tbin], phi);
-    return surf->tbin[tbin].p[pbin].bin;
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- *
- * Clears the reference points from the bins and (re)initializes the edges
- * of the azimuthal bins.
- */
-static void
-clear_surface_points(t_methoddata_insolidangle *surf)
-{
-    int i, j, c;
-
-    surf->nbins = 0;
-    for (i = 0; i < surf->ntbins; ++i)
-    {
-        c = min(sin(surf->tbinsize*i), sin(surf->tbinsize*(i+1)))
-              * M_2PI / surf->targetbinsize + 1;
-        if (c <= 0)
-        {
-            c = 1;
-        }
-        surf->tbin[i].n = c;
-        for (j = 0; j < c; ++j)
-        {
-            surf->tbin[i].p[j].left = -M_PI + j*M_2PI/c - 0.0001;
-            surf->tbin[i].p[j].bin = surf->nbins;
-            surf->bin[surf->nbins].n = 0;
-            surf->nbins++;
-        }
-        surf->tbin[i].p[c].left = M_PI + 0.0001;
-        surf->tbin[i].p[c].bin = -1;
-    }
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- */
-static void
-free_surface_points(t_methoddata_insolidangle *surf)
-{
-    int i;
-
-    for (i = 0; i < surf->nbins; ++i)
-    {
-        if (surf->bin[i].x)
-        {
-            sfree(surf->bin[i].x);
-        }
-        surf->bin[i].n_alloc = 0;
-        surf->bin[i].x = NULL;
-    }
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- * \param[in]     tbin Bin number in the zenith angle direction.
- * \param[in]     pbin Bin number in the azimuthal angle direction.
- * \param[in]     x    Point to store.
- */
-static void
-add_surface_point(t_methoddata_insolidangle *surf, int tbin, int pbin, rvec x)
-{
-    int bin;
-
-    bin = surf->tbin[tbin].p[pbin].bin;
-    /* Return if bin is already completely covered */
-    if (surf->bin[bin].n == -1)
-        return;
-    /* Allocate more space if necessary */
-    if (surf->bin[bin].n == surf->bin[bin].n_alloc) {
-        surf->bin[bin].n_alloc += 10;
-        srenew(surf->bin[bin].x, surf->bin[bin].n_alloc);
-    }
-    /* Add the point to the bin */
-    copy_rvec(x, surf->bin[bin].x[surf->bin[bin].n]);
-    ++surf->bin[bin].n;
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- * \param[in]     tbin Bin number in the zenith angle direction.
- * \param[in]     pbin Bin number in the azimuthal angle direction.
- */
-static void
-mark_surface_covered(t_methoddata_insolidangle *surf, int tbin, int pbin)
-{
-    int bin;
-
-    bin = surf->tbin[tbin].p[pbin].bin;
-    surf->bin[bin].n = -1;
-}
-
-/*!
- * \param[in,out] surf      Surface data structure.
- * \param[in]     tbin      Bin number in the zenith angle direction.
- * \param[in]     phi       Azimuthal angle of \p x.
- * \param[in]     pdelta1   Width of the cone at the lower edge of \p tbin.
- * \param[in]     pdelta2   Width of the cone at the uppper edge of \p tbin.
- * \param[in]     pdeltamax Max. width of the cone inside \p tbin.
- * \param[in]     x         Point to store (should have unit length).
- */
-static void
-update_surface_bin(t_methoddata_insolidangle *surf, int tbin,
-                   real phi, real pdelta1, real pdelta2, real pdeltamax,
-                   rvec x)
-{
-    real pdelta, phi1, phi2;
-    int  pbin1, pbin2, pbin;
-
-    /* Find the edges of the bins affected */
-    pdelta = max(max(pdelta1, pdelta2), pdeltamax);
-    phi1 = phi - pdelta;
-    if (phi1 < -M_PI)
-    {
-        phi1 += M_2PI;
-    }
-    phi2 = phi + pdelta;
-    if (phi2 > M_PI)
-    {
-        phi2 -= M_2PI;
-    }
-    pbin1 = find_partition_bin(&surf->tbin[tbin], phi1);
-    pbin2 = find_partition_bin(&surf->tbin[tbin], phi2);
-    /* Find the edges of completely covered region */
-    pdelta = min(pdelta1, pdelta2);
-    phi1 = phi - pdelta;
-    if (phi1 < -M_PI)
-    {
-        phi1 += M_2PI;
-    }
-    phi2 = phi + pdelta;
-    /* Loop over all affected bins */
-    pbin = pbin1;
-    do
-    {
-        /* Wrap bin around if end reached */
-        if (pbin == surf->tbin[tbin].n)
-        {
-            pbin = 0;
-            phi1 -= M_2PI;
-            phi2 -= M_2PI;
-        }
-        /* Check if bin is completely covered and update */
-        if (surf->tbin[tbin].p[pbin].left >= phi1
-            && surf->tbin[tbin].p[pbin+1].left <= phi2)
-        {
-            mark_surface_covered(surf, tbin, pbin);
-        }
-        else
-        {
-            add_surface_point(surf, tbin, pbin, x);
-        }
-    }
-    while (pbin++ != pbin2); /* Loop including pbin2 */
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- * \param[in]     x    Point to store (should have unit length).
- *
- * Finds all the bins covered by the cone centered at \p x and calls
- * update_surface_bin() to update them.
- */
-static void
-store_surface_point(t_methoddata_insolidangle *surf, rvec x)
-{
-    real theta, phi;
-    real pdeltamax, tmax;
-    real theta1, theta2, pdelta1, pdelta2;
-    int  tbin, pbin, bin;
-
-    theta = acos(x[ZZ]);
-    phi = atan2(x[YY], x[XX]);
-    /* Find the maximum extent in the phi direction */
-    if (theta <= surf->angcut)
-    {
-        pdeltamax = M_PI;
-        tmax = 0;
-    }
-    else if (theta >= M_PI - surf->angcut)
-    {
-        pdeltamax = M_PI;
-        tmax = M_PI;
-    }
-    else
-    {
-        pdeltamax = asin(sin(surf->angcut) / sin(theta));
-        tmax = acos(cos(theta) / cos(surf->angcut));
-    }
-    /* Find the first affected bin */
-    tbin = max(floor((theta - surf->angcut) / surf->tbinsize), 0);
-    theta1 = tbin * surf->tbinsize;
-    if (theta1 < theta - surf->angcut)
-    {
-        pdelta1 = 0;
-    }
-    else
-    {
-        pdelta1 = M_PI;
-    }
-    /* Loop through all affected bins */
-    while (tbin < ceil((theta + surf->angcut) / surf->tbinsize)
-           && tbin < surf->ntbins)
-    {
-        /* Calculate the next boundaries */
-        theta2 = (tbin+1) * surf->tbinsize;
-        if (theta2 > theta + surf->angcut)
-        {
-            pdelta2 = 0;
-        }
-        else if (tbin == surf->ntbins - 1)
-        {
-            pdelta2 = M_PI;
-        }
-        else
-        {
-            pdelta2 = 2*asin(sqrt(
-                    (sqr(sin(surf->angcut/2)) - sqr(sin((theta2-theta)/2))) /
-                    (sin(theta) * sin(theta2))));
-        }
-        /* Update the bin */
-        if (tmax >= theta1 && tmax <= theta2)
-        {
-            update_surface_bin(surf, tbin, phi, pdelta1, pdelta2, pdeltamax, x);
-        }
-        else
-        {
-            update_surface_bin(surf, tbin, phi, pdelta1, pdelta2, 0, x);
-        }
-        /* Next bin */
-        theta1 = theta2;
-        pdelta1 = pdelta2;
-        ++tbin;
-    }
-}
-
-/*!
- * \param[in,out] surf Surface data structure.
- *
- * Currently, this function does nothing.
- */
-static void
-optimize_surface_points(t_methoddata_insolidangle *surf)
-{
-    /* TODO: Implement */
-}
-
-/*!
- * \param[in] surf Surface data structure.
- * \returns   An estimate for the area covered by the reference points.
- */
-static real
-estimate_covered_fraction(t_methoddata_insolidangle *surf)
-{
-    int  t, p, n;
-    real cfrac, tfrac, pfrac;
-
-    cfrac = 0.0;
-    for (t = 0; t < surf->ntbins; ++t)
-    {
-        tfrac = cos(t * surf->tbinsize) - cos((t+1) * surf->tbinsize);
-        for (p = 0; p < surf->tbin[t].n; ++p)
-        {
-            pfrac = surf->tbin[t].p[p+1].left - surf->tbin[t].p[p].left;
-            n = surf->bin[surf->tbin[t].p[p].bin].n;
-            if (n == -1) /* Bin completely covered */
-            {
-                cfrac += tfrac * pfrac;
-            }
-            else if (n > 0) /* Bin partially covered */
-            {
-                cfrac += tfrac * pfrac / 2; /* A rough estimate */
-            }
-        }
-    }
-    return cfrac / (4*M_PI);
-}
-
-/*!
- * \param[in] surf  Surface data structure to search.
- * \param[in] x     Unit vector to check.
- * \returns   TRUE if \p x is within the solid angle, FALSE otherwise.
- */
-static gmx_bool
-is_surface_covered(t_methoddata_insolidangle *surf, rvec x)
-{
-    int  bin, i;
-
-    bin = find_surface_bin(surf, x);
-    /* Check for completely covered bin */
-    if (surf->bin[bin].n == -1)
-    {
-        return TRUE;
-    }
-    /* Check each point that partially covers the bin */
-    for (i = 0; i < surf->bin[bin].n; ++i)
-    {
-        if (sph_distc(x, surf->bin[bin].x[i]) < surf->distccut)
-        {
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
diff --git a/src/gmxlib/selection/sm_keywords.c b/src/gmxlib/selection/sm_keywords.c
deleted file mode 100644 (file)
index afcb2e3..0000000
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementations of internal selection methods for numeric and
- * string keyword evaluation.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>  /*old Mac needs types before regex.h*/
-#endif
-#ifdef HAVE_REGEX_H
-#include <regex.h>
-#define USE_REGEX
-#endif
-
-#include <gmx_fatal.h>
-#include <macros.h>
-#include <smalloc.h>
-#include <string2.h>
-
-#include <selmethod.h>
-
-#include "keywords.h"
-#include "parsetree.h"
-#include "selelem.h"
-
-/** Allocates data for integer keyword evaluation. */
-static void *
-init_data_kwint(int npar, gmx_ana_selparam_t *param);
-/** Allocates data for real keyword evaluation. */
-static void *
-init_data_kwreal(int npar, gmx_ana_selparam_t *param);
-/** Allocates data for string keyword evaluation. */
-static void *
-init_data_kwstr(int npar, gmx_ana_selparam_t *param);
-/** Initializes data for integer keyword evaluation. */
-static int
-init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes data for real keyword evaluation. */
-static int
-init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes data for string keyword evaluation. */
-static int
-init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the memory allocated for string keyword evaluation. */
-static void
-free_data_kwstr(void *data);
-/** Evaluates integer selection keywords. */
-static int
-evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates real selection keywords. */
-static int
-evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates string selection keywords. */
-static int
-evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/*! \internal \brief
- * Data structure for integer keyword expression evaluation.
- */
-typedef struct t_methoddata_kwint
-{
-    /** Array of values for the keyword. */
-    int               *v;
-    /** Number of ranges in the \p r array. */
-    int                n;
-    /*! \brief
-     * Array of sorted integer ranges to match against.
-     *
-     * Each range is made of two integers, giving the endpoints (inclusive).
-     * This field stores the pointer to the ranges allocated by the
-     * parameter parser; see \ref SPAR_RANGES for more information.
-     */
-    int               *r;
-} t_methoddata_kwint;
-
-/*! \internal \brief
- * Data structure for real keyword expression evaluation.
- */
-typedef struct t_methoddata_kwreal
-{
-    /** Array of values for the keyword. */
-    real              *v;
-    /** Number of ranges in the \p r array. */
-    int                n;
-    /*! \brief
-     * Array of sorted ranges to match against.
-     *
-     * Each range is made of two values, giving the endpoints (inclusive).
-     * This field stores the pointer to the ranges allocated by the
-     * parameter parser; see \ref SPAR_RANGES for more information.
-     */
-    real              *r;
-} t_methoddata_kwreal;
-
-/*! \internal \brief
- * Data structure for string keyword expression evaluation.
- */
-typedef struct t_methoddata_kwstr
-{
-    /** Array of values for the keyword. */
-    char             **v;
-    /** Number of elements in the \p val array. */
-    int                n;
-    /*! \internal \brief
-     * Array of strings/regular expressions to match against.
-     */
-    struct t_methoddata_kwstr_match {
-        /** TRUE if the expression is a regular expression, FALSE otherwise. */
-        gmx_bool           bRegExp;
-        /** The value to match against. */
-        union {
-#ifdef USE_REGEX
-            /** Compiled regular expression if \p bRegExp is TRUE. */
-            regex_t    r;
-#endif
-            /** The string if \p bRegExp is FALSE; */
-            char      *s;
-        }              u;
-    }                 *m;
-} t_methoddata_kwstr;
-
-/** Parameters for integer keyword evaluation. */
-static gmx_ana_selparam_t smparams_keyword_int[] = {
-    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
-    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
-};
-
-/** Parameters for real keyword evaluation. */
-static gmx_ana_selparam_t smparams_keyword_real[] = {
-    {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL | SPAR_DYNAMIC},
-    {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
-};
-
-/** Parameters for string keyword evaluation. */
-static gmx_ana_selparam_t smparams_keyword_str[] = {
-    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
-    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_VARNUM},
-};
-
-/** \internal Selection method data for integer keyword evaluation. */
-gmx_ana_selmethod_t sm_keyword_int = {
-    "kw_int", GROUP_VALUE, SMETH_SINGLEVAL,
-    asize(smparams_keyword_int), smparams_keyword_int,
-    &init_data_kwint,
-     NULL,
-    &init_kwint,
-     NULL,
-     NULL,
-     NULL,
-    &evaluate_keyword_int,
-     NULL,
-    {NULL, 0, NULL},
-};
-
-/** \internal Selection method data for real keyword evaluation. */
-gmx_ana_selmethod_t sm_keyword_real = {
-    "kw_real", GROUP_VALUE, SMETH_SINGLEVAL,
-    asize(smparams_keyword_real), smparams_keyword_real,
-    &init_data_kwreal,
-     NULL,
-    &init_kwreal,
-     NULL,
-     NULL,
-     NULL,
-    &evaluate_keyword_real,
-     NULL,
-    {NULL, 0, NULL},
-};
-
-/** \internal Selection method data for string keyword evaluation. */
-gmx_ana_selmethod_t sm_keyword_str = {
-    "kw_str", GROUP_VALUE, SMETH_SINGLEVAL,
-    asize(smparams_keyword_str), smparams_keyword_str,
-    &init_data_kwstr,
-     NULL,
-    &init_kwstr,
-     NULL,
-    &free_data_kwstr,
-     NULL,
-    &evaluate_keyword_str,
-     NULL,
-    {NULL, 0, NULL},
-};
-
-/** Initializes keyword evaluation for an arbitrary group. */
-static int
-init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes output for keyword evaluation in an arbitrary group. */
-static int
-init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data);
-/** Frees the data allocated for keyword evaluation in an arbitrary group. */
-static void
-free_data_kweval(void *data);
-/** Initializes frame evaluation for keyword evaluation in an arbitrary group. */
-static int
-init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/** Evaluates keywords in an arbitrary group. */
-static int
-evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/*! \internal \brief
- * Data structure for keyword evaluation in arbitrary groups.
- */
-typedef struct
-{
-    /** Wrapped keyword method for evaluating the values. */
-    gmx_ana_selmethod_t  *kwmethod;
-    /** Method data for \p kwmethod. */
-    void                 *kwmdata;
-    /** Group in which \p kwmethod should be evaluated. */
-    gmx_ana_index_t       g;
-} t_methoddata_kweval;
-
-/** Parameters for keyword evaluation in an arbitrary group. */
-static gmx_ana_selparam_t smparams_kweval[] = {
-    {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
-};
-
-
-/********************************************************************
- * INTEGER KEYWORD EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] npar  Not used.
- * \param     param Not used.
- * \returns   Pointer to the allocated data (\ref t_methoddata_kwint).
- *
- * Allocates memory for a \ref t_methoddata_kwint structure.
- */
-static void *
-init_data_kwint(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_kwint *data;
-
-    snew(data, 1);
-    return data;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 2).
- * \param[in] param Method parameters (should point to \ref smparams_keyword_int).
- * \param[in] data  Should point to \ref t_methoddata_kwint.
- * \returns   0 (the initialization always succeeds).
- */
-static int
-init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_kwint *d = (t_methoddata_kwint *)data;
-
-    d->v = param[0].val.u.i;
-    d->n = param[1].val.nr;
-    d->r = param[1].val.u.i;
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_kwint.
- *
- * Does a binary search to find which atoms match the ranges in the
- * \c t_methoddata_kwint structure for this selection.
- * Matching atoms are stored in \p out->u.g.
- */
-static int
-evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_kwint *d = (t_methoddata_kwint *)data;
-    int                 n, i, j, jmin, jmax;
-    int                 val;
-
-    out->u.g->isize = 0;
-    n    = d->n;
-    for (i = 0; i < g->isize; ++i)
-    {
-        val = d->v[i];
-        if (d->r[0] > val || d->r[2*n-1] < val)
-        {
-            continue;
-        }
-        jmin = 0;
-        jmax = n;
-        while (jmax - jmin > 1)
-        {
-            j = jmin + (jmax - jmin) / 2;
-            if (val < d->r[2*j])
-            {
-                jmax = j;
-            }
-            else
-            {
-                jmin = j;
-                if (val <= d->r[2*j+1])
-                {
-                    break;
-                }
-                /* ++jmin;*/
-            }
-        }
-        if (val <= d->r[2*jmin+1])
-        {
-            out->u.g->index[out->u.g->isize++] = g->index[i];
-        }
-    }
-    return 0;
-}
-
-
-/********************************************************************
- * REAL KEYWORD EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] npar  Not used.
- * \param     param Not used.
- * \returns   Pointer to the allocated data (\ref t_methoddata_kwreal).
- *
- * Allocates memory for a \ref t_methoddata_kwreal structure.
- */
-static void *
-init_data_kwreal(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_kwreal *data;
-
-    snew(data, 1);
-    return data;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 2).
- * \param[in] param Method parameters (should point to \ref smparams_keyword_real).
- * \param[in] data  Should point to \ref t_methoddata_kwreal.
- * \returns   0 (the initialization always succeeds).
- */
-static int
-init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
-
-    d->v = param[0].val.u.r;
-    d->n = param[1].val.nr;
-    d->r = param[1].val.u.r;
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_kwreal.
- *
- * Does a binary search to find which atoms match the ranges in the
- * \c t_methoddata_kwreal structure for this selection.
- * Matching atoms are stored in \p out->u.g.
- */
-static int
-evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
-    int                  n, i, j, jmin, jmax;
-    real                 val;
-
-    out->u.g->isize = 0;
-    n    = d->n;
-    for (i = 0; i < g->isize; ++i)
-    {
-        val = d->v[i];
-        if (d->r[0] > val || d->r[2*n-1] < val)
-        {
-            continue;
-        }
-        jmin = 0;
-        jmax = n;
-        while (jmax - jmin > 1)
-        {
-            j = jmin + (jmax - jmin) / 2;
-            if (val < d->r[2*j])
-            {
-                jmax = j;
-            }
-            else
-            {
-                jmin = j;
-                if (val <= d->r[2*j+1])
-                {
-                    break;
-                }
-                /* ++jmin;*/
-            }
-        }
-        if (val <= d->r[2*jmin+1])
-        {
-            out->u.g->index[out->u.g->isize++] = g->index[i];
-        }
-    }
-    return 0;
-}
-
-
-/********************************************************************
- * STRING KEYWORD EVALUATION
- ********************************************************************/
-
-/*!
- * \param[in] npar  Not used.
- * \param     param Not used.
- * \returns Pointer to the allocated data (\ref t_methoddata_kwstr).
- *
- * Allocates memory for a \ref t_methoddata_kwstr structure.
- */
-static void *
-init_data_kwstr(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_kwstr *data;
-
-    snew(data, 1);
-    return data;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 2).
- * \param[in] param Method parameters (should point to \ref smparams_keyword_str).
- * \param[in] data  Should point to \ref t_methoddata_kwstr.
- * \returns   0 (the initialization always succeeds).
- */
-static int
-init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
-    char               *buf;
-    char               *s;
-    int                 i;
-    size_t              j;
-    gmx_bool                bRegExp;
-
-    d->v   = param[0].val.u.s;
-    d->n   = param[1].val.nr;
-    /* Return if this is not the first time */
-    if (d->m)
-    {
-        return 0;
-    }
-    snew(d->m, d->n);
-    for (i = 0; i < d->n; ++i)
-    {
-        s = param[1].val.u.s[i];
-        bRegExp = FALSE;
-        for (j = 0; j < strlen(s); ++j)
-        {
-            if (ispunct(s[j]) && s[j] != '?' && s[j] != '*')
-            {
-                bRegExp = TRUE;
-                break;
-            }
-        }
-        if (bRegExp)
-        {
-#ifdef USE_REGEX
-            snew(buf, strlen(s) + 3);
-            sprintf(buf, "^%s$", s);
-            if (regcomp(&d->m[i].u.r, buf, REG_EXTENDED | REG_NOSUB))
-            {
-                bRegExp = FALSE;
-                fprintf(stderr, "WARNING: error in regular expression,\n"
-                                "         will match '%s' as a simple string\n", s);
-            }
-            sfree(buf);
-#else
-            bRegExp = FALSE;
-            fprintf(stderr, "WARNING: no regular expressions support,\n"
-                            "         will match '%s' as a simple string\n", s);
-#endif
-        }
-        if (!bRegExp)
-        {
-            d->m[i].u.s = s;
-        }
-        d->m[i].bRegExp = bRegExp;
-    }
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_kwstr).
- *
- * Frees the memory allocated for t_methoddata_kwstr::val.
- */
-static void
-free_data_kwstr(void *data)
-{
-    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
-    int                 i;
-
-    for (i = 0; i < d->n; ++i)
-    {
-        if (d->m[i].bRegExp)
-        {
-#ifdef USE_REGEX
-            /* This branch should only be taken if regular expressions
-             * are available, but the ifdef is still needed. */
-            regfree(&d->m[i].u.r);
-#endif
-        }
-    }
-    sfree(d->m);
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_kwstr.
- *
- * Does a linear search to find which atoms match the strings in the
- * \c t_methoddata_kwstr structure for this selection.
- * Wildcards are allowed in the strings.
- * Matching atoms are stored in \p out->u.g.
- */
-static int
-evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
-    int                 i, j;
-    gmx_bool                bFound;
-
-    out->u.g->isize = 0;
-    for (i = 0; i < g->isize; ++i)
-    {
-        bFound = FALSE;
-        for (j = 0; j < d->n && !bFound; ++j)
-        {
-            if (d->m[j].bRegExp)
-            {
-#ifdef USE_REGEX
-                /* This branch should only be taken if regular expressions
-                 * are available, but the ifdef is still needed. */
-                if (!regexec(&d->m[j].u.r, d->v[i], 0, NULL, 0))
-                {
-                    bFound = TRUE;
-                }
-#endif
-            }
-            else
-            {
-                if (gmx_wcmatch(d->m[j].u.s, d->v[i]) == 0)
-                {
-                    bFound = TRUE;
-                }
-            }
-        }
-        if (bFound)
-        {
-            out->u.g->index[out->u.g->isize++] = g->index[i];
-        }
-    }
-    return 0;
-}
-
-
-/********************************************************************
- * KEYWORD EVALUATION FOR ARBITRARY GROUPS
- ********************************************************************/
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used.
- * \param[in] param Not used.
- * \param[in] data  Should point to \ref t_methoddata_kweval.
- * \returns   0 on success, a non-zero error code on return.
- *
- * Calls the initialization method of the wrapped keyword.
- */
-static int
-init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
-
-    return d->kwmethod->init(top, 0, NULL, d->kwmdata);
-}
-
-/*!
- * \param[in]     top   Not used.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_kweval.
- * \returns       0 for success.
- */
-static int
-init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
-
-    out->nr = d->g.isize;
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \c t_methoddata_kweval).
- *
- * Frees the memory allocated for all the members of \c t_methoddata_kweval.
- */
-static void
-free_data_kweval(void *data)
-{
-    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
-
-    _gmx_selelem_free_method(d->kwmethod, d->kwmdata);
-}
-
-/*!
- * \param[in]  top  Topology.
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  PBC structure.
- * \param      data Should point to a \ref t_methoddata_kweval.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Creates a lookup structure that enables fast queries of whether a point
- * is within the solid angle or not.
- */
-static int
-init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
-{
-    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
-
-    return d->kwmethod->init_frame(top, fr, pbc, d->kwmdata);
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_kweval.
- *
- * Calls the evaluation function of the wrapped keyword with the given
- * parameters, with the exception of using \c t_methoddata_kweval::g for the
- * evaluation group.
- */
-static int
-evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
-
-    return d->kwmethod->update(top, fr, pbc, &d->g, out, d->kwmdata);
-}
-
-/*!
- * \param[out]  selp    Pointer to receive a pointer to the created selection
- *      element (set to NULL on error).
- * \param[in]   method  Keyword selection method to evaluate.
- * \param[in]   param   Parameter that gives the group to evaluate \p method in.
- * \param[in]   scanner Scanner data structure.
- * \returns     0 on success, non-zero error code on error.
- *
- * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
- * that evaluates the keyword method given by \p method in the group given by
- * \p param.
- */
-int
-_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
-                                t_selexpr_param *param, void *scanner)
-{
-    t_selelem            *sel;
-    t_methoddata_kweval  *data;
-
-    if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
-        || method->outinit || method->pupdate)
-    {
-        _gmx_selexpr_free_params(param);
-        gmx_incons("unsupported keyword method for arbitrary group evaluation");
-        return -1;
-    }
-
-    *selp = NULL;
-    sel = _gmx_selelem_create(SEL_EXPRESSION);
-    _gmx_selelem_set_method(sel, method, scanner);
-
-    snew(data, 1);
-    data->kwmethod = sel->u.expr.method;
-    data->kwmdata  = sel->u.expr.mdata;
-    gmx_ana_index_clear(&data->g);
-
-    snew(sel->u.expr.method, 1);
-    memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
-    sel->u.expr.method->flags       |= SMETH_VARNUMVAL;
-    sel->u.expr.method->init_data    = NULL;
-    sel->u.expr.method->set_poscoll  = NULL;
-    sel->u.expr.method->init         = method->init ? &init_kweval : NULL;
-    sel->u.expr.method->outinit      = &init_output_kweval;
-    sel->u.expr.method->free         = &free_data_kweval;
-    sel->u.expr.method->init_frame   = method->init_frame ? &init_frame_kweval : NULL;
-    sel->u.expr.method->update       = &evaluate_kweval;
-    sel->u.expr.method->pupdate      = NULL;
-    sel->u.expr.method->nparams      = asize(smparams_kweval);
-    sel->u.expr.method->param        = smparams_kweval;
-    _gmx_selelem_init_method_params(sel, scanner);
-    sel->u.expr.mdata = data;
-
-    sel->u.expr.method->param[0].val.u.g = &data->g;
-
-    sfree(param->name);
-    param->name = NULL;
-    if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
-                               sel->u.expr.method->param, sel, scanner))
-    {
-        _gmx_selelem_free(sel);
-        return -1;
-    }
-    *selp = sel;
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_merge.c b/src/gmxlib/selection/sm_merge.c
deleted file mode 100644 (file)
index 34d2b0d..0000000
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of the merging selection modifier.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <smalloc.h>
-#include <vec.h>
-
-#include <position.h>
-#include <selmethod.h>
-
-/*! \internal \brief
- * Data structure for the merging selection modifiers.
- */
-typedef struct
-{
-    /** Input positions. */
-    gmx_ana_pos_t    p1;
-    /** Other input positions. */
-    gmx_ana_pos_t    p2;
-    /** Group to store the output atom indices. */
-    gmx_ana_index_t  g;
-    /** Stride for merging (\c stride values from \c p1 for each in \c p2). */
-    int              stride;
-} t_methoddata_merge;
-
-/** Allocates data for the merging selection modifiers. */
-static void *
-init_data_merge(int npar, gmx_ana_selparam_t *param);
-/** Initializes data for the merging selection modifiers. */
-static int
-init_merge(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes output for the \p merge selection modifier. */
-static int
-init_output_merge(t_topology *top, gmx_ana_selvalue_t *out, void *data);
-/** Initializes output for the \p plus selection modifier. */
-static int
-init_output_plus(t_topology *top, gmx_ana_selvalue_t *out, void *data);
-/** Frees the memory allocated for the merging selection modifiers. */
-static void
-free_data_merge(void *data);
-/** Evaluates the \p merge selection modifier. */
-static int
-evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p plus selection modifier. */
-static int
-evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for the merging selection modifiers. */
-static gmx_ana_selparam_t smparams_merge[] = {
-    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-    {"stride",   {INT_VALUE,  1, {NULL}}, NULL, SPAR_OPTIONAL},
-};
-
-/** Help text for the merging selection modifiers. */
-static const char *help_merge[] = {
-    "MERGING SELECTIONS[PAR]",
-
-    "[TT]POSEXPR merge POSEXPR [stride INT][tt][BR]",
-    "[TT]POSEXPR merge POSEXPR [merge POSEXPR ...][tt][BR]",
-    "[TT]POSEXPR plus POSEXPR [plus POSEXPR ...][tt][PAR]",
-
-    "Basic selection keywords can only create selections where each atom",
-    "occurs at most once. The [TT]merge[tt] and [TT]plus[tt] selection",
-    "keywords can be used to work around this limitation. Both create",
-    "a selection that contains the positions from all the given position",
-    "expressions, even if they contain duplicates.",
-    "The difference between the two is that [TT]merge[tt] expects two or more",
-    "selections with the same number of positions, and the output contains",
-    "the input positions selected from each expression in turn, i.e.,",
-    "the output is like A1 B1 A2 B2 and so on. It is also possible to merge",
-    "selections of unequal size as long as the size of the first is a",
-    "multiple of the second one. The [TT]stride[tt] parameter can be used",
-    "to explicitly provide this multiplicity.",
-    "[TT]plus[tt] simply concatenates the positions after each other, and",
-    "can work also with selections of different sizes.",
-    "These keywords are valid only at the selection level, not in any",
-    "subexpressions.[PAR]",
-};
-
-/** \internal Selection method data for the \p plus modifier. */
-gmx_ana_selmethod_t sm_merge = {
-    "merge", POS_VALUE, SMETH_MODIFIER,
-    asize(smparams_merge), smparams_merge,
-    &init_data_merge,
-    NULL,
-    &init_merge,
-    &init_output_merge,
-    &free_data_merge,
-    NULL,
-    NULL,
-    &evaluate_merge,
-    {"merge POSEXPR", asize(help_merge), help_merge},
-};
-
-/** \internal Selection method data for the \p plus modifier. */
-gmx_ana_selmethod_t sm_plus = {
-    "plus", POS_VALUE, SMETH_MODIFIER,
-    asize(smparams_merge)-1, smparams_merge,
-    &init_data_merge,
-    NULL,
-    &init_merge,
-    &init_output_plus,
-    &free_data_merge,
-    NULL,
-    NULL,
-    &evaluate_plus,
-    {"plus POSEXPR", asize(help_merge), help_merge},
-};
-
-/*!
- * \param[in]     npar  Should be 2 for \c plus and 3 for \c merge.
- * \param[in,out] param Method parameters (should point to a copy of
- *   \ref smparams_merge).
- * \returns Pointer to the allocated data (\p t_methoddata_merge).
- *
- * Allocates memory for a \p t_methoddata_merge structure.
- */
-static void *
-init_data_merge(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_merge *data;
-
-    snew(data, 1);
-    data->stride = 0;
-    param[0].val.u.p = &data->p1;
-    param[1].val.u.p = &data->p2;
-    if (npar > 2)
-    {
-        param[2].val.u.i = &data->stride;
-    }
-    return data;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 2 or 3).
- * \param[in] param Method parameters (should point to \ref smparams_merge).
- * \param[in] data  Should point to a \p t_methoddata_merge.
- * \returns   0 if everything is successful, -1 on error.
- */
-static int
-init_merge(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-    int                 i;
-
-    if (d->stride < 0)
-    {
-        fprintf(stderr, "error: stride for merging should be positive\n");
-        return -1;
-    }
-    /* If no stride given, deduce it from the input sizes */
-    if (d->stride == 0)
-    {
-        d->stride = d->p1.nr / d->p2.nr;
-    }
-    if (d->p1.nr != d->stride*d->p2.nr)
-    {
-        fprintf(stderr, "error: the number of positions to be merged are not compatible\n");
-        return -1;
-    }
-    /* We access the m.b.nra field instead of g->isize in the position
-     * data structures to handle cases where g is NULL
-     * (this occurs with constant positions. */
-    gmx_ana_index_reserve(&d->g, d->p1.m.b.nra + d->p2.m.b.nra);
-    d->g.isize = d->p1.m.b.nra + d->p2.m.b.nra;
-    return 0;
-}
-
-/*! \brief
- * Does common initialization to all merging modifiers.
- *
- * \param[in]     top   Topology data structure.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_merge.
- * \returns       0 for success.
- */
-static int
-init_output_common(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-
-    if (d->p1.m.type != d->p2.m.type)
-    {
-        /* TODO: Maybe we could pick something else here? */
-        out->u.p->m.type = INDEX_UNKNOWN;
-    }
-    else
-    {
-        out->u.p->m.type = d->p1.m.type;
-    }
-    gmx_ana_pos_reserve(out->u.p, d->p1.nr + d->p2.nr, d->g.isize);
-    if (d->p1.v)
-    {
-        gmx_ana_pos_reserve_velocities(out->u.p);
-    }
-    if (d->p1.f)
-    {
-        gmx_ana_pos_reserve_forces(out->u.p);
-    }
-    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
-    gmx_ana_pos_empty_init(out->u.p);
-    d->g.isize = 0;
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_merge.
- * \returns       0 for success.
- */
-static int
-init_output_merge(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-    int                 i, j;
-
-    init_output_common(top, out, data);
-    for (i = 0; i < d->p2.nr; ++i)
-    {
-        for (j = 0; j < d->stride; ++j)
-        {
-            gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, d->stride*i+j);
-        }
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_merge.
- * \returns       0 for success.
- */
-static int
-init_output_plus(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-    int                 i;
-
-    init_output_common(top, out, data);
-    for (i = 0; i < d->p1.nr; ++i)
-    {
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, i);
-    }
-    for (i = 0; i < d->p2.nr; ++i)
-    {
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
-    }
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \p t_methoddata_merge).
- *
- * Frees the memory allocated for \c t_methoddata_merge.
- */
-static void
-free_data_merge(void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-
-    gmx_ana_index_deinit(&d->g);
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  p     Positions to merge (should point to \p data->p1).
- * \param[out] out   Output data structure (\p out->u.p is used).
- * \param[in]  data  Should point to a \p t_methoddata_merge.
- * \returns    0 on success.
- */
-static int
-evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-    int                 i, j;
-    int                 refid;
-
-    if (d->p1.nr != d->stride*d->p2.nr)
-    {
-        fprintf(stderr, "error: the number of positions to be merged are not compatible\n");
-        return -1;
-    }
-    d->g.isize = 0;
-    gmx_ana_pos_empty(out->u.p);
-    for (i = 0; i < d->p2.nr; ++i)
-    {
-        for (j = 0; j < d->stride; ++j)
-        {
-            refid = d->p1.m.refid[d->stride*i+j];
-            if (refid != -1)
-            {
-                refid = (d->stride+1) * (refid / d->stride) + (refid % d->stride);
-            }
-            gmx_ana_pos_append(out->u.p, &d->g, &d->p1, d->stride*i+j, refid);
-        }
-        refid = (d->stride+1)*d->p2.m.refid[i]+d->stride;
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
-    }
-    gmx_ana_pos_append_finish(out->u.p);
-    return 0;
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  p     Positions to merge (should point to \p data->p1).
- * \param[out] out   Output data structure (\p out->u.p is used).
- * \param[in]  data  Should point to a \p t_methoddata_merge.
- * \returns    0 on success.
- */
-static int
-evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_merge *d = (t_methoddata_merge *)data;
-    int                 i;
-    int                 refid;
-
-    d->g.isize = 0;
-    gmx_ana_pos_empty(out->u.p);
-    for (i = 0; i < d->p1.nr; ++i)
-    {
-        refid = d->p1.m.refid[i];
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p1, i, refid);
-    }
-    for (i = 0; i < d->p2.nr; ++i)
-    {
-        refid = d->p2.m.refid[i];
-        if (refid != -1)
-        {
-            refid += d->p1.m.b.nr;
-        }
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
-    }
-    gmx_ana_pos_append_finish(out->u.p);
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_permute.c b/src/gmxlib/selection/sm_permute.c
deleted file mode 100644 (file)
index a318912..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of the \p permute selection modifier.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <smalloc.h>
-#include <vec.h>
-
-#include <position.h>
-#include <selmethod.h>
-
-/*! \internal \brief
- * Data structure for the \p permute selection modifier.
- */
-typedef struct
-{
-    /** Positions to permute. */
-    gmx_ana_pos_t    p;
-    /** Group to receive the output permutation. */
-    gmx_ana_index_t  g;
-    /** Number of elements in the permutation. */
-    int              n;
-    /** Array describing the permutation. */
-    int             *perm;
-    /** Array that has the permutation reversed. */
-    int             *rperm;
-} t_methoddata_permute;
-
-/** Allocates data for the \p permute selection modifier. */
-static void *
-init_data_permute(int npar, gmx_ana_selparam_t *param);
-/** Initializes data for the \p permute selection modifier. */
-static int
-init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes output for the \p permute selection modifier. */
-static int
-init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data);
-/** Frees the memory allocated for the \p permute selection modifier. */
-static void
-free_data_permute(void *data);
-/** Evaluates the \p permute selection modifier. */
-static int
-evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for the \p permute selection modifier. */
-static gmx_ana_selparam_t smparams_permute[] = {
-    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-    {NULL,       {INT_VALUE, -1, {NULL}}, NULL, SPAR_VARNUM},
-};
-
-/** Help text for the \p permute selection modifier. */
-static const char *help_permute[] = {
-    "PERMUTING SELECTIONS[PAR]",
-
-    "[TT]permute P1 ... PN[tt][PAR]",
-
-    "By default, all selections are evaluated such that the atom indices are",
-    "returned in ascending order. This can be changed by appending",
-    "[TT]permute P1 P2 ... PN[tt] to an expression.",
-    "The [TT]Pi[tt] should form a permutation of the numbers 1 to N.",
-    "This keyword permutes each N-position block in the selection such that",
-    "the i'th position in the block becomes Pi'th.",
-    "Note that it is the positions that are permuted, not individual atoms.",
-    "A fatal error occurs if the size of the selection is not a multiple of n.",
-    "It is only possible to permute the whole selection expression, not any",
-    "subexpressions, i.e., the [TT]permute[tt] keyword should appear last in",
-    "a selection.",
-};
-
-/** \internal Selection method data for the \p permute modifier. */
-gmx_ana_selmethod_t sm_permute = {
-    "permute", POS_VALUE, SMETH_MODIFIER,
-    asize(smparams_permute), smparams_permute,
-    &init_data_permute,
-    NULL,
-    &init_permute,
-    &init_output_permute,
-    &free_data_permute,
-    NULL,
-    NULL,
-    &evaluate_permute,
-    {"permute P1 ... PN", asize(help_permute), help_permute},
-};
-
-/*!
- * \param[in]     npar  Not used (should be 2).
- * \param[in,out] param Method parameters (should point to a copy of
- *   \ref smparams_permute).
- * \returns Pointer to the allocated data (\p t_methoddata_permute).
- *
- * Allocates memory for a \p t_methoddata_permute structure.
- */
-static void *
-init_data_permute(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_permute *data;
-
-    snew(data, 1);
-    param[0].val.u.p = &data->p;
-    return data;
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used (should be 2).
- * \param[in] param Method parameters (should point to \ref smparams_permute).
- * \param[in] data  Should point to a \p t_methoddata_permute.
- * \returns   0 if the input permutation is valid, -1 on error.
- */
-static int
-init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_permute *d = (t_methoddata_permute *)data;
-    int                   i;
-
-    gmx_ana_index_reserve(&d->g, d->p.g->isize);
-    d->n    = param[1].val.nr;
-    d->perm = param[1].val.u.i;
-    if (d->p.nr % d->n != 0)
-    {
-        fprintf(stderr, "error: the number of positions to be permuted is not divisible by %d\n",
-                d->n);
-        return -1;
-    }
-    snew(d->rperm, d->n);
-    for (i = 0; i < d->n; ++i)
-    {
-        d->rperm[i] = -1;
-    }
-    for (i = 0; i < d->n; ++i)
-    {
-        d->perm[i]--;
-        if (d->perm[i] < 0 || d->perm[i] >= d->n)
-        {
-            fprintf(stderr, "invalid permutation");
-            return -1;
-        }
-        if (d->rperm[d->perm[i]] >= 0)
-        {
-            fprintf(stderr, "invalid permutation");
-            return -1;
-        }
-        d->rperm[d->perm[i]] = i;
-    }
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_permute.
- * \returns       0 for success.
- */
-static int
-init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_permute *d = (t_methoddata_permute *)data;
-    int                   i, j, b, k;
-
-    gmx_ana_pos_copy(out->u.p, &d->p, TRUE);
-    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
-    d->g.isize = 0;
-    gmx_ana_pos_empty_init(out->u.p);
-    for (i = 0; i < d->p.nr; i += d->n)
-    {
-        for (j = 0; j < d->n; ++j)
-        {
-            b = i + d->rperm[j];
-            gmx_ana_pos_append_init(out->u.p, &d->g, &d->p, b);
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \p t_methoddata_permute).
- *
- * Frees the memory allocated for \c t_methoddata_permute.
- */
-static void
-free_data_permute(void *data)
-{
-    t_methoddata_permute *d = (t_methoddata_permute *)data;
-
-    gmx_ana_index_deinit(&d->g);
-    sfree(d->rperm);
-}
-
-/*!
- * \param[in]  top   Not used.
- * \param[in]  fr    Not used.
- * \param[in]  pbc   Not used.
- * \param[in]  p     Positions to permute (should point to \p data->p).
- * \param[out] out   Output data structure (\p out->u.p is used).
- * \param[in]  data  Should point to a \p t_methoddata_permute.
- * \returns    0 if \p p could be permuted, -1 on error.
- *
- * Returns -1 if the size of \p p is not divisible by the number of
- * elements in the permutation.
- */
-static int
-evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_permute *d = (t_methoddata_permute *)data;
-    int                   i, j, b, k;
-    int                   refid;
-
-    if (d->p.nr % d->n != 0)
-    {
-        fprintf(stderr, "error: the number of positions to be permuted is not divisible by %d\n",
-                d->n);
-        return -1;
-    }
-    d->g.isize = 0;
-    gmx_ana_pos_empty(out->u.p);
-    for (i = 0; i < d->p.nr; i += d->n)
-    {
-        for (j = 0; j < d->n; ++j)
-        {
-            b = i + d->rperm[j];
-            refid = d->p.m.refid[b];
-            if (refid != -1)
-            {
-                /* De-permute the reference ID */
-                refid = refid - (refid % d->n) + d->perm[refid % d->n];
-            }
-            gmx_ana_pos_append(out->u.p, &d->g, p, b, refid);
-        }
-    }
-    gmx_ana_pos_append_finish(out->u.p);
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_position.c b/src/gmxlib/selection/sm_position.c
deleted file mode 100644 (file)
index 6a3ae6a..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of position evaluation selection methods.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <smalloc.h>
-#include <string2.h>
-
-#include <indexutil.h>
-#include <poscalc.h>
-#include <position.h>
-#include <selmethod.h>
-
-#include "keywords.h"
-#include "selelem.h"
-
-/*! \internal \brief
- * Data structure for position keyword evaluation.
- */
-typedef struct
-{
-    /** Position calculation collection to use. */
-    gmx_ana_poscalc_coll_t *pcc;
-    /** Index group for which the center should be evaluated. */
-    gmx_ana_index_t    g;
-    /** Position evaluation data structure. */
-    gmx_ana_poscalc_t *pc;
-    /** TRUE if periodic boundary conditions should be used. */
-    gmx_bool               bPBC;
-    /** Type of positions to calculate. */
-    char              *type;
-    /** Flags for the position calculation. */
-    int                flags;
-} t_methoddata_pos;
-
-/** Allocates data for position evaluation selection methods. */
-static void *
-init_data_pos(int npar, gmx_ana_selparam_t *param);
-/** Sets the position calculation collection for position evaluation selection methods. */
-static void
-set_poscoll_pos(gmx_ana_poscalc_coll_t *pcc, void *data);
-/** Initializes position evaluation keywords. */
-static int
-init_kwpos(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes the \p cog selection method. */
-static int
-init_cog(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes the \p cog selection method. */
-static int
-init_com(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Initializes output for position evaluation selection methods. */
-static int
-init_output_pos(t_topology *top, gmx_ana_selvalue_t *out, void *data);
-/** Frees the data allocated for position evaluation selection methods. */
-static void
-free_data_pos(void *data);
-/** Evaluates position evaluation selection methods. */
-static int
-evaluate_pos(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for position keyword evaluation. */
-static gmx_ana_selparam_t smparams_keyword_pos[] = {
-    {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
-};
-
-/** Parameters for the \p cog and \p com selection methods. */
-static gmx_ana_selparam_t smparams_com[] = {
-    {"of",   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
-    {"pbc",  {NO_VALUE,    0, {NULL}}, NULL, 0},
-};
-
-/** \internal Selection method data for position keyword evaluation. */
-gmx_ana_selmethod_t sm_keyword_pos = {
-    "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL,
-    asize(smparams_keyword_pos), smparams_keyword_pos,
-    &init_data_pos,
-    &set_poscoll_pos,
-    &init_kwpos,
-    &init_output_pos,
-    &free_data_pos,
-     NULL,
-    &evaluate_pos,
-     NULL,
-    {NULL, 0, NULL},
-};
-
-/** \internal Selection method data for the \p cog method. */
-gmx_ana_selmethod_t sm_cog = {
-    "cog", POS_VALUE, SMETH_DYNAMIC | SMETH_SINGLEVAL,
-    asize(smparams_com), smparams_com,
-    &init_data_pos,
-    &set_poscoll_pos,
-    &init_cog,
-    &init_output_pos,
-    &free_data_pos,
-     NULL,
-    &evaluate_pos,
-     NULL,
-    {"cog of ATOM_EXPR [pbc]", 0, NULL},
-};
-
-/** \internal Selection method data for the \p com method. */
-gmx_ana_selmethod_t sm_com = {
-    "com", POS_VALUE, SMETH_REQTOP | SMETH_DYNAMIC | SMETH_SINGLEVAL,
-    asize(smparams_com), smparams_com,
-    &init_data_pos,
-    &set_poscoll_pos,
-    &init_com,
-    &init_output_pos,
-    &free_data_pos,
-     NULL,
-    &evaluate_pos,
-     NULL,
-    {"com of ATOM_EXPR [pbc]", 0, NULL},
-};
-
-/*!
- * \param[in]     npar  Should be 1 or 2.
- * \param[in,out] param Method parameters (should point to
- *   \ref smparams_keyword_pos or \ref smparams_com).
- * \returns       Pointer to the allocated data (\c t_methoddata_pos).
- *
- * Allocates memory for a \c t_methoddata_pos structure and initializes
- * the first parameter to define the value for \c t_methoddata_pos::g.
- * If a second parameter is present, it is used for setting the
- * \c t_methoddata_pos::bPBC flag.
- */
-static void *
-init_data_pos(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_pos *data;
-
-    snew(data, 1);
-    param[0].val.u.g = &data->g;
-    if (npar > 1)
-    {
-        param[1].val.u.b = &data->bPBC;
-    }
-    data->pc       = NULL;
-    data->bPBC     = FALSE;
-    data->type     = NULL;
-    data->flags    = -1;
-    return data;
-}
-
-/*!
- * \param[in]     pcc   Position calculation collection to use.
- * \param[in,out] data  Should point to \c t_methoddata_pos.
- */
-static void
-set_poscoll_pos(gmx_ana_poscalc_coll_t *pcc, void *data)
-{
-    ((t_methoddata_pos *)data)->pcc = pcc;
-}
-
-/*!
- * \param[in,out] sel   Selection element to initialize.
- * \param[in]     type  One of the enum values acceptable for
- *   gmx_ana_poscalc_type_from_enum().
- *
- * Initializes the reference position type for position evaluation.
- * If called multiple times, the first setting takes effect, and later calls
- * are neglected.
- */
-void
-_gmx_selelem_set_kwpos_type(t_selelem *sel, const char *type)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
-
-    if (sel->type != SEL_EXPRESSION || !sel->u.expr.method
-        || sel->u.expr.method->name != sm_keyword_pos.name)
-    {
-        return;
-    }
-    if (!d->type && type)
-    {
-        d->type  = strdup(type);
-        /* FIXME: It would be better not to have the string here hardcoded. */
-        if (type[0] != 'a')
-        {
-            sel->u.expr.method->flags |= SMETH_REQTOP;
-        }
-    }
-}
-
-/*!
- * \param[in,out] sel   Selection element to initialize.
- * \param[in]     flags Default completion flags
- *   (see gmx_ana_poscalc_type_from_enum()).
- *
- * Initializes the flags for position evaluation.
- * If called multiple times, the first setting takes effect, and later calls
- * are neglected.
- */
-void
-_gmx_selelem_set_kwpos_flags(t_selelem *sel, int flags)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
-
-    if (sel->type != SEL_EXPRESSION || !sel->u.expr.method
-        || sel->u.expr.method->name != sm_keyword_pos.name)
-    {
-        return;
-    }
-    if (d->flags == -1)
-    {
-        d->flags = flags;
-    }
-}
-
-/*!
- * \param[in] top   Not used.
- * \param[in] npar  Not used.
- * \param[in] param Not used.
- * \param[in,out] data  Should point to \c t_methoddata_pos.
- * \returns       0 on success, a non-zero error code on error.
- *
- * The \c t_methoddata_pos::type field should have been initialized
- * externally using _gmx_selelem_set_kwpos_type().
- */
-static int
-init_kwpos(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-    int               rc;
-
-    if (!(param[0].flags & SPAR_DYNAMIC))
-    {
-        d->flags &= ~(POS_DYNAMIC | POS_MASKONLY);
-    }
-    else if (!(d->flags & POS_MASKONLY))
-    {
-        d->flags |= POS_DYNAMIC;
-    }
-    rc = gmx_ana_poscalc_create_enum(&d->pc, d->pcc, d->type, d->flags);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in]     npar  Not used.
- * \param[in]     param Not used.
- * \param[in,out] data  Should point to \c t_methoddata_pos.
- * \returns       0 on success, a non-zero error code on error.
- */
-static int
-init_cog(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-    int               rc;
-
-    d->flags = (param[0].flags & SPAR_DYNAMIC) ? POS_DYNAMIC : 0;
-    rc = gmx_ana_poscalc_create(&d->pc, d->pcc, d->bPBC ? POS_ALL_PBC : POS_ALL,
-                                d->flags);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in]     npar  Not used.
- * \param[in]     param Not used.
- * \param[in,out] data  Should point to \c t_methoddata_pos.
- * \returns       0 on success, a non-zero error code on error.
- */
-static int
-init_com(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-    int               rc;
-
-    d->flags  = (param[0].flags & SPAR_DYNAMIC) ? POS_DYNAMIC : 0;
-    d->flags |= POS_MASS;
-    rc = gmx_ana_poscalc_create(&d->pc, d->pcc, d->bPBC ? POS_ALL_PBC : POS_ALL,
-                                d->flags);
-    if (rc != 0)
-    {
-        return rc;
-    }
-    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
-    return 0;
-}
-
-/*!
- * \param[in]     top   Topology data structure.
- * \param[in,out] out   Pointer to output data structure.
- * \param[in,out] data  Should point to \c t_methoddata_pos.
- * \returns       0 for success.
- */
-static int
-init_output_pos(t_topology *top, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-
-    gmx_ana_poscalc_init_pos(d->pc, out->u.p);
-    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \c t_methoddata_pos).
- *
- * Frees the memory allocated for \c t_methoddata_pos::g and
- * \c t_methoddata_pos::pc.
- */
-static void
-free_data_pos(void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-
-    sfree(d->type);
-    gmx_ana_poscalc_free(d->pc);
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_pos.
- *
- * Calculates the positions using \c t_methoddata_pos::pc for the index group
- * in \c t_methoddata_pos::g and stores the results in \p out->u.p.
- */
-static int
-evaluate_pos(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_pos *d = (t_methoddata_pos *)data;
-
-    gmx_ana_poscalc_update(d->pc, out->u.p, &d->g, fr, pbc);
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_same.c b/src/gmxlib/selection/sm_same.c
deleted file mode 100644 (file)
index d50221e..0000000
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of the \p same selection method.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-
-#include <macros.h>
-#include <smalloc.h>
-#include <string2.h>
-
-#include <selmethod.h>
-
-#include "keywords.h"
-#include "parsetree.h"
-#include "selelem.h"
-
-/*! \internal \brief
- * Data structure for the \p same selection method.
- *
- * To avoid duplicate initialization code, the same data structure is used
- * for matching both integer and string keywords; hence the unions.
- */
-typedef struct
-{
-    /** Value for each atom to match. */
-    union
-    {
-        int                 *i;
-        char               **s;
-        void                *ptr;
-    }                        val;
-    /*! \brief
-     * Number of values in the \p as array.
-     *
-     * For string values, this is actually the number of values in the
-     * \p as_s_sorted array.
-     */
-    int                      nas;
-    /** Values to match against. */
-    union
-    {
-        int                 *i;
-        char               **s;
-        void                *ptr;
-    }                        as;
-    /*! \brief
-     * Separate array for sorted \p as.s array.
-     *
-     * The array of strings returned as the output value of a parameter should
-     * not be messed with to avoid memory corruption (the pointers in the array
-     * may be reused for several evaluations), so we keep our own copy for
-     * modifications.
-     */
-    char                   **as_s_sorted;
-    /** Whether simple matching can be used. */
-    gmx_bool                     bSorted;
-} t_methoddata_same;
-
-/** Allocates data for the \p same selection method. */
-static void *
-init_data_same(int npar, gmx_ana_selparam_t *param);
-/** Initializes the \p same selection method. */
-static int
-init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the data allocated for the \p same selection method. */
-static void
-free_data_same(void *data);
-/** Initializes the evaluation of the \p same selection method for a frame. */
-static int
-init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/** Evaluates the \p same selection method. */
-static int
-evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Initializes the evaluation of the \p same selection method for a frame. */
-static int
-init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/** Evaluates the \p same selection method. */
-static int
-evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/** Parameters for the \p same selection method. */
-static gmx_ana_selparam_t smparams_same_int[] = {
-    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
-    {"as", {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-};
-
-/** Parameters for the \p same selection method. */
-static gmx_ana_selparam_t smparams_same_str[] = {
-    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
-    {"as", {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
-};
-
-/** Help text for the \p same selection method. */
-static const char *help_same[] = {
-    "EXTENDING SELECTIONS[PAR]",
-
-    "[TT]same KEYWORD as ATOM_EXPR[tt][PAR]",
-
-    "The keyword [TT]same[tt] can be used to select all atoms for which",
-    "the given [TT]KEYWORD[tt] matches any of the atoms in [TT]ATOM_EXPR[tt].",
-    "Keywords that evaluate to integer or string values are supported.",
-};
-
-/*! \internal \brief Selection method data for the \p same method. */
-gmx_ana_selmethod_t sm_same = {
-    "same", GROUP_VALUE, 0,
-    asize(smparams_same_int), smparams_same_int,
-    &init_data_same,
-    NULL,
-    &init_same,
-    NULL,
-    &free_data_same,
-    &init_frame_same_int,
-    &evaluate_same_int,
-    NULL,
-    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
-};
-
-/*! \brief
- * Selection method data for the \p same method.
- *
- * This selection method is used for matching string keywords. The parser
- * never sees this method; _gmx_selelem_custom_init_same() replaces sm_same
- * with this method in cases where it is required.
- */
-static gmx_ana_selmethod_t sm_same_str = {
-    "same", GROUP_VALUE, SMETH_SINGLEVAL,
-    asize(smparams_same_str), smparams_same_str,
-    &init_data_same,
-    NULL,
-    &init_same,
-    NULL,
-    &free_data_same,
-    &init_frame_same_str,
-    &evaluate_same_str,
-    NULL,
-    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
-};
-
-/*!
- * \param[in]     npar  Not used (should be 2).
- * \param[in,out] param Method parameters (should point to 
- *   \ref smparams_same).
- * \returns Pointer to the allocated data (\ref t_methoddata_same).
- */
-static void *
-init_data_same(int npar, gmx_ana_selparam_t *param)
-{
-    t_methoddata_same *data;
-
-    snew(data, 1);
-    data->as_s_sorted = NULL;
-    param[1].nvalptr = &data->nas;
-    return data;
-}
-
-/*!
- * \param[in,out] method  The method to initialize.
- * \param[in,out] params  Pointer to the first parameter.
- * \param[in]     scanner Scanner data structure.
- * \returns       0 on success, a non-zero error code on error.
- *
- * If \p *method is not a \c same method, this function returns zero
- * immediately.
- */
-int
-_gmx_selelem_custom_init_same(gmx_ana_selmethod_t **method,
-                              t_selexpr_param *params,
-                              void *scanner)
-{
-    gmx_ana_selmethod_t *kwmethod;
-    t_selelem           *kwelem;
-    t_selexpr_param     *param;
-    char                *pname;
-    int                  rc;
-
-    /* Do nothing if this is not a same method. */
-    if (!*method || (*method)->name != sm_same.name)
-    {
-        return 0;
-    }
-
-    if (params->nval != 1 || !params->value->bExpr
-        || params->value->u.expr->type != SEL_EXPRESSION)
-    {
-        _gmx_selparser_error("error: 'same' should be followed by a single keyword");
-        return -1;
-    }
-    kwmethod = params->value->u.expr->u.expr.method;
-
-    if (kwmethod->type == STR_VALUE)
-    {
-        *method = &sm_same_str;
-    }
-
-    /* We do custom processing with the second parameter, so remove it from
-     * the params list, but save the name for later. */
-    param        = params->next;
-    params->next = NULL;
-    pname        = param->name;
-    param->name  = NULL;
-    /* Create a second keyword evaluation element for the keyword given as
-     * the first parameter, evaluating the keyword in the group given by the
-     * second parameter. */
-    rc = _gmx_sel_init_keyword_evaluator(&kwelem, kwmethod, param, scanner);
-    if (rc != 0)
-    {
-        sfree(pname);
-        return rc;
-    }
-    /* Replace the second parameter with one with a value from \p kwelem. */
-    param        = _gmx_selexpr_create_param(pname);
-    param->nval  = 1;
-    param->value = _gmx_selexpr_create_value_expr(kwelem);
-    params->next = param;
-    return 0;
-}
-
-/*!
- * \param   top   Not used.
- * \param   npar  Not used (should be 2).
- * \param   param Initialized method parameters (should point to a copy of
- *      \ref smparams_same).
- * \param   data  Pointer to \ref t_methoddata_same to initialize.
- * \returns 0 on success, -1 on failure.
- */
-static int
-init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-
-    d->val.ptr = param[0].val.u.ptr;
-    d->as.ptr  = param[1].val.u.ptr;
-    if (param[1].val.type == STR_VALUE)
-    {
-        snew(d->as_s_sorted, d->nas);
-    }
-    if (!(param[0].flags & SPAR_ATOMVAL))
-    {
-        fprintf(stderr, "ERROR: the same selection keyword combined with a "
-                        "non-keyword does not make sense\n");
-        return -1;
-    }
-    return 0;
-}
-
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_same).
- */
-static void
-free_data_same(void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-
-    sfree(d->as_s_sorted);
-}
-
-/*! \brief
- * Helper function for comparison of two integers.
- */
-static int
-cmp_int(const void *a, const void *b)
-{
-    if (*(int *)a < *(int *)b)
-    {
-        return -1;
-    }
-    if (*(int *)a > *(int *)b)
-    {
-        return 1;
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top  Not used.
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  PBC structure.
- * \param      data Should point to a \ref t_methoddata_same.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Sorts the \c data->as.i array and removes identical values for faster and
- * simpler lookup.
- */
-static int
-init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-    int                i, j;
-
-    /* Collapse adjacent values, and check whether the array is sorted. */
-    d->bSorted = TRUE;
-    for (i = 1, j = 0; i < d->nas; ++i)
-    {
-        if (d->as.i[i] != d->as.i[j])
-        {
-            if (d->as.i[i] < d->as.i[j])
-            {
-                d->bSorted = FALSE;
-            }
-            ++j;
-            d->as.i[j] = d->as.i[i];
-        }
-    }
-    d->nas = j + 1;
-
-    if (!d->bSorted)
-    {
-        qsort(d->as.i, d->nas, sizeof(d->as.i[0]), &cmp_int);
-        /* More identical values may become adjacent after sorting. */
-        for (i = 1, j = 0; i < d->nas; ++i)
-        {
-            if (d->as.i[i] != d->as.i[j])
-            {
-                ++j;
-                d->as.i[j] = d->as.i[i];
-            }
-        }
-        d->nas = j + 1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_same.
- *
- * Calculates which values in \c data->val.i can be found in \c data->as.i
- * (assumed sorted), and writes the corresponding atoms to output.
- * If \c data->val is sorted, uses a linear scan of both arrays, otherwise a
- * binary search of \c data->as is performed for each block of values in
- * \c data->val.
- */
-static int
-evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-    int                    i, j;
-
-    out->u.g->isize = 0;
-    i = j = 0;
-    while (j < g->isize)
-    {
-        if (d->bSorted)
-        {
-            /* If we are sorted, we can do a simple linear scan. */
-            while (i < d->nas && d->as.i[i] < d->val.i[j]) ++i;
-        }
-        else
-        {
-            /* If not, we must do a binary search of all the values. */
-            int i1, i2;
-
-            i1 = 0;
-            i2 = d->nas;
-            while (i2 - i1 > 1)
-            {
-                int itry = (i1 + i2) / 2;
-                if (d->as.i[itry] <= d->val.i[j])
-                {
-                    i1 = itry;
-                }
-                else
-                {
-                    i2 = itry;
-                }
-            }
-            i = (d->as.i[i1] == d->val.i[j] ? i1 : d->nas);
-        }
-        /* Check whether the value was found in the as list. */
-        if (i == d->nas || d->as.i[i] != d->val.i[j])
-        {
-            /* If not, skip all atoms with the same value. */
-            int tmpval = d->val.i[j];
-            ++j;
-            while (j < g->isize && d->val.i[j] == tmpval) ++j;
-        }
-        else
-        {
-            /* Copy all the atoms with this value to the output. */
-            while (j < g->isize && d->val.i[j] == d->as.i[i])
-            {
-                out->u.g->index[out->u.g->isize++] = g->index[j];
-                ++j;
-            }
-        }
-        if (j < g->isize && d->val.i[j] < d->val.i[j - 1])
-        {
-            d->bSorted = FALSE;
-        }
-    }
-    return 0;
-}
-
-/*! \brief
- * Helper function for comparison of two strings.
- */
-static int
-cmp_str(const void *a, const void *b)
-{
-    return strcmp(*(char **)a, *(char **)b);
-}
-
-/*!
- * \param[in]  top  Not used.
- * \param[in]  fr   Current frame.
- * \param[in]  pbc  PBC structure.
- * \param      data Should point to a \ref t_methoddata_same.
- * \returns    0 on success, a non-zero error code on error.
- *
- * Sorts the \c data->as.s array and removes identical values for faster and
- * simpler lookup.
- */
-static int
-init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-    int                i, j;
-
-    /* Collapse adjacent values.
-     * For strings, it's unlikely that the values would be sorted originally,
-     * so set bSorted always to FALSE. */
-    d->bSorted = FALSE;
-    d->as_s_sorted[0] = d->as.s[0];
-    for (i = 1, j = 0; i < d->nas; ++i)
-    {
-        if (strcmp(d->as.s[i], d->as_s_sorted[j]) != 0)
-        {
-            ++j;
-            d->as_s_sorted[j] = d->as.s[i];
-        }
-    }
-    d->nas = j + 1;
-
-    qsort(d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
-    /* More identical values may become adjacent after sorting. */
-    for (i = 1, j = 0; i < d->nas; ++i)
-    {
-        if (strcmp(d->as_s_sorted[i], d->as_s_sorted[j]) != 0)
-        {
-            ++j;
-            d->as_s_sorted[j] = d->as_s_sorted[i];
-        }
-    }
-    d->nas = j + 1;
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data should point to a \c t_methoddata_same.
- *
- * Calculates which strings in \c data->val.s can be found in \c data->as.s
- * (assumed sorted), and writes the corresponding atoms to output.
- * A binary search of \c data->as is performed for each block of values in
- * \c data->val.
- */
-static int
-evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    t_methoddata_same *d = (t_methoddata_same *)data;
-    int                    i, j;
-
-    out->u.g->isize = 0;
-    j = 0;
-    while (j < g->isize)
-    {
-        /* Do a binary search of the strings. */
-        void *ptr;
-        ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas,
-                      sizeof(d->as_s_sorted[0]), &cmp_str);
-        /* Check whether the value was found in the as list. */
-        if (ptr == NULL)
-        {
-            /* If not, skip all atoms with the same value. */
-            const char *tmpval = d->val.s[j];
-            ++j;
-            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0) ++j;
-        }
-        else
-        {
-            const char *tmpval = d->val.s[j];
-            /* Copy all the atoms with this value to the output. */
-            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0)
-            {
-                out->u.g->index[out->u.g->isize++] = g->index[j];
-                ++j;
-            }
-        }
-    }
-    return 0;
-}
diff --git a/src/gmxlib/selection/sm_simple.c b/src/gmxlib/selection/sm_simple.c
deleted file mode 100644 (file)
index 1810b12..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementations of simple keyword selection methods.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <position.h>
-#include <selmethod.h>
-
-/** Evaluates the \p all selection keyword. */
-static int
-evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p none selection keyword. */
-static int
-evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p atomnr selection keyword. */
-static int
-evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p resnr selection keyword. */
-static int
-evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p resindex selection keyword. */
-static int
-evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Checks whether molecule information is present in the topology. */
-static int
-check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Evaluates the \p molindex selection keyword. */
-static int
-evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p name selection keyword. */
-static int
-evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Checks whether atom types are present in the topology. */
-static int
-check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Evaluates the \p type selection keyword. */
-static int
-evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p insertcode selection keyword. */
-static int
-evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p chain selection keyword. */
-static int
-evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p mass selection keyword. */
-static int
-evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p charge selection keyword. */
-static int
-evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Checks whether PDB info is present in the topology. */
-static int
-check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Evaluates the \p altloc selection keyword. */
-static int
-evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p occupancy selection keyword. */
-static int
-evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p betafactor selection keyword. */
-static int
-evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p resname selection keyword. */
-static int
-evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-
-/** Evaluates the \p x selection keyword. */
-static int
-evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p y selection keyword. */
-static int
-evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p z selection keyword. */
-static int
-evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
-
-/** \internal Selection method data for \p all selection keyword. */
-gmx_ana_selmethod_t sm_all = {
-    "all", GROUP_VALUE, 0,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_all,
-    NULL,
-};
-
-/** \internal Selection method data for \p none selection keyword. */
-gmx_ana_selmethod_t sm_none = {
-    "none", GROUP_VALUE, 0,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_none,
-    NULL,
-};
-
-/** \internal Selection method data for \p atomnr selection keyword. */
-gmx_ana_selmethod_t sm_atomnr = {
-    "atomnr", INT_VALUE, 0,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_atomnr,
-    NULL,
-};
-
-/** \internal Selection method data for \p resnr selection keyword. */
-gmx_ana_selmethod_t sm_resnr = {
-    "resnr", INT_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_resnr,
-    NULL,
-};
-
-/** \internal Selection method data for \p resindex selection keyword. */
-gmx_ana_selmethod_t sm_resindex = {
-    "resindex", INT_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_resindex,
-    NULL,
-};
-
-/** \internal Selection method data for \p molindex selection keyword. */
-gmx_ana_selmethod_t sm_molindex = {
-    "molindex", INT_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    &check_molecules,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_molindex,
-    NULL,
-};
-
-/** \internal Selection method data for \p name selection keyword. */
-gmx_ana_selmethod_t sm_atomname = {
-    "name", STR_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_atomname,
-    NULL,
-};
-
-/** \internal Selection method data for \p type selection keyword. */
-gmx_ana_selmethod_t sm_atomtype = {
-    "type", STR_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    &check_atomtype,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_atomtype,
-    NULL,
-};
-
-/** \internal Selection method data for \p resname selection keyword. */
-gmx_ana_selmethod_t sm_resname = {
-    "resname", STR_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_resname,
-    NULL,
-};
-
-/** \internal Selection method data for \p chain selection keyword. */
-gmx_ana_selmethod_t sm_insertcode = {
-    "insertcode", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_insertcode,
-    NULL,
-};
-
-/** \internal Selection method data for \p chain selection keyword. */
-gmx_ana_selmethod_t sm_chain = {
-    "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_chain,
-    NULL,
-};
-
-/** \internal Selection method data for \p mass selection keyword. */
-gmx_ana_selmethod_t sm_mass = {
-    "mass", REAL_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_mass,
-    NULL,
-};
-
-/** \internal Selection method data for \p charge selection keyword. */
-gmx_ana_selmethod_t sm_charge = {
-    "charge", REAL_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_charge,
-    NULL,
-};
-
-/** \internal Selection method data for \p chain selection keyword. */
-gmx_ana_selmethod_t sm_altloc = {
-    "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
-    0, NULL,
-    NULL,
-    NULL,
-    &check_pdbinfo,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_altloc,
-    NULL,
-};
-
-/** \internal Selection method data for \p occupancy selection keyword. */
-gmx_ana_selmethod_t sm_occupancy = {
-    "occupancy", REAL_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    &check_pdbinfo,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_occupancy,
-    NULL,
-};
-
-/** \internal Selection method data for \p betafactor selection keyword. */
-gmx_ana_selmethod_t sm_betafactor = {
-    "betafactor", REAL_VALUE, SMETH_REQTOP,
-    0, NULL,
-    NULL,
-    NULL,
-    &check_pdbinfo,
-    NULL,
-    NULL,
-    NULL,
-    &evaluate_betafactor,
-    NULL,
-};
-
-/** \internal Selection method data for \p x selection keyword. */
-gmx_ana_selmethod_t sm_x = {
-    "x", REAL_VALUE, SMETH_DYNAMIC,
-    0, NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-    &evaluate_x,
-};
-
-/** \internal Selection method data for \p y selection keyword. */
-gmx_ana_selmethod_t sm_y = {
-    "y", REAL_VALUE, SMETH_DYNAMIC,
-    0, NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-    &evaluate_y,
-};
-
-/** \internal Selection method data for \p z selection keyword. */
-gmx_ana_selmethod_t sm_z = {
-    "z", REAL_VALUE, SMETH_DYNAMIC,
-    0, NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-     NULL,
-    &evaluate_z,
-};
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Copies \p g to \p out->u.g.
- */
-static int
-evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    gmx_ana_index_copy(out->u.g, g, FALSE);
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns an empty \p out->u.g.
- */
-static int
-evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    out->u.g->isize = 0;
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the indices for each atom in \p out->u.i.
- */
-static int
-evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.i[i] = g->index[i] + 1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the residue numbers for each atom in \p out->u.i.
- */
-static int
-evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-    int  resind;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        resind = top->atoms.atom[g->index[i]].resind;
-        out->u.i[i] = top->atoms.resinfo[resind].nr;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the residue indices for each atom in \p out->u.i.
- */
-static int
-evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.i[i] = top->atoms.atom[g->index[i]].resind + 1;
-    }
-    return 0;
-}
-
-/*!
- * \param[in] top  Topology structure.
- * \param     npar Not used.
- * \param     param Not used.
- * \param     data Not used.
- * \returns   0 if molecule info is present in the topology, -1 otherwise.
- *
- * If molecule information is not found, also prints an error message.
- */
-static int
-check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    gmx_bool bOk;
-
-    bOk = (top != NULL && top->mols.nr > 0);
-    if (!bOk)
-    {
-        fprintf(stderr, "Molecule information not available in topology!\n");
-        return -1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the molecule indices for each atom in \p out->u.i.
- */
-static int
-evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i, j;
-
-    out->nr = g->isize;
-    for (i = j = 0; i < g->isize; ++i)
-    {
-        while (top->mols.index[j + 1] <= g->index[i]) ++j;
-        out->u.i[i] = j + 1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the atom name for each atom in \p out->u.s.
- */
-static int
-evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.s[i] = *top->atoms.atomname[g->index[i]];
-    }
-    return 0;
-}
-
-/*!
- * \param[in] top  Topology structure.
- * \param     npar Not used.
- * \param     param Not used.
- * \param     data Not used.
- * \returns   0 if atom types are present in the topology, -1 otherwise.
- *
- * If the atom types are not found, also prints an error message.
- */
-static int
-check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    gmx_bool bOk;
-
-    bOk = (top != NULL && top->atoms.atomtype != NULL);
-    if (!bOk)
-    {
-        fprintf(stderr, "Atom types not available in topology!\n");
-        return -1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the atom type for each atom in \p out->u.s.
- * Segfaults if atom types are not found in the topology.
- */
-static int
-evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.s[i] = *top->atoms.atomtype[g->index[i]];
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the residue name for each atom in \p out->u.s.
- */
-static int
-evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-    int  resind;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        resind = top->atoms.atom[g->index[i]].resind;
-        out->u.s[i] = *top->atoms.resinfo[resind].name;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the insertion code for each atom in \p out->u.s.
- */
-static int
-evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-    int  resind;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        resind = top->atoms.atom[g->index[i]].resind;
-        out->u.s[i][0] = top->atoms.resinfo[resind].ic;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the chain for each atom in \p out->u.s.
- */
-static int
-evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-    int  resind;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        resind = top->atoms.atom[g->index[i]].resind;
-        out->u.s[i][0] = top->atoms.resinfo[resind].chainid;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the mass for each atom in \p out->u.r.
- */
-static int
-evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.r[i] = top->atoms.atom[g->index[i]].m;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the charge for each atom in \p out->u.r.
- */
-static int
-evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.r[i] = top->atoms.atom[g->index[i]].q;
-    }
-    return 0;
-}
-
-/*!
- * \param[in] top  Topology structure.
- * \param     npar Not used.
- * \param     param Not used.
- * \param     data Not used.
- * \returns   0 if PDB info is present in the topology, -1 otherwise.
- *
- * If PDB info is not found, also prints an error message.
- */
-static int
-check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
-{
-    gmx_bool bOk;
-
-    bOk = (top != NULL && top->atoms.pdbinfo != NULL);
-    if (!bOk)
-    {
-        fprintf(stderr, "PDB info not available in topology!\n");
-        return -1;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the alternate location identifier for each atom in \p out->u.s.
- */
-static int
-evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.s[i][0] = top->atoms.pdbinfo[g->index[i]].altloc;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the occupancy numbers for each atom in \p out->u.r.
- * Segfaults if PDB info is not found in the topology.
- */
-static int
-evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.r[i] = top->atoms.pdbinfo[g->index[i]].occup;
-    }
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the B-factors for each atom in \p out->u.r.
- * Segfaults if PDB info is not found in the topology.
- */
-static int
-evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
-{
-    int  i;
-
-    out->nr = g->isize;
-    for (i = 0; i < g->isize; ++i)
-    {
-        out->u.r[i] = top->atoms.pdbinfo[g->index[i]].bfac;
-    }
-    return 0;
-}
-
-/*! \brief
- * Internal utility function for position keyword evaluation.
- *
- * \param[in]  fr   Current frame.
- * \param[in]  g    Index group for which the coordinates should be evaluated.
- * \param[out] out  Output array.
- * \param[in]  pos  Position data to use instead of atomic coordinates
- *   (can be NULL).
- * \param[in]  d    Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
- *
- * This function is used internally by evaluate_x(), evaluate_y() and
- * evaluate_z() to do the actual evaluation.
- */
-static void
-evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
-               gmx_ana_pos_t *pos, int d)
-{
-    int  b, i;
-    real v;
-
-    if (pos)
-    {
-        for (b = 0; b < pos->nr; ++b)
-        {
-            v = pos->x[b][d];
-            for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
-            {
-                out[i] = v;
-            }
-        }
-    }
-    else
-    {
-        for (i = 0; i < g->isize; ++i)
-        {
-            out[i] = fr->x[g->index[i]][d];
-        }
-    }
-}
-
-/*!
- * See sel_updatefunc_pos() for description of the parameters.
- * \p data is not used.
- *
- * Returns the \p x coordinate for each atom in \p out->u.r.
- */
-static int
-evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, XX);
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the \p y coordinate for each atom in \p out->u.r.
- */
-static int
-evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, YY);
-    return 0;
-}
-
-/*!
- * See sel_updatefunc() for description of the parameters.
- * \p data is not used.
- *
- * Returns the \p z coordinate for each atom in \p out->u.r.
- */
-static int
-evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
-{
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, ZZ);
-    return 0;
-}
diff --git a/src/gmxlib/selection/symrec.c b/src/gmxlib/selection/symrec.c
deleted file mode 100644 (file)
index 2e40096..0000000
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in symrec.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <macros.h>
-#include <smalloc.h>
-#include <string2.h>
-#include <typedefs.h>
-#include <gmx_fatal.h>
-
-#include <poscalc.h>
-
-#include "selelem.h"
-#include "symrec.h"
-
-/*! \internal \brief
- * Symbol table for the selection parser.
- */
-struct gmx_sel_symtab_t
-{
-    /** Pointer to the first symbol in the linked list of symbols. */
-    gmx_sel_symrec_t *first;
-};
-
-/*! \internal \brief
- * Single symbol for the selection parser.
- */
-struct gmx_sel_symrec_t
-{
-    /** Name of the symbol. */
-    char                           *name;
-    /** Type of the symbol. */
-    e_symbol_t                      type;
-    /** Value of the symbol. */
-    union {
-        /** Pointer to the method structure (\ref SYMBOL_METHOD). */
-        struct gmx_ana_selmethod_t *meth;
-        /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
-        struct t_selelem           *var;
-    }                               u;
-    /** Pointer to the next symbol. */
-    struct gmx_sel_symrec_t        *next;
-};
-
-/** List of reserved symbols to register in add_reserved_symbols(). */
-static const char *const sym_reserved[] = {
-    "group",
-    "to",
-    "not",
-    "and",
-    "or",
-    "xor",
-    "yes",
-    "no",
-    "on",
-    "off",
-    "help",
-};
-
-/*!
- * \param[in] sym Symbol to query.
- * \returns   The name of \p sym.
- *
- * The returned pointer should not be free'd.
- */
-char *
-_gmx_sel_sym_name(gmx_sel_symrec_t *sym)
-{
-    return sym->name;
-}
-
-/*!
- * \param[in] sym Symbol to query.
- * \returns   The type of \p sym.
- */
-e_symbol_t
-_gmx_sel_sym_type(gmx_sel_symrec_t *sym)
-{
-    return sym->type;
-}
-
-/*!
- * \param[in] sym Symbol to query.
- * \returns   The method associated with \p sym, or NULL if \p sym is not a
- *   \ref SYMBOL_METHOD symbol.
- */
-struct gmx_ana_selmethod_t *
-_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym)
-{
-    if (sym->type != SYMBOL_METHOD)
-    {
-        gmx_call("symbol is not a method symbol");
-        return NULL;
-    }
-    return sym->u.meth;
-}
-
-/*!
- * \param[in] sym Symbol to query.
- * \returns   The variable expression associated with \p sym, or NULL if
- *   \p sym is not a \ref SYMBOL_VARIABLE symbol.
- */
-struct t_selelem *
-_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym)
-{
-    if (sym->type != SYMBOL_VARIABLE)
-    {
-        gmx_call("symbol is not a variable symbol");
-        return NULL;
-    }
-    return sym->u.var;
-}
-
-/*! \brief
- * Adds the reserved symbols to a symbol table.
- * 
- * \param[in,out] tab  Symbol table to which the symbols are added.
- *
- * Assumes that the symbol table is empty.
- */
-static void
-add_reserved_symbols(gmx_sel_symtab_t *tab)
-{
-    gmx_sel_symrec_t *sym;
-    gmx_sel_symrec_t *last;
-    size_t            i;
-
-    last = NULL;
-    for (i = 0; i < asize(sym_reserved); ++i)
-    {
-        snew(sym, 1);
-        sym->name = strdup(sym_reserved[i]);
-        sym->type = SYMBOL_RESERVED;
-        sym->next = NULL;
-        if (last)
-        {
-            last->next = sym;
-        }
-        else
-        {
-            tab->first = sym;
-        }
-        last = sym;
-    }
-}
-
-/*! \brief
- * Adds the position symbols to the symbol list.
- * 
- * \param[in,out] tab  Symbol table to which the symbols are added.
- */
-static void
-add_position_symbols(gmx_sel_symtab_t *tab)
-{
-    const char       **postypes;
-    gmx_sel_symrec_t  *sym;
-    gmx_sel_symrec_t  *last;
-    int                i;
-
-    postypes = gmx_ana_poscalc_create_type_enum(TRUE);
-    last = tab->first;
-    while (last && last->next)
-    {
-        last = last->next;
-    }
-    for (i = 1; postypes[i] != NULL; ++i)
-    {
-        snew(sym, 1);
-        sym->name = strdup(postypes[i]);
-        sym->type = SYMBOL_POS;
-        sym->next = NULL;
-        if (last)
-        {
-            last->next = sym;
-        }
-        else
-        {
-            tab->first = sym;
-        }
-        last = sym;
-    }
-    sfree(postypes);
-}
-
-/*!
- * \param[out] tabp Symbol table pointer to initialize.
- *
- * Reserved and position symbols are added to the created table.
- */
-int
-_gmx_sel_symtab_create(gmx_sel_symtab_t **tabp)
-{
-    gmx_sel_symtab_t *tab;
-
-    snew(tab, 1);
-    add_reserved_symbols(tab);
-    add_position_symbols(tab);
-    *tabp = tab;
-    return 0;
-}
-
-/*!
- * \param[in] tab Symbol table to free.
- *
- * The pointer \p tab is invalid after the call.
- */
-void
-_gmx_sel_symtab_free(gmx_sel_symtab_t *tab)
-{
-    gmx_sel_symrec_t *sym;
-
-    while (tab->first)
-    {
-        sym = tab->first;
-        tab->first = sym->next;
-        if (sym->type == SYMBOL_VARIABLE)
-        {
-            _gmx_selelem_free(sym->u.var);
-        }
-        sfree(sym->name);
-        sfree(sym);
-    }
-    sfree(tab);
-}
-
-/*!
- * \param[in] tab    Symbol table to search.
- * \param[in] name   Symbol name to find.
- * \param[in] bExact If FALSE, symbols that begin with \p name are also
- *   considered.
- * \returns   Pointer to the symbol with name \p name, or NULL if not found.
- *
- * If no exact match is found and \p bExact is FALSE, returns a symbol that
- * begins with \p name if a unique matching symbol is found.
- */
-gmx_sel_symrec_t *
-_gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact)
-{
-    return _gmx_sel_find_symbol_len(tab, name, strlen(name), bExact);
-}
-
-/*!
- * \param[in] tab    Symbol table to search.
- * \param[in] name   Symbol name to find.
- * \param[in] len    Only consider the first \p len characters of \p name.
- * \param[in] bExact If FALSE, symbols that begin with \p name are also
- *   considered.
- * \returns   Pointer to the symbol with name \p name, or NULL if not found.
- *
- * If no exact match is found and \p bExact is FALSE, returns a symbol that
- * begins with \p name if a unique matching symbol is found.
- *
- * The parameter \p len is there to allow using this function from scanner.l
- * without modifying the text to be scanned or copying it.
- */
-gmx_sel_symrec_t *
-_gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
-                         gmx_bool bExact)
-{
-    gmx_sel_symrec_t *sym;
-    gmx_sel_symrec_t *match;
-    gmx_bool              bUnique;
-    gmx_bool              bMatch;
-
-    match = NULL;
-    bUnique = TRUE;
-    bMatch  = FALSE;
-    sym = tab->first;
-    while (sym)
-    {
-        if (!strncmp(sym->name, name, len))
-        {
-            if (strlen(sym->name) == len)
-            {
-                return sym;
-            }
-            if (bMatch)
-            {
-                bUnique = FALSE;
-            }
-            bMatch = TRUE;
-            if (sym->type == SYMBOL_METHOD)
-            {
-                match = sym;
-            }
-        }
-        sym = sym->next;
-    }
-    if (bExact)
-    {
-        return NULL;
-    }
-
-    if (!bUnique)
-    {
-        fprintf(stderr, "parse error: ambiguous symbol\n");
-        return NULL;
-    }
-    return match;
-}
-
-/*!
- * \param[in] tab   Symbol table to search.
- * \param[in] type  Type of symbol to find.
- * \returns   The first symbol in \p tab with type \p type,
- *   or NULL if there are no such symbols.
- */
-gmx_sel_symrec_t *
-_gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type)
-{
-    gmx_sel_symrec_t *sym;
-
-    sym = tab->first;
-    while (sym)
-    {
-        if (sym->type == type)
-        {
-            return sym;
-        }
-        sym = sym->next;
-    }
-    return NULL;
-}
-
-/*!
- * \param[in] after Start the search after this symbol.
- * \param[in] type  Type of symbol to find.
- * \returns   The next symbol after \p after with type \p type,
- *   or NULL if there are no more symbols.
- */
-gmx_sel_symrec_t *
-_gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type)
-{
-    gmx_sel_symrec_t *sym;
-
-    sym = after->next;
-    while (sym)
-    {
-        if (sym->type == type)
-        {
-            return sym;
-        }
-        sym = sym->next;
-    }
-    return NULL;
-}
-
-/*! \brief
- * Internal utility function used in adding symbols to a symbol table.
- *
- * \param[in,out] tab   Symbol table to add the symbol to.
- * \param[in]     name  Name of the symbol to add.
- * \param[out]    ctype On error, the type of the conflicting symbol is
- *   written to \p *ctype.
- * \returns       Pointer to the new symbol record, or NULL if \p name
- *   conflicts with an existing symbol.
- */
-static gmx_sel_symrec_t *
-add_symbol(gmx_sel_symtab_t *tab, const char *name, e_symbol_t *ctype)
-{
-    gmx_sel_symrec_t *sym, *psym;
-    int               len;
-
-    /* Check if there is a conflicting symbol */
-    psym = NULL;
-    sym  = tab->first;
-    while (sym)
-    {
-        if (!gmx_strcasecmp(sym->name, name))
-        {
-            *ctype = sym->type;
-            return NULL;
-        }
-        psym = sym;
-        sym  = sym->next;
-    }
-
-    /* Create a new symbol record */
-    if (psym == NULL)
-    {
-        snew(tab->first, 1);
-        sym = tab->first;
-    }
-    else
-    {
-        snew(psym->next, 1);
-        sym = psym->next;
-    }
-    sym->name = strdup(name);
-    return sym;
-}
-
-/*!
- * \param[in,out] tab    Symbol table to add the symbol to.
- * \param[in]     name   Name of the new symbol.
- * \param[in]     sel    Value of the variable.
- * \returns       Pointer to the created symbol record, or NULL if there was a
- *   symbol with the same name.
- */
-gmx_sel_symrec_t *
-_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
-                        struct t_selelem *sel)
-{
-    gmx_sel_symrec_t *sym;
-    e_symbol_t        ctype;
-
-    sym = add_symbol(tab, name, &ctype);
-    if (!sym)
-    {
-        fprintf(stderr, "parse error: ");
-        switch (ctype)
-        {
-            case SYMBOL_RESERVED:
-            case SYMBOL_POS:
-                fprintf(stderr, "variable name (%s) conflicts with a reserved keyword\n",
-                        name);
-                break;
-            case SYMBOL_VARIABLE:
-                fprintf(stderr, "duplicate variable name (%s)\n", name);
-                break;
-            case SYMBOL_METHOD:
-                fprintf(stderr, "variable name (%s) conflicts with a selection keyword\n",
-                        name);
-                break;
-        }
-        return NULL;
-    }
-
-    sym->type  = SYMBOL_VARIABLE;
-    sym->u.var = sel;
-    sel->refcount++;
-    return sym;
-}
-
-/*!
- * \param[in,out] tab    Symbol table to add the symbol to.
- * \param[in]     name   Name of the new symbol.
- * \param[in]     method Method that this symbol represents.
- * \returns       Pointer to the created symbol record, or NULL if there was a
- *   symbol with the same name.
- */
-gmx_sel_symrec_t *
-_gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
-                           struct gmx_ana_selmethod_t *method)
-{
-    gmx_sel_symrec_t *sym;
-    e_symbol_t        ctype;
-
-    sym = add_symbol(tab, name, &ctype);
-    if (!sym)
-    {
-        fprintf(stderr, "parse error: ");
-        switch (ctype)
-        {
-            case SYMBOL_RESERVED:
-            case SYMBOL_POS:
-                fprintf(stderr, "method name (%s) conflicts with a reserved keyword\n",
-                        name);
-                break;
-            case SYMBOL_VARIABLE:
-                fprintf(stderr, "method name (%s) conflicts with a variable name\n",
-                        name);
-                break;
-            case SYMBOL_METHOD:
-                fprintf(stderr, "duplicate method name (%s)\n", name);
-                break;
-        }
-        return NULL;
-    }
-
-    sym->type   = SYMBOL_METHOD;
-    sym->u.meth = method;
-    return sym;
-}
diff --git a/src/gmxlib/selection/symrec.h b/src/gmxlib/selection/symrec.h
deleted file mode 100644 (file)
index bbf21b1..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Handling of selection parser symbol table.
- *
- * This is an implementation header: there should be no need to use it outside
- * this directory.
- */
-#ifndef SELECTION_SYMREC_H
-#define SELECTION_SYMREC_H
-
-struct t_selelem;
-struct gmx_ana_selmethod_t;
-
-/** Defines the type of the symbol. */
-typedef enum
-{
-    SYMBOL_RESERVED,    /**< The symbol is a reserved keyword. */
-    SYMBOL_VARIABLE,    /**< The symbol is a variable. */
-    SYMBOL_METHOD,      /**< The symbol is a selection method. */
-    SYMBOL_POS          /**< The symbol is a position keyword. */
-} e_symbol_t;
-
-/** Symbol table for the selection parser. */
-typedef struct gmx_sel_symtab_t gmx_sel_symtab_t;
-/** Single symbol for the selection parser. */
-typedef struct gmx_sel_symrec_t gmx_sel_symrec_t;
-
-/** Returns the name of a symbol. */
-char *
-_gmx_sel_sym_name(gmx_sel_symrec_t *sym);
-/** Returns the type of a symbol. */
-e_symbol_t
-_gmx_sel_sym_type(gmx_sel_symrec_t *sym);
-/** Returns the method associated with a \ref SYMBOL_METHOD symbol. */
-struct gmx_ana_selmethod_t *
-_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym);
-/** Returns the method associated with a \ref SYMBOL_VARIABLE symbol. */
-struct t_selelem *
-_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym);
-
-/** Creates a new symbol table. */
-int
-_gmx_sel_symtab_create(gmx_sel_symtab_t **tabp);
-/** Frees all memory allocated for a symbol table. */
-void
-_gmx_sel_symtab_free(gmx_sel_symtab_t *tab);
-/** Finds a symbol by name. */
-gmx_sel_symrec_t *
-_gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact);
-/** Finds a symbol by name. */
-gmx_sel_symrec_t *
-_gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
-                         gmx_bool bExact);
-/** Returns the first symbol of a given type. */
-gmx_sel_symrec_t *
-_gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type);
-/** Returns the next symbol of a given type. */
-gmx_sel_symrec_t *
-_gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type);
-/** Adds a new variable symbol. */
-gmx_sel_symrec_t *
-_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
-                        struct t_selelem *sel);
-/** Adds a new method symbol. */
-gmx_sel_symrec_t *
-_gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
-                           struct gmx_ana_selmethod_t *method);
-
-#endif
diff --git a/src/gmxlib/selection/test_selection.c b/src/gmxlib/selection/test_selection.c
deleted file mode 100644 (file)
index bde0ad1..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Testing/debugging tool for the selection engine.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <copyrite.h>
-#include <filenm.h>
-#include <macros.h>
-#include <smalloc.h>
-#include <statutil.h>
-
-#include <trajana.h>
-
-typedef struct
-{
-    gmx_bool                     bFrameTree;
-    int                      nmaxind;
-    gmx_ana_selcollection_t *sc;
-} t_dumpdata;
-
-int
-dump_frame(t_topology * top, t_trxframe * fr, t_pbc * pbc,
-           int nr, gmx_ana_selection_t *sel[], void *data)
-{
-    t_dumpdata         *d = (t_dumpdata *)data;
-    int                 g, i, n;
-
-    fprintf(stderr, "\n");
-    if (d->bFrameTree)
-    {
-        gmx_ana_selcollection_print_tree(stderr, d->sc, TRUE);
-    }
-    for (g = 0; g < nr; ++g)
-    {
-        gmx_ana_index_dump(sel[g]->g, g, d->nmaxind);
-        fprintf(stderr, "  Positions (%d pcs):\n", sel[g]->p.nr);
-        n = sel[g]->p.nr;
-        if (d->nmaxind >= 0 && n > d->nmaxind)
-        {
-            n = d->nmaxind;
-        }
-        for (i = 0; i < n; ++i)
-        {
-            fprintf(stderr, "    (%.2f,%.2f,%.2f) r=%d, m=%d, b=%d-%d\n",
-                    sel[g]->p.x[i][XX], sel[g]->p.x[i][YY], sel[g]->p.x[i][ZZ],
-                    sel[g]->p.m.refid[i], sel[g]->p.m.mapid[i],
-                    sel[g]->p.m.mapb.index[i]+1,
-                    sel[g]->p.m.mapb.index[i+1]);
-        }
-        if (n < sel[g]->p.nr)
-        {
-            fprintf(stderr, "    ...\n");
-        }
-    }
-    fprintf(stderr, "\n");
-    return 0;
-}
-
-static void
-print_selections(int nr, gmx_ana_selection_t **sel, int nmaxind)
-{
-    int                 g, i, n;
-
-    fprintf(stderr, "\nSelections:\n");
-    for (g = 0; g < nr; ++g)
-    {
-        fprintf(stderr, "  ");
-        gmx_ana_selection_print_info(sel[g]);
-        fprintf(stderr, "    ");
-        gmx_ana_index_dump(sel[g]->g, g, nmaxind);
-
-        fprintf(stderr, "    Block (size=%d):", sel[g]->p.m.mapb.nr);
-        if (!sel[g]->p.m.mapb.index)
-        {
-            fprintf(stderr, " (null)");
-        }
-        else
-        {
-            n = sel[g]->p.m.mapb.nr;
-            if (nmaxind >= 0 && n > nmaxind)
-                n = nmaxind;
-            for (i = 0; i <= n; ++i)
-                fprintf(stderr, " %d", sel[g]->p.m.mapb.index[i]);
-            if (n < sel[g]->p.m.mapb.nr)
-                fprintf(stderr, " ...");
-        }
-        fprintf(stderr, "\n");
-
-        n = sel[g]->p.m.nr;
-        if (nmaxind >= 0 && n > nmaxind)
-            n = nmaxind;
-        fprintf(stderr, "    RefId:");
-        if (!sel[g]->p.m.refid)
-        {
-            fprintf(stderr, " (null)");
-        }
-        else
-        {
-            for (i = 0; i < n; ++i)
-                fprintf(stderr, " %d", sel[g]->p.m.refid[i]);
-            if (n < sel[g]->p.m.nr)
-                fprintf(stderr, " ...");
-        }
-        fprintf(stderr, "\n");
-
-        fprintf(stderr, "    MapId:");
-        if (!sel[g]->p.m.mapid)
-        {
-            fprintf(stderr, " (null)");
-        }
-        else
-        {
-            for (i = 0; i < n; ++i)
-                fprintf(stderr, " %d", sel[g]->p.m.mapid[i]);
-            if (n < sel[g]->p.m.nr)
-                fprintf(stderr, " ...");
-        }
-        fprintf(stderr, "\n");
-    }
-    fprintf(stderr, "\n");
-}
-
-int
-gmx_test_selection(int argc, char *argv[])
-{
-    const char         *desc[] = {
-        "This is a test program for selections.",
-    };
-
-    gmx_bool                bMaskOnly  = FALSE;
-    gmx_bool                bFrameTree = FALSE;
-    gmx_bool                bDebugCompile = FALSE;
-    int                 nref       = 0;
-    int                 nmaxind    = 20;
-    t_pargs             pa[] = {
-        {"-mask",   FALSE, etBOOL, {&bMaskOnly},
-         "Test position mask functionality"},
-        {"-compdebug", FALSE, etBOOL, {&bDebugCompile},
-         "Print intermediate trees during compilation"},
-        {"-frtree", FALSE, etBOOL, {&bFrameTree},
-         "Print the whole evaluation tree for each frame"},
-        {"-nref",   FALSE, etINT,  {&nref},
-         "Number of reference selections to ask for"},
-        {"-pmax",   FALSE, etINT,  {&nmaxind},
-         "Maximum number of indices to print in lists (-1 = print all)"},
-    };
-
-    t_filenm            fnm[] = {
-        {efDAT, "-o", "debug", ffOPTWR},
-    };
-
-    gmx_ana_traj_t       *trj;
-    t_dumpdata            d;
-    int                   ngrps;
-    gmx_ana_selection_t **sel;
-    output_env_t          oenv;
-
-#define NFILE asize(fnm)
-
-    CopyRight(stderr, argv[0]);
-
-    gmx_ana_traj_create(&trj, ANA_DEBUG_SELECTION | ANA_USER_SELINIT | ANA_USE_FULLGRPS);
-    gmx_ana_get_selcollection(trj, &d.sc);
-    gmx_ana_set_nanagrps(trj, -1);
-    parse_trjana_args(trj, &argc, argv, 0,
-                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL,
-                      &oenv);
-    if (bMaskOnly)
-    {
-        gmx_ana_add_flags(trj, ANA_USE_POSMASK);
-        gmx_ana_selcollection_set_outpostype(d.sc, NULL, TRUE);
-    }
-    gmx_ana_selcollection_set_compile_debug(d.sc, bDebugCompile);
-    gmx_ana_set_nrefgrps(trj, nref);
-    gmx_ana_init_selections(trj);
-    gmx_ana_get_ngrps(trj, &ngrps);
-    gmx_ana_get_anagrps(trj, &sel);
-
-    d.bFrameTree = bFrameTree;
-    d.nmaxind    = nmaxind;
-
-    print_selections(ngrps, sel, d.nmaxind);
-
-    gmx_ana_do(trj, 0, &dump_frame, &d);
-
-    print_selections(ngrps, sel, d.nmaxind);
-
-    gmx_ana_traj_free(trj);
-    done_filenms(NFILE, fnm);
-
-    return 0;
-}
-
-int
-main(int argc, char *argv[])
-{
-    gmx_test_selection(argc, argv);
-    return 0;
-}
diff --git a/src/gmxlib/statistics/gmx_statistics.c b/src/gmxlib/statistics/gmx_statistics.c
deleted file mode 100644 (file)
index 7b50f92..0000000
+++ /dev/null
@@ -1,786 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- */
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Green Red Orange Magenta Azure Cyan Skyblue
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-#include "typedefs.h"
-#include "smalloc.h"
-#include "gmx_statistics.h"
-
-static double sqr(double x)
-{
-    return x*x;
-}
-
-static int gmx_nint(double x)
-{
-    return (int) (x+0.5);
-}
-
-typedef struct gmx_stats {
-    double aa,a,b,sigma_aa,sigma_a,sigma_b,aver,sigma_aver,error;
-    double rmsd,Rdata,Rfit,Rfitaa,chi2,chi2aa;
-    double *x,*y,*dx,*dy;
-    int    computed;
-    int    np,np_c,nalloc;
-} gmx_stats;
-
-gmx_stats_t gmx_stats_init()
-{
-    gmx_stats *stats;
-  
-    snew(stats,1);
-  
-    return (gmx_stats_t) stats;
-}
-
-int gmx_stats_get_npoints(gmx_stats_t gstats, int *N)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-  
-    *N = stats->np;
-  
-    return estatsOK;
-}
-
-int gmx_stats_done(gmx_stats_t gstats)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-  
-    sfree(stats->x);
-    stats->x = NULL;
-    sfree(stats->y);
-    stats->y = NULL;
-    sfree(stats->dx);
-    stats->dx = NULL;
-    sfree(stats->dy);
-    stats->dy = NULL;
-  
-    return estatsOK;
-}
-
-int gmx_stats_add_point(gmx_stats_t gstats,double x,double y,
-                        double dx,double dy)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int i;
-  
-    if (stats->np+1 >= stats->nalloc) 
-    {
-        if (stats->nalloc == 0) 
-            stats->nalloc = 1024;
-        else
-            stats->nalloc *= 2;
-        srenew(stats->x,stats->nalloc);
-        srenew(stats->y,stats->nalloc);
-        srenew(stats->dx,stats->nalloc);
-        srenew(stats->dy,stats->nalloc);
-        for(i=stats->np; (i<stats->nalloc); i++) 
-        {
-            stats->x[i]  = 0;
-            stats->y[i]  = 0;
-            stats->dx[i] = 0;
-            stats->dy[i] = 0;
-        }
-    }
-    stats->x[stats->np]  = x;
-    stats->y[stats->np]  = y;
-    stats->dx[stats->np] = dx;
-    stats->dy[stats->np] = dy;
-    stats->np++;
-    stats->computed = 0;
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_point(gmx_stats_t gstats,real *x,real *y,
-                        real *dx,real *dy)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-  
-    if (stats->np_c < stats->np) 
-    {
-        if (NULL != x)  *x  = stats->x[stats->np_c];
-        if (NULL != y)  *y  = stats->y[stats->np_c];
-        if (NULL != dx) *dx = stats->dx[stats->np_c];
-        if (NULL != dy) *dy = stats->dy[stats->np_c];
-        stats->np_c++;
-    
-        return estatsOK;
-    }
-    stats->np_c = 0;
-  
-    return estatsNO_POINTS;
-}
-
-int gmx_stats_add_points(gmx_stats_t gstats,int n,real *x,real *y,
-                         real *dx,real *dy)
-{
-    int i,ok;
-  
-    for(i=0; (i<n); i++) 
-    {
-        if ((ok = gmx_stats_add_point(gstats,x[i],y[i],
-                                      (NULL != dx) ? dx[i] : 0,
-                                      (NULL != dy) ? dy[i] : 0)) != estatsOK)
-        {
-            return ok;
-        }
-    }
-    return estatsOK;
-}
-
-static int gmx_stats_compute(gmx_stats *stats,int weight)
-{
-    double yy,yx,xx,sx,sy,dy,chi2,chi2aa,d2;
-    double ssxx,ssyy,ssxy;
-    double w,wtot,yx_nw,sy_nw,sx_nw,yy_nw,xx_nw,dx2,dy2;
-    int i,N;
-  
-    N = stats->np;
-    if (stats->computed == 0) 
-    {
-        if (N < 1)
-        {
-            return estatsNO_POINTS;
-        }
-      
-        xx = xx_nw = 0;
-        yy = yy_nw = 0;
-        yx = yx_nw = 0;
-        sx = sx_nw = 0;
-        sy = sy_nw = 0;
-        wtot = 0;
-        d2   = 0;
-        for(i=0; (i<N); i++) 
-        {
-            d2 += sqr(stats->x[i]-stats->y[i]);
-            if ((stats->dy[i]) && (weight == elsqWEIGHT_Y))
-            {
-                w = 1/sqr(stats->dy[i]);
-            }
-            else
-            {
-                w = 1;
-            }
-            
-            wtot  += w;
-            
-            xx    += w*sqr(stats->x[i]);
-            xx_nw += sqr(stats->x[i]);
-            
-            yy    += w*sqr(stats->y[i]);
-            yy_nw += sqr(stats->y[i]);
-            
-            yx    += w*stats->y[i]*stats->x[i];
-            yx_nw += stats->y[i]*stats->x[i];
-            
-            sx    += w*stats->x[i];
-            sx_nw += stats->x[i];
-            
-            sy    += w*stats->y[i];
-            sy_nw += stats->y[i];
-        }
-      
-        /* Compute average, sigma and error */
-        stats->aver       = sy_nw/N;
-        stats->sigma_aver = sqrt(yy_nw/N - sqr(sy_nw/N));
-        stats->error      = stats->sigma_aver/sqrt(N);
-
-        /* Compute RMSD between x and y */
-        stats->rmsd = sqrt(d2/N);
-       
-        /* Correlation coefficient for data */
-        yx_nw /= N;
-        xx_nw /= N;
-        yy_nw /= N;
-        sx_nw /= N;
-        sy_nw /= N;
-        ssxx = N*(xx_nw - sqr(sx_nw));
-        ssyy = N*(yy_nw - sqr(sy_nw));
-        ssxy = N*(yx_nw - (sx_nw*sy_nw));
-        stats->Rdata = sqrt(sqr(ssxy)/(ssxx*ssyy)); 
-        
-        /* Compute straight line through datapoints, either with intercept
-           zero (result in aa) or with intercept variable (results in a
-           and b) */
-        yx = yx/wtot;
-        xx = xx/wtot;
-        sx = sx/wtot;
-        sy = sy/wtot;
-  
-        stats->aa = (yx/xx);  
-        stats->a  = (yx-sx*sy)/(xx-sx*sx);
-        stats->b  = (sy)-(stats->a)*(sx);
-    
-        /* Compute chi2, deviation from a line y = ax+b. Also compute
-           chi2aa which returns the deviation from a line y = ax. */
-        chi2   = 0;
-        chi2aa = 0;
-        for(i=0; (i<N); i++) 
-        {
-            if (stats->dy[i] > 0)
-            {
-                dy = stats->dy[i];
-            }
-            else
-            {
-                dy = 1;
-            }
-            chi2aa += sqr((stats->y[i]-(stats->aa*stats->x[i]))/dy);
-            chi2   += sqr((stats->y[i]-(stats->a*stats->x[i]+stats->b))/dy);
-        }
-        if (N > 2) 
-        {
-            stats->chi2   = sqrt(chi2/(N-2));
-            stats->chi2aa = sqrt(chi2aa/(N-2));
-            
-            /* Look up equations! */
-            dx2 = (xx-sx*sx);
-            dy2 = (yy-sy*sy);
-            stats->sigma_a = sqrt(stats->chi2/((N-2)*dx2));
-            stats->sigma_b = stats->sigma_a*sqrt(xx);
-            stats->Rfit    = fabs(ssxy)/sqrt(ssxx*ssyy);
-                /*stats->a*sqrt(dx2/dy2);*/
-            stats->Rfitaa  = stats->aa*sqrt(dx2/dy2);  
-        }
-        else
-        {
-            stats->chi2    = 0;
-            stats->chi2aa  = 0;
-            stats->sigma_a = 0;
-            stats->sigma_b = 0;
-            stats->Rfit    = 0;
-            stats->Rfitaa  = 0;
-        }    
-
-        stats->computed = 1;
-    }
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_ab(gmx_stats_t gstats,int weight,
-                     real *a,real *b,real *da,real *db,
-                     real *chi2,real *Rfit)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,weight)) != estatsOK)
-        return ok;
-    if (NULL != a)
-    {
-        *a    = stats->a;
-    }
-    if (NULL != b)   
-    {
-        *b    = stats->b;
-    }
-    if (NULL != da)  
-    {
-        *da   = stats->sigma_a;
-    }
-    if (NULL != db)  
-    {
-        *db   = stats->sigma_b;
-    }
-    if (NULL != chi2) 
-    {
-        *chi2 = stats->chi2;
-    }
-    if (NULL != Rfit) 
-    {
-        *Rfit = stats->Rfit;
-    }
-    
-    return estatsOK;
-}
-
-int gmx_stats_get_a(gmx_stats_t gstats,int weight,real *a,real *da,
-                    real *chi2,real *Rfit)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,weight)) != estatsOK)
-        return ok;
-    if (NULL != a)    *a    = stats->aa;
-    if (NULL != da)   *da   = stats->sigma_aa;
-    if (NULL != chi2) *chi2 = stats->chi2aa;
-    if (NULL != Rfit) *Rfit = stats->Rfitaa;
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_average(gmx_stats_t gstats,real *aver)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-    {
-        return ok;
-    }
-    
-    *aver = stats->aver;
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_ase(gmx_stats_t gstats,real *aver,real *sigma,real *error)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-    {
-        return ok;
-    }
-    
-    if (NULL != aver)
-    {
-        *aver  = stats->aver;
-    }
-    if (NULL != sigma) 
-    {
-        *sigma = stats->sigma_aver;
-    }
-    if (NULL != error) 
-    {
-        *error = stats->error;
-    }
-    
-    return estatsOK;
-}
-
-int gmx_stats_get_sigma(gmx_stats_t gstats,real *sigma)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-        return ok;
-
-    *sigma = stats->sigma_aver;
-    
-    return estatsOK;
-}
-
-int gmx_stats_get_error(gmx_stats_t gstats,real *error)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-        return ok;
-
-    *error = stats->error;
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_corr_coeff(gmx_stats_t gstats,real *R)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-        return ok;
-
-    *R = stats->Rdata;
-  
-    return estatsOK;
-}
-
-int gmx_stats_get_rmsd(gmx_stats_t gstats,real *rmsd)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int ok;
-  
-    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
-    {
-        return ok;
-    }
-    
-    *rmsd = stats->rmsd;
-  
-    return estatsOK;
-}
-
-int gmx_stats_dump_xy(gmx_stats_t gstats,FILE *fp)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int i,ok;
-  
-    for(i=0; (i<stats->np); i++) 
-    {
-        fprintf(fp,"%12g  %12g  %12g  %12g\n",stats->x[i],stats->y[i],
-                stats->dx[i],stats->dy[i]);
-    }
-    
-    return estatsOK;
-}
-
-int gmx_stats_remove_outliers(gmx_stats_t gstats,double level)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int  i,iter=1,done=0,ok;
-    real rmsd,r;
-  
-    while ((stats->np >= 10) && !done) 
-    {
-        if ((ok = gmx_stats_get_rmsd(gstats,&rmsd)) != estatsOK)
-        {
-            return ok;
-        }
-        done = 1;
-        for(i=0; (i<stats->np); ) 
-        {
-            r = fabs(stats->x[i]-stats->y[i]);
-            if (r > level*rmsd) 
-            {
-                fprintf(stderr,"Removing outlier, iter = %d, rmsd = %g, x = %g, y = %g\n",
-                        iter,rmsd,stats->x[i],stats->y[i]);
-                if (i < stats->np-1) 
-                {
-                    stats->x[i]  = stats->x[stats->np-1];
-                    stats->y[i]  = stats->y[stats->np-1];
-                    stats->dx[i] = stats->dx[stats->np-1];
-                    stats->dy[i] = stats->dy[stats->np-1];
-                }
-                stats->np--;
-                done = 0;
-            }
-            else 
-            {
-                i++;
-            }
-        }
-        iter++;
-    }
-    
-    return estatsOK;
-}
-
-int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nb,
-                             int ehisto,int normalized,real **x,real **y)
-{
-    gmx_stats *stats = (gmx_stats *) gstats;
-    int    i,ok,index=0,nbins=*nb,*nindex;
-    double minx,maxx,maxy,miny,delta,dd,minh;
-  
-    if (((binwidth <= 0) && (nbins <= 0)) ||
-        ((binwidth > 0) && (nbins > 0)))
-    {
-        return estatsINVALID_INPUT;
-    }
-    if (stats->np <= 2)
-    {
-        return estatsNO_POINTS;
-    }
-    minx = maxx = stats->x[0];
-    miny = maxy = stats->y[0];
-    for(i=1; (i<stats->np); i++) 
-    {
-        miny = (stats->y[i] < miny) ? stats->y[i] : miny;
-        maxy = (stats->y[i] > maxy) ? stats->y[i] : maxy;
-        minx = (stats->x[i] < minx) ? stats->x[i] : minx;
-        maxx = (stats->x[i] > maxx) ? stats->x[i] : maxx;
-    }
-    if (ehisto == ehistoX)
-    {
-        delta = maxx-minx;
-        minh = minx;
-    }
-    else if (ehisto == ehistoY)
-    {
-        delta = maxy-miny;
-        minh = miny;
-    }
-    else
-        return estatsINVALID_INPUT;
-        
-    if (binwidth == 0)
-    {
-        binwidth = (delta)/nbins;
-    }
-    else
-    {
-        nbins = gmx_nint((delta)/binwidth + 0.5);
-    }
-    snew(*x,nbins);
-    snew(nindex,nbins);
-    for(i=0; (i<nbins); i++) 
-    {
-        (*x)[i] = minh + binwidth*(i+0.5);
-    }
-    if (normalized == 0)
-    {
-        dd = 1;
-    }
-    else
-    {
-        dd = 1.0/(binwidth*stats->np);
-    }
-    
-    snew(*y,nbins);
-    for(i=0; (i<stats->np); i++) 
-    {
-        if (ehisto == ehistoY)
-            index = (stats->y[i]-miny)/binwidth;
-               else if (ehisto == ehistoX)
-            index = (stats->x[i]-minx)/binwidth;
-               if (index<0)
-               {
-                       index = 0;
-               }
-               if (index>nbins-1)
-               {
-                       index = nbins-1;
-               }
-        (*y)[index] += dd;
-        nindex[index]++;
-    }
-    if (*nb == 0)
-        *nb = nbins;
-    for(i=0; (i<nbins); i++)
-        if (nindex[i] > 0)
-            (*y)[i] /= nindex[i];
-            
-    sfree(nindex);
-    
-    return estatsOK;
-}
-
-static const char *stats_error[estatsNR] = 
-{
-    "All well in STATS land",
-    "No points",
-    "Not enough memory",
-    "Invalid histogram input",
-    "Unknown error",
-    "Not implemented yet"
-};
-
-const char *gmx_stats_message(int estats)
-{
-    if ((estats >= 0) && (estats < estatsNR))
-    {
-        return stats_error[estats];
-    }
-    else
-    {
-        return stats_error[estatsERROR];
-    }
-}
-    
-/* Old convenience functions, should be merged with the core
-   statistics above. */
-int lsq_y_ax(int n, real x[], real y[], real *a)
-{
-    gmx_stats_t lsq = gmx_stats_init();
-    int  ok;
-    real da,chi2,Rfit;
-  
-    gmx_stats_add_points(lsq,n,x,y,0,0);
-    if ((ok = gmx_stats_get_a(lsq,elsqWEIGHT_NONE,a,&da,&chi2,&Rfit)) != estatsOK)
-    {
-        return ok;
-    }
-    
-    /*  int    i;
-        double xx,yx;
-  
-        yx=xx=0.0;
-        for (i=0; i<n; i++) {
-        yx+=y[i]*x[i];
-        xx+=x[i]*x[i];
-        }
-        *a=yx/xx;
-        */
-    return estatsOK;
-}
-
-static int low_lsq_y_ax_b(int n, real *xr, double *xd, real yr[],
-                          real *a, real *b,real *r,real *chi2)
-{
-    int    i,ok;
-    gmx_stats_t lsq;
-  
-    lsq = gmx_stats_init();
-    for(i=0; (i<n); i++) 
-    {
-        if ((ok = gmx_stats_add_point(lsq,(NULL != xd) ? xd[i] : xr[i],yr[i],0,0)) 
-            != estatsOK)
-        {
-            return ok;
-        }
-    }
-    if ((ok = gmx_stats_get_ab(lsq,elsqWEIGHT_NONE,a,b,NULL,NULL,chi2,r)) != estatsOK)
-    {
-        return ok;
-    }
-    
-    return estatsOK;
-    /*
-      double x,y,yx,xx,yy,sx,sy,chi2;
-
-      yx=xx=yy=sx=sy=0.0;
-      for (i=0; i<n; i++) {
-      if (xd != NULL) {
-      x = xd[i];
-      } else {
-      x = xr[i];
-      }
-      y =   yr[i];
-
-      yx += y*x;
-      xx += x*x;
-      yy += y*y;
-      sx += x;
-      sy += y;
-      }
-      *a = (n*yx-sy*sx)/(n*xx-sx*sx);
-      *b = (sy-(*a)*sx)/n;
-      *r = sqrt((xx-sx*sx)/(yy-sy*sy));
-  
-      chi2 = 0;
-      if (xd != NULL) {
-      for(i=0; i<n; i++)
-      chi2 += sqr(yr[i] - ((*a)*xd[i] + (*b)));
-      } else {
-      for(i=0; i<n; i++)
-      chi2 += sqr(yr[i] - ((*a)*xr[i] + (*b)));
-      }
-  
-      if (n > 2)
-      return sqrt(chi2/(n-2));
-      else
-      return 0;
-    */
-}
-
-int lsq_y_ax_b(int n, real x[], real y[], real *a, real *b,real *r,real *chi2)
-{
-    return low_lsq_y_ax_b(n,x,NULL,y,a,b,r,chi2);
-}
-
-int lsq_y_ax_b_xdouble(int n, double x[], real y[], real *a, real *b,
-                       real *r,real *chi2)
-{
-    return low_lsq_y_ax_b(n,NULL,x,y,a,b,r,chi2);
-}
-
-int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
-                     real *a, real *b, real *da, real *db,
-                     real *r,real *chi2)
-{
-    gmx_stats_t lsq;
-    int    i,ok;
-  
-    lsq = gmx_stats_init();
-    for(i=0; (i<n); i++)
-    {
-        if ((ok = gmx_stats_add_point(lsq,x[i],y[i],0,dy[i])) != estatsOK)
-        {
-            return ok;
-        }
-    }
-    if ((ok = gmx_stats_get_ab(lsq,elsqWEIGHT_Y,a,b,da,db,chi2,r)) != estatsOK)
-    {
-        return ok;
-    }
-    if ((ok = gmx_stats_done(lsq)) != estatsOK)
-    {
-        return ok;
-    }
-    sfree(lsq);
-
-    return estatsOK;
-    /*
-      double sxy,sxx,syy,sx,sy,w,s_2,dx2,dy2,mins;
-
-      sxy=sxx=syy=sx=sy=w=0.0;
-      mins = dy[0];
-      for(i=1; (i<n); i++)
-      mins = min(mins,dy[i]);
-      if (mins <= 0)
-      gmx_fatal(FARGS,"Zero or negative weigths in linear regression analysis");
-    
-      for (i=0; i<n; i++) {
-      s_2  = sqr(1.0/dy[i]);
-      sxx += s_2*sqr(x[i]);
-      sxy += s_2*y[i]*x[i];
-      syy += s_2*sqr(y[i]);
-      sx  += s_2*x[i];
-      sy  += s_2*y[i];
-      w   += s_2;
-      }
-      sxx = sxx/w;
-      sxy = sxy/w;
-      syy = syy/w;
-      sx  = sx/w;
-      sy  = sy/w;
-      dx2 = (sxx-sx*sx);
-      dy2 = (syy-sy*sy);
-      *a=(sxy-sy*sx)/dx2;
-      *b=(sy-(*a)*sx);
-  
-      *chi2=0;
-      for(i=0; i<n; i++)
-      *chi2+=sqr((y[i]-((*a)*x[i]+(*b)))/dy[i]);
-      *chi2 = *chi2/w;
-  
-      *da = sqrt(*chi2/((n-2)*dx2));
-      *db = *da*sqrt(sxx);
-      *r  = *a*sqrt(dx2/dy2);
-  
-      if (debug)
-      fprintf(debug,"sx = %g, sy = %g, sxy = %g, sxx = %g, w = %g\n"
-      "chi2 = %g, dx2 = %g\n",
-      sx,sy,sxy,sxx,w,*chi2,dx2);
-  
-      if (n > 2)
-      *chi2 = sqrt(*chi2/(n-2));
-      else
-      *chi2 = 0;
-      */
-}
-
-
diff --git a/src/gmxlib/string2.c b/src/gmxlib/string2.c
deleted file mode 100644 (file)
index ce6f341..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-/* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef GMX_CRAY_XT3
-#undef HAVE_PWD_H
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <time.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#include <time.h>
-
-#include "typedefs.h"
-#include "smalloc.h"
-#include "gmx_fatal.h"
-#include "macros.h"
-#include "string2.h"
-#include "futil.h"
-
-int continuing(char *s)
-/* strip trailing spaces and if s ends with a CONTINUE remove that too.
- * returns TRUE if s ends with a CONTINUE, FALSE otherwise.
- */
-{
-  int sl;
-
-  rtrim(s);
-  sl = strlen(s);
-  if ((sl > 0) && (s[sl-1] == CONTINUE)) {
-    s[sl-1] = 0;
-    return TRUE;
-  }
-  else
-    return FALSE;
-}
-
-
-
-char *fgets2(char *line, int n, FILE *stream)
-/* This routine reads a string from stream of max length n
- * and zero terminated, without newlines
- * line should be long enough (>= n)
- */
-{
-  char *c;
-  if (fgets(line,n,stream) == NULL) {
-    return NULL;
-  }
-  if ((c=strchr(line,'\n')) != NULL) {
-    *c = '\0';
-  } else {
-    /* A line not ending in a newline can only occur at the end of a file,
-     * or because of n being too small.
-     * Since both cases occur very infrequently, we can check for EOF.
-     */
-    if (!gmx_eof(stream)) {
-      gmx_fatal(FARGS,"An input file contains a line longer than %d characters, while the buffer passed to fgets2 has size %d. The line starts with: '%20.20s'",n,n,line);
-    }
-  }
-  if ((c=strchr(line,'\r')) != NULL) {
-    *c = '\0';
-  }
-
-  return line;
-}
-
-void strip_comment (char *line)
-{
-  char *c;
-
-  if (!line)
-    return;
-
-  /* search for a comment mark and replace it by a zero */
-  if ((c = strchr(line,COMMENTSIGN)) != NULL) 
-    (*c) = 0;
-}
-
-void upstring (char *str)
-{
-  int i;
-
-  for (i=0; (i < (int)strlen(str)); i++) 
-    str[i] = toupper(str[i]);
-}
-
-void ltrim (char *str)
-{
-  char *tr;
-  int i,c;
-
-  if (NULL == str)
-    return;
-
-  c = 0;
-  while (('\0' != str[c]) && isspace(str[c]))
-    c++;
-  if (c > 0) 
-    {
-      for(i=c; ('\0' != str[i]); i++)
-       str[i-c] = str[i];
-      str[i-c] = '\0';
-    }
-}
-
-void rtrim (char *str)
-{
-  int nul;
-
-  if (NULL == str)
-    return;
-
-  nul = strlen(str)-1;
-  while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
-    str[nul] = '\0';
-    nul--;
-  }
-}
-
-void trim (char *str)
-{
-  ltrim (str);
-  rtrim (str);
-}
-
-char *
-gmx_ctime_r(const time_t *clock,char *buf, int n)
-{
-    char tmpbuf[STRLEN];
-  
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-    /* Windows */
-    ctime_s( tmpbuf, STRLEN, clock );
-#elif (defined(__sun))
-    /*Solaris*/
-    ctime_r(clock, tmpbuf, n);
-#else
-    ctime_r(clock,tmpbuf);
-#endif
-    strncpy(buf,tmpbuf,n-1);
-    buf[n-1]='\0';
-    
-    return buf;
-}
-          
-void nice_header (FILE *out,const char *fn)
-{
-  const char *unk = "onbekend";
-  time_t clock;
-  char   *user=NULL;
-  int    gh;
-  uid_t  uid;
-  char   buf[256];
-  char   timebuf[STRLEN];
-#ifdef HAVE_PWD_H
-  struct passwd *pw;
-#endif
-
-  /* Print a nice header above the file */
-  time(&clock);
-  fprintf (out,"%c\n",COMMENTSIGN);
-  fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
-  
-#ifdef HAVE_PWD_H
-  uid = getuid();
-  pw  = getpwuid(uid);
-  gh  = gethostname(buf,255);
-  user= pw->pw_name;
-#else
-  uid = 0;
-  gh  = -1;
-#endif
-  
-  gmx_ctime_r(&clock,timebuf,STRLEN);
-  fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
-          user ? user : unk,(int) uid);
-  fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
-
-  fprintf (out,"%c\tAt date: %s",COMMENTSIGN,timebuf);
-  fprintf (out,"%c\n",COMMENTSIGN);
-}
-
-int gmx_strcasecmp_min(const char *str1, const char *str2)
-{
-  char ch1,ch2;
-  
-  do
-    {
-      do
-       ch1=toupper(*(str1++));
-      while ((ch1=='-') || (ch1=='_'));
-      do 
-       ch2=toupper(*(str2++));
-      while ((ch2=='-') || (ch2=='_'));
-      if (ch1!=ch2) return (ch1-ch2);
-    }
-  while (ch1);
-  return 0; 
-}
-
-int gmx_strncasecmp_min(const char *str1, const char *str2, int n)
-{
-  char ch1,ch2;
-  char *stri1, *stri2;
-
-  stri1=(char *)str1;
-  stri2=(char *)str2;  
-  do
-    {
-      do
-       ch1=toupper(*(str1++));
-      while ((ch1=='-') || (ch1=='_'));
-      do 
-       ch2=toupper(*(str2++));
-      while ((ch2=='-') || (ch2=='_'));
-      if (ch1!=ch2) return (ch1-ch2);
-    }
-  while (ch1 && (str1-stri1<n) && (str2-stri2<n));
-  return 0; 
-}
-
-int gmx_strcasecmp(const char *str1, const char *str2)
-{
-  char ch1,ch2;
-  
-  do
-    {
-      ch1=toupper(*(str1++));
-      ch2=toupper(*(str2++));
-      if (ch1!=ch2) return (ch1-ch2);
-    }
-  while (ch1);
-  return 0; 
-}
-
-int gmx_strncasecmp(const char *str1, const char *str2, int n)
-{
-  char ch1,ch2;
-  if(n==0) 
-    return 0;
-
-  do
-    {
-      ch1=toupper(*(str1++));
-      ch2=toupper(*(str2++));
-      if (ch1!=ch2) return (ch1-ch2);
-      n--;
-    }
-  while (ch1 && n);
-  return 0; 
-}
-
-char *gmx_strdup(const char *src)
-{
-  char *dest;
-
-  snew(dest,strlen(src)+1);
-  strcpy(dest,src);
-  
-  return dest;
-}
-
-char *
-gmx_strndup(const char *src, int n)
-{
-    int   len;
-    char *dest;
-
-    len = strlen(src);
-    if (len > n) 
-    {
-        len = n;
-    }
-    snew(dest, len+1);
-    strncpy(dest, src, len);
-    dest[len] = 0;
-    return dest;
-}
-
-/*!
- * \param[in] pattern  Pattern to match against.
- * \param[in] str      String to match.
- * \returns   0 on match, GMX_NO_WCMATCH if there is no match.
- *
- * Matches \p str against \p pattern, which may contain * and ? wildcards.
- * All other characters are matched literally.
- * Currently, it is not possible to match literal * or ?.
- */
-int
-gmx_wcmatch(const char *pattern, const char *str)
-{
-    while (*pattern)
-    {
-        if (*pattern == '*')
-        {
-            /* Skip multiple wildcards in a sequence */
-            while (*pattern == '*' || *pattern == '?')
-            {
-                ++pattern;
-                /* For ?, we need to check that there are characters left
-                 * in str. */
-                if (*pattern == '?')
-                {
-                    if (*str == 0)
-                    {
-                        return GMX_NO_WCMATCH;
-                    }
-                    else
-                    {
-                        ++str;
-                    }
-                }
-            }
-            /* If the pattern ends after the star, we have a match */
-            if (*pattern == 0)
-            {
-                return 0;
-            }
-            /* Match the rest against each possible suffix of str */
-            while (*str)
-            {
-                /* Only do the recursive call if the first character
-                 * matches. We don't have to worry about wildcards here,
-                 * since we have processed them above. */
-                if (*pattern == *str)
-                {
-                    int rc;
-                    /* Match the suffix, and return if a match or an error */
-                    rc = gmx_wcmatch(pattern, str);
-                    if (rc != GMX_NO_WCMATCH)
-                    {
-                        return rc;
-                    }
-                }
-                ++str;
-            }
-            /* If no suffix of str matches, we don't have a match */
-            return GMX_NO_WCMATCH;
-        }
-        else if ((*pattern == '?' && *str != 0) || *pattern == *str)
-        {
-            ++str;
-        }
-        else
-        {
-            return GMX_NO_WCMATCH;
-        }
-        ++pattern;
-    }
-    /* When the pattern runs out, we have a match if the string has ended. */
-    return (*str == 0) ? 0 : GMX_NO_WCMATCH;
-}
-
-char *wrap_lines(const char *buf,int line_width, int indent,gmx_bool bIndentFirst)
-{
-  char *b2;
-  int i,i0,i2,j,b2len,lspace=0,l2space=0;
-  gmx_bool bFirst,bFitsOnLine;
-
-  /* characters are copied from buf to b2 with possible spaces changed
-   * into newlines and extra space added for indentation.
-   * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
-   * i0 points to the beginning of the current line (in buf, source)
-   * lspace and l2space point to the last space on the current line
-   * bFirst is set to prevent indentation of first line
-   * bFitsOnLine says if the first space occurred before line_width, if 
-   * that is not the case, we have a word longer than line_width which 
-   * will also not fit on the next line, so we might as well keep it on 
-   * the current line (where it also won't fit, but looks better)
-   */
-  
-  b2=NULL;
-  b2len=strlen(buf)+1+indent;
-  snew(b2,b2len);
-  i0=i2=0;
-  if (bIndentFirst)
-    for(i2=0; (i2<indent); i2++)
-      b2[i2] = ' ';
-  bFirst=TRUE;
-  do {
-    l2space = -1;
-    /* find the last space before end of line */
-    for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
-      b2[i2++] = buf[i];
-      /* remember the position of a space */
-      if (buf[i] == ' ') {
-        lspace = i;
-       l2space = i2-1;
-      }
-      /* if we have a newline before the line is full, reset counters */
-      if (buf[i]=='\n' && buf[i+1]) { 
-       i0=i+1;
-       b2len+=indent;
-       srenew(b2, b2len);
-       /* add indentation after the newline */
-       for(j=0; (j<indent); j++)
-         b2[i2++]=' ';
-      }
-    }
-    /* If we are at the last newline, copy it */
-    if (buf[i]=='\n' && !buf[i+1]) {
-      b2[i2++] = buf[i++];
-    }
-    /* if we're not at the end of the string */
-    if (buf[i]) {
-      /* check if one word does not fit on the line */
-      bFitsOnLine = (i-i0 <= line_width);
-      /* reset line counters to just after the space */
-      i0 = lspace+1;
-      i2 = l2space+1;
-      /* if the words fit on the line, and we're beyond the indentation part */
-      if ( (bFitsOnLine) && (l2space >= indent) ) {
-       /* start a new line */
-       b2[l2space] = '\n';
-       /* and add indentation */
-       if (indent) {
-         if (bFirst) {
-           line_width-=indent;
-           bFirst=FALSE;
-         }
-         b2len+=indent;
-         srenew(b2, b2len);
-         for(j=0; (j<indent); j++)
-           b2[i2++]=' ';
-         /* no extra spaces after indent; */
-         while(buf[i0]==' ')
-           i0++;
-       }
-      }
-    }
-  } while (buf[i]);
-  b2[i2] = '\0';
-  
-  return b2;
-}
-
-char **split(char sep,char *str)
-{
-  char **ptr = NULL;
-  int  n,nn,nptr = 0;
-  
-  if (str == NULL)
-    return NULL;
-  nn = strlen(str);
-  for(n=0; (n<nn); n++)
-    if (str[n] == sep)
-      nptr++;
-  snew(ptr,nptr+2);
-  nptr = 0;
-  while (*str != '\0') {
-    while ((*str != '\0') && (*str == sep))
-      str++;
-    if (*str != '\0') {
-      snew(ptr[nptr],1+strlen(str));
-      n = 0;
-      while ((*str != '\0') && (*str != sep)) {
-       ptr[nptr][n] = *str;
-       str++;
-       n++;
-      }
-      ptr[nptr][n] = '\0';
-      nptr++;
-    }
-  }
-  ptr[nptr] = NULL;
-  
-  return ptr;
-}
-
-
-gmx_large_int_t
-str_to_large_int_t(const char *str, char **endptr)
-{
-       int         sign = 1;
-       gmx_large_int_t  val  = 0;
-       char        ch;
-       const char  *p;
-       
-       p = str;
-       if(p==NULL)
-       {
-               *endptr=NULL;
-               return 0;
-       }
-       
-       /* Strip off initial white space */
-       while(isspace(*p))
-       {
-               p++;
-       }
-       /* Conform to ISO C99 - return original pointer if string does not contain a number */
-       if(*str=='\0')
-       {
-               *endptr=(char *)str;
-       }
-       
-       if(*p=='-')
-       {
-               p++;
-               sign *= -1;
-       }
-       
-       while( ((ch=*p) != '\0') && isdigit(ch) )
-       {
-               /* Important to add sign here, so we dont overflow in final multiplication */
-               ch = (ch-'0')*sign; 
-               val = val*10 + ch;
-               if(ch != val%10) 
-               {
-                       /* Some sort of overflow has occured, set endptr to original string */
-                       *endptr=(char *)str;
-                       errno = ERANGE;
-                       return(0);
-               }
-               p++;
-       }
-       
-       *endptr=(char *)p;
-       
-       return val;
-}
-
-char *gmx_strsep(char **stringp, const char *delim)
-{
-    char *ret;
-    int len=strlen(delim);
-    int i,j=0;
-    int found=0;
-
-    if (! *stringp)
-        return NULL;
-    ret=*stringp;
-    do
-    {
-        if ( (*stringp)[j] == '\0')
-        {
-            found=1;
-            *stringp=NULL;
-            break;
-        }
-        for (i=0;i<len;i++)
-        {
-            if ( (*stringp)[j]==delim[i])
-            {
-                (*stringp)[j]='\0';
-                *stringp=*stringp+j+1;
-                found=1;
-                break;
-            }
-        }
-        j++;
-    } while (!found);
-
-    return ret;
-}
-
diff --git a/src/gmxlib/tpxio.c b/src/gmxlib/tpxio.c
deleted file mode 100644 (file)
index fd30a89..0000000
+++ /dev/null
@@ -1,2426 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* This file is completely threadsafe - keep it that way! */
-#ifdef GMX_THREADS
-#include <thread_mpi.h>
-#endif
-
-
-#include <ctype.h>
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "string2.h"
-#include "gmx_fatal.h"
-#include "macros.h"
-#include "names.h"
-#include "symtab.h"
-#include "futil.h"
-#include "filenm.h"
-#include "gmxfio.h"
-#include "topsort.h"
-#include "tpxio.h"
-#include "txtdump.h"
-#include "confio.h"
-#include "atomprop.h"
-#include "copyrite.h"
-#include "vec.h"
-#include "mtop_util.h"
-
-/* This number should be increased whenever the file format changes! */
-static const int tpx_version = 73;
-
-/* This number should only be increased when you edit the TOPOLOGY section
- * of the tpx format. This way we can maintain forward compatibility too
- * for all analysis tools and/or external programs that only need to
- * know the atom/residue names, charges, and bond connectivity.
- *  
- * It first appeared in tpx version 26, when I also moved the inputrecord
- * to the end of the tpx file, so we can just skip it if we only
- * want the topology.
- */
-static const int tpx_generation = 23;
-
-/* This number should be the most recent backwards incompatible version 
- * I.e., if this number is 9, we cannot read tpx version 9 with this code.
- */
-static const int tpx_incompatible_version = 9;
-
-
-
-/* Struct used to maintain tpx compatibility when function types are added */
-typedef struct {
-  int fvnr; /* file version number in which the function type first appeared */
-  int ftype; /* function type */
-} t_ftupd;
-
-/* 
- *The entries should be ordered in:
- * 1. ascending file version number
- * 2. ascending function type number
- */
-/*static const t_ftupd ftupd[] = {
-  { 20, F_CUBICBONDS        },
-  { 20, F_CONNBONDS         },
-  { 20, F_HARMONIC          },
-  { 20, F_EQM,              },
-  { 22, F_DISRESVIOL        },
-  { 22, F_ORIRES            },
-  { 22, F_ORIRESDEV         },
-  { 26, F_FOURDIHS          },
-  { 26, F_PIDIHS            },
-  { 26, F_DIHRES            },
-  { 26, F_DIHRESVIOL        },
-  { 30, F_CROSS_BOND_BONDS  },
-  { 30, F_CROSS_BOND_ANGLES },
-  { 30, F_UREY_BRADLEY      },
-  { 30, F_POLARIZATION      }
-  };*/
-  
-/* 
- *The entries should be ordered in:
- * 1. ascending function type number
- * 2. ascending file version number
- */
-static const t_ftupd ftupd[] = {
-  { 20, F_CUBICBONDS        },
-  { 20, F_CONNBONDS         },
-  { 20, F_HARMONIC          },
-  { 34, F_FENEBONDS         },
-  { 43, F_TABBONDS          },
-  { 43, F_TABBONDSNC        },
-  { 70, F_RESTRBONDS        },
-  { 30, F_CROSS_BOND_BONDS  },
-  { 30, F_CROSS_BOND_ANGLES },
-  { 30, F_UREY_BRADLEY      },
-  { 34, F_QUARTIC_ANGLES    },
-  { 43, F_TABANGLES         },
-  { 26, F_FOURDIHS          },
-  { 26, F_PIDIHS            },
-  { 43, F_TABDIHS           },
-  { 65, F_CMAP              },
-  { 60, F_GB12              },
-  { 61, F_GB13              },
-  { 61, F_GB14              }, 
-  { 72, F_GBPOL             },
-  { 72, F_NPSOLVATION       },
-  { 41, F_LJC14_Q           },
-  { 41, F_LJC_PAIRS_NB      },
-  { 32, F_BHAM_LR           },
-  { 32, F_RF_EXCL           },
-  { 32, F_COUL_RECIP        },
-  { 46, F_DPD               },
-  { 30, F_POLARIZATION      },
-  { 36, F_THOLE_POL         },
-  { 22, F_DISRESVIOL        },
-  { 22, F_ORIRES            },
-  { 22, F_ORIRESDEV         },
-  { 26, F_DIHRES            },
-  { 26, F_DIHRESVIOL        },
-  { 49, F_VSITE4FDN         },
-  { 50, F_VSITEN            },
-  { 46, F_COM_PULL          },
-  { 20, F_EQM               },
-  { 46, F_ECONSERVED        },
-  { 69, F_VTEMP             },
-  { 66, F_PDISPCORR         },
-  { 54, F_DHDL_CON          },
-};
-#define NFTUPD asize(ftupd)
-
-/* Needed for backward compatibility */
-#define MAXNODES 256
-
-static void _do_section(t_fileio *fio,int key,gmx_bool bRead,const char *src,
-                        int line)
-{
-  char buf[STRLEN];
-  gmx_bool bDbg;
-
-  if (gmx_fio_getftp(fio) == efTPA) {
-    if (!bRead) {
-      gmx_fio_write_string(fio,itemstr[key]);
-      bDbg       = gmx_fio_getdebug(fio);
-      gmx_fio_setdebug(fio,FALSE);
-      gmx_fio_write_string(fio,comment_str[key]);
-      gmx_fio_setdebug(fio,bDbg);
-    }
-    else {
-      if (gmx_fio_getdebug(fio))
-       fprintf(stderr,"Looking for section %s (%s, %d)",
-               itemstr[key],src,line);
-      
-      do {
-       gmx_fio_do_string(fio,buf);
-      } while ((gmx_strcasecmp(buf,itemstr[key]) != 0));
-      
-      if (gmx_strcasecmp(buf,itemstr[key]) != 0) 
-       gmx_fatal(FARGS,"\nCould not find section heading %s",itemstr[key]);
-      else if (gmx_fio_getdebug(fio))
-       fprintf(stderr," and found it\n");
-    }
-  }
-}
-
-#define do_section(fio,key,bRead) _do_section(fio,key,bRead,__FILE__,__LINE__)
-
-/**************************************************************
- *
- * Now the higer level routines that do io of the structures and arrays
- *
- **************************************************************/
-static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, gmx_bool bRead, 
-                       int file_version)
-{
-  gmx_bool bDum=TRUE;
-  int  i;
-
-  gmx_fio_do_int(fio,pgrp->nat);
-  if (bRead)
-    snew(pgrp->ind,pgrp->nat);
-  bDum=gmx_fio_ndo_int(fio,pgrp->ind,pgrp->nat);
-  gmx_fio_do_int(fio,pgrp->nweight);
-  if (bRead)
-    snew(pgrp->weight,pgrp->nweight);
-  bDum=gmx_fio_ndo_real(fio,pgrp->weight,pgrp->nweight);
-  gmx_fio_do_int(fio,pgrp->pbcatom);
-  gmx_fio_do_rvec(fio,pgrp->vec);
-  gmx_fio_do_rvec(fio,pgrp->init);
-  gmx_fio_do_real(fio,pgrp->rate);
-  gmx_fio_do_real(fio,pgrp->k);
-  if (file_version >= 56) {
-    gmx_fio_do_real(fio,pgrp->kB);
-  } else {
-    pgrp->kB = pgrp->k;
-  }
-}
-
-static void do_pull(t_fileio *fio, t_pull *pull,gmx_bool bRead, int file_version)
-{
-  int g;
-
-  gmx_fio_do_int(fio,pull->ngrp);
-  gmx_fio_do_int(fio,pull->eGeom);
-  gmx_fio_do_ivec(fio,pull->dim);
-  gmx_fio_do_real(fio,pull->cyl_r1);
-  gmx_fio_do_real(fio,pull->cyl_r0);
-  gmx_fio_do_real(fio,pull->constr_tol);
-  gmx_fio_do_int(fio,pull->nstxout);
-  gmx_fio_do_int(fio,pull->nstfout);
-  if (bRead)
-    snew(pull->grp,pull->ngrp+1);
-  for(g=0; g<pull->ngrp+1; g++)
-    do_pullgrp(fio,&pull->grp[g],bRead,file_version);
-}
-
-static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead, 
-                        int file_version, real *fudgeQQ)
-{
-    int  i,j,k,*tmp,idum=0; 
-    gmx_bool bDum=TRUE;
-    real rdum,bd_temp;
-    rvec vdum;
-    gmx_bool bSimAnn;
-    real zerotemptime,finish_t,init_temp,finish_temp;
-    
-    if (file_version != tpx_version)
-    {
-        /* Give a warning about features that are not accessible */
-        fprintf(stderr,"Note: tpx file_version %d, software version %d\n",
-                file_version,tpx_version);
-    }
-
-    if (bRead)
-    {
-        init_inputrec(ir);
-    }
-
-    if (file_version == 0)
-    {
-        return;
-    }
-
-    /* Basic inputrec stuff */  
-    gmx_fio_do_int(fio,ir->eI); 
-    if (file_version >= 62) {
-      gmx_fio_do_gmx_large_int(fio, ir->nsteps);
-    } else {
-      gmx_fio_do_int(fio,idum);
-      ir->nsteps = idum;
-    }
-    if(file_version > 25) {
-      if (file_version >= 62) {
-       gmx_fio_do_gmx_large_int(fio, ir->init_step);
-      } else {
-       gmx_fio_do_int(fio,idum);
-       ir->init_step = idum;
-      }
-    }  else {
-      ir->init_step=0;
-    }
-
-       if(file_version >= 58)
-         gmx_fio_do_int(fio,ir->simulation_part);
-       else
-         ir->simulation_part=1;
-         
-    if (file_version >= 67) {
-      gmx_fio_do_int(fio,ir->nstcalcenergy);
-    } else {
-      ir->nstcalcenergy = 1;
-    }
-    if (file_version < 53) {
-      /* The pbc info has been moved out of do_inputrec,
-       * since we always want it, also without reading the inputrec.
-       */
-      gmx_fio_do_int(fio,ir->ePBC);
-      if ((file_version <= 15) && (ir->ePBC == 2))
-       ir->ePBC = epbcNONE;
-      if (file_version >= 45) {
-       gmx_fio_do_int(fio,ir->bPeriodicMols);
-      } else {
-       if (ir->ePBC == 2) {
-         ir->ePBC = epbcXYZ;
-         ir->bPeriodicMols = TRUE;
-       } else {
-       ir->bPeriodicMols = FALSE;
-       }
-      }
-    }
-    gmx_fio_do_int(fio,ir->ns_type);
-    gmx_fio_do_int(fio,ir->nstlist);
-    gmx_fio_do_int(fio,ir->ndelta);
-    if (file_version < 41) {
-      gmx_fio_do_int(fio,idum);
-      gmx_fio_do_int(fio,idum);
-    }
-    if (file_version >= 45)
-      gmx_fio_do_real(fio,ir->rtpi);
-    else
-      ir->rtpi = 0.05;
-    gmx_fio_do_int(fio,ir->nstcomm); 
-    if (file_version > 34)
-      gmx_fio_do_int(fio,ir->comm_mode);
-    else if (ir->nstcomm < 0) 
-      ir->comm_mode = ecmANGULAR;
-    else
-      ir->comm_mode = ecmLINEAR;
-    ir->nstcomm = abs(ir->nstcomm);
-    
-    if(file_version > 25)
-      gmx_fio_do_int(fio,ir->nstcheckpoint);
-    else
-      ir->nstcheckpoint=0;
-    
-    gmx_fio_do_int(fio,ir->nstcgsteep); 
-
-    if(file_version>=30)
-      gmx_fio_do_int(fio,ir->nbfgscorr); 
-    else if (bRead)
-      ir->nbfgscorr = 10;
-
-    gmx_fio_do_int(fio,ir->nstlog); 
-    gmx_fio_do_int(fio,ir->nstxout); 
-    gmx_fio_do_int(fio,ir->nstvout); 
-    gmx_fio_do_int(fio,ir->nstfout); 
-    gmx_fio_do_int(fio,ir->nstenergy); 
-    gmx_fio_do_int(fio,ir->nstxtcout); 
-    if (file_version >= 59) {
-      gmx_fio_do_double(fio,ir->init_t);
-      gmx_fio_do_double(fio,ir->delta_t);
-    } else {
-      gmx_fio_do_real(fio,rdum);
-      ir->init_t = rdum;
-      gmx_fio_do_real(fio,rdum);
-      ir->delta_t = rdum;
-    }
-    gmx_fio_do_real(fio,ir->xtcprec); 
-    if (file_version < 19) {
-      gmx_fio_do_int(fio,idum); 
-      gmx_fio_do_int(fio,idum);
-    }
-    if(file_version < 18)
-      gmx_fio_do_int(fio,idum); 
-    gmx_fio_do_real(fio,ir->rlist); 
-    if (file_version >= 67) {
-      gmx_fio_do_real(fio,ir->rlistlong);
-    }
-    gmx_fio_do_int(fio,ir->coulombtype); 
-    if (file_version < 32 && ir->coulombtype == eelRF)
-      ir->coulombtype = eelRF_NEC;      
-    gmx_fio_do_real(fio,ir->rcoulomb_switch); 
-    gmx_fio_do_real(fio,ir->rcoulomb); 
-    gmx_fio_do_int(fio,ir->vdwtype);
-    gmx_fio_do_real(fio,ir->rvdw_switch); 
-    gmx_fio_do_real(fio,ir->rvdw); 
-    if (file_version < 67) {
-      ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
-    }
-    gmx_fio_do_int(fio,ir->eDispCorr); 
-    gmx_fio_do_real(fio,ir->epsilon_r);
-    if (file_version >= 37) {
-      gmx_fio_do_real(fio,ir->epsilon_rf);
-    } else {
-      if (EEL_RF(ir->coulombtype)) {
-       ir->epsilon_rf = ir->epsilon_r;
-       ir->epsilon_r  = 1.0;
-      } else {
-       ir->epsilon_rf = 1.0;
-      }
-    }
-    if (file_version >= 29)
-      gmx_fio_do_real(fio,ir->tabext);
-    else
-      ir->tabext=1.0;
-    if(file_version > 25) {
-      gmx_fio_do_int(fio,ir->gb_algorithm);
-      gmx_fio_do_int(fio,ir->nstgbradii);
-      gmx_fio_do_real(fio,ir->rgbradii);
-      gmx_fio_do_real(fio,ir->gb_saltconc);
-      gmx_fio_do_int(fio,ir->implicit_solvent);
-    } else {
-      ir->gb_algorithm=egbSTILL;
-      ir->nstgbradii=1;
-      ir->rgbradii=1.0;
-      ir->gb_saltconc=0;
-      ir->implicit_solvent=eisNO;
-    }
-       if(file_version>=55)
-       {
-               gmx_fio_do_real(fio,ir->gb_epsilon_solvent);
-               gmx_fio_do_real(fio,ir->gb_obc_alpha);
-               gmx_fio_do_real(fio,ir->gb_obc_beta);
-               gmx_fio_do_real(fio,ir->gb_obc_gamma);
-               if(file_version>=60)
-               {
-                       gmx_fio_do_real(fio,ir->gb_dielectric_offset);
-                       gmx_fio_do_int(fio,ir->sa_algorithm);
-               }
-               else
-               {
-                       ir->gb_dielectric_offset = 0.009;
-                       ir->sa_algorithm = esaAPPROX;
-               }
-               gmx_fio_do_real(fio,ir->sa_surface_tension);
-
-    /* Override sa_surface_tension if it is not changed in the mpd-file */
-    if(ir->sa_surface_tension<0)
-    {
-      if(ir->gb_algorithm==egbSTILL)
-      {
-        ir->sa_surface_tension = 0.0049 * 100 * CAL2JOULE;
-      }
-      else if(ir->gb_algorithm==egbHCT || ir->gb_algorithm==egbOBC)
-      {
-        ir->sa_surface_tension = 0.0054 * 100 * CAL2JOULE;
-      }
-    }
-    
-       }
-       else
-       {
-               /* Better use sensible values than insane (0.0) ones... */
-               ir->gb_epsilon_solvent = 80;
-               ir->gb_obc_alpha       = 1.0;
-               ir->gb_obc_beta        = 0.8;
-               ir->gb_obc_gamma       = 4.85;
-               ir->sa_surface_tension = 2.092;
-       }
-
-         
-    gmx_fio_do_int(fio,ir->nkx); 
-    gmx_fio_do_int(fio,ir->nky); 
-    gmx_fio_do_int(fio,ir->nkz);
-    gmx_fio_do_int(fio,ir->pme_order);
-    gmx_fio_do_real(fio,ir->ewald_rtol);
-
-    if (file_version >=24) 
-      gmx_fio_do_int(fio,ir->ewald_geometry);
-    else
-      ir->ewald_geometry=eewg3D;
-
-    if (file_version <=17) {
-      ir->epsilon_surface=0;
-      if (file_version==17)
-       gmx_fio_do_int(fio,idum);
-    } 
-    else
-      gmx_fio_do_real(fio,ir->epsilon_surface);
-    
-    gmx_fio_do_gmx_bool(fio,ir->bOptFFT);
-
-    gmx_fio_do_gmx_bool(fio,ir->bContinuation); 
-    gmx_fio_do_int(fio,ir->etc);
-    /* before version 18, ir->etc was a gmx_bool (ir->btc),
-     * but the values 0 and 1 still mean no and
-     * berendsen temperature coupling, respectively.
-     */
-    if (file_version >= 71)
-    {
-        gmx_fio_do_int(fio,ir->nsttcouple);
-    }
-    else
-    {
-        ir->nsttcouple = ir->nstcalcenergy;
-    }
-    if (file_version <= 15)
-    {
-        gmx_fio_do_int(fio,idum);
-    }
-    if (file_version <=17)
-    {
-        gmx_fio_do_int(fio,ir->epct); 
-        if (file_version <= 15)
-        {
-            if (ir->epct == 5)
-            {
-                ir->epct = epctSURFACETENSION;
-            }
-            gmx_fio_do_int(fio,idum);
-        }
-        ir->epct -= 1;
-        /* we have removed the NO alternative at the beginning */
-        if(ir->epct==-1)
-        {
-            ir->epc=epcNO;
-            ir->epct=epctISOTROPIC;
-        } 
-        else
-        {
-            ir->epc=epcBERENDSEN;
-        }
-    } 
-    else
-    {
-        gmx_fio_do_int(fio,ir->epc);
-        gmx_fio_do_int(fio,ir->epct);
-    }
-    if (file_version >= 71)
-    {
-        gmx_fio_do_int(fio,ir->nstpcouple);
-    }
-    else
-    {
-        ir->nstpcouple = ir->nstcalcenergy;
-    }
-    gmx_fio_do_real(fio,ir->tau_p); 
-    if (file_version <= 15) {
-      gmx_fio_do_rvec(fio,vdum);
-      clear_mat(ir->ref_p);
-      for(i=0; i<DIM; i++)
-       ir->ref_p[i][i] = vdum[i];
-    } else {
-      gmx_fio_do_rvec(fio,ir->ref_p[XX]);
-      gmx_fio_do_rvec(fio,ir->ref_p[YY]);
-      gmx_fio_do_rvec(fio,ir->ref_p[ZZ]);
-    }
-    if (file_version <= 15) {
-      gmx_fio_do_rvec(fio,vdum);
-      clear_mat(ir->compress);
-      for(i=0; i<DIM; i++)
-       ir->compress[i][i] = vdum[i];
-    } 
-    else {
-      gmx_fio_do_rvec(fio,ir->compress[XX]);
-      gmx_fio_do_rvec(fio,ir->compress[YY]);
-      gmx_fio_do_rvec(fio,ir->compress[ZZ]);
-    }
-    if (file_version >= 47) {
-      gmx_fio_do_int(fio,ir->refcoord_scaling);
-      gmx_fio_do_rvec(fio,ir->posres_com);
-      gmx_fio_do_rvec(fio,ir->posres_comB);
-    } else {
-      ir->refcoord_scaling = erscNO;
-      clear_rvec(ir->posres_com);
-      clear_rvec(ir->posres_comB);
-    }
-    if(file_version > 25)
-      gmx_fio_do_int(fio,ir->andersen_seed);
-    else
-      ir->andersen_seed=0;
-    
-    if(file_version < 26) {
-      gmx_fio_do_gmx_bool(fio,bSimAnn); 
-      gmx_fio_do_real(fio,zerotemptime);
-    }
-    
-    if (file_version < 37)
-      gmx_fio_do_real(fio,rdum); 
-
-    gmx_fio_do_real(fio,ir->shake_tol);
-    if (file_version < 54)
-      gmx_fio_do_real(fio,*fudgeQQ);
-    gmx_fio_do_int(fio,ir->efep);
-    if (file_version <= 14 && ir->efep > efepNO)
-      ir->efep = efepYES;
-    if (file_version >= 59) {
-      gmx_fio_do_double(fio, ir->init_lambda); 
-      gmx_fio_do_double(fio, ir->delta_lambda);
-    } else {
-      gmx_fio_do_real(fio,rdum);
-      ir->init_lambda = rdum;
-      gmx_fio_do_real(fio,rdum);
-      ir->delta_lambda = rdum;
-    }
-    if (file_version >= 64) {
-      gmx_fio_do_int(fio,ir->n_flambda);
-      if (bRead) {
-       snew(ir->flambda,ir->n_flambda);
-      }
-      bDum=gmx_fio_ndo_double(fio,ir->flambda,ir->n_flambda);
-    } else {
-      ir->n_flambda = 0;
-      ir->flambda   = NULL;
-    }
-    if (file_version >= 13)
-      gmx_fio_do_real(fio,ir->sc_alpha);
-    else
-      ir->sc_alpha = 0;
-    if (file_version >= 38)
-      gmx_fio_do_int(fio,ir->sc_power);
-    else
-      ir->sc_power = 2;
-    if (file_version >= 15)
-      gmx_fio_do_real(fio,ir->sc_sigma);
-    else
-      ir->sc_sigma = 0.3;
-    if (bRead)
-    {
-        if (file_version >= 71)
-        {
-            ir->sc_sigma_min = ir->sc_sigma;
-        }
-        else
-        {
-            ir->sc_sigma_min = 0;
-        }
-    }
-    if (file_version >= 64) {
-      gmx_fio_do_int(fio,ir->nstdhdl);
-    } else {
-      ir->nstdhdl = 1;
-    }
-
-    if (file_version >= 73)
-    {
-        gmx_fio_do_int(fio, ir->separate_dhdl_file);
-        gmx_fio_do_int(fio, ir->dhdl_derivatives);
-    }
-    else
-    {
-        ir->separate_dhdl_file = sepdhdlfileYES;
-        ir->dhdl_derivatives = dhdlderivativesYES;
-    }
-
-    if (file_version >= 71)
-    {
-        gmx_fio_do_int(fio,ir->dh_hist_size);
-        gmx_fio_do_double(fio,ir->dh_hist_spacing);
-    }
-    else
-    {
-        ir->dh_hist_size    = 0;
-        ir->dh_hist_spacing = 0.1;
-    }
-    if (file_version >= 57) {
-      gmx_fio_do_int(fio,ir->eDisre); 
-    }
-    gmx_fio_do_int(fio,ir->eDisreWeighting); 
-    if (file_version < 22) {
-      if (ir->eDisreWeighting == 0)
-       ir->eDisreWeighting = edrwEqual;
-      else
-       ir->eDisreWeighting = edrwConservative;
-    }
-    gmx_fio_do_gmx_bool(fio,ir->bDisreMixed); 
-    gmx_fio_do_real(fio,ir->dr_fc); 
-    gmx_fio_do_real(fio,ir->dr_tau); 
-    gmx_fio_do_int(fio,ir->nstdisreout);
-    if (file_version >= 22) {
-      gmx_fio_do_real(fio,ir->orires_fc);
-      gmx_fio_do_real(fio,ir->orires_tau);
-      gmx_fio_do_int(fio,ir->nstorireout);
-    } else {
-      ir->orires_fc = 0;
-      ir->orires_tau = 0;
-      ir->nstorireout = 0;
-    }
-    if(file_version >= 26) {
-      gmx_fio_do_real(fio,ir->dihre_fc);
-      if (file_version < 56) {
-       gmx_fio_do_real(fio,rdum);
-       gmx_fio_do_int(fio,idum);
-      }
-    } else {
-      ir->dihre_fc=0;
-    }
-
-    gmx_fio_do_real(fio,ir->em_stepsize); 
-    gmx_fio_do_real(fio,ir->em_tol); 
-    if (file_version >= 22) 
-      gmx_fio_do_gmx_bool(fio,ir->bShakeSOR);
-    else if (bRead)
-      ir->bShakeSOR = TRUE;
-    if (file_version >= 11)
-      gmx_fio_do_int(fio,ir->niter);
-    else if (bRead) {
-      ir->niter = 25;
-      fprintf(stderr,"Note: niter not in run input file, setting it to %d\n",
-             ir->niter);
-    }
-    if (file_version >= 21)
-      gmx_fio_do_real(fio,ir->fc_stepsize);
-    else
-      ir->fc_stepsize = 0;
-    gmx_fio_do_int(fio,ir->eConstrAlg);
-    gmx_fio_do_int(fio,ir->nProjOrder);
-    gmx_fio_do_real(fio,ir->LincsWarnAngle);
-    if (file_version <= 14)
-      gmx_fio_do_int(fio,idum);
-    if (file_version >=26)
-      gmx_fio_do_int(fio,ir->nLincsIter);
-    else if (bRead) {
-      ir->nLincsIter = 1;
-      fprintf(stderr,"Note: nLincsIter not in run input file, setting it to %d\n",
-             ir->nLincsIter);
-    }
-    if (file_version < 33)
-      gmx_fio_do_real(fio,bd_temp);
-    gmx_fio_do_real(fio,ir->bd_fric);
-    gmx_fio_do_int(fio,ir->ld_seed);
-    if (file_version >= 33) {
-      for(i=0; i<DIM; i++)
-       gmx_fio_do_rvec(fio,ir->deform[i]);
-    } else {
-      for(i=0; i<DIM; i++)
-       clear_rvec(ir->deform[i]);
-    }
-    if (file_version >= 14)
-      gmx_fio_do_real(fio,ir->cos_accel);
-    else if (bRead)
-      ir->cos_accel = 0;
-    gmx_fio_do_int(fio,ir->userint1); 
-    gmx_fio_do_int(fio,ir->userint2); 
-    gmx_fio_do_int(fio,ir->userint3); 
-    gmx_fio_do_int(fio,ir->userint4); 
-    gmx_fio_do_real(fio,ir->userreal1); 
-    gmx_fio_do_real(fio,ir->userreal2); 
-    gmx_fio_do_real(fio,ir->userreal3); 
-    gmx_fio_do_real(fio,ir->userreal4); 
-    
-    /* pull stuff */
-    if (file_version >= 48) {
-      gmx_fio_do_int(fio,ir->ePull);
-      if (ir->ePull != epullNO) {
-       if (bRead)
-         snew(ir->pull,1);
-       do_pull(fio, ir->pull,bRead,file_version);
-      }
-    } else {
-      ir->ePull = epullNO;
-    }
-    
-    /* grpopts stuff */
-    gmx_fio_do_int(fio,ir->opts.ngtc); 
-    if (file_version >= 69) {
-      gmx_fio_do_int(fio,ir->opts.nhchainlength);
-    } else {
-      ir->opts.nhchainlength = 1;
-    }
-    gmx_fio_do_int(fio,ir->opts.ngacc); 
-    gmx_fio_do_int(fio,ir->opts.ngfrz); 
-    gmx_fio_do_int(fio,ir->opts.ngener);
-    
-    if (bRead) {
-      snew(ir->opts.nrdf,   ir->opts.ngtc); 
-      snew(ir->opts.ref_t,  ir->opts.ngtc); 
-      snew(ir->opts.annealing, ir->opts.ngtc); 
-      snew(ir->opts.anneal_npoints, ir->opts.ngtc); 
-      snew(ir->opts.anneal_time, ir->opts.ngtc); 
-      snew(ir->opts.anneal_temp, ir->opts.ngtc); 
-      snew(ir->opts.tau_t,  ir->opts.ngtc); 
-      snew(ir->opts.nFreeze,ir->opts.ngfrz); 
-      snew(ir->opts.acc,    ir->opts.ngacc); 
-      snew(ir->opts.egp_flags,ir->opts.ngener*ir->opts.ngener);
-    } 
-    if (ir->opts.ngtc > 0) {
-      if (bRead && file_version<13) {
-       snew(tmp,ir->opts.ngtc);
-       bDum=gmx_fio_ndo_int(fio,tmp, ir->opts.ngtc);
-       for(i=0; i<ir->opts.ngtc; i++)
-         ir->opts.nrdf[i] = tmp[i];
-       sfree(tmp);
-      } else {
-       bDum=gmx_fio_ndo_real(fio,ir->opts.nrdf, ir->opts.ngtc);
-      }
-      bDum=gmx_fio_ndo_real(fio,ir->opts.ref_t,ir->opts.ngtc); 
-      bDum=gmx_fio_ndo_real(fio,ir->opts.tau_t,ir->opts.ngtc); 
-      if (file_version<33 && ir->eI==eiBD) {
-       for(i=0; i<ir->opts.ngtc; i++)
-         ir->opts.tau_t[i] = bd_temp;
-      }
-    }
-    if (ir->opts.ngfrz > 0) 
-      bDum=gmx_fio_ndo_ivec(fio,ir->opts.nFreeze,ir->opts.ngfrz);
-    if (ir->opts.ngacc > 0) 
-      gmx_fio_ndo_rvec(fio,ir->opts.acc,ir->opts.ngacc); 
-    if (file_version >= 12)
-      bDum=gmx_fio_ndo_int(fio,ir->opts.egp_flags,
-                           ir->opts.ngener*ir->opts.ngener);
-
-    if(bRead && file_version < 26) {
-      for(i=0;i<ir->opts.ngtc;i++) {
-       if(bSimAnn) {
-         ir->opts.annealing[i] = eannSINGLE;
-         ir->opts.anneal_npoints[i] = 2;
-         snew(ir->opts.anneal_time[i],2);
-         snew(ir->opts.anneal_temp[i],2);
-         /* calculate the starting/ending temperatures from reft, zerotemptime, and nsteps */
-         finish_t = ir->init_t + ir->nsteps * ir->delta_t;
-         init_temp = ir->opts.ref_t[i]*(1-ir->init_t/zerotemptime);
-         finish_temp = ir->opts.ref_t[i]*(1-finish_t/zerotemptime);
-         ir->opts.anneal_time[i][0] = ir->init_t;
-         ir->opts.anneal_time[i][1] = finish_t;
-         ir->opts.anneal_temp[i][0] = init_temp;
-         ir->opts.anneal_temp[i][1] = finish_temp;
-       } else {
-         ir->opts.annealing[i] = eannNO;
-         ir->opts.anneal_npoints[i] = 0;
-       }
-      }
-    } else {
-      /* file version 26 or later */
-      /* First read the lists with annealing and npoints for each group */
-      bDum=gmx_fio_ndo_int(fio,ir->opts.annealing,ir->opts.ngtc);
-      bDum=gmx_fio_ndo_int(fio,ir->opts.anneal_npoints,ir->opts.ngtc);
-      for(j=0;j<(ir->opts.ngtc);j++) {
-       k=ir->opts.anneal_npoints[j];
-       if(bRead) {
-         snew(ir->opts.anneal_time[j],k);
-         snew(ir->opts.anneal_temp[j],k);
-       }
-       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_time[j],k);
-       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_temp[j],k);
-      }
-    }
-    /* Walls */
-    if (file_version >= 45) {
-      gmx_fio_do_int(fio,ir->nwall);
-      gmx_fio_do_int(fio,ir->wall_type);
-      if (file_version >= 50)
-       gmx_fio_do_real(fio,ir->wall_r_linpot);
-      else
-       ir->wall_r_linpot = -1;
-      gmx_fio_do_int(fio,ir->wall_atomtype[0]);
-      gmx_fio_do_int(fio,ir->wall_atomtype[1]);
-      gmx_fio_do_real(fio,ir->wall_density[0]);
-      gmx_fio_do_real(fio,ir->wall_density[1]);
-      gmx_fio_do_real(fio,ir->wall_ewald_zfac);
-    } else {
-      ir->nwall = 0;
-      ir->wall_type = 0;
-      ir->wall_atomtype[0] = -1;
-      ir->wall_atomtype[1] = -1;
-      ir->wall_density[0] = 0;
-      ir->wall_density[1] = 0;
-      ir->wall_ewald_zfac = 3;
-    }
-    /* Cosine stuff for electric fields */
-    for(j=0; (j<DIM); j++) {
-      gmx_fio_do_int(fio,ir->ex[j].n);
-      gmx_fio_do_int(fio,ir->et[j].n);
-      if (bRead) {
-       snew(ir->ex[j].a,  ir->ex[j].n);
-       snew(ir->ex[j].phi,ir->ex[j].n);
-       snew(ir->et[j].a,  ir->et[j].n);
-       snew(ir->et[j].phi,ir->et[j].n);
-      }
-      bDum=gmx_fio_ndo_real(fio,ir->ex[j].a,  ir->ex[j].n);
-      bDum=gmx_fio_ndo_real(fio,ir->ex[j].phi,ir->ex[j].n);
-      bDum=gmx_fio_ndo_real(fio,ir->et[j].a,  ir->et[j].n);
-      bDum=gmx_fio_ndo_real(fio,ir->et[j].phi,ir->et[j].n);
-    }
-    
-    /* QMMM stuff */
-    if(file_version>=39){
-      gmx_fio_do_gmx_bool(fio,ir->bQMMM);
-      gmx_fio_do_int(fio,ir->QMMMscheme);
-      gmx_fio_do_real(fio,ir->scalefactor);
-      gmx_fio_do_int(fio,ir->opts.ngQM);
-      if (bRead) {
-        snew(ir->opts.QMmethod,    ir->opts.ngQM);
-        snew(ir->opts.QMbasis,     ir->opts.ngQM);
-        snew(ir->opts.QMcharge,    ir->opts.ngQM);
-        snew(ir->opts.QMmult,      ir->opts.ngQM);
-        snew(ir->opts.bSH,         ir->opts.ngQM);
-        snew(ir->opts.CASorbitals, ir->opts.ngQM);
-        snew(ir->opts.CASelectrons,ir->opts.ngQM);
-        snew(ir->opts.SAon,        ir->opts.ngQM);
-        snew(ir->opts.SAoff,       ir->opts.ngQM);
-        snew(ir->opts.SAsteps,     ir->opts.ngQM);
-        snew(ir->opts.bOPT,        ir->opts.ngQM);
-        snew(ir->opts.bTS,         ir->opts.ngQM);
-      }
-      if (ir->opts.ngQM > 0) {
-        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmethod,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.QMbasis,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.QMcharge,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmult,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bSH,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.CASorbitals,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.CASelectrons,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_real(fio,ir->opts.SAon,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_real(fio,ir->opts.SAoff,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_int(fio,ir->opts.SAsteps,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bOPT,ir->opts.ngQM);
-        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bTS,ir->opts.ngQM);
-      }
-      /* end of QMMM stuff */
-    }    
-}
-
-
-static void do_harm(t_fileio *fio, t_iparams *iparams,gmx_bool bRead)
-{
-  gmx_fio_do_real(fio,iparams->harmonic.rA);
-  gmx_fio_do_real(fio,iparams->harmonic.krA);
-  gmx_fio_do_real(fio,iparams->harmonic.rB);
-  gmx_fio_do_real(fio,iparams->harmonic.krB);
-}
-
-void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
-                gmx_bool bRead, int file_version)
-{
-  int i;
-  gmx_bool bDum;
-  real rdum;
-  
-  if (!bRead)
-    gmx_fio_set_comment(fio, interaction_function[ftype].name);
-  switch (ftype) {
-  case F_ANGLES:
-  case F_G96ANGLES:
-  case F_BONDS:
-  case F_G96BONDS:
-  case F_HARMONIC:
-  case F_IDIHS:
-    do_harm(fio, iparams,bRead);
-    if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && bRead) {
-      /* Correct incorrect storage of parameters */
-      iparams->pdihs.phiB = iparams->pdihs.phiA;
-      iparams->pdihs.cpB  = iparams->pdihs.cpA;
-    }
-    break;
-  case F_FENEBONDS:
-    gmx_fio_do_real(fio,iparams->fene.bm);
-    gmx_fio_do_real(fio,iparams->fene.kb);
-    break;
-  case F_RESTRBONDS:
-    gmx_fio_do_real(fio,iparams->restraint.lowA);
-    gmx_fio_do_real(fio,iparams->restraint.up1A);
-    gmx_fio_do_real(fio,iparams->restraint.up2A);
-    gmx_fio_do_real(fio,iparams->restraint.kA);
-    gmx_fio_do_real(fio,iparams->restraint.lowB);
-    gmx_fio_do_real(fio,iparams->restraint.up1B);
-    gmx_fio_do_real(fio,iparams->restraint.up2B);
-    gmx_fio_do_real(fio,iparams->restraint.kB);
-    break;
-  case F_TABBONDS:
-  case F_TABBONDSNC:
-  case F_TABANGLES:
-  case F_TABDIHS:
-    gmx_fio_do_real(fio,iparams->tab.kA);
-    gmx_fio_do_int(fio,iparams->tab.table);
-    gmx_fio_do_real(fio,iparams->tab.kB);
-    break;
-  case F_CROSS_BOND_BONDS:
-    gmx_fio_do_real(fio,iparams->cross_bb.r1e);
-    gmx_fio_do_real(fio,iparams->cross_bb.r2e);
-    gmx_fio_do_real(fio,iparams->cross_bb.krr);
-    break;
-  case F_CROSS_BOND_ANGLES:
-    gmx_fio_do_real(fio,iparams->cross_ba.r1e);
-    gmx_fio_do_real(fio,iparams->cross_ba.r2e);
-    gmx_fio_do_real(fio,iparams->cross_ba.r3e);
-    gmx_fio_do_real(fio,iparams->cross_ba.krt);
-    break;
-  case F_UREY_BRADLEY:
-    gmx_fio_do_real(fio,iparams->u_b.theta);
-    gmx_fio_do_real(fio,iparams->u_b.ktheta);
-    gmx_fio_do_real(fio,iparams->u_b.r13);
-    gmx_fio_do_real(fio,iparams->u_b.kUB);
-    break;
-  case F_QUARTIC_ANGLES:
-    gmx_fio_do_real(fio,iparams->qangle.theta);
-    bDum=gmx_fio_ndo_real(fio,iparams->qangle.c,5);
-    break;
-  case F_BHAM:
-    gmx_fio_do_real(fio,iparams->bham.a);
-    gmx_fio_do_real(fio,iparams->bham.b);
-    gmx_fio_do_real(fio,iparams->bham.c);
-    break;
-  case F_MORSE:
-    gmx_fio_do_real(fio,iparams->morse.b0);
-    gmx_fio_do_real(fio,iparams->morse.cb);
-    gmx_fio_do_real(fio,iparams->morse.beta);
-    break;
-  case F_CUBICBONDS:
-    gmx_fio_do_real(fio,iparams->cubic.b0);
-    gmx_fio_do_real(fio,iparams->cubic.kb);
-    gmx_fio_do_real(fio,iparams->cubic.kcub);
-    break;
-  case F_CONNBONDS:
-    break;
-  case F_POLARIZATION:
-    gmx_fio_do_real(fio,iparams->polarize.alpha);
-    break;
-  case F_WATER_POL:
-    if (file_version < 31) 
-      gmx_fatal(FARGS,"Old tpr files with water_polarization not supported. Make a new.");
-    gmx_fio_do_real(fio,iparams->wpol.al_x);
-    gmx_fio_do_real(fio,iparams->wpol.al_y);
-    gmx_fio_do_real(fio,iparams->wpol.al_z);
-    gmx_fio_do_real(fio,iparams->wpol.rOH);
-    gmx_fio_do_real(fio,iparams->wpol.rHH);
-    gmx_fio_do_real(fio,iparams->wpol.rOD);
-    break;
-  case F_THOLE_POL:
-    gmx_fio_do_real(fio,iparams->thole.a);
-    gmx_fio_do_real(fio,iparams->thole.alpha1);
-    gmx_fio_do_real(fio,iparams->thole.alpha2);
-    gmx_fio_do_real(fio,iparams->thole.rfac);
-    break;
-  case F_LJ:
-    gmx_fio_do_real(fio,iparams->lj.c6);
-    gmx_fio_do_real(fio,iparams->lj.c12);
-    break;
-  case F_LJ14:
-    gmx_fio_do_real(fio,iparams->lj14.c6A);
-    gmx_fio_do_real(fio,iparams->lj14.c12A);
-    gmx_fio_do_real(fio,iparams->lj14.c6B);
-    gmx_fio_do_real(fio,iparams->lj14.c12B);
-    break;
-  case F_LJC14_Q:
-    gmx_fio_do_real(fio,iparams->ljc14.fqq);
-    gmx_fio_do_real(fio,iparams->ljc14.qi);
-    gmx_fio_do_real(fio,iparams->ljc14.qj);
-    gmx_fio_do_real(fio,iparams->ljc14.c6);
-    gmx_fio_do_real(fio,iparams->ljc14.c12);
-    break;
-  case F_LJC_PAIRS_NB:
-    gmx_fio_do_real(fio,iparams->ljcnb.qi);
-    gmx_fio_do_real(fio,iparams->ljcnb.qj);
-    gmx_fio_do_real(fio,iparams->ljcnb.c6);
-    gmx_fio_do_real(fio,iparams->ljcnb.c12);
-    break;
-  case F_PDIHS:
-  case F_PIDIHS:
-  case F_ANGRES:
-  case F_ANGRESZ:
-    gmx_fio_do_real(fio,iparams->pdihs.phiA);
-    gmx_fio_do_real(fio,iparams->pdihs.cpA);
-    if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && file_version < 42) {
-      /* Read the incorrectly stored multiplicity */
-      gmx_fio_do_real(fio,iparams->harmonic.rB);
-      gmx_fio_do_real(fio,iparams->harmonic.krB);
-      iparams->pdihs.phiB = iparams->pdihs.phiA;
-      iparams->pdihs.cpB  = iparams->pdihs.cpA;
-    } else {
-      gmx_fio_do_real(fio,iparams->pdihs.phiB);
-      gmx_fio_do_real(fio,iparams->pdihs.cpB);
-      gmx_fio_do_int(fio,iparams->pdihs.mult);
-    }
-    break;
-  case F_DISRES:
-    gmx_fio_do_int(fio,iparams->disres.label);
-    gmx_fio_do_int(fio,iparams->disres.type);
-    gmx_fio_do_real(fio,iparams->disres.low);
-    gmx_fio_do_real(fio,iparams->disres.up1);
-    gmx_fio_do_real(fio,iparams->disres.up2);
-    gmx_fio_do_real(fio,iparams->disres.kfac);
-    break;
-  case F_ORIRES:
-    gmx_fio_do_int(fio,iparams->orires.ex);
-    gmx_fio_do_int(fio,iparams->orires.label);
-    gmx_fio_do_int(fio,iparams->orires.power);
-    gmx_fio_do_real(fio,iparams->orires.c);
-    gmx_fio_do_real(fio,iparams->orires.obs);
-    gmx_fio_do_real(fio,iparams->orires.kfac);
-    break;
-  case F_DIHRES:
-    gmx_fio_do_int(fio,iparams->dihres.power);
-    gmx_fio_do_int(fio,iparams->dihres.label);
-    gmx_fio_do_real(fio,iparams->dihres.phi);
-    gmx_fio_do_real(fio,iparams->dihres.dphi);
-    gmx_fio_do_real(fio,iparams->dihres.kfac);
-    break;
-  case F_POSRES:
-    gmx_fio_do_rvec(fio,iparams->posres.pos0A);
-    gmx_fio_do_rvec(fio,iparams->posres.fcA);
-    if (bRead && file_version < 27) {
-      copy_rvec(iparams->posres.pos0A,iparams->posres.pos0B);
-      copy_rvec(iparams->posres.fcA,iparams->posres.fcB);
-    } else {
-      gmx_fio_do_rvec(fio,iparams->posres.pos0B);
-      gmx_fio_do_rvec(fio,iparams->posres.fcB);
-    }
-    break;
-  case F_RBDIHS:
-    bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA,NR_RBDIHS);
-    if(file_version>=25) 
-      bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB,NR_RBDIHS);
-    break;
-  case F_FOURDIHS:
-    /* Fourier dihedrals are internally represented
-     * as Ryckaert-Bellemans since those are faster to compute.
-     */
-     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA, NR_RBDIHS);
-     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB, NR_RBDIHS);
-    break;
-  case F_CONSTR:
-  case F_CONSTRNC:
-    gmx_fio_do_real(fio,iparams->constr.dA);
-    gmx_fio_do_real(fio,iparams->constr.dB);
-    break;
-  case F_SETTLE:
-    gmx_fio_do_real(fio,iparams->settle.doh);
-    gmx_fio_do_real(fio,iparams->settle.dhh);
-    break;
-  case F_VSITE2:
-    gmx_fio_do_real(fio,iparams->vsite.a);
-    break;
-  case F_VSITE3:
-  case F_VSITE3FD:
-  case F_VSITE3FAD:
-    gmx_fio_do_real(fio,iparams->vsite.a);
-    gmx_fio_do_real(fio,iparams->vsite.b);
-    break;
-  case F_VSITE3OUT:
-  case F_VSITE4FD: 
-  case F_VSITE4FDN: 
-    gmx_fio_do_real(fio,iparams->vsite.a);
-    gmx_fio_do_real(fio,iparams->vsite.b);
-    gmx_fio_do_real(fio,iparams->vsite.c);
-    break;
-  case F_VSITEN:
-    gmx_fio_do_int(fio,iparams->vsiten.n);
-    gmx_fio_do_real(fio,iparams->vsiten.a);
-    break;
-  case F_GB12:
-  case F_GB13:
-  case F_GB14:
-    /* We got rid of some parameters in version 68 */
-    if(bRead && file_version<68)
-    {
-        gmx_fio_do_real(fio,rdum);     
-        gmx_fio_do_real(fio,rdum);     
-        gmx_fio_do_real(fio,rdum);     
-        gmx_fio_do_real(fio,rdum);     
-    }
-       gmx_fio_do_real(fio,iparams->gb.sar);   
-       gmx_fio_do_real(fio,iparams->gb.st);
-       gmx_fio_do_real(fio,iparams->gb.pi);
-       gmx_fio_do_real(fio,iparams->gb.gbr);
-       gmx_fio_do_real(fio,iparams->gb.bmlt);
-       break;
-  case F_CMAP:
-       gmx_fio_do_int(fio,iparams->cmap.cmapA);
-       gmx_fio_do_int(fio,iparams->cmap.cmapB);
-    break;
-  default:
-    gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
-               
-               ftype,interaction_function[ftype].name,__FILE__,__LINE__);
-  }
-  if (!bRead)
-    gmx_fio_unset_comment(fio);
-}
-
-static void do_ilist(t_fileio *fio, t_ilist *ilist,gmx_bool bRead,int file_version,
-                    int ftype)
-{
-  int  i,k,idum;
-  gmx_bool bDum=TRUE;
-  
-  if (!bRead) {
-    gmx_fio_set_comment(fio, interaction_function[ftype].name);
-  }
-  if (file_version < 44) {
-    for(i=0; i<MAXNODES; i++)
-      gmx_fio_do_int(fio,idum);
-  }
-  gmx_fio_do_int(fio,ilist->nr);
-  if (bRead)
-    snew(ilist->iatoms,ilist->nr);
-  bDum=gmx_fio_ndo_int(fio,ilist->iatoms,ilist->nr);
-  if (!bRead)
-    gmx_fio_unset_comment(fio);
-}
-
-static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
-                       gmx_bool bRead, int file_version)
-{
-  int  idum,i,j;
-  gmx_bool bDum=TRUE;
-  unsigned int k;
-
-  gmx_fio_do_int(fio,ffparams->atnr);
-  if (file_version < 57) {
-    gmx_fio_do_int(fio,idum);
-  }
-  gmx_fio_do_int(fio,ffparams->ntypes);
-  if (bRead && debug)
-    fprintf(debug,"ffparams->atnr = %d, ntypes = %d\n",
-           ffparams->atnr,ffparams->ntypes);
-  if (bRead) {
-    snew(ffparams->functype,ffparams->ntypes);
-    snew(ffparams->iparams,ffparams->ntypes);
-  }
-  /* Read/write all the function types */
-  bDum=gmx_fio_ndo_int(fio,ffparams->functype,ffparams->ntypes);
-  if (bRead && debug)
-    pr_ivec(debug,0,"functype",ffparams->functype,ffparams->ntypes,TRUE);
-
-  if (file_version >= 66) {
-    gmx_fio_do_double(fio,ffparams->reppow);
-  } else {
-    ffparams->reppow = 12.0;
-  }
-
-  if (file_version >= 57) {
-    gmx_fio_do_real(fio,ffparams->fudgeQQ);
-  }
-
-  /* Check whether all these function types are supported by the code.
-   * In practice the code is backwards compatible, which means that the
-   * numbering may have to be altered from old numbering to new numbering
-   */
-  for (i=0; (i<ffparams->ntypes); i++) {
-    if (bRead)
-      /* Loop over file versions */
-      for (k=0; (k<NFTUPD); k++)
-       /* Compare the read file_version to the update table */
-       if ((file_version < ftupd[k].fvnr) && 
-           (ffparams->functype[i] >= ftupd[k].ftype)) {
-         ffparams->functype[i] += 1;
-         if (debug) {
-           fprintf(debug,"Incrementing function type %d to %d (due to %s)\n",
-                   i,ffparams->functype[i],
-                   interaction_function[ftupd[k].ftype].longname);
-           fflush(debug);
-         }
-       }
-    
-    do_iparams(fio, ffparams->functype[i],&ffparams->iparams[i],bRead,
-               file_version);
-    if (bRead && debug)
-      pr_iparams(debug,ffparams->functype[i],&ffparams->iparams[i]);
-  }
-}
-
-static void do_ilists(t_fileio *fio, t_ilist *ilist,gmx_bool bRead, 
-                      int file_version)
-{
-  int i,j,renum[F_NRE];
-  gmx_bool bDum=TRUE,bClear;
-  unsigned int k;
-  
-  for(j=0; (j<F_NRE); j++) {
-    bClear = FALSE;
-    if (bRead)
-      for (k=0; k<NFTUPD; k++)
-       if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype))
-         bClear = TRUE;
-    if (bClear) {
-      ilist[j].nr = 0;
-      ilist[j].iatoms = NULL;
-    } else {
-      do_ilist(fio, &ilist[j],bRead,file_version,j);
-    }
-    /*
-    if (bRead && gmx_debug_at)
-      pr_ilist(debug,0,interaction_function[j].longname,
-              functype,&ilist[j],TRUE);
-    */
-  }
-}
-
-static void do_idef(t_fileio *fio, gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
-                   gmx_bool bRead, int file_version)
-{
-  do_ffparams(fio, ffparams,bRead,file_version);
-    
-  if (file_version >= 54) {
-    gmx_fio_do_real(fio,ffparams->fudgeQQ);
-  }
-
-  do_ilists(fio, molt->ilist,bRead,file_version);
-}
-
-static void do_block(t_fileio *fio, t_block *block,gmx_bool bRead,int file_version)
-{
-  int  i,idum,dum_nra,*dum_a;
-  gmx_bool bDum=TRUE;
-
-  if (file_version < 44)
-    for(i=0; i<MAXNODES; i++)
-      gmx_fio_do_int(fio,idum);
-  gmx_fio_do_int(fio,block->nr);
-  if (file_version < 51)
-    gmx_fio_do_int(fio,dum_nra);
-  if (bRead) {
-    block->nalloc_index = block->nr+1;
-    snew(block->index,block->nalloc_index);
-  }
-  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
-
-  if (file_version < 51 && dum_nra > 0) {
-    snew(dum_a,dum_nra);
-    bDum=gmx_fio_ndo_int(fio,dum_a,dum_nra);
-    sfree(dum_a);
-  }
-}
-
-static void do_blocka(t_fileio *fio, t_blocka *block,gmx_bool bRead,
-                      int file_version)
-{
-  int  i,idum;
-  gmx_bool bDum=TRUE;
-
-  if (file_version < 44)
-    for(i=0; i<MAXNODES; i++)
-      gmx_fio_do_int(fio,idum);
-  gmx_fio_do_int(fio,block->nr);
-  gmx_fio_do_int(fio,block->nra);
-  if (bRead) {
-    block->nalloc_index = block->nr+1;
-    snew(block->index,block->nalloc_index);
-    block->nalloc_a = block->nra;
-    snew(block->a,block->nalloc_a);
-  }
-  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
-  bDum=gmx_fio_ndo_int(fio,block->a,block->nra);
-}
-
-static void do_atom(t_fileio *fio, t_atom *atom,int ngrp,gmx_bool bRead, 
-                    int file_version, gmx_groups_t *groups,int atnr)
-{ 
-  int i,myngrp;
-  
-  gmx_fio_do_real(fio,atom->m);
-  gmx_fio_do_real(fio,atom->q);
-  gmx_fio_do_real(fio,atom->mB);
-  gmx_fio_do_real(fio,atom->qB);
-  gmx_fio_do_ushort(fio, atom->type);
-  gmx_fio_do_ushort(fio, atom->typeB);
-  gmx_fio_do_int(fio,atom->ptype);
-  gmx_fio_do_int(fio,atom->resind);
-  if (file_version >= 52)
-    gmx_fio_do_int(fio,atom->atomnumber);
-  else if (bRead)
-    atom->atomnumber = NOTSET;
-  if (file_version < 23) 
-    myngrp = 8;
-  else if (file_version < 39) 
-    myngrp = 9;
-  else
-    myngrp = ngrp;
-
-  if (file_version < 57) {
-    unsigned char uchar[egcNR];
-    gmx_fio_ndo_uchar(fio,uchar,myngrp);
-    for(i=myngrp; (i<ngrp); i++) {
-      uchar[i] = 0;
-    }
-    /* Copy the old data format to the groups struct */
-    for(i=0; i<ngrp; i++) {
-      groups->grpnr[i][atnr] = uchar[i];
-    }
-  }
-}
-
-static void do_grps(t_fileio *fio, int ngrp,t_grps grps[],gmx_bool bRead, 
-                    int file_version)
-{
-  int i,j,myngrp;
-  gmx_bool bDum=TRUE;
-  
-  if (file_version < 23) 
-    myngrp = 8;
-  else if (file_version < 39) 
-    myngrp = 9;
-  else
-    myngrp = ngrp;
-
-  for(j=0; (j<ngrp); j++) {
-    if (j<myngrp) {
-      gmx_fio_do_int(fio,grps[j].nr);
-      if (bRead)
-       snew(grps[j].nm_ind,grps[j].nr);
-      bDum=gmx_fio_ndo_int(fio,grps[j].nm_ind,grps[j].nr);
-    }
-    else {
-      grps[j].nr = 1;
-      snew(grps[j].nm_ind,grps[j].nr);
-    }
-  }
-}
-
-static void do_symstr(t_fileio *fio, char ***nm,gmx_bool bRead,t_symtab *symtab)
-{
-  int ls;
-  
-  if (bRead) {
-    gmx_fio_do_int(fio,ls);
-    *nm = get_symtab_handle(symtab,ls);
-  }
-  else {
-    ls = lookup_symtab(symtab,*nm);
-    gmx_fio_do_int(fio,ls);
-  }
-}
-
-static void do_strstr(t_fileio *fio, int nstr,char ***nm,gmx_bool bRead,
-                      t_symtab *symtab)
-{
-  int  j;
-  
-  for (j=0; (j<nstr); j++) 
-    do_symstr(fio, &(nm[j]),bRead,symtab);
-}
-
-static void do_resinfo(t_fileio *fio, int n,t_resinfo *ri,gmx_bool bRead,
-                       t_symtab *symtab, int file_version)
-{
-  int  j;
-  
-  for (j=0; (j<n); j++) {
-    do_symstr(fio, &(ri[j].name),bRead,symtab);
-    if (file_version >= 63) {
-      gmx_fio_do_int(fio,ri[j].nr);
-      gmx_fio_do_uchar(fio, ri[j].ic);
-    } else {
-      ri[j].nr = j + 1;
-      ri[j].ic = ' ';
-    }
-  }
-}
-
-static void do_atoms(t_fileio *fio, t_atoms *atoms,gmx_bool bRead,t_symtab *symtab,
-                    int file_version,
-                    gmx_groups_t *groups)
-{
-  int i;
-  
-  gmx_fio_do_int(fio,atoms->nr);
-  gmx_fio_do_int(fio,atoms->nres);
-  if (file_version < 57) {
-    gmx_fio_do_int(fio,groups->ngrpname);
-    for(i=0; i<egcNR; i++) {
-      groups->ngrpnr[i] = atoms->nr;
-      snew(groups->grpnr[i],groups->ngrpnr[i]);
-    }
-  }
-  if (bRead) {
-    snew(atoms->atom,atoms->nr);
-    snew(atoms->atomname,atoms->nr);
-    snew(atoms->atomtype,atoms->nr);
-    snew(atoms->atomtypeB,atoms->nr);
-    snew(atoms->resinfo,atoms->nres);
-    if (file_version < 57) {
-      snew(groups->grpname,groups->ngrpname);
-    }
-    atoms->pdbinfo = NULL;
-  }
-  for(i=0; (i<atoms->nr); i++) {
-    do_atom(fio, &atoms->atom[i],egcNR,bRead, file_version,groups,i);
-  }
-  do_strstr(fio, atoms->nr,atoms->atomname,bRead,symtab);
-  if (bRead && (file_version <= 20)) {
-    for(i=0; i<atoms->nr; i++) {
-      atoms->atomtype[i]  = put_symtab(symtab,"?");
-      atoms->atomtypeB[i] = put_symtab(symtab,"?");
-    }
-  } else {
-    do_strstr(fio, atoms->nr,atoms->atomtype,bRead,symtab);
-    do_strstr(fio, atoms->nr,atoms->atomtypeB,bRead,symtab);
-  }
-  do_resinfo(fio, atoms->nres,atoms->resinfo,bRead,symtab,file_version);
-
-  if (file_version < 57) {
-    do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
-  
-    do_grps(fio, egcNR,groups->grps,bRead,file_version);
-  }
-}
-
-static void do_groups(t_fileio *fio, gmx_groups_t *groups,
-                     gmx_bool bRead,t_symtab *symtab,
-                     int file_version)
-{
-  int  g,n,i;
-  gmx_bool bDum=TRUE;
-
-  do_grps(fio, egcNR,groups->grps,bRead,file_version);
-  gmx_fio_do_int(fio,groups->ngrpname);
-  if (bRead) {
-    snew(groups->grpname,groups->ngrpname);
-  }
-  do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
-  for(g=0; g<egcNR; g++) {
-    gmx_fio_do_int(fio,groups->ngrpnr[g]);
-    if (groups->ngrpnr[g] == 0) {
-      if (bRead) {
-       groups->grpnr[g] = NULL;
-      }
-    } else {
-      if (bRead) {
-       snew(groups->grpnr[g],groups->ngrpnr[g]);
-      }
-      bDum=gmx_fio_ndo_uchar(fio, groups->grpnr[g],groups->ngrpnr[g]);
-    }
-  }
-}
-
-static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes,gmx_bool bRead,
-                        t_symtab *symtab,int file_version)
-{
-  int i,j;
-  gmx_bool bDum = TRUE;
-  
-  if (file_version > 25) {
-    gmx_fio_do_int(fio,atomtypes->nr);
-    j=atomtypes->nr;
-    if (bRead) {
-      snew(atomtypes->radius,j);
-      snew(atomtypes->vol,j);
-      snew(atomtypes->surftens,j);
-      snew(atomtypes->atomnumber,j);
-      snew(atomtypes->gb_radius,j);
-      snew(atomtypes->S_hct,j);
-    }
-    bDum=gmx_fio_ndo_real(fio,atomtypes->radius,j);
-    bDum=gmx_fio_ndo_real(fio,atomtypes->vol,j);
-    bDum=gmx_fio_ndo_real(fio,atomtypes->surftens,j);
-    if(file_version >= 40)
-    {
-        bDum=gmx_fio_ndo_int(fio,atomtypes->atomnumber,j);
-    }
-       if(file_version >= 60)
-       {
-               bDum=gmx_fio_ndo_real(fio,atomtypes->gb_radius,j);
-               bDum=gmx_fio_ndo_real(fio,atomtypes->S_hct,j);
-       }
-  } else {
-    /* File versions prior to 26 cannot do GBSA, 
-     * so they dont use this structure 
-     */
-    atomtypes->nr = 0;
-    atomtypes->radius = NULL;
-    atomtypes->vol = NULL;
-    atomtypes->surftens = NULL;
-    atomtypes->atomnumber = NULL;
-    atomtypes->gb_radius = NULL;
-    atomtypes->S_hct = NULL;
-  }  
-}
-
-static void do_symtab(t_fileio *fio, t_symtab *symtab,gmx_bool bRead)
-{
-  int i,nr;
-  t_symbuf *symbuf;
-  char buf[STRLEN];
-  
-  gmx_fio_do_int(fio,symtab->nr);
-  nr     = symtab->nr;
-  if (bRead) {
-    snew(symtab->symbuf,1);
-    symbuf = symtab->symbuf;
-    symbuf->bufsize = nr;
-    snew(symbuf->buf,nr);
-    for (i=0; (i<nr); i++) {
-      gmx_fio_do_string(fio,buf);
-      symbuf->buf[i]=strdup(buf);
-    }
-  }
-  else {
-    symbuf = symtab->symbuf;
-    while (symbuf!=NULL) {
-      for (i=0; (i<symbuf->bufsize) && (i<nr); i++) 
-       gmx_fio_do_string(fio,symbuf->buf[i]);
-      nr-=i;
-      symbuf=symbuf->next;
-    }
-    if (nr != 0)
-      gmx_fatal(FARGS,"nr of symtab strings left: %d",nr);
-  }
-}
-
-static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, gmx_bool bRead)
-{
-       int i,j,ngrid,gs,nelem;
-       
-       gmx_fio_do_int(fio,cmap_grid->ngrid);
-       gmx_fio_do_int(fio,cmap_grid->grid_spacing);
-       
-       ngrid = cmap_grid->ngrid;
-       gs    = cmap_grid->grid_spacing;
-       nelem = gs * gs;
-       
-       if(bRead)
-       {
-               snew(cmap_grid->cmapdata,ngrid);
-               
-               for(i=0;i<cmap_grid->ngrid;i++)
-               {
-                       snew(cmap_grid->cmapdata[i].cmap,4*nelem);
-               }
-       }
-       
-       for(i=0;i<cmap_grid->ngrid;i++)
-       {
-               for(j=0;j<nelem;j++)
-               {
-                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4]);
-                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+1]);
-                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+2]);
-                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+3]);
-               }
-       }       
-}
-
-
-void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
-{
-    int m,a,a0,a1,r;
-    char c,chainid;
-    int  chainnum;
-    
-    /* We always assign a new chain number, but save the chain id characters 
-     * for larger molecules.
-     */
-#define CHAIN_MIN_ATOMS 15
-    
-    chainnum=0;
-    chainid='A';
-    for(m=0; m<mols->nr; m++) 
-    {
-        a0=mols->index[m];
-        a1=mols->index[m+1];
-        if ((a1-a0 >= CHAIN_MIN_ATOMS) && (chainid <= 'Z')) 
-        {
-            c=chainid;
-            chainid++;
-        } 
-        else
-        {
-            c=' ';
-        }
-        for(a=a0; a<a1; a++) 
-        {
-            atoms->resinfo[atoms->atom[a].resind].chainnum = chainnum;
-            atoms->resinfo[atoms->atom[a].resind].chainid  = c;
-        }
-        chainnum++;
-    }
-    
-    /* Blank out the chain id if there was only one chain */
-    if (chainid == 'B') 
-    {
-        for(r=0; r<atoms->nres; r++) 
-        {
-            atoms->resinfo[r].chainid = ' ';
-        }
-    }
-}
-  
-static void do_moltype(t_fileio *fio, gmx_moltype_t *molt,gmx_bool bRead,
-                       t_symtab *symtab, int file_version,
-                      gmx_groups_t *groups)
-{
-  int i;
-
-  if (file_version >= 57) {
-    do_symstr(fio, &(molt->name),bRead,symtab);
-  }
-
-  do_atoms(fio, &molt->atoms, bRead, symtab, file_version, groups);
-
-  if (bRead && gmx_debug_at) {
-    pr_atoms(debug,0,"atoms",&molt->atoms,TRUE);
-  }
-  
-  if (file_version >= 57) {
-    do_ilists(fio, molt->ilist,bRead,file_version);
-
-    do_block(fio, &molt->cgs,bRead,file_version);
-    if (bRead && gmx_debug_at) {
-      pr_block(debug,0,"cgs",&molt->cgs,TRUE);
-    }
-  }
-
-  /* This used to be in the atoms struct */
-  do_blocka(fio, &molt->excls, bRead, file_version);
-}
-
-static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,gmx_bool bRead,
-                        int file_version)
-{
-  int i;
-
-  gmx_fio_do_int(fio,molb->type);
-  gmx_fio_do_int(fio,molb->nmol);
-  gmx_fio_do_int(fio,molb->natoms_mol);
-  /* Position restraint coordinates */
-  gmx_fio_do_int(fio,molb->nposres_xA);
-  if (molb->nposres_xA > 0) {
-    if (bRead) {
-      snew(molb->posres_xA,molb->nposres_xA);
-    }
-    gmx_fio_ndo_rvec(fio,molb->posres_xA,molb->nposres_xA);
-  }
-  gmx_fio_do_int(fio,molb->nposres_xB);
-  if (molb->nposres_xB > 0) {
-    if (bRead) {
-      snew(molb->posres_xB,molb->nposres_xB);
-    }
-    gmx_fio_ndo_rvec(fio,molb->posres_xB,molb->nposres_xB);
-  }
-
-}
-
-static t_block mtop_mols(gmx_mtop_t *mtop)
-{
-  int mb,m,a,mol;
-  t_block mols;
-
-  mols.nr = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    mols.nr += mtop->molblock[mb].nmol;
-  }
-  mols.nalloc_index = mols.nr + 1;
-  snew(mols.index,mols.nalloc_index);
-
-  a = 0;
-  m = 0;
-  mols.index[m] = a;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    for(mol=0; mol<mtop->molblock[mb].nmol; mol++) {
-      a += mtop->molblock[mb].natoms_mol;
-      m++;
-      mols.index[m] = a;
-    }
-  }
-  
-  return mols;
-}
-
-static void add_posres_molblock(gmx_mtop_t *mtop)
-{
-  t_ilist *il;
-  int am,i,mol,a;
-  gmx_bool bFE;
-  gmx_molblock_t *molb;
-  t_iparams *ip;
-
-  il = &mtop->moltype[0].ilist[F_POSRES];
-  if (il->nr == 0) {
-    return;
-  }
-  am = 0;
-  bFE = FALSE;
-  for(i=0; i<il->nr; i+=2) {
-    ip = &mtop->ffparams.iparams[il->iatoms[i]];
-    am = max(am,il->iatoms[i+1]);
-    if (ip->posres.pos0B[XX] != ip->posres.pos0A[XX] ||
-       ip->posres.pos0B[YY] != ip->posres.pos0A[YY] ||
-       ip->posres.pos0B[ZZ] != ip->posres.pos0A[ZZ]) {
-      bFE = TRUE;
-    }
-  }
-  /* Make the posres coordinate block end at a molecule end */
-  mol = 0;
-  while(am >= mtop->mols.index[mol+1]) {
-    mol++;
-  }
-  molb = &mtop->molblock[0];
-  molb->nposres_xA = mtop->mols.index[mol+1];
-  snew(molb->posres_xA,molb->nposres_xA);
-  if (bFE) {
-    molb->nposres_xB = molb->nposres_xA;
-    snew(molb->posres_xB,molb->nposres_xB);
-  } else {
-    molb->nposres_xB = 0;
-  }
-  for(i=0; i<il->nr; i+=2) {
-    ip = &mtop->ffparams.iparams[il->iatoms[i]];
-    a  = il->iatoms[i+1];
-    molb->posres_xA[a][XX] = ip->posres.pos0A[XX];
-    molb->posres_xA[a][YY] = ip->posres.pos0A[YY];
-    molb->posres_xA[a][ZZ] = ip->posres.pos0A[ZZ];
-    if (bFE) {
-      molb->posres_xB[a][XX] = ip->posres.pos0B[XX];
-      molb->posres_xB[a][YY] = ip->posres.pos0B[YY];
-      molb->posres_xB[a][ZZ] = ip->posres.pos0B[ZZ];
-    }
-  }
-}
-
-static void set_disres_npair(gmx_mtop_t *mtop)
-{
-  int mt,i,npair;
-  t_iparams *ip;
-  t_ilist *il;
-  t_iatom *a;
-
-  ip = mtop->ffparams.iparams;
-
-  for(mt=0; mt<mtop->nmoltype; mt++) {
-    il = &mtop->moltype[mt].ilist[F_DISRES];
-    if (il->nr > 0) {
-      a = il->iatoms;
-      npair = 0;
-      for(i=0; i<il->nr; i+=3) {
-       npair++;
-       if (i+3 == il->nr || ip[a[i]].disres.label != ip[a[i+3]].disres.label) {
-         ip[a[i]].disres.npair = npair;
-         npair = 0;
-       }
-      }
-    }
-  }
-}
-
-static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop,gmx_bool bRead, 
-                    int file_version)
-{
-  int  mt,mb,i;
-  t_blocka dumb;
-
-  if (bRead)
-    init_mtop(mtop);
-  do_symtab(fio, &(mtop->symtab),bRead);
-  if (bRead && debug) 
-    pr_symtab(debug,0,"symtab",&mtop->symtab);
-  
-  do_symstr(fio, &(mtop->name),bRead,&(mtop->symtab));
-  
-  if (file_version >= 57) {
-    do_ffparams(fio, &mtop->ffparams,bRead,file_version);
-
-    gmx_fio_do_int(fio,mtop->nmoltype);
-  } else {
-    mtop->nmoltype = 1;
-  }
-  if (bRead) {
-    snew(mtop->moltype,mtop->nmoltype);
-    if (file_version < 57) {
-      mtop->moltype[0].name = mtop->name;
-    }
-  }
-  for(mt=0; mt<mtop->nmoltype; mt++) {
-    do_moltype(fio, &mtop->moltype[mt],bRead,&mtop->symtab,file_version,
-              &mtop->groups);
-  }
-
-  if (file_version >= 57) {
-    gmx_fio_do_int(fio,mtop->nmolblock);
-  } else {
-    mtop->nmolblock = 1;
-  }
-  if (bRead) {
-    snew(mtop->molblock,mtop->nmolblock);
-  }
-  if (file_version >= 57) {
-    for(mb=0; mb<mtop->nmolblock; mb++) {
-      do_molblock(fio, &mtop->molblock[mb],bRead,file_version);
-    }
-    gmx_fio_do_int(fio,mtop->natoms);
-  } else {
-    mtop->molblock[0].type = 0;
-    mtop->molblock[0].nmol = 1;
-    mtop->molblock[0].natoms_mol = mtop->moltype[0].atoms.nr;
-    mtop->molblock[0].nposres_xA = 0;
-    mtop->molblock[0].nposres_xB = 0;
-  }
-
-  do_atomtypes (fio, &(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
-  if (bRead && debug) 
-    pr_atomtypes(debug,0,"atomtypes",&mtop->atomtypes,TRUE);
-
-  if (file_version < 57) {
-    /* Debug statements are inside do_idef */    
-    do_idef (fio, &mtop->ffparams,&mtop->moltype[0],bRead,file_version);
-    mtop->natoms = mtop->moltype[0].atoms.nr;
-  }
-       
-  if(file_version >= 65)
-  {
-      do_cmap(fio, &mtop->ffparams.cmap_grid,bRead);
-  }
-  else
-  {
-      mtop->ffparams.cmap_grid.ngrid        = 0;
-      mtop->ffparams.cmap_grid.grid_spacing = 0.1;
-      mtop->ffparams.cmap_grid.cmapdata     = NULL;
-  }
-         
-  if (file_version >= 57) {
-    do_groups(fio, &mtop->groups,bRead,&(mtop->symtab),file_version);
-  }
-
-  if (file_version < 57) {
-    do_block(fio, &mtop->moltype[0].cgs,bRead,file_version);
-    if (bRead && gmx_debug_at) {
-      pr_block(debug,0,"cgs",&mtop->moltype[0].cgs,TRUE);
-    }
-    do_block(fio, &mtop->mols,bRead,file_version);
-    /* Add the posres coordinates to the molblock */
-    add_posres_molblock(mtop);
-  }
-  if (bRead) {
-    if (file_version >= 57) {
-      mtop->mols = mtop_mols(mtop);
-    }
-    if (gmx_debug_at) { 
-      pr_block(debug,0,"mols",&mtop->mols,TRUE);
-    }
-  }
-
-  if (file_version < 51) {
-    /* Here used to be the shake blocks */
-    do_blocka(fio, &dumb,bRead,file_version);
-    if (dumb.nr > 0)
-      sfree(dumb.index);
-    if (dumb.nra > 0)
-      sfree(dumb.a);
-  }
-
-  if (bRead) {
-    close_symtab(&(mtop->symtab));
-  }
-}
-
-/* If TopOnlyOK is TRUE then we can read even future versions
- * of tpx files, provided the file_generation hasn't changed.
- * If it is FALSE, we need the inputrecord too, and bail out
- * if the file is newer than the program.
- * 
- * The version and generation if the topology (see top of this file)
- * are returned in the two last arguments.
- * 
- * If possible, we will read the inputrec even when TopOnlyOK is TRUE.
- */
-static void do_tpxheader(t_fileio *fio,gmx_bool bRead,t_tpxheader *tpx, 
-                         gmx_bool TopOnlyOK, int *file_version, 
-                         int *file_generation)
-{
-  char  buf[STRLEN];
-  gmx_bool  bDouble;
-  int   precision;
-  int   fver,fgen;
-  int   idum=0;
-  real  rdum=0;
-
-  gmx_fio_checktype(fio);
-  gmx_fio_setdebug(fio,bDebugMode());
-  
-  /* NEW! XDR tpb file */
-  precision = sizeof(real);
-  if (bRead) {
-    gmx_fio_do_string(fio,buf);
-    if (strncmp(buf,"VERSION",7))
-      gmx_fatal(FARGS,"Can not read file %s,\n"
-                 "             this file is from a Gromacs version which is older than 2.0\n"
-                 "             Make a new one with grompp or use a gro or pdb file, if possible",
-                 gmx_fio_getname(fio));
-    gmx_fio_do_int(fio,precision);
-    bDouble = (precision == sizeof(double));
-    if ((precision != sizeof(float)) && !bDouble)
-      gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
-                 "instead of %d or %d",
-                 gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
-    gmx_fio_setprecision(fio,bDouble);
-    fprintf(stderr,"Reading file %s, %s (%s precision)\n",
-           gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
-  }
-  else {
-    gmx_fio_write_string(fio,GromacsVersion());
-    bDouble = (precision == sizeof(double));
-    gmx_fio_setprecision(fio,bDouble);
-    gmx_fio_do_int(fio,precision);
-    fver = tpx_version;
-    fgen = tpx_generation;
-  }
-  
-  /* Check versions! */
-  gmx_fio_do_int(fio,fver);
-  
-  if(fver>=26)
-    gmx_fio_do_int(fio,fgen);
-  else
-    fgen=0;
-  if(file_version!=NULL)
-    *file_version = fver;
-  if(file_generation!=NULL)
-    *file_generation = fgen;
-   
-  
-  if ((fver <= tpx_incompatible_version) ||
-      ((fver > tpx_version) && !TopOnlyOK) ||
-      (fgen > tpx_generation))
-    gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",
-               gmx_fio_getname(fio),fver,tpx_version);
-  
-  do_section(fio,eitemHEADER,bRead);
-  gmx_fio_do_int(fio,tpx->natoms);
-  if (fver >= 28)
-    gmx_fio_do_int(fio,tpx->ngtc);
-  else
-    tpx->ngtc = 0;
-  if (fver < 62) {
-    gmx_fio_do_int(fio,idum);
-    gmx_fio_do_real(fio,rdum);
-  }
-  gmx_fio_do_real(fio,tpx->lambda);
-  gmx_fio_do_int(fio,tpx->bIr);
-  gmx_fio_do_int(fio,tpx->bTop);
-  gmx_fio_do_int(fio,tpx->bX);
-  gmx_fio_do_int(fio,tpx->bV);
-  gmx_fio_do_int(fio,tpx->bF);
-  gmx_fio_do_int(fio,tpx->bBox);
-
-  if((fgen > tpx_generation)) {
-    /* This can only happen if TopOnlyOK=TRUE */
-    tpx->bIr=FALSE;
-  }
-}
-
-static int do_tpx(t_fileio *fio, gmx_bool bRead,
-                 t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop,
-                 gmx_bool bXVallocated)
-{
-  t_tpxheader tpx;
-  t_inputrec  dum_ir;
-  gmx_mtop_t  dum_top;
-  gmx_bool        TopOnlyOK,bDum=TRUE;
-  int         file_version,file_generation;
-  int         i;
-  rvec        *xptr,*vptr;
-  int         ePBC;
-  gmx_bool        bPeriodicMols;
-
-  if (!bRead) {
-    tpx.natoms = state->natoms;
-    tpx.ngtc   = state->ngtc;
-    tpx.lambda = state->lambda;
-    tpx.bIr  = (ir       != NULL);
-    tpx.bTop = (mtop     != NULL);
-    tpx.bX   = (state->x != NULL);
-    tpx.bV   = (state->v != NULL);
-    tpx.bF   = (f        != NULL);
-    tpx.bBox = TRUE;
-  }
-  
-  TopOnlyOK = (ir==NULL);
-  
-  do_tpxheader(fio,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
-
-  if (bRead) {
-    state->flags  = 0;
-    state->lambda = tpx.lambda;
-    /* The init_state calls initialize the Nose-Hoover xi integrals to zero */
-    if (bXVallocated) {
-      xptr = state->x;
-      vptr = state->v;
-      init_state(state,0,tpx.ngtc,0,0);  /* nose-hoover chains */ /* eventually, need to add nnhpres here? */
-      state->natoms = tpx.natoms; 
-      state->nalloc = tpx.natoms; 
-      state->x = xptr;
-      state->v = vptr;
-    } else {
-      init_state(state,tpx.natoms,tpx.ngtc,0,0);  /* nose-hoover chains */
-    }
-  }
-
-#define do_test(fio,b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fio)) 
-
-  do_test(fio,tpx.bBox,state->box);
-  do_section(fio,eitemBOX,bRead);
-  if (tpx.bBox) {
-    gmx_fio_ndo_rvec(fio,state->box,DIM);
-    if (file_version >= 51) {
-      gmx_fio_ndo_rvec(fio,state->box_rel,DIM);
-    } else {
-      /* We initialize box_rel after reading the inputrec */
-      clear_mat(state->box_rel);
-    }
-    if (file_version >= 28) {
-      gmx_fio_ndo_rvec(fio,state->boxv,DIM);
-      if (file_version < 56) {
-       matrix mdum;
-       gmx_fio_ndo_rvec(fio,mdum,DIM);
-      }
-    }
-  }
-  
-  if (state->ngtc > 0 && file_version >= 28) {
-    real *dumv;
-    /*ndo_double(state->nosehoover_xi,state->ngtc,bDum);*/
-    /*ndo_double(state->nosehoover_vxi,state->ngtc,bDum);*/
-    /*ndo_double(state->therm_integral,state->ngtc,bDum);*/
-    snew(dumv,state->ngtc);
-    if (file_version < 69) {
-      bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
-    }
-    /* These used to be the Berendsen tcoupl_lambda's */
-    bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
-    sfree(dumv);
-  }
-
-  /* Prior to tpx version 26, the inputrec was here.
-   * I moved it to enable partial forward-compatibility
-   * for analysis/viewer programs.
-   */
-  if(file_version<26) {
-    do_test(fio,tpx.bIr,ir);
-    do_section(fio,eitemIR,bRead);
-    if (tpx.bIr) {
-      if (ir) {
-       do_inputrec(fio, ir,bRead,file_version,
-                    mtop ? &mtop->ffparams.fudgeQQ : NULL);
-       if (bRead && debug) 
-         pr_inputrec(debug,0,"inputrec",ir,FALSE);
-      }
-      else {
-       do_inputrec(fio, &dum_ir,bRead,file_version,
-                    mtop ? &mtop->ffparams.fudgeQQ :NULL);
-       if (bRead && debug) 
-         pr_inputrec(debug,0,"inputrec",&dum_ir,FALSE);
-       done_inputrec(&dum_ir);
-      }
-      
-    }
-  }
-  
-  do_test(fio,tpx.bTop,mtop);
-  do_section(fio,eitemTOP,bRead);
-  if (tpx.bTop) {
-    if (mtop) {
-      do_mtop(fio,mtop,bRead, file_version);
-    } else {
-      do_mtop(fio,&dum_top,bRead,file_version);
-      done_mtop(&dum_top,TRUE);
-    }
-  }
-  do_test(fio,tpx.bX,state->x);  
-  do_section(fio,eitemX,bRead);
-  if (tpx.bX) {
-    if (bRead) {
-      state->flags |= (1<<estX);
-    }
-    gmx_fio_ndo_rvec(fio,state->x,state->natoms);
-  }
-  
-  do_test(fio,tpx.bV,state->v);
-  do_section(fio,eitemV,bRead);
-  if (tpx.bV) {
-    if (bRead) {
-      state->flags |= (1<<estV);
-    }
-    gmx_fio_ndo_rvec(fio,state->v,state->natoms);
-  }
-
-  do_test(fio,tpx.bF,f);
-  do_section(fio,eitemF,bRead);
-  if (tpx.bF) gmx_fio_ndo_rvec(fio,f,state->natoms);
-
-  /* Starting with tpx version 26, we have the inputrec
-   * at the end of the file, so we can ignore it 
-   * if the file is never than the software (but still the
-   * same generation - see comments at the top of this file.
-   *
-   * 
-   */
-  ePBC = -1;
-  bPeriodicMols = FALSE;
-  if (file_version >= 26) {
-    do_test(fio,tpx.bIr,ir);
-    do_section(fio,eitemIR,bRead);
-    if (tpx.bIr) {
-      if (file_version >= 53) {
-       /* Removed the pbc info from do_inputrec, since we always want it */
-       if (!bRead) {
-         ePBC          = ir->ePBC;
-         bPeriodicMols = ir->bPeriodicMols;
-       }
-       gmx_fio_do_int(fio,ePBC);
-       gmx_fio_do_gmx_bool(fio,bPeriodicMols);
-      }
-      if (file_generation <= tpx_generation && ir) {
-       do_inputrec(fio, ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
-       if (bRead && debug) 
-         pr_inputrec(debug,0,"inputrec",ir,FALSE);
-       if (file_version < 51)
-         set_box_rel(ir,state);
-       if (file_version < 53) {
-         ePBC          = ir->ePBC;
-         bPeriodicMols = ir->bPeriodicMols;
-       }
-      }
-      if (bRead && ir && file_version >= 53) {
-       /* We need to do this after do_inputrec, since that initializes ir */
-       ir->ePBC          = ePBC;
-       ir->bPeriodicMols = bPeriodicMols;
-      }
-    }
-  }
-
-    if (bRead)
-    {
-        if (tpx.bIr && ir)
-        {
-            if (state->ngtc == 0)
-            {
-                /* Reading old version without tcoupl state data: set it */
-                init_gtc_state(state,ir->opts.ngtc,0,ir->opts.nhchainlength);
-            }
-            if (tpx.bTop && mtop)
-            {
-                if (file_version < 57)
-                {
-                    if (mtop->moltype[0].ilist[F_DISRES].nr > 0)
-                    {
-                        ir->eDisre = edrSimple;
-                    }
-                    else
-                    {
-                        ir->eDisre = edrNone;
-                    }
-                }
-                set_disres_npair(mtop);
-            }
-        }
-
-        if (tpx.bTop && mtop)
-        {
-            gmx_mtop_finalize(mtop);
-        }
-
-        if (file_version >= 57)
-        {
-            char *env;
-            int  ienv;
-            env = getenv("GMX_NOCHARGEGROUPS");
-            if (env != NULL)
-            {
-                sscanf(env,"%d",&ienv);
-                fprintf(stderr,"\nFound env.var. GMX_NOCHARGEGROUPS = %d\n",
-                        ienv);
-                if (ienv > 0)
-                {
-                    fprintf(stderr,
-                            "Will make single atomic charge groups in non-solvent%s\n",
-                            ienv > 1 ? " and solvent" : "");
-                    gmx_mtop_make_atomic_charge_groups(mtop,ienv==1);
-                }
-                fprintf(stderr,"\n");
-            }
-        }
-    }
-
-    return ePBC;
-}
-
-/************************************************************
- *
- *  The following routines are the exported ones
- *
- ************************************************************/
-
-t_fileio *open_tpx(const char *fn,const char *mode)
-{
-  return gmx_fio_open(fn,mode);
-}    
-void close_tpx(t_fileio *fio)
-{
-  gmx_fio_close(fio);
-}
-
-void read_tpxheader(const char *fn, t_tpxheader *tpx, gmx_bool TopOnlyOK,
-                    int *file_version, int *file_generation)
-{
-  t_fileio *fio;
-
-  fio = open_tpx(fn,"r");
-  do_tpxheader(fio,TRUE,tpx,TopOnlyOK,file_version,file_generation);
-  close_tpx(fio);
-}
-
-void write_tpx_state(const char *fn,
-                    t_inputrec *ir,t_state *state,gmx_mtop_t *mtop)
-{
-  t_fileio *fio;
-
-  fio = open_tpx(fn,"w");
-  do_tpx(fio,FALSE,ir,state,NULL,mtop,FALSE);
-  close_tpx(fio);
-}
-
-void read_tpx_state(const char *fn,
-                   t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop)
-{
-  t_fileio *fio;
-       
-  fio = open_tpx(fn,"r");
-  do_tpx(fio,TRUE,ir,state,f,mtop,FALSE);
-  close_tpx(fio);
-}
-
-int read_tpx(const char *fn,
-            t_inputrec *ir, matrix box,int *natoms,
-            rvec *x,rvec *v,rvec *f,gmx_mtop_t *mtop)
-{
-  t_fileio *fio;
-  t_state state;
-  int ePBC;
-
-  state.x = x;
-  state.v = v;
-  fio = open_tpx(fn,"r");
-  ePBC = do_tpx(fio,TRUE,ir,&state,f,mtop,TRUE);
-  close_tpx(fio);
-  *natoms = state.natoms;
-  if (box) 
-    copy_mat(state.box,box);
-  state.x = NULL;
-  state.v = NULL;
-  done_state(&state);
-
-  return ePBC;
-}
-
-int read_tpx_top(const char *fn,
-                t_inputrec *ir, matrix box,int *natoms,
-                rvec *x,rvec *v,rvec *f,t_topology *top)
-{
-  gmx_mtop_t mtop;
-  t_topology *ltop;
-  int ePBC;
-
-  ePBC = read_tpx(fn,ir,box,natoms,x,v,f,&mtop);
-  
-  *top = gmx_mtop_t_to_t_topology(&mtop);
-
-  return ePBC;
-}
-
-gmx_bool fn2bTPX(const char *file)
-{
-  switch (fn2ftp(file)) {
-  case efTPR:
-  case efTPB:
-  case efTPA:
-    return TRUE;
-  default:
-    return FALSE;
-  }
-}
-
-gmx_bool read_tps_conf(const char *infile,char *title,t_topology *top,int *ePBC,
-                  rvec **x,rvec **v,matrix box,gmx_bool bMass)
-{
-  t_tpxheader  header;
-  int          natoms,i,version,generation;
-  gmx_bool         bTop,bXNULL;
-  gmx_mtop_t   *mtop;
-  t_topology   *topconv;
-  gmx_atomprop_t aps;
-  
-  bTop = fn2bTPX(infile);
-  *ePBC = -1;
-  if (bTop) {
-    read_tpxheader(infile,&header,TRUE,&version,&generation);
-    if (x)
-      snew(*x,header.natoms);
-    if (v)
-      snew(*v,header.natoms);
-    snew(mtop,1);
-    *ePBC = read_tpx(infile,NULL,box,&natoms,
-                    (x==NULL) ? NULL : *x,(v==NULL) ? NULL : *v,NULL,mtop);
-    *top = gmx_mtop_t_to_t_topology(mtop);
-    sfree(mtop);
-    strcpy(title,*top->name);
-    tpx_make_chain_identifiers(&top->atoms,&top->mols);
-  }
-  else {
-    get_stx_coordnum(infile,&natoms);
-    init_t_atoms(&top->atoms,natoms,FALSE);
-    bXNULL = (x == NULL);
-    snew(*x,natoms);
-    if (v)
-      snew(*v,natoms);
-    read_stx_conf(infile,title,&top->atoms,*x,(v==NULL) ? NULL : *v,ePBC,box);
-    if (bXNULL) {
-      sfree(*x);
-      x = NULL;
-    }
-    if (bMass) {
-      aps = gmx_atomprop_init();
-      for(i=0; (i<natoms); i++)
-       if (!gmx_atomprop_query(aps,epropMass,
-                               *top->atoms.resinfo[top->atoms.atom[i].resind].name,
-                               *top->atoms.atomname[i],
-                               &(top->atoms.atom[i].m))) {
-         if (debug) 
-           fprintf(debug,"Can not find mass for atom %s %d %s, setting to 1\n",
-                   *top->atoms.resinfo[top->atoms.atom[i].resind].name,
-                   top->atoms.resinfo[top->atoms.atom[i].resind].nr,
-                   *top->atoms.atomname[i]);
-       }
-      gmx_atomprop_destroy(aps);
-    }
-    top->idef.ntypes=-1;
-  }
-
-  return bTop;
-}
diff --git a/src/gmxlib/trajana/.cvsignore b/src/gmxlib/trajana/.cvsignore
deleted file mode 100644 (file)
index e9407c9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.libs
-.deps
diff --git a/src/gmxlib/trajana/centerofmass.c b/src/gmxlib/trajana/centerofmass.c
deleted file mode 100644 (file)
index bc46cfd..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in centerofmass.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <typedefs.h>
-#include <pbc.h>
-#include <vec.h>
-
-#include <centerofmass.h>
-
-/*!
- * \param[in]  top    Topology structure (unused, can be NULL).
- * \param[in]  x      Position vectors of all atoms.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index  Indices of atoms.
- * \param[out] xout   COG position for the indexed atoms.
- * \returns    0 on success.
- */
-int
-gmx_calc_cog(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
-{
-    int                 m, j, ai;
-
-    clear_rvec(xout);
-    for (m = 0; m < nrefat; ++m)
-    {
-        ai = index[m];
-        rvec_inc(xout, x[ai]);
-    }
-    svmul(1.0/nrefat, xout, xout);
-    return 0;
-}
-
-/*!
- * \param[in]  top    Topology structure with masses.
- * \param[in]  x      Position vectors of all atoms.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index  Indices of atoms.
- * \param[out] xout   COM position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL.
- *
- * Works exactly as gmx_calc_cog() with the exception that a center of
- * mass are calculated, and hence a topology with masses is required.
- */
-int
-gmx_calc_com(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
-{
-    int                 m, j, ai;
-    real                mass, mtot;
-
-    if (!top)
-    {
-        gmx_incons("no masses available while mass weighting was requested");
-        return EINVAL;
-    }
-    clear_rvec(xout);
-    mtot = 0;
-    for (m = 0; m < nrefat; ++m)
-    {
-        ai = index[m];
-        mass = top->atoms.atom[ai].m;
-        for (j = 0; j < DIM; ++j)
-        {
-            xout[j] += mass * x[ai][j];
-        }
-        mtot += mass;
-    }
-    svmul(1.0/mtot, xout, xout);
-    return 0;
-}
-
-/*!
- * \param[in]  top    Topology structure with masses.
- * \param[in]  f      Forces on all atoms.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index  Indices of atoms.
- * \param[out] fout   Force on the COG position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL.
- *
- * No special function is provided for calculating the force on the center of
- * mass, because this can be achieved with gmx_calc_cog().
- */
-int
-gmx_calc_cog_f(t_topology *top, rvec f[], int nrefat, atom_id index[], rvec fout)
-{
-    int                 m, j, ai;
-    real                mass, mtot;
-
-    if (!top)
-    {
-        gmx_incons("no masses available while mass weighting was needed");
-        return EINVAL;
-    }
-    clear_rvec(fout);
-    mtot = 0;
-    for (m = 0; m < nrefat; ++m)
-    {
-        ai = index[m];
-        mass = top->atoms.atom[ai].m;
-        for (j = 0; j < DIM; ++j)
-        {
-            fout[j] += f[ai][j] / mass;
-        }
-        mtot += mass;
-    }
-    svmul(mtot, fout, fout);
-    return 0;
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==FALSE).
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index Indices of atoms.
- * \param[in]  bMass If TRUE, mass weighting is used.
- * \param[out] xout  COM/COG position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
- *
- * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
- * \p bMass.
- * Other parameters are passed unmodified to these functions.
- */
-int
-gmx_calc_comg(t_topology *top, rvec x[], int nrefat, atom_id index[],
-              gmx_bool bMass, rvec xout)
-{
-    if (bMass)
-    {
-        return gmx_calc_com(top, x, nrefat, index, xout);
-    }
-    else
-    {
-        return gmx_calc_cog(top, x, nrefat, index, xout);
-    }
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==TRUE).
- * \param[in]  x     Forces on all atoms.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index Indices of atoms.
- * \param[in]  bMass If TRUE, force on COM is calculated.
- * \param[out] xout  Force on the COM/COG position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is FALSE.
- *
- * Calls either gmx_calc_cog() or gmx_calc_cog_f() depending on the value of
- * \p bMass.
- * Other parameters are passed unmodified to these functions.
- */
-int
-gmx_calc_comg_f(t_topology *top, rvec f[], int nrefat, atom_id index[],
-                gmx_bool bMass, rvec fout)
-{
-    if (bMass)
-    {
-        return gmx_calc_cog(top, f, nrefat, index, fout);
-    }
-    else
-    {
-        return gmx_calc_cog_f(top, f, nrefat, index, fout);
-    }
-}
-
-
-/*!
- * \param[in]  top    Topology structure (unused, can be NULL).
- * \param[in]  x      Position vectors of all atoms.
- * \param[in]  pbc    Periodic boundary conditions structure.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index  Indices of atoms.
- * \param[out] xout   COG position for the indexed atoms.
- * \returns    0 on success.
- *
- * Works exactly as gmx_calc_com_pbc(), but calculates the center of geometry.
- */
-int
-gmx_calc_cog_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                 int nrefat, atom_id index[], rvec xout)
-{
-    const real          tol = 1e-4;
-    gmx_bool                bChanged;
-    int                 m, j, ai, iter;
-    rvec                dx, xtest;
-
-    /* First simple calculation */
-    gmx_calc_cog(top, x, nrefat, index, xout);
-    /* Now check if any atom is more than half the box from the COM */
-    if (pbc)
-    {
-        iter = 0;
-        do
-        {
-            bChanged = FALSE;
-            for (m = 0; m < nrefat; ++m)
-            {
-                ai = index[m];
-                pbc_dx(pbc, x[ai], xout, dx);
-                rvec_add(xout, dx, xtest);
-                for (j = 0; j < DIM; ++j)
-                {
-                    if (fabs(xtest[j] - x[ai][j]) > tol)
-                    {
-                        /* Here we have used the wrong image for contributing to the COM */
-                        xout[j] += (xtest[j] - x[ai][j]) / nrefat;
-                        x[ai][j] = xtest[j];
-                        bChanged = TRUE;
-                    }
-                }
-            }
-            iter++;
-        }
-        while (bChanged);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top    Topology structure with masses.
- * \param[in]  x      Position vectors of all atoms.
- * \param[in]  pbc    Periodic boundary conditions structure.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index  Indices of atoms.
- * \param[out] xout   COM position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL.
- *
- * Works as gmx_calc_com(), but takes into account periodic boundary
- * conditions: If any atom is more than half the box from the COM,
- * it is wrapped around and a new COM is calculated. This is repeated
- * until no atoms violate the condition.
- *
- * Modified from src/tools/gmx_sorient.c in Gromacs distribution.
- */
-int
-gmx_calc_com_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                 int nrefat, atom_id index[], rvec xout)
-{
-    const real          tol = 1e-4;
-    gmx_bool                bChanged;
-    int                 m, j, ai, iter;
-    real                mass, mtot;
-    rvec                dx, xtest;
-
-    if (!top)
-    {
-        gmx_incons("no masses available while mass weighting was requested");
-        return EINVAL;
-    }
-    /* First simple calculation */
-    clear_rvec(xout);
-    mtot = 0;
-    for (m = 0; m < nrefat; ++m)
-    {
-        ai = index[m];
-        mass = top->atoms.atom[ai].m;
-        for (j = 0; j < DIM; ++j)
-        {
-            xout[j] += mass * x[ai][j];
-        }
-        mtot += mass;
-    }
-    svmul(1.0/mtot, xout, xout);
-    /* Now check if any atom is more than half the box from the COM */
-    if (pbc)
-    {
-        iter = 0;
-        do
-        {
-            bChanged = FALSE;
-            for (m = 0; m < nrefat; ++m)
-            {
-                ai = index[m];
-                mass = top->atoms.atom[ai].m / mtot;
-                pbc_dx(pbc, x[ai], xout, dx);
-                rvec_add(xout, dx, xtest);
-                for (j = 0; j < DIM; ++j)
-                {
-                    if (fabs(xtest[j] - x[ai][j]) > tol)
-                    {
-                        /* Here we have used the wrong image for contributing to the COM */
-                        xout[j] += mass * (xtest[j] - x[ai][j]);
-                        x[ai][j] = xtest[j];
-                        bChanged = TRUE;
-                    }
-                }
-            }
-            iter++;
-        }
-        while (bChanged);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==FALSE).
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  pbc    Periodic boundary conditions structure.
- * \param[in]  nrefat Number of atoms in the index.
- * \param[in]  index Indices of atoms.
- * \param[in]  bMass If TRUE, mass weighting is used.
- * \param[out] xout  COM/COG position for the indexed atoms.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
- *
- * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
- * \p bMass.
- * Other parameters are passed unmodified to these functions.
- */
-int
-gmx_calc_comg_pbc(t_topology *top, rvec x[], t_pbc *pbc,
-                  int nrefat, atom_id index[], gmx_bool bMass, rvec xout)
-{
-    if (bMass)
-    {
-        return gmx_calc_com_pbc(top, x, pbc, nrefat, index, xout);
-    }
-    else
-    {
-        return gmx_calc_cog_pbc(top, x, pbc, nrefat, index, xout);
-    }
-}
-
-
-/*!
- * \param[in]  top   Topology structure (unused, can be NULL).
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  block t_block structure that divides \p index into blocks.
- * \param[in]  index Indices of atoms.
- * \param[out] xout  \p block->nr COG positions.
- * \returns    0 on success.
- */
-int
-gmx_calc_cog_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
-                   rvec xout[])
-{
-    int                 b, i, ai;
-    rvec                xb;
-
-    for (b = 0; b < block->nr; ++b)
-    {
-        clear_rvec(xb);
-        for (i = block->index[b]; i < block->index[b+1]; ++i)
-        {
-            ai = index[i];
-            rvec_inc(xb, x[ai]);
-        }
-        svmul(1.0/(block->index[b+1] - block->index[b]), xb, xout[b]);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top   Topology structure with masses.
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  block t_block structure that divides \p index into blocks.
- * \param[in]  index Indices of atoms.
- * \param[out] xout  \p block->nr COM positions.
- * \returns    0 on success, EINVAL if \p top is NULL.
- *
- * Works exactly as gmx_calc_cog_block() with the exception that centers of
- * mass are calculated, and hence a topology with masses is required.
- */
-int
-gmx_calc_com_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
-                   rvec xout[])
-{
-    int                 b, i, ai, d;
-    rvec                xb;
-    real                mass, mtot;
-
-    if (!top)
-    {
-        gmx_incons("no masses available while mass weighting was requested");
-        return EINVAL;
-    }
-    for (b = 0; b < block->nr; ++b)
-    {
-        clear_rvec(xb);
-        mtot = 0;
-        for (i = block->index[b]; i < block->index[b+1]; ++i)
-        {
-            ai = index[i];
-            mass = top->atoms.atom[ai].m;
-            for (d = 0; d < DIM; ++d)
-            {
-                xb[d] += mass * x[ai][d];
-            }
-            mtot += mass;
-        }
-        svmul(1.0/mtot, xb, xout[b]);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top   Topology structure with masses.
- * \param[in]  f     Forces on all atoms.
- * \param[in]  block t_block structure that divides \p index into blocks.
- * \param[in]  index Indices of atoms.
- * \param[out] xout  \p block->nr Forces on COG positions.
- * \returns    0 on success, EINVAL if \p top is NULL.
- */
-int
-gmx_calc_cog_f_block(t_topology *top, rvec f[], t_block *block, atom_id index[],
-                     rvec fout[])
-{
-    int                 b, i, ai, d;
-    rvec                fb;
-    real                mass, mtot;
-
-    if (!top)
-    {
-        gmx_incons("no masses available while mass weighting was needed");
-        return EINVAL;
-    }
-    for (b = 0; b < block->nr; ++b)
-    {
-        clear_rvec(fb);
-        mtot = 0;
-        for (i = block->index[b]; i < block->index[b+1]; ++i)
-        {
-            ai = index[i];
-            mass = top->atoms.atom[ai].m;
-            for (d = 0; d < DIM; ++d)
-            {
-                fb[d] += f[ai][d] / mass;
-            }
-            mtot += mass;
-        }
-        svmul(mtot, fb, fout[b]);
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==FALSE).
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  block t_block structure that divides \p index into blocks.
- * \param[in]  index Indices of atoms.
- * \param[in]  bMass If TRUE, mass weighting is used.
- * \param[out] xout  \p block->nr COM/COG positions.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
- *
- * Calls either gmx_calc_com_block() or gmx_calc_cog_block() depending on the
- * value of \p bMass.
- * Other parameters are passed unmodified to these functions.
- */
-int
-gmx_calc_comg_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
-                    gmx_bool bMass, rvec xout[])
-{
-    if (bMass)
-    {
-        return gmx_calc_com_block(top, x, block, index, xout);
-    }
-    else
-    {
-        return gmx_calc_cog_block(top, x, block, index, xout);
-    }
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==FALSE).
- * \param[in]  f     Forces on all atoms.
- * \param[in]  block t_block structure that divides \p index into blocks.
- * \param[in]  index Indices of atoms.
- * \param[in]  bMass If TRUE, force on COM is calculated.
- * \param[out] xout  \p block->nr forces on the COM/COG positions.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
- *
- * Calls either gmx_calc_com_block() or gmx_calc_cog_block() depending on the
- * value of \p bMass.
- * Other parameters are passed unmodified to these functions.
- */
-int
-gmx_calc_comg_f_block(t_topology *top, rvec f[], t_block *block, atom_id index[],
-                      gmx_bool bMass, rvec fout[])
-{
-    if (bMass)
-    {
-        return gmx_calc_cog_block(top, f, block, index, fout);
-    }
-    else
-    {
-        return gmx_calc_cog_f_block(top, f, block, index, fout);
-    }
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==FALSE).
- * \param[in]  x     Position vectors of all atoms.
- * \param[in]  block Blocks for calculation.
- * \param[in]  bMass If TRUE, mass weighting is used.
- * \param[out] xout  \p block->nr COM/COG positions.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
- *
- * Calls gmx_calc_comg_block(), converting the \p t_blocka structure into
- * a \p t_block and an index. Other parameters are passed unmodified.
- *
- * \attention
- * This function assumes that a pointer to \c t_blocka can be safely typecast
- * into \c t_block such that the index fields can still be referenced.
- * With the present Gromacs defitions of these types, this is the case,
- * but if the layout of these structures is changed, this may lead to strange
- * crashes.
- */
-int
-gmx_calc_comg_blocka(t_topology *top, rvec x[], t_blocka *block,
-                     gmx_bool bMass, rvec xout[])
-{
-    /* TODO: It would probably be better to do this without the type cast */
-    return gmx_calc_comg_block(top, x, (t_block *)block, block->a, bMass, xout);
-}
-
-/*!
- * \param[in]  top   Topology structure with masses
- *   (can be NULL if \p bMASS==TRUE).
- * \param[in]  f     Forces on all atoms.
- * \param[in]  block Blocks for calculation.
- * \param[in]  bMass If TRUE, force on COM is calculated.
- * \param[out] fout  \p block->nr forces on the COM/COG positions.
- * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is FALSE.
- *
- * Calls gmx_calc_comg_f_block(), converting the \p t_blocka structure into
- * a \p t_block and an index. Other parameters are passed unmodified.
- *
- * \attention
- * This function assumes that a pointer to \c t_blocka can be safely typecast
- * into \c t_block such that the index fields can still be referenced.
- * With the present Gromacs defitions of these types, this is the case,
- * but if the layout of these structures is changed, this may lead to strange
- * crashes.
- */
-int
-gmx_calc_comg_f_blocka(t_topology *top, rvec f[], t_blocka *block,
-                       gmx_bool bMass, rvec fout[])
-{
-    /* TODO: It would probably be better to do this without the type cast */
-    return gmx_calc_comg_f_block(top, f, (t_block *)block, block->a, bMass, fout);
-}
diff --git a/src/gmxlib/trajana/indexutil.c b/src/gmxlib/trajana/indexutil.c
deleted file mode 100644 (file)
index ab5c131..0000000
+++ /dev/null
@@ -1,1453 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in indexutil.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <index.h>
-#include <smalloc.h>
-#include <string2.h>
-#include <typedefs.h>
-#include <gmx_fatal.h>
-
-#include <indexutil.h>
-
-/********************************************************************
- * gmx_ana_indexgrps_t functions
- ********************************************************************/
-
-/*! \internal \brief
- * Stores a set of index groups.
- */
-struct gmx_ana_indexgrps_t
-{
-    /** Number of index groups. */
-    int                 nr;
-    /** Array of index groups. */
-    gmx_ana_index_t    *g;
-};
-
-/*!
- * \param[out] g     Index group structure.
- * \param[in]  ngrps Number of groups for which memory is allocated.
- */
-void
-gmx_ana_indexgrps_alloc(gmx_ana_indexgrps_t **g, int ngrps)
-{
-    snew(*g, 1);
-    (*g)->nr = ngrps;
-    snew((*g)->g,    ngrps);
-}
-
-/*!
- * \param[out] g     Index group structure.
- * \param[in]  ngrps Number of index groups.
- * \param[in]  isize Array of index group sizes.
- * \param[in]  index Array of pointers to indices of each group.
- * \param[in]  name  Array of names of the groups.
- * \param[in]  bFree If TRUE, the \p isize, \p index and \p name arrays
- *   are freed after they have been copied.
- */
-void
-gmx_ana_indexgrps_set(gmx_ana_indexgrps_t **g, int ngrps, int *isize,
-                      atom_id **index, char **name, gmx_bool bFree)
-{
-    int  i;
-
-    gmx_ana_indexgrps_alloc(g, ngrps);
-    for (i = 0; i < ngrps; ++i)
-    {
-        gmx_ana_index_set(&(*g)->g[i], isize[i], index[i], name[i], isize[i]);
-    }
-    if (bFree)
-    {
-        sfree(isize);
-        sfree(index);
-        sfree(name);
-    }
-}
-
-/*!
- * \param[out] g     Index group structure.
- * \param[in]  top   Topology structure.
- * \param[in]  fnm   File name for the index file.
- *   Memory is automatically allocated.
- *
- * One or both of \p top or \p fnm can be NULL.
- * If \p top is NULL, an index file is required and the groups are read
- * from the file (uses Gromacs routine init_index()).
- * If \p fnm is NULL, default groups are constructed based on the
- * topology (uses Gromacs routine analyse()).
- * If both are null, the index group structure is initialized empty.
- */
-void
-gmx_ana_indexgrps_init(gmx_ana_indexgrps_t **g, t_topology *top, 
-                       const char *fnm)
-{
-    t_blocka *block = NULL;
-    char    **names = NULL;
-    int       i, j;
-
-    if (fnm)
-    {
-        block = init_index(fnm, &names);
-    }
-    else if (top)
-    {
-        block = new_blocka();
-        analyse(&top->atoms, block, &names, FALSE, FALSE);
-    }
-    else
-    {
-        snew(*g, 1);
-        (*g)->nr    = 0;
-        (*g)->g     = NULL;
-        return;
-    }
-
-    gmx_ana_indexgrps_alloc(g, block->nr);
-    for (i = 0; i < block->nr; ++i)
-    {
-        gmx_ana_index_t *grp = &(*g)->g[i];
-
-        grp->isize = block->index[i+1] - block->index[i];
-        snew(grp->index, grp->isize);
-        for (j = 0; j < grp->isize; ++j)
-        {
-            grp->index[j] = block->a[block->index[i]+j];
-        }
-        grp->name = names[i];
-        grp->nalloc_index = grp->isize;
-    }
-
-    done_blocka(block);
-    sfree(block);
-    sfree(names);
-}
-
-/*!
- * \param[out] g     Index group structure.
- * \param[in]  top   Topology structure.
- * \param[in]  fnm   File name for the index file.
- * \param[in]  ngrps Number of required groups.
- *   Memory is automatically allocated.
- *
- * One of \p top or \p fnm can be NULL, but not both.
- * If \p top is NULL, an index file is required and the groups are read
- * from the file (uses Gromacs routine rd_index()).
- * If \p fnm is NULL, default groups are constructed based on the
- * topology (uses Gromacs routine get_index()).
- */
-void
-gmx_ana_indexgrps_get(gmx_ana_indexgrps_t **g, t_topology *top, 
-                      const char *fnm, int ngrps)
-{
-    int      *isize;
-    atom_id **index;
-    char    **name;
-
-    snew(isize, ngrps);
-    snew(index, ngrps);
-    snew(name,  ngrps);
-    if (!top)
-    {
-        rd_index(fnm, ngrps, isize, index, name);
-    }
-    else
-    {
-        get_index(&(top->atoms), fnm, ngrps, isize, index, name);
-    }
-    gmx_ana_indexgrps_set(g, ngrps, isize, index, name, TRUE);
-}
-
-/*!
- * \param[out] g     Index group structure.
- * \param[in]  fnm   File name for the index file.
- * \param[in]  ngrps Number of required groups.
- *   Memory is automatically allocated.
- *
- * This is a convenience function for calling the Gromacs routine
- * rd_index().
- */
-void
-gmx_ana_indexgrps_rd(gmx_ana_indexgrps_t **g, const char *fnm, int ngrps)
-{
-    gmx_ana_indexgrps_get(g, NULL, fnm, ngrps);
-}
-
-/*!
- * \param[in] g  Index groups structure.
- *
- * The pointer \p g is invalid after the call.
- */
-void
-gmx_ana_indexgrps_free(gmx_ana_indexgrps_t *g)
-{
-    int  i;
-
-    if (g->nr == 0)
-    {
-        sfree(g);
-        return;
-    }
-    for (i = 0; i < g->nr; ++i)
-    {
-        gmx_ana_index_deinit(&g->g[i]);
-    }
-    sfree(g->g);
-    g->nr    = 0;
-    g->g     = NULL;
-    sfree(g);
-}
-
-/*!
- * \param[out] dest Destination index groups.
- * \param[in]  src  Source index groups.
- *
- * A deep copy is made for all fields, including the group names.
- */
-void
-gmx_ana_indexgrps_clone(gmx_ana_indexgrps_t **dest, gmx_ana_indexgrps_t *src)
-{
-    int g;
-
-    gmx_ana_indexgrps_alloc(dest, src->nr);
-    for (g = 0; g < src->nr; ++g)
-    {
-        gmx_ana_index_copy(&(*dest)->g[g], &src->g[g], TRUE);
-    }
-}
-
-/*!
- * \param[out] g     Index group structure.
- * \returns    TRUE if \p g is empty, i.e., has 0 index groups.
- */
-gmx_bool
-gmx_ana_indexgrps_is_empty(gmx_ana_indexgrps_t *g)
-{
-    return g->nr == 0;
-}
-
-/*!
- * \param[in]  g     Index groups structure.
- * \param[in]  n     Index group number to get.
- * \returns    Pointer to the \p n'th index group in \p g.
- *
- * The returned pointer should not be freed.
- */
-gmx_ana_index_t *
-gmx_ana_indexgrps_get_grp(gmx_ana_indexgrps_t *g, int n)
-{
-    if (n < 0 || n >= g->nr)
-    {
-        return NULL;
-    }
-    return &g->g[n];
-}
-
-/*!
- * \param[out] dest Output structure.
- * \param[in]  src  Input index groups.
- * \param[in]  n    Number of the group to extract.
- * \returns TRUE if \p n is a valid group in \p src, FALSE otherwise.
- */
-gmx_bool
-gmx_ana_indexgrps_extract(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, int n)
-{
-    if (n < 0 || n >= src->nr)
-    {
-        dest->isize = 0;
-        return FALSE;
-    }
-
-    gmx_ana_index_copy(dest, &src->g[n], TRUE);
-    return TRUE;
-}
-
-/*!
- * \param[out] dest Output structure.
- * \param[in]  src  Input index groups.
- * \param[in]  name Name (or part of the name) of the group to extract.
- * \returns TRUE if \p name is a valid group in \p src, FALSE otherwise.
- *
- * Uses the Gromacs routine find_group() to find the actual group;
- * the comparison is case-insensitive.
- */
-gmx_bool
-gmx_ana_indexgrps_find(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, char *name)
-{
-    int    i;
-    char **names;
-
-    snew(names, src->nr);
-    for (i = 0; i < src->nr; ++i)
-    {
-        names[i] = src->g[i].name;
-    }
-    i = find_group(name, src->nr, names);
-    sfree(names);
-    if (i == NOTSET)
-    {
-        dest->isize = 0;
-        return FALSE;
-    }
-
-    return gmx_ana_indexgrps_extract(dest, src, i);
-}
-
-/*!
- * \param[in]  g      Index groups to print.
- * \param[in]  maxn   Maximum number of indices to print
- *      (-1 = print all, 0 = print only names).
- */
-void
-gmx_ana_indexgrps_print(gmx_ana_indexgrps_t *g, int maxn)
-{
-    int  i;
-
-    for (i = 0; i < g->nr; ++i)
-    {
-        fprintf(stderr, " %2d: ", i);
-        gmx_ana_index_dump(&g->g[i], i, maxn);
-    }
-}
-
-/********************************************************************
- * gmx_ana_index_t functions
- ********************************************************************/
-
-/*!
- * \param[in,out] g      Index group structure.
- * \param[in]     isize  Maximum number of atoms to reserve space for.
- */
-void
-gmx_ana_index_reserve(gmx_ana_index_t *g, int isize)
-{
-    if (g->nalloc_index < isize)
-    {
-        srenew(g->index, isize);
-        g->nalloc_index = isize;
-    }
-}
-
-/*!
- * \param[in,out] g      Index group structure.
- *
- * Resizes the memory allocated for holding the indices such that the
- * current contents fit.
- */
-void
-gmx_ana_index_squeeze(gmx_ana_index_t *g)
-{
-    srenew(g->index, g->isize);
-    g->nalloc_index = g->isize;
-}
-
-/*!
- * \param[out] g      Output structure.
- *
- * Any contents of \p g are discarded without freeing.
- */
-void
-gmx_ana_index_clear(gmx_ana_index_t *g)
-{
-    g->isize        = 0;
-    g->index        = NULL;
-    g->name         = NULL;
-    g->nalloc_index = 0;
-}
-
-/*!
- * \param[out] g      Output structure.
- * \param[in]  isize  Number of atoms in the new group.
- * \param[in]  index  Array of \p isize atoms (can be NULL if \p isize is 0).
- * \param[in]  name   Name for the new group (can be NULL).
- * \param[in]  nalloc Number of elements allocated for \p index
- *   (if 0, \p index is not freed in gmx_ana_index_deinit())
- *
- * No copy if \p index is made.
- */
-void
-gmx_ana_index_set(gmx_ana_index_t *g, int isize, atom_id *index, char *name,
-                  int nalloc)
-{
-    g->isize        = isize;
-    g->index        = index;
-    g->name         = name;
-    g->nalloc_index = nalloc;
-}
-
-/*!
- * \param[out] g      Output structure.
- * \param[in]  natoms Number of atoms.
- * \param[in]  name   Name for the new group (can be NULL).
- */
-void
-gmx_ana_index_init_simple(gmx_ana_index_t *g, int natoms, char *name)
-{
-    int  i;
-
-    g->isize = natoms;
-    snew(g->index, natoms);
-    for (i = 0; i < natoms; ++i)
-    {
-        g->index[i] = i;
-    }
-    g->name = name;
-    g->nalloc_index = natoms;
-}
-
-/*!
- * \param[in] g  Index group structure.
- *
- * The pointer \p g is not freed.
- */
-void
-gmx_ana_index_deinit(gmx_ana_index_t *g)
-{
-    if (g->nalloc_index > 0)
-    {
-        sfree(g->index);
-    }
-    sfree(g->name);
-    gmx_ana_index_clear(g);
-}
-
-/*!
- * \param[out] dest   Destination index group.
- * \param[in]  src    Source index group.
- * \param[in]  bAlloc If TRUE, memory is allocated at \p dest; otherwise,
- *   it is assumed that enough memory has been allocated for index.
- *
- * A deep copy of the name is only made if \p bAlloc is TRUE.
- */
-void
-gmx_ana_index_copy(gmx_ana_index_t *dest, gmx_ana_index_t *src, gmx_bool bAlloc)
-{
-    dest->isize = src->isize;
-    if (dest->isize > 0)
-    {
-        if (bAlloc)
-        {
-            snew(dest->index, dest->isize);
-            dest->nalloc_index = dest->isize;
-        }
-        memcpy(dest->index, src->index, dest->isize*sizeof(*dest->index));
-    }
-    if (bAlloc && src->name)
-    {
-        dest->name = strdup(src->name);
-    }
-    else if (bAlloc || src->name)
-    {
-        dest->name = src->name;
-    }
-}
-
-/*!
- * \param[in]  g      Index group to print.
- * \param[in]  i      Group number to use if the name is NULL.
- * \param[in]  maxn   Maximum number of indices to print (-1 = print all).
- */
-void
-gmx_ana_index_dump(gmx_ana_index_t *g, int i, int maxn)
-{
-    int  j, n;
-
-    if (g->name)
-    {
-        fprintf(stderr, "\"%s\"", g->name);
-    }
-    else
-    {
-        fprintf(stderr, "Group %d", i+1);
-    }
-    fprintf(stderr, " (%d atoms)", g->isize);
-    if (maxn != 0)
-    {
-        fprintf(stderr, ":");
-        n = g->isize;
-        if (maxn >= 0 && n > maxn)
-        {
-            n = maxn;
-        }
-        for (j = 0; j < n; ++j)
-        {
-            fprintf(stderr, " %d", g->index[j]+1);
-        }
-        if (n < g->isize)
-        {
-            fprintf(stderr, " ...");
-        }
-    }
-    fprintf(stderr, "\n");
-}
-
-/*!
- * \param[in]  g      Input index group.
- * \param[in]  natoms Number of atoms to check against.
- *
- * If any atom index in the index group is less than zero or >= \p natoms,
- * gmx_fatal() is called.
- */
-void
-gmx_ana_index_check(gmx_ana_index_t *g, int natoms)
-{
-    int  j;
-
-    for (j = 0; j < g->isize; ++j)
-    {
-        if (g->index[j] >= natoms)
-        {
-            gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) "
-              "larger than number of atoms in trajectory (%d atoms)",
-              g->index[j], g->name, g->isize, natoms);
-        }
-        else if (g->index[j] < 0)
-        {
-            gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) "
-              "is less than zero",
-              g->index[j], g->name, g->isize);
-        }
-    }
-}
-
-/*!
- * \param[in]  g      Index group to check.
- * \returns    TRUE if the index group is sorted and has no duplicates,
- *   FALSE otherwise.
- */
-gmx_bool
-gmx_ana_index_check_sorted(gmx_ana_index_t *g)
-{
-    int  i;
-
-    for (i = 0; i < g->isize-1; ++i)
-    {
-        if (g->index[i+1] <= g->index[i])
-        {
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-/********************************************************************
- * Set operations
- ********************************************************************/
-
-/** Helper function for gmx_ana_index_sort(). */
-static int
-cmp_atomid(const void *a, const void *b)
-{
-    if (*(atom_id *)a < *(atom_id *)b) return -1;
-    if (*(atom_id *)a > *(atom_id *)b) return 1;
-    return 0;
-}
-
-/*!
- * \param[in,out] g  Index group to be sorted.
- */
-void
-gmx_ana_index_sort(gmx_ana_index_t *g)
-{
-    qsort(g->index, g->isize, sizeof(*g->index), cmp_atomid);
-}
-
-/*!
- * \param[in]  a      Index group to check.
- * \param[in]  b      Index group to check.
- * \returns    TRUE if \p a and \p b are equal, FALSE otherwise.
- */
-gmx_bool
-gmx_ana_index_equals(gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int  i;
-
-    if (a->isize != b->isize)
-    {
-        return FALSE;
-    }
-    for (i = 0; i < a->isize; ++i)
-    {
-        if (a->index[i] != b->index[i])
-        {
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-/*!
- * \param[in]  a      Index group to check against.
- * \param[in]  b      Index group to check.
- * \returns    TRUE if \p b is contained in \p a,
- *   FALSE otherwise.
- *
- * If the elements are not in the same order in both groups, the function
- * fails. However, the groups do not need to be sorted.
- */
-gmx_bool
-gmx_ana_index_contains(gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int  i, j;
-
-    for (i = j = 0; j < b->isize; ++i, ++j) {
-        while (i < a->isize && a->index[i] != b->index[j])
-        {
-            ++i;
-        }
-        if (i == a->isize)
-        {
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-/*!
- * \param[out] dest Output index group (the intersection of \p a and \p b).
- * \param[in]  a    First index group.
- * \param[in]  b    Second index group.
- *
- * \p dest can be the same as \p a or \p b.
- */
-void
-gmx_ana_index_intersection(gmx_ana_index_t *dest,
-                           gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int i, j, k;
-
-    for (i = j = k = 0; i < a->isize && j < b->isize; ++i) {
-        while (j < b->isize && b->index[j] < a->index[i])
-        {
-            ++j;
-        }
-        if (j < b->isize && b->index[j] == a->index[i])
-        {
-            dest->index[k++] = b->index[j++];
-        }
-    }
-    dest->isize = k;
-}
-
-/*!
- * \param[out] dest Output index group (the difference \p a - \p b).
- * \param[in]  a    First index group.
- * \param[in]  b    Second index group.
- *
- * \p dest can equal \p a, but not \p b.
- */
-void
-gmx_ana_index_difference(gmx_ana_index_t *dest,
-                         gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int i, j, k;
-
-    for (i = j = k = 0; i < a->isize; ++i)
-    {
-        while (j < b->isize && b->index[j] < a->index[i])
-        {
-            ++j;
-        }
-        if (j == b->isize || b->index[j] != a->index[i])
-        {
-            dest->index[k++] = a->index[i];
-        }
-    }
-    dest->isize = k;
-}
-
-/*!
- * \param[in]  a    First index group.
- * \param[in]  b    Second index group.
- * \returns    Size of the difference \p a - \p b.
- */
-int
-gmx_ana_index_difference_size(gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int i, j, k;
-
-    for (i = j = k = 0; i < a->isize; ++i)
-    {
-        while (j < b->isize && b->index[j] < a->index[i])
-        {
-            ++j;
-        }
-        if (j == b->isize || b->index[j] != a->index[i])
-        {
-            ++k;
-        }
-    }
-    return k;
-}
-
-/*!
- * \param[out] dest1 Output group 1 (will equal \p g).
- * \param[out] dest2 Output group 2 (will equal \p src - \p g).
- * \param[in]  src   Group to be partitioned.
- * \param[in]  g     One partition.
- *
- * \pre \p g is a subset of \p src and both sets are sorted
- * \pre \p dest1 has allocated storage to store \p src
- * \post \p dest1 == \p g
- * \post \p dest2 == \p src - \p g
- *
- * No storage should be allocated for \p dest2; after the call,
- * \p dest2->index points to the memory allocated for \p dest1
- * (to a part that is not used by \p dest1).
- *
- * The calculation can be performed in-place by setting \p dest1 equal to
- * \p src.
- */
-void
-gmx_ana_index_partition(gmx_ana_index_t *dest1, gmx_ana_index_t *dest2,
-                        gmx_ana_index_t *src, gmx_ana_index_t *g)
-                     
-{
-    int i, j, k;
-
-    dest2->index = dest1->index + g->isize;
-    dest2->isize = src->isize - g->isize;
-    for (i = g->isize-1, j = src->isize-1, k = dest2->isize-1; i >= 0; --i, --j)
-    {
-        while (j >= 0 && src->index[j] != g->index[i])
-        {
-            dest2->index[k--] = src->index[j--];
-        }
-    }
-    while (j >= 0)
-    {
-        dest2->index[k--] = src->index[j--];
-    }
-    gmx_ana_index_copy(dest1, g, FALSE);
-}
-
-/*!
- * \param[out] dest Output index group (the union of \p a and \p b).
- * \param[in]  a    First index group.
- * \param[in]  b    Second index group.
- *
- * \p a and \p b can have common items.
- * \p dest can equal \p a or \p b.
- *
- * \see gmx_ana_index_merge()
- */
-void
-gmx_ana_index_union(gmx_ana_index_t *dest,
-                    gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int dsize;
-    int i, j, k;
-
-    dsize = gmx_ana_index_difference_size(b, a);
-    i = a->isize - 1;
-    j = b->isize - 1;
-    dest->isize = a->isize + dsize;
-    for (k = dest->isize - 1; k >= 0; k--)
-    {
-        if (i < 0 || (j >= 0 && a->index[i] < b->index[j]))
-        {
-            dest->index[k] = b->index[j--];
-        }
-        else
-        {
-            if (j >= 0 && a->index[i] == b->index[j])
-            {
-                --j;
-            }
-            dest->index[k] = a->index[i--];
-        }
-    }
-}
-
-/*!
- * \param[out] dest Output index group (the union of \p a and \p b).
- * \param[in]  a    First index group.
- * \param[in]  b    Second index group.
- *
- * \p a and \p b should not have common items.
- * \p dest can equal \p a or \p b.
- *
- * \see gmx_ana_index_union()
- */
-void
-gmx_ana_index_merge(gmx_ana_index_t *dest,
-                    gmx_ana_index_t *a, gmx_ana_index_t *b)
-{
-    int i, j, k;
-
-    i = a->isize - 1;
-    j = b->isize - 1;
-    dest->isize = a->isize + b->isize;
-    for (k = dest->isize - 1; k >= 0; k--)
-    {
-        if (i < 0 || (j >= 0 && a->index[i] < b->index[j]))
-        {
-            dest->index[k] = b->index[j--];
-        }
-        else
-        {
-            dest->index[k] = a->index[i--];
-        }
-    }
-}
-
-/********************************************************************
- * gmx_ana_indexmap_t and related things
- ********************************************************************/
-
-/*!
- * \param[in,out] t    Output block.
- * \param[in]  top  Topology structure
- *   (only used if \p type is \ref INDEX_RES or \ref INDEX_MOL, can be NULL
- *   otherwise).
- * \param[in]  g    Index group
- *   (can be NULL if \p type is \ref INDEX_UNKNOWN).
- * \param[in]  type Type of partitioning to make.
- * \param[in]  bComplete
- *   If TRUE, the index group is expanded to include any residue/molecule
- *   (depending on \p type) that is partially contained in the group.
- *   If \p type is not INDEX_RES or INDEX_MOL, this has no effect.
- *
- * \p m should have been initialized somehow (calloc() is enough) unless
- * \p type is INDEX_UNKNOWN.
- * \p g should be sorted.
- */
-void
-gmx_ana_index_make_block(t_blocka *t, t_topology *top, gmx_ana_index_t *g,
-                         e_index_t type, gmx_bool bComplete)
-{
-    int      i, j, ai;
-    int      id, cur;
-
-    if (type == INDEX_UNKNOWN)
-    {
-        t->nr           = 1;
-        snew(t->index, 2);
-        t->nalloc_index = 2;
-        t->index[0]     = 0;
-        t->index[1]     = 0;
-        t->nra          = 0;
-        t->a            = NULL;
-        t->nalloc_a     = 0;
-        return;
-    }
-
-    /* bComplete only does something for INDEX_RES or INDEX_MOL, so turn it
-     * off otherwise. */
-    if (type != INDEX_RES && type != INDEX_MOL)
-    {
-        bComplete = FALSE;
-    }
-    /* Allocate memory for the atom array and fill it unless we are using
-     * completion. */
-    if (bComplete)
-    {
-        t->nra = 0;
-        /* We may allocate some extra memory here because we don't know in
-         * advance how much will be needed. */
-        if (t->nalloc_a < top->atoms.nr)
-        {
-            srenew(t->a, top->atoms.nr);
-            t->nalloc_a = top->atoms.nr;
-        }
-    }
-    else
-    {
-        t->nra      = g->isize;
-        if (t->nalloc_a < g->isize)
-        {
-            srenew(t->a, g->isize);
-            t->nalloc_a = g->isize;
-        }
-        memcpy(t->a, g->index, g->isize*sizeof(*(t->a)));
-    }
-
-    /* Allocate memory for the block index. We don't know in advance
-     * how much will be needed, so we allocate some extra and free it in the
-     * end. */
-    if (t->nalloc_index < g->isize + 1)
-    {
-        srenew(t->index, g->isize + 1);
-        t->nalloc_index = g->isize + 1;
-    }
-    /* Clear counters */
-    t->nr = 0;
-    j = 0; /* j is used by residue completion for the first atom not stored */
-    id = cur = -1;
-    for (i = 0; i < g->isize; ++i)
-    {
-        ai = g->index[i];
-        /* Find the ID number of the atom/residue/molecule corresponding to
-         * atom ai. */
-        switch (type)
-        {
-            case INDEX_ATOM:
-                id = ai;
-                break;
-            case INDEX_RES:
-                id = top->atoms.atom[ai].resind;
-                break;
-            case INDEX_MOL:
-                while (ai >= top->mols.index[id+1])
-                {
-                    id++;
-                }
-                break;
-            case INDEX_UNKNOWN: /* Should not occur */
-            case INDEX_ALL:
-                id = 0;
-                break;
-        }
-        /* If this is the first atom in a new block, initialize the block. */
-        if (id != cur)
-        {
-            if (bComplete)
-            {
-                /* For completion, we first set the start of the block. */
-                t->index[t->nr++] = t->nra;
-                /* And then we find all the atoms that should be included. */
-                switch (type)
-                {
-                    case INDEX_RES:
-                        while (top->atoms.atom[j].resind != id)
-                        {
-                            ++j;
-                        }
-                        while (j < top->atoms.nr && top->atoms.atom[j].resind == id)
-                        {
-                            t->a[t->nra++] = j;
-                            ++j;
-                        }
-                        break;
-
-                    case INDEX_MOL:
-                        for (j = top->mols.index[id]; j < top->mols.index[id+1]; ++j)
-                        {
-                            t->a[t->nra++] = j;
-                        }
-                        break;
-
-                    default: /* Should not be reached */
-                        gmx_bug("internal error");
-                        break;
-                }
-            }
-            else
-            {
-                /* If not using completion, simply store the start of the block. */
-                t->index[t->nr++] = i;
-            }
-            cur = id;
-        }
-    }
-    /* Set the end of the last block */
-    t->index[t->nr] = t->nra;
-    /* Free any unnecessary memory */
-    srenew(t->index, t->nr+1);
-    t->nalloc_index = t->nr+1;
-    if (bComplete)
-    {
-        srenew(t->a, t->nra);
-        t->nalloc_a = t->nra;
-    }
-}
-
-/*!
- * \param[in] g   Index group to check.
- * \param[in] b   Block data to check against.
- * \returns   TRUE if \p g consists of one or more complete blocks from \p b,
- *   FALSE otherwise.
- *
- * The atoms in \p g are assumed to be sorted.
- */
-gmx_bool
-gmx_ana_index_has_full_blocks(gmx_ana_index_t *g, t_block *b)
-{
-    int  i, j, bi;
-
-    i = bi = 0;
-    /* Each round in the loop matches one block */
-    while (i < g->isize)
-    {
-        /* Find the block that begins with the first unmatched atom */
-        while (bi < b->nr && b->index[bi] != g->index[i])
-        {
-            ++bi;
-        }
-        /* If not found, or if too large, return */
-        if (bi == b->nr || i + b->index[bi+1] -  b->index[bi] > g->isize)
-        {
-            return FALSE;
-        }
-        /* Check that the block matches the index */
-        for (j = b->index[bi]; j < b->index[bi+1]; ++j, ++i)
-        {
-            if (g->index[i] != j)
-            {
-                return FALSE;
-            }
-        }
-        /* Move the search to the next block */
-        ++bi;
-    }
-    return TRUE;
-}
-
-/*!
- * \param[in] g   Index group to check.
- * \param[in] b   Block data to check against.
- * \returns   TRUE if \p g consists of one or more complete blocks from \p b,
- *   FALSE otherwise.
- *
- * The atoms in \p g and \p b->a are assumed to be in the same order.
- */
-gmx_bool
-gmx_ana_index_has_full_ablocks(gmx_ana_index_t *g, t_blocka *b)
-{
-    int  i, j, bi;
-
-    i = bi = 0;
-    /* Each round in the loop matches one block */
-    while (i < g->isize)
-    {
-        /* Find the block that begins with the first unmatched atom */
-        while (bi < b->nr && b->a[b->index[bi]] != g->index[i])
-        {
-            ++bi;
-        }
-        /* If not found, or if too large, return */
-        if (bi == b->nr || i + b->index[bi+1] -  b->index[bi] > g->isize)
-        {
-            return FALSE;
-        }
-        /* Check that the block matches the index */
-        for (j = b->index[bi]; j < b->index[bi+1]; ++j, ++i)
-        {
-            if (b->a[j] != g->index[i])
-            {
-                return FALSE;
-            }
-        }
-        /* Move the search to the next block */
-        ++bi;
-    }
-    return TRUE;
-}
-
-/*!
- * \param[in] g     Index group to check.
- * \param[in] type  Block data to check against.
- * \param[in] top   Topology data.
- * \returns   TRUE if \p g consists of one or more complete elements of type
- *   \p type, FALSE otherwise.
- *
- * If \p type is \ref INDEX_ATOM, the return value is always TRUE.
- * If \p type is \ref INDEX_UNKNOWN or \ref INDEX_ALL, the return value is
- * always FALSE.
- */
-gmx_bool
-gmx_ana_index_has_complete_elems(gmx_ana_index_t *g, e_index_t type,
-                                 t_topology *top)
-{
-    switch (type)
-    {
-        case INDEX_UNKNOWN:
-        case INDEX_ALL:
-            return FALSE;
-
-        case INDEX_ATOM:
-            return TRUE;
-
-        case INDEX_RES:
-        {
-            int      i, ai;
-            int      id, prev;
-
-            prev = -1;
-            for (i = 0; i < g->isize; ++i)
-            {
-                ai = g->index[i];
-                id = top->atoms.atom[ai].resind;
-                if (id != prev)
-                {
-                    if (ai > 0 && top->atoms.atom[ai-1].resind == id)
-                    {
-                        return FALSE;
-                    }
-                    if (i > 0 && g->index[i-1] < top->atoms.nr - 1
-                        && top->atoms.atom[g->index[i-1]+1].resind == prev)
-                    {
-                        return FALSE;
-                    }
-                }
-                prev = id;
-            }
-            if (g->index[i-1] < top->atoms.nr - 1
-                && top->atoms.atom[g->index[i-1]+1].resind == prev)
-            {
-                return FALSE;
-            }
-            break;
-        }
-
-        case INDEX_MOL:
-            return gmx_ana_index_has_full_blocks(g, &top->mols);
-    }
-    return TRUE;
-}
-
-/*!
- * \param[out] m      Output structure.
- *
- * Any contents of \p m are discarded without freeing.
- */
-void
-gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m)
-{
-    m->type              = INDEX_UNKNOWN;
-    m->nr                = 0;
-    m->refid             = NULL;
-    m->mapid             = NULL;
-    m->mapb.nr           = 0;
-    m->mapb.index        = NULL;
-    m->mapb.nalloc_index = 0;
-    m->orgid             = NULL;
-    m->b.nr              = 0;
-    m->b.index           = NULL;
-    m->b.nra             = 0;
-    m->b.a               = NULL;
-    m->b.nalloc_index    = 0;
-    m->b.nalloc_a        = 0;
-    m->bStatic           = TRUE;
-    m->bMapStatic        = TRUE;
-}
-
-/*!
- * \param[in,out] m      Mapping structure.
- * \param[in]     nr     Maximum number of blocks to reserve space for.
- * \param[in]     isize  Maximum number of atoms to reserve space for.
- */
-void
-gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize)
-{
-    if (m->mapb.nalloc_index < nr + 1)
-    {
-        srenew(m->refid,      nr);
-        srenew(m->mapid,      nr);
-        srenew(m->orgid,      nr);
-        srenew(m->mapb.index, nr + 1);
-        srenew(m->b.index,    nr + 1);
-        m->mapb.nalloc_index = nr + 1;
-        m->b.nalloc_index    = nr + 1;
-    }
-    if (m->b.nalloc_a < isize)
-    {
-        srenew(m->b.a,        isize);
-        m->b.nalloc_a = isize;
-    }
-}
-
-/*!
- * \param[in,out] m    Mapping structure to initialize.
- * \param[in]     g    Index group to map
- *   (can be NULL if \p type is \ref INDEX_UNKNOWN).
- * \param[in]     top  Topology structure
- *   (can be NULL if \p type is not \ref INDEX_RES or \ref INDEX_MOL).
- * \param[in]     type Type of mapping to construct.
- *
- * Initializes a new index group mapping.
- * The index group provided to gmx_ana_indexmap_update() should always be a
- * subset of the \p g given here.
- *
- * \p m should have been initialized somehow (calloc() is enough).
- */
-void
-gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
-                      t_topology *top, e_index_t type)
-{
-    int      i, ii, mi;
-
-    m->type   = type;
-    gmx_ana_index_make_block(&m->b, top, g, type, FALSE);
-    gmx_ana_indexmap_reserve(m, m->b.nr, m->b.nra);
-    m->nr = m->b.nr;
-    for (i = mi = 0; i < m->nr; ++i)
-    {
-        ii = (type == INDEX_UNKNOWN ? 0 : m->b.a[m->b.index[i]]);
-        switch (type)
-        {
-            case INDEX_ATOM:
-                m->orgid[i] = ii;
-                break;
-            case INDEX_RES:
-                m->orgid[i] = top->atoms.atom[ii].resind;
-                break;
-            case INDEX_MOL:
-                while (top->mols.index[mi+1] <= ii)
-                {
-                    ++mi;
-                }
-                m->orgid[i] = mi;
-                break;
-            case INDEX_ALL:
-            case INDEX_UNKNOWN:
-                m->orgid[i] = 0;
-                break;
-        }
-    }
-    for (i = 0; i < m->nr; ++i)
-    {
-        m->refid[i] = i;
-        m->mapid[i] = m->orgid[i];
-    }
-    m->mapb.nr = m->nr;
-    memcpy(m->mapb.index, m->b.index, (m->nr+1)*sizeof(*(m->mapb.index)));
-    m->bStatic    = TRUE;
-    m->bMapStatic = TRUE;
-}
-
-/*!
- * \param[in,out] m    Mapping structure to initialize.
- * \param[in]     b    Block information to use for data.
- *
- * Frees some memory that is not necessary for static index group mappings.
- * Internal pointers are set to point to data in \p b; it is the responsibility
- * of the caller to ensure that the block information matches the contents of
- * the mapping.
- * After this function has been called, the index group provided to
- * gmx_ana_indexmap_update() should always be the same as \p g given here.
- *
- * This function breaks modularity of the index group mapping interface in an
- * ugly way, but allows reducing memory usage of static selections by a
- * significant amount.
- */
-void
-gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b)
-{
-    sfree(m->mapid);
-    m->mapid = m->orgid;
-    sfree(m->b.index);
-    m->b.nalloc_index = 0;
-    m->b.index = b->index;
-    sfree(m->mapb.index);
-    m->mapb.nalloc_index = 0;
-    m->mapb.index = m->b.index;
-    sfree(m->b.a);
-    m->b.nalloc_a = 0;
-    m->b.a = b->a;
-}
-
-/*!
- * \param[in,out] dest Destination data structure.
- * \param[in]     src  Source mapping.
- * \param[in]     bFirst If TRUE, memory is allocated for \p dest and a full
- *   copy is made; otherwise, only variable parts are copied, and no memory
- *   is allocated.
- *
- * \p dest should have been initialized somehow (calloc() is enough).
- */
-void
-gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, gmx_bool bFirst)
-{
-    if (bFirst)
-    {
-        gmx_ana_indexmap_reserve(dest, src->b.nr, src->b.nra);
-        dest->type       = src->type;
-        dest->b.nr       = src->b.nr;
-        dest->b.nra      = src->b.nra;
-        memcpy(dest->orgid,      src->orgid,      dest->b.nr*sizeof(*dest->orgid));
-        memcpy(dest->b.index,    src->b.index,   (dest->b.nr+1)*sizeof(*dest->b.index));
-        memcpy(dest->b.a,        src->b.a,        dest->b.nra*sizeof(*dest->b.a));
-    }
-    dest->nr         = src->nr;
-    dest->mapb.nr    = src->mapb.nr;
-    memcpy(dest->refid,      src->refid,      dest->nr*sizeof(*dest->refid));
-    memcpy(dest->mapid,      src->mapid,      dest->nr*sizeof(*dest->mapid));
-    memcpy(dest->mapb.index, src->mapb.index,(dest->mapb.nr+1)*sizeof(*dest->mapb.index));
-    dest->bStatic    = src->bStatic;
-    dest->bMapStatic = src->bMapStatic;
-}
-
-/*!
- * \param[in,out] m         Mapping structure.
- * \param[in]     g         Current index group.
- * \param[in]     bMaskOnly TRUE if the unused blocks should be masked with
- *   -1 instead of removing them.
- *
- * Updates the index group mapping with the new index group \p g.
- *
- * \see gmx_ana_indexmap_t
- */
-void
-gmx_ana_indexmap_update(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
-                        gmx_bool bMaskOnly)
-{
-    int i, j, bi, bj;
-    gmx_bool bStatic;
-
-    /* Process the simple cases first */
-    if (m->type == INDEX_UNKNOWN && m->b.nra == 0)
-    {
-        return;
-    }
-    if (m->type == INDEX_ALL)
-    {
-        if (m->b.nr > 0)
-        {
-            m->mapb.index[1] = g->isize;
-        }
-        return;
-    }
-    /* Reset the reference IDs and mapping if necessary */
-    bStatic = (g->isize == m->b.nra && m->nr == m->b.nr);
-    if (bStatic || bMaskOnly)
-    {
-        if (!m->bStatic)
-        {
-            for (bj = 0; bj < m->b.nr; ++bj)
-            {
-                m->refid[bj] = bj;
-            }
-        }
-        if (!m->bMapStatic)
-        {
-            for (bj = 0; bj < m->b.nr; ++bj)
-            {
-                m->mapid[bj] = m->orgid[bj];
-            }
-            for (bj = 0; bj <= m->b.nr; ++bj)
-            {
-                m->mapb.index[bj] = m->b.index[bj];
-            }
-            m->bMapStatic = TRUE;
-        }
-    }
-    /* Exit immediately if the group is static */
-    if (bStatic)
-    {
-        m->bStatic = TRUE;
-        return;
-    }
-
-    if (bMaskOnly)
-    {
-        m->nr = m->b.nr;
-        for (i = j = bj = 0; i < g->isize; ++i, ++j)
-        {
-            /* Find the next atom in the block */
-            while (m->b.a[j] != g->index[i])
-            {
-                ++j;
-            }
-            /* Mark blocks that did not contain any atoms */
-            while (bj < m->b.nr && m->b.index[bj+1] <= j)
-            {
-                m->refid[bj++] = -1;
-            }
-            /* Advance the block index if we have reached the next block */
-            if (m->b.index[bj] <= j)
-            {
-                ++bj;
-            }
-        }
-        /* Mark the last blocks as not accessible */
-        while (bj < m->b.nr)
-        {
-            m->refid[bj++] = -1;
-        }
-    }
-    else
-    {
-        for (i = j = bi = 0, bj = -1; i < g->isize; ++i)
-        {
-            /* Find the next atom in the block */
-            while (m->b.a[j] != g->index[i])
-            {
-                ++j;
-            }
-            /* If we have reached a new block, add it */
-            if (m->b.index[bj+1] <= j)
-            {
-                /* Skip any blocks in between */
-                while (bj < m->b.nr && m->b.index[bj+1] <= j)
-                {
-                    ++bj;
-                }
-                m->refid[bi] = bj;
-                m->mapid[bi] = m->orgid[bj];
-                m->mapb.index[bi] = i;
-                bi++;
-            }
-        }
-        /* Update the number of blocks */
-        m->mapb.index[bi] = g->isize;
-        m->nr             = bi;
-        m->bMapStatic     = FALSE;
-    }
-    m->mapb.nr = m->nr;
-    m->bStatic = FALSE;
-}
-
-/*!
- * \param[in,out] m         Mapping structure to free.
- *
- * All the memory allocated for the mapping structure is freed, and
- * the pointers set to NULL.
- * The pointer \p m is not freed.
- */
-void
-gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m)
-{
-    sfree(m->refid);
-    if (m->mapid != m->orgid)
-    {
-        sfree(m->mapid);
-    }
-    if (m->mapb.nalloc_index > 0)
-    {
-        sfree(m->mapb.index);
-    }
-    sfree(m->orgid);
-    if (m->b.nalloc_index > 0)
-    {
-        sfree(m->b.index);
-    }
-    if (m->b.nalloc_a > 0)
-    {
-        sfree(m->b.a);
-    }
-    gmx_ana_indexmap_clear(m);
-}
diff --git a/src/gmxlib/trajana/nbsearch.c b/src/gmxlib/trajana/nbsearch.c
deleted file mode 100644 (file)
index a0a0861..0000000
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \page nbsearch Neighborhood search routines
- *
- * Functions to find particles within a neighborhood of a set of particles
- * are defined in nbsearch.h.
- * The usage is simple: a data structure is allocated with
- * gmx_ana_nbsearch_create(), and the box shape and reference positions for a
- * frame are set using gmx_ana_nbsearch_init() or gmx_ana_nbsearch_pos_init().
- * Searches can then be performed with gmx_ana_nbsearch_is_within() and
- * gmx_ana_nbsearch_mindist(), or with versions that take the \c gmx_ana_pos_t
- * data structure.
- * When the data structure is no longer required, it can be freed with
- * gmx_ana_nbsearch_free().
- *
- * \internal
- *
- * \todo
- * The grid implementation could still be optimized in several different ways:
- *   - Triclinic grid cells are not the most efficient shape, but make PBC
- *     handling easier.
- *   - Precalculating the required PBC shift for a pair of cells outside the
- *     inner loop. After this is done, it should be quite straightforward to
- *     move to rectangular cells.
- *   - Pruning grid cells from the search list if they are completely outside
- *     the sphere that is being considered.
- *   - A better heuristic could be added for falling back to simple loops for a
- *     small number of reference particles.
- *   - A better heuristic for selecting the grid size.
- *   - A multi-level grid implementation could be used to be able to use small
- *     grids for short cutoffs with very inhomogeneous particle distributions
- *     without a memory cost.
- */
-/*! \internal \file
- * \brief Implementation of functions in nbsearch.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-
-#include <smalloc.h>
-#include <typedefs.h>
-#include <pbc.h>
-#include <vec.h>
-
-#include <nbsearch.h>
-#include <position.h>
-
-/*! \internal \brief
- * Data structure for neighborhood searches.
- */
-struct gmx_ana_nbsearch_t
-{
-    /** The cutoff. */
-    real           cutoff;
-    /** The cutoff squared. */
-    real           cutoff2;
-    /** Maximum number of reference points. */
-    int            maxnref;
-
-    /** Number of reference points for the current frame. */
-    int            nref;
-    /** Reference point positions. */
-    rvec          *xref;
-    /** Reference position ids (NULL if not available). */
-    int           *refid;
-    /** PBC data. */
-    t_pbc         *pbc;
-
-    /** Number of excluded reference positions for current test particle. */
-    int            nexcl;
-    /** Exclusions for current test particle. */
-    int           *excl;
-
-    /** Whether to try grid searching. */
-    gmx_bool           bTryGrid;
-    /** Whether grid searching is actually used for the current positions. */
-    gmx_bool           bGrid;
-    /** Array allocated for storing in-unit-cell reference positions. */
-    rvec          *xref_alloc;
-    /** FALSE if the box is rectangular. */
-    gmx_bool           bTric;
-    /** Box vectors of a single grid cell. */
-    matrix         cellbox;
-    /** The reciprocal cell vectors as columns; the inverse of \p cellbox. */
-    matrix         recipcell;
-    /** Number of cells along each dimension. */
-    ivec           ncelldim;
-    /** Total number of cells. */
-    int            ncells;
-    /** Number of reference positions in each cell. */
-    int           *ncatoms;
-    /** List of reference positions in each cell. */
-    atom_id      **catom;
-    /** Allocation counts for each \p catom[i]. */
-    int           *catom_nalloc;
-    /** Allocation count for the per-cell arrays. */
-    int            cells_nalloc;
-    /** Number of neighboring cells to consider. */
-    int            ngridnb;
-    /** Offsets of the neighboring cells to consider. */
-    ivec          *gnboffs;
-    /** Allocation count for \p gnboffs. */
-    int            gnboffs_nalloc;
-
-    /** Stores test position during a pair loop. */
-    rvec           xtest;
-    /** Stores the previous returned position during a pair loop. */
-    int            previ;
-    /** Stores the current exclusion index during loops. */
-    int            exclind;
-    /** Stores the test particle cell index during loops. */
-    ivec           testcell;
-    /** Stores the current cell neighbor index during pair loops. */
-    int            prevnbi;
-    /** Stores the index within the current cell during pair loops. */
-    int            prevcai;
-};
-
-/*!
- * \param[out] data   Neighborhood search data structure pointer to initialize.
- * \param[in]  cutoff Cutoff distance for the search
- *   (<=0 stands for no cutoff).
- * \param[in]  maxn   Maximum number of reference particles.
- * \returns    0 on success.
- */
-int
-gmx_ana_nbsearch_create(gmx_ana_nbsearch_t **data, real cutoff, int maxn)
-{
-    gmx_ana_nbsearch_t *d;
-    
-    snew(d, 1);
-    d->bTryGrid = TRUE;
-    if (cutoff <= 0)
-    {
-        cutoff = GMX_REAL_MAX;
-        d->bTryGrid = FALSE;
-    }
-    d->cutoff = cutoff;
-    d->cutoff2 = sqr(cutoff);
-    d->maxnref = maxn;
-
-    d->xref = NULL;
-    d->nexcl = 0;
-    d->exclind = 0;
-
-    d->xref_alloc = NULL;
-    d->ncells = 0;
-    d->ncatoms = NULL;
-    d->catom = NULL;
-    d->catom_nalloc = 0;
-    d->cells_nalloc = 0;
-
-    d->ngridnb = 0;
-    d->gnboffs = NULL;
-    d->gnboffs_nalloc = 0;
-
-    *data = d;
-    return 0;
-}
-
-/*!
- * \param     d Data structure to free.
- *
- * After the call, the pointer \p d is no longer valid.
- */
-void
-gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d)
-{
-    sfree(d->xref_alloc);
-    sfree(d->ncatoms);
-    if (d->catom)
-    {
-        int ci;
-
-        for (ci = 0; ci < d->ncells; ++ci)
-        {
-            sfree(d->catom[ci]);
-        }
-        sfree(d->catom);
-    }
-    sfree(d->catom_nalloc);
-    sfree(d->gnboffs);
-    sfree(d);
-}
-
-/*! \brief
- * Calculates offsets to neighboring grid cells that should be considered.
- *
- * \param[in,out] d    Grid information.
- * \param[in]     pbc  Information about the box.
- */
-static void
-grid_init_cell_nblist(gmx_ana_nbsearch_t *d, t_pbc *pbc)
-{
-    int   maxx, maxy, maxz;
-    int   x, y, z, i;
-    real  rvnorm;
-
-    /* Find the extent of the sphere in triclinic coordinates */
-    maxz = (int)(d->cutoff * d->recipcell[ZZ][ZZ]) + 1;
-    rvnorm = sqrt(sqr(d->recipcell[YY][YY]) + sqr(d->recipcell[ZZ][YY]));
-    maxy = (int)(d->cutoff * rvnorm) + 1;
-    rvnorm = sqrt(sqr(d->recipcell[XX][XX]) + sqr(d->recipcell[YY][XX])
-                  + sqr(d->recipcell[ZZ][XX]));
-    maxx = (int)(d->cutoff * rvnorm) + 1;
-
-    /* Calculate the number of cells and reallocate if necessary */
-    d->ngridnb = (2 * maxx + 1) * (2 * maxy + 1) * (2 * maxz + 1);
-    if (d->gnboffs_nalloc < d->ngridnb)
-    {
-        d->gnboffs_nalloc = d->ngridnb;
-        srenew(d->gnboffs, d->gnboffs_nalloc);
-    }
-
-    /* Store the whole cube */
-    /* TODO: Prune off corners that are not needed */
-    i = 0;
-    for (x = -maxx; x <= maxx; ++x)
-    {
-        for (y = -maxy; y <= maxy; ++y)
-        {
-            for (z = -maxz; z <= maxz; ++z)
-            {
-                d->gnboffs[i][XX] = x;
-                d->gnboffs[i][YY] = y;
-                d->gnboffs[i][ZZ] = z;
-                ++i;
-            }
-        }
-    }
-}
-
-/*! \brief
- * Determines a suitable grid size.
- *
- * \param[in,out] d    Grid information.
- * \param[in]     pbc  Information about the box.
- * \returns  FALSE if grid search is not suitable.
- */
-static gmx_bool
-grid_setup_cells(gmx_ana_nbsearch_t *d, t_pbc *pbc)
-{
-    real targetsize;
-    int  dd;
-
-#ifdef HAVE_CBRT
-    targetsize = cbrt(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
-                      * 10 / d->nref);
-#else
-    targetsize = pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
-                      * 10 / d->nref, 1./3.);
-#endif
-
-    d->ncells = 1;
-    for (dd = 0; dd < DIM; ++dd)
-    {
-        d->ncelldim[dd] = (int)(pbc->box[dd][dd] / targetsize);
-        d->ncells *= d->ncelldim[dd];
-        if (d->ncelldim[dd] < 3)
-        {
-            return FALSE;
-        }
-    }
-    /* Reallocate if necessary */
-    if (d->cells_nalloc < d->ncells)
-    {
-        int  i;
-
-        srenew(d->ncatoms, d->ncells);
-        srenew(d->catom, d->ncells);
-        srenew(d->catom_nalloc, d->ncells);
-        for (i = d->cells_nalloc; i < d->ncells; ++i)
-        {
-            d->catom[i] = NULL;
-            d->catom_nalloc[i] = 0;
-        }
-        d->cells_nalloc = d->ncells;
-    }
-    return TRUE;
-}
-
-/*! \brief
- * Sets ua a search grid for a given box.
- *
- * \param[in,out] d    Grid information.
- * \param[in]     pbc  Information about the box.
- * \returns  FALSE if grid search is not suitable.
- */
-static gmx_bool
-grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc)
-{
-    int dd;
-
-    /* TODO: This check could be improved. */
-    if (0.5*pbc->max_cutoff2 < d->cutoff2)
-    {
-        return FALSE;
-    }
-
-    if (!grid_setup_cells(d, pbc))
-    {
-        return FALSE;
-    }
-
-    d->bTric = TRICLINIC(pbc->box);
-    if (d->bTric)
-    {
-        for (dd = 0; dd < DIM; ++dd)
-        {
-            svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]);
-        }
-        m_inv_ur0(d->cellbox, d->recipcell);
-    }
-    else
-    {
-        for (dd = 0; dd < DIM; ++dd)
-        {
-            d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd];
-            d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd];
-        }
-    }
-    grid_init_cell_nblist(d, pbc);
-    return TRUE;
-}
-
-/*! \brief
- * Maps a point into a grid cell.
- *
- * \param[in]  d    Grid information.
- * \param[in]  x    Point to map.
- * \param[out] cell Indices of the grid cell in which \p x lies.
- *
- * \p x should be in the triclinic unit cell.
- */
-static void
-grid_map_onto(gmx_ana_nbsearch_t *d, const rvec x, ivec cell)
-{
-    int dd;
-
-    if (d->bTric)
-    {
-        rvec tx;
-
-        tmvmul_ur0(d->recipcell, x, tx);
-        for (dd = 0; dd < DIM; ++dd)
-        {
-            cell[dd] = (int)tx[dd];
-        }
-    }
-    else
-    {
-        for (dd = 0; dd < DIM; ++dd)
-        {
-            cell[dd] = (int)(x[dd] * d->recipcell[dd][dd]);
-        }
-    }
-}
-
-/*! \brief
- * Calculates linear index of a grid cell.
- *
- * \param[in]  d    Grid information.
- * \param[in]  cell Cell indices.
- * \returns    Linear index of \p cell.
- */
-static int
-grid_index(gmx_ana_nbsearch_t *d, const ivec cell)
-{
-    return cell[XX] + cell[YY] * d->ncelldim[XX]
-        + cell[ZZ] * d->ncelldim[XX] * d->ncelldim[YY];
-}
-
-/*! \brief
- * Clears all grid cells.
- *
- * \param[in,out] d    Grid information.
- */
-static void
-grid_clear_cells(gmx_ana_nbsearch_t *d)
-{
-    int  ci;
-
-    for (ci = 0; ci < d->ncells; ++ci)
-    {
-        d->ncatoms[ci] = 0;
-    }
-}
-
-/*! \brief
- * Adds an index into a grid cell.
- *
- * \param[in,out] d    Grid information.
- * \param[in]     cell Cell into which \p i should be added.
- * \param[in]     i    Index to add.
- */
-static void
-grid_add_to_cell(gmx_ana_nbsearch_t *d, const ivec cell, int i)
-{
-    int ci = grid_index(d, cell);
-
-    if (d->ncatoms[ci] == d->catom_nalloc[ci])
-    {
-        d->catom_nalloc[ci] += 10;
-        srenew(d->catom[ci], d->catom_nalloc[ci]);
-    }
-    d->catom[ci][d->ncatoms[ci]++] = i;
-}
-
-/*!
- * \param[in,out] d   Neighborhood search data structure.
- * \param[in]     pbc PBC information for the frame.
- * \param[in]     n   Number of reference positions for the frame.
- * \param[in]     x   \p n reference positions for the frame.
- * \returns       0 on success.
- *
- * Initializes the data structure \p d such that it can be used to search
- * for the neighbors of \p x.
- */
-int
-gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, rvec x[])
-{
-    d->pbc  = pbc;
-    d->nref = n;
-    if (!pbc)
-    {
-        d->bGrid = FALSE;
-    }
-    else if (d->bTryGrid)
-    {
-        d->bGrid = grid_set_box(d, pbc);
-    }
-    if (d->bGrid)
-    {
-        int  i;
-
-        if (!d->xref_alloc)
-        {
-            snew(d->xref_alloc, d->maxnref);
-        }
-        d->xref = d->xref_alloc;
-        grid_clear_cells(d);
-
-        for (i = 0; i < n; ++i)
-        {
-            copy_rvec(x[i], d->xref[i]);
-        }
-        put_atoms_in_triclinic_unitcell(ecenterTRIC, pbc->box, n, d->xref);
-        for (i = 0; i < n; ++i)
-        {
-            ivec refcell;
-
-            grid_map_onto(d, d->xref[i], refcell);
-            grid_add_to_cell(d, refcell, i);
-        }
-    }
-    else
-    {
-        d->xref = x;
-    }
-    d->refid = NULL;
-    return 0;
-}
-
-/*!
- * \param[in,out] d   Neighborhood search data structure.
- * \param[in]     pbc PBC information for the frame.
- * \param[in]     p   Reference positions for the frame.
- * \returns       0 on success.
- *
- * A convenience wrapper for gmx_ana_nbsearch_init().
- */
-int
-gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, gmx_ana_pos_t *p)
-{
-    int rc;
-
-    rc = gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
-    d->refid = (p->nr < d->maxnref ? p->m.refid : NULL);
-    return rc;
-}
-
-/*!
- * \param[in,out] d     Neighborhood search data structure.
- * \param[in]     nexcl Number of reference positions to exclude from next
- *      search.
- * \param[in]     excl  Indices of reference positions to exclude.
- * \returns       0 on success.
- *
- * The set exclusions remain in effect until the next call of this function.
- */
-int
-gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
-{
-
-    d->nexcl = nexcl;
-    d->excl = excl;
-    return 0;
-}
-
-/*! \brief
- * Helper function to check whether a reference point should be excluded.
- */
-static gmx_bool
-is_excluded(gmx_ana_nbsearch_t *d, int j)
-{
-    if (d->exclind < d->nexcl)
-    {
-        if (d->refid)
-        {
-            while (d->exclind < d->nexcl && d->refid[j] > d->excl[d->exclind])
-            {
-                ++d->exclind;
-            }
-            if (d->exclind < d->nexcl && d->refid[j] == d->excl[d->exclind])
-            {
-                ++d->exclind;
-                return TRUE;
-            }
-        }
-        else
-        {
-            while (d->bGrid && d->exclind < d->nexcl && d->excl[d->exclind] < j)
-            {
-                ++d->exclind;
-            }
-            if (d->excl[d->exclind] == j)
-            {
-                ++d->exclind;
-                return TRUE;
-            }
-        }
-    }
-    return FALSE;
-}
-
-/*! \brief
- * Initializes a grid search to find reference positions neighboring \p x.
- */
-static void
-grid_search_start(gmx_ana_nbsearch_t *d, rvec x)
-{
-    copy_rvec(x, d->xtest);
-    if (d->bGrid)
-    {
-        put_atoms_in_triclinic_unitcell(ecenterTRIC, d->pbc->box, 1, &d->xtest);
-        grid_map_onto(d, d->xtest, d->testcell);
-        d->prevnbi = 0;
-        d->prevcai = -1;
-    }
-    else
-    {
-        d->previ = -1;
-    }
-    d->exclind = 0;
-}
-
-/*! \brief
- * Does a grid search.
- */
-static gmx_bool
-grid_search(gmx_ana_nbsearch_t *d,
-            gmx_bool (*action)(gmx_ana_nbsearch_t *d, int i, real r2))
-{
-    int  i;
-    rvec dx;
-    real r2;
-
-    if (d->bGrid)
-    {
-        int  nbi, ci, cai;
-
-        nbi = d->prevnbi;
-        cai = d->prevcai + 1;
-
-        for ( ; nbi < d->ngridnb; ++nbi)
-        {
-            ivec cell;
-
-            ivec_add(d->testcell, d->gnboffs[nbi], cell);
-            /* TODO: Support for 2D and screw PBC */
-            cell[XX] = (cell[XX] + d->ncelldim[XX]) % d->ncelldim[XX];
-            cell[YY] = (cell[YY] + d->ncelldim[YY]) % d->ncelldim[YY];
-            cell[ZZ] = (cell[ZZ] + d->ncelldim[ZZ]) % d->ncelldim[ZZ];
-            ci = grid_index(d, cell);
-            /* TODO: Calculate the required PBC shift outside the inner loop */
-            for ( ; cai < d->ncatoms[ci]; ++cai)
-            {
-                i = d->catom[ci][cai];
-                if (is_excluded(d, i))
-                {
-                    continue;
-                }
-                pbc_dx_aiuc(d->pbc, d->xtest, d->xref[i], dx);
-                r2 = norm2(dx);
-                if (r2 <= d->cutoff2)
-                {
-                    if (action(d, i, r2))
-                    {
-                        d->prevnbi = nbi;
-                        d->prevcai = cai;
-                        d->previ   = i;
-                        return TRUE;
-                    }
-                }
-            }
-            d->exclind = 0;
-            cai = 0;
-        }
-    }
-    else
-    {
-        i = d->previ + 1;
-        for ( ; i < d->nref; ++i)
-        {
-            if (is_excluded(d, i))
-            {
-                continue;
-            }
-            if (d->pbc)
-            {
-                pbc_dx(d->pbc, d->xtest, d->xref[i], dx);
-            }
-            else
-            {
-                rvec_sub(d->xtest, d->xref[i], dx);
-            }
-            r2 = norm2(dx);
-            if (r2 <= d->cutoff2)
-            {
-                if (action(d, i, r2))
-                {
-                    d->previ = i;
-                    return TRUE;
-                }
-            }
-        }
-    }
-    return FALSE;
-}
-
-/*! \brief
- * Helper function to use with grid_search() to find the next neighbor.
- *
- * Simply breaks the loop on the first found neighbor.
- */
-static gmx_bool
-within_action(gmx_ana_nbsearch_t *d, int i, real r2)
-{
-    return TRUE;
-}
-
-/*! \brief
- * Helper function to use with grid_search() to find the minimum distance.
- */
-static gmx_bool
-mindist_action(gmx_ana_nbsearch_t *d, int i, real r2)
-{
-    d->cutoff2 = r2;
-    return FALSE;
-}
-
-/*!
- * \param[in] d   Neighborhood search data structure.
- * \param[in] x   Test position.
- * \returns   TRUE if \p x is within the cutoff of any reference position,
- *   FALSE otherwise.
- */
-gmx_bool
-gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x)
-{
-    grid_search_start(d, x);
-    return grid_search(d, &within_action);
-}
-
-/*!
- * \param[in] d   Neighborhood search data structure.
- * \param[in] p   Test positions.
- * \param[in] i   Use the i'th position in \p p for testing.
- * \returns   TRUE if the test position is within the cutoff of any reference
- *   position, FALSE otherwise.
- */
-gmx_bool
-gmx_ana_nbsearch_pos_is_within(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p, int i)
-{
-    return gmx_ana_nbsearch_is_within(d, p->x[i]);
-}
-
-/*!
- * \param[in] d   Neighborhood search data structure.
- * \param[in] x   Test position.
- * \returns   The distance to the nearest reference position, or the cutoff
- *   value if there are no reference positions within the cutoff.
- */
-real
-gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, rvec x)
-{
-    real mind;
-
-    grid_search_start(d, x);
-    grid_search(d, &mindist_action);
-    mind = sqrt(d->cutoff2);
-    d->cutoff2 = sqr(d->cutoff);
-    return mind;
-}
-
-/*!
- * \param[in] d   Neighborhood search data structure.
- * \param[in] p   Test positions.
- * \param[in] i   Use the i'th position in \p p for testing.
- * \returns   The distance to the nearest reference position, or the cutoff
- *   value if there are no reference positions within the cutoff.
- */
-real
-gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p, int i)
-{
-    return gmx_ana_nbsearch_mindist(d, p->x[i]);
-}
-
-/*!
- * \param[in]  d   Neighborhood search data structure.
- * \param[in]  n   Number of test positions in \p x.
- * \param[in]  x   Test positions.
- * \param[out] jp  Index of the reference position in the first pair.
- * \returns    TRUE if there are positions within the cutoff.
- */
-gmx_bool
-gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp)
-{
-    grid_search_start(d, x);
-    return gmx_ana_nbsearch_next_within(d, jp);
-}
-
-/*!
- * \param[in]  d   Neighborhood search data structure.
- * \param[in]  p   Test positions.
- * \param[in]  i   Use the i'th position in \p p.
- * \param[out] jp  Index of the reference position in the first pair.
- * \returns    TRUE if there are positions within the cutoff.
- */
-gmx_bool
-gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p,
-                                  int i, int *jp)
-{
-    return gmx_ana_nbsearch_first_within(d, p->x[i], jp);
-}
-
-/*!
- * \param[in]  d   Neighborhood search data structure.
- * \param[out] jp  Index of the test position in the next pair.
- * \returns    TRUE if there are positions within the cutoff.
- */
-gmx_bool
-gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp)
-{
-    if (grid_search(d, &within_action))
-    {
-        *jp = d->previ;
-        return TRUE;
-    }
-    *jp = -1;
-    return FALSE;
-}
diff --git a/src/gmxlib/trajana/poscalc.c b/src/gmxlib/trajana/poscalc.c
deleted file mode 100644 (file)
index 81259fc..0000000
+++ /dev/null
@@ -1,1464 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal
- * \page poscalcengine Position calculation engine
- *
- * The header file \ref poscalc.h defines an API for calculating positions
- * in an automated way. This is useful mostly in the selection engine, in
- * particular with dynamic selections, because the same COM/COG positions
- * may be needed in several contexts. The API makes it possible to
- * optimize the evaluation such that any heavy calculation is only done once,
- * and the results just copied if needed more than once.
- * The functions also provide a convenient interface for keeping the whole
- * \c gmx_ana_pos_t structure up-to-date.
- *
- * A new collection of position calculations is allocated with
- * gmx_ana_poscalc_coll_create().
- * Calculations within one collection should share the same topology, and
- * they are optimized. Calculations in different collections do not interact.
- * The topology for a collection can be set with
- * gmx_ana_poscalc_coll_set_topology().
- * This needs to be done before calling gmx_ana_poscalc_set_maxindex() for
- * any calculation in the collection, unless that calculation does not
- * require topology information.
- * All memory allocated for a collection and the calculations in it can be
- * freed with gmx_ana_poscalc_coll_free().
- *
- * A new calculation is created with gmx_ana_poscalc_create().
- * If flags need to be adjusted later, gmx_ana_poscalc_set_flags() can be
- * used.
- * After the flags are final, the largest possible index group for which the
- * positions are needed has to be set with gmx_ana_poscalc_set_maxindex().
- * gmx_ana_poscalc_coll_set_topology() should have been called before this
- * function is called.
- * After the above calls, gmx_ana_poscalc_init_pos() can be used to initialize
- * output to a \c gmx_ana_pos_t structure. Several different structures can be
- * initialized for the same calculation; the only requirement is that the
- * structure passed later to gmx_ana_poscalc_update() has been initialized
- * properly.
- * The memory allocated for a calculation can be freed with
- * gmx_ana_poscalc_free().
- *
- * The position evaluation is simple: gmx_ana_poscalc_init_frame() should be
- * called once for each frame, and gmx_ana_poscalc_update() can then be called
- * for each calculation that is needed for that frame.
- *
- * It is also possible to initialize the calculations based on a type provided
- * as a string.
- * The possible strings are returned by gmx_ana_poscalc_create_type_enum(),
- * and the string can be converted to the parameters for
- * gmx_ana_poscalc_create() using gmx_ana_poscalc_type_from_enum().
- * gmx_ana_poscalc_create_enum() is also provided for convenience.
- */
-/*! \internal \file
- * \brief Implementation of functions in poscalc.h.
- *
- * \todo
- * There is probably some room for optimization in the calculation of
- * positions with bases.
- * In particular, the current implementation may do a lot of unnecessary
- * copying.
- * The interface would need to be changed to make it possible to use the
- * same output positions for several calculations.
- *
- * \todo
- * The current algorithm for setting up base calculations could be improved
- * in cases when there are calculations that cannot use a common base but
- * still overlap partially (e.g., with three calculations A, B, and C
- * such that A could use both B and C as a base, but B and C cannot use the
- * same base).
- * Setting up the bases in an optimal manner in every possible situation can
- * be quite difficult unless several bases are allowed for one calculation,
- * but better heuristics could probably be implemented.
- * For best results, the setup should probably be postponed (at least
- * partially) to gmx_ana_poscalc_init_eval().
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <macros.h>
-#include <smalloc.h>
-#include <typedefs.h>
-#include <pbc.h>
-#include <vec.h>
-
-#include <centerofmass.h>
-#include <indexutil.h>
-#include <poscalc.h>
-#include <position.h>
-
-/*! \internal \brief
- * Collection of \c gmx_ana_poscalc_t structures for the same topology.
- *
- * Calculations within the same structure are optimized to eliminate duplicate
- * calculations.
- */
-struct gmx_ana_poscalc_coll_t
-{
-    /*! \brief
-     * Topology data.
-     *
-     * Can be NULL if none of the calculations require topology data or if
-     * gmx_ana_poscalc_coll_set_topology() has not been called.
-     */
-    t_topology               *top;
-    /** Pointer to the first data structure. */
-    gmx_ana_poscalc_t        *first;
-    /** Pointer to the last data structure. */
-    gmx_ana_poscalc_t        *last;
-    /** Whether the collection has been initialized for evaluation. */
-    gmx_bool                      bInit;
-};
-
-/*! \internal \brief
- * Data structure for position calculation.
- */
-struct gmx_ana_poscalc_t
-{
-    /*! \brief
-     * Type of calculation.
-     *
-     * This field may differ from the type requested by the user, because
-     * it is changed internally to the most effective calculation.
-     * For example, if the user requests a COM calculation for residues
-     * consisting of single atoms, it is simply set to POS_ATOM.
-     * To provide a consistent interface to the user, the field \p itype
-     * should be used when information should be given out.
-     */
-    e_poscalc_t               type;
-    /*! \brief
-     * Flags for calculation options.
-     *
-     * See \ref poscalc_flags "documentation of the flags".
-     */
-    int                       flags;
-
-    /*! \brief
-     * Type for the created indices.
-     *
-     * This field always agrees with the type that the user requested, but
-     * may differ from \p type.
-     */
-    e_index_t                 itype;
-    /*! \brief
-     * Block data for the calculation.
-     */
-    t_blocka                  b;
-    /*! \brief
-     * Mapping from the blocks to the blocks of \p sbase.
-     *
-     * If \p sbase is NULL, this field is also.
-     */
-    int                      *baseid;
-    /*! \brief
-     * Maximum evaluation group.
-     */
-    gmx_ana_index_t           gmax;
-
-    /** Position storage for calculations that are used as a base. */
-    gmx_ana_pos_t            *p;
-
-    /** TRUE if the positions have been evaluated for the current frame. */
-    gmx_bool                      bEval;
-    /*! \brief
-     * Base position data for this calculation.
-     *
-     * If not NULL, the centers required by this calculation have
-     * already been calculated in \p sbase.
-     * The structure pointed by \p sbase is always a static calculation.
-     */
-    struct gmx_ana_poscalc_t *sbase;
-    /** Next structure in the linked list of calculations. */
-    struct gmx_ana_poscalc_t *next;
-    /** Previous structure in the linked list of calculations. */
-    struct gmx_ana_poscalc_t *prev;
-    /** Number of references to this structure. */
-    int                       refcount;
-    /** Collection this calculation belongs to. */
-    gmx_ana_poscalc_coll_t   *coll;
-};
-    
-static const char *const poscalc_enum_strings[] = {
-    "atom",
-    "res_com",       "res_cog",
-    "mol_com",       "mol_cog",
-    "whole_res_com", "whole_res_cog",
-    "whole_mol_com", "whole_mol_cog",
-    "part_res_com",  "part_res_cog",
-    "part_mol_com",  "part_mol_cog",
-    "dyn_res_com",   "dyn_res_cog",
-    "dyn_mol_com",   "dyn_mol_cog",
-    NULL,
-};
-#define NENUM asize(poscalc_enum_strings)
-
-/*! \brief
- * Returns the partition type for a given position type.
- *
- * \param [in] type  \c e_poscalc_t value to convert.
- * \returns    Corresponding \c e_indet_t.
- */
-static e_index_t
-index_type_for_poscalc(e_poscalc_t type)
-{
-    switch(type)
-    {
-        case POS_ATOM:    return INDEX_ATOM;
-        case POS_RES:     return INDEX_RES;
-        case POS_MOL:     return INDEX_MOL;
-        case POS_ALL:     return INDEX_ALL;
-        case POS_ALL_PBC: return INDEX_ALL;
-    }
-    return INDEX_UNKNOWN;
-}
-
-/*!
- * \param[in]     post  String (typically an enum command-line argument).
- *   Allowed values: 'atom', 'res_com', 'res_cog', 'mol_com', 'mol_cog',
- *   or one of the last four prepended by 'whole_', 'part_', or 'dyn_'.
- * \param[out]    type  \c e_poscalc_t corresponding to \p post.
- * \param[in,out] flags Flags corresponding to \p post.
- *   On input, the flags should contain the default flags.
- *   On exit, the flags \ref POS_MASS, \ref POS_COMPLMAX and
- *   \ref POS_COMPLWHOLE have been set according to \p post
- *   (the completion flags are left at the default values if no completion
- *   prefix is given).
- * \returns       0 if \p post is one of the valid strings, EINVAL otherwise.
- *
- * \attention
- * Checking is not complete, and other values than those listed above
- * may be accepted for \p post, but the results are undefined.
- */
-int
-gmx_ana_poscalc_type_from_enum(const char *post, e_poscalc_t *type, int *flags)
-{
-    const char *ptr;
-
-    if (post[0] == 'a')
-    {
-        *type   = POS_ATOM;
-        *flags &= ~(POS_MASS | POS_COMPLMAX | POS_COMPLWHOLE);
-        return 0;
-    }
-
-    /* Process the prefix */
-    ptr = post;
-    if (post[0] == 'w')
-    {
-        *flags &= ~POS_COMPLMAX;
-        *flags |= POS_COMPLWHOLE;
-        ptr = post + 6;
-    }
-    else if (post[0] == 'p')
-    {
-        *flags &= ~POS_COMPLWHOLE;
-        *flags |= POS_COMPLMAX;
-        ptr = post + 5;
-    }
-    else if (post[0] == 'd')
-    {
-        *flags &= ~(POS_COMPLMAX | POS_COMPLWHOLE);
-        ptr = post + 4;
-    }
-
-    if (ptr[0] == 'r')
-    {
-        *type = POS_RES;
-    }
-    else if (ptr[0] == 'm')
-    {
-        *type = POS_MOL;
-    }
-    else
-    {
-        gmx_incons("unknown position calculation type");
-        return EINVAL;
-    }
-    if (ptr[6] == 'm')
-    {
-        *flags |= POS_MASS;
-    }
-    else if (ptr[6] == 'g')
-    {
-        *flags &= ~POS_MASS;
-    }
-    else
-    {
-        gmx_incons("unknown position calculation type");
-        return EINVAL;
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  bAtom    If TRUE, the "atom" value is included.
- * \returns    NULL-terminated array of strings that contains the string
- *   values acceptable for gmx_ana_poscalc_type_from_enum().
- *
- * The first string in the returned list is always NULL to allow the list to
- * be used with Gromacs command-line parsing.
- */
-const char **
-gmx_ana_poscalc_create_type_enum(gmx_bool bAtom)
-{
-    const char **pcenum;
-    size_t       i;
-
-    if (bAtom)
-    {
-        snew(pcenum, NENUM+1);
-        for (i = 0; i < NENUM; ++i)
-        {
-            pcenum[i+1] = poscalc_enum_strings[i];
-        }
-    }
-    else
-    {
-        snew(pcenum, NENUM+1-1);
-        for (i = 1; i < NENUM; ++i)
-        {
-            pcenum[i] = poscalc_enum_strings[i];
-        }
-    }
-    pcenum[0] = NULL;
-    return pcenum;
-}
-
-/*!
- * \param[out] pccp   Allocated position calculation collection.
- * \returns    0 for success.
- */
-int
-gmx_ana_poscalc_coll_create(gmx_ana_poscalc_coll_t **pccp)
-{
-    gmx_ana_poscalc_coll_t *pcc;
-
-    snew(pcc, 1);
-    pcc->top   = NULL;
-    pcc->first = NULL;
-    pcc->last  = NULL;
-    pcc->bInit = FALSE;
-    *pccp = pcc;
-    return 0;
-}
-
-/*!
- * \param[in,out] pcc   Position calculation collection data structure.
- * \param[in]     top   Topology data structure.
- *
- * This function should be called to set the topology before using
- * gmx_ana_poscalc_set_maxindex() for any calculation that requires
- * topology information.
- */
-void
-gmx_ana_poscalc_coll_set_topology(gmx_ana_poscalc_coll_t *pcc, t_topology *top)
-{
-    pcc->top = top;
-}
-
-/*!
- * \param[in] pcc   Position calculation collection to free.
- *
- * The pointer \p pcc is invalid after the call.
- * Any calculations in the collection are also freed, no matter how many
- * references to them are left.
- */
-void
-gmx_ana_poscalc_coll_free(gmx_ana_poscalc_coll_t *pcc)
-{
-    while (pcc->first)
-    {
-        gmx_ana_poscalc_free(pcc->first);
-    }
-    sfree(pcc);
-}
-
-/*!
- * \param[in] fp    File handle to receive the output.
- * \param[in] pcc   Position calculation collection to print.
- *
- * The output is very technical, making this function mainly useful for
- * debugging purposes.
- */
-void
-gmx_ana_poscalc_coll_print_tree(FILE *fp, gmx_ana_poscalc_coll_t *pcc)
-{
-    gmx_ana_poscalc_t *pc;
-    int                i, j;
-
-    fprintf(fp, "Position calculations:\n");
-    i  = 1;
-    pc = pcc->first;
-    while (pc)
-    {
-        fprintf(fp, "%2d ", i);
-        switch (pc->type)
-        {
-            case POS_ATOM:    fprintf(fp, "ATOM");    break;
-            case POS_RES:     fprintf(fp, "RES");     break;
-            case POS_MOL:     fprintf(fp, "MOL");     break;
-            case POS_ALL:     fprintf(fp, "ALL");     break;
-            case POS_ALL_PBC: fprintf(fp, "ALL_PBC"); break;
-        }
-        if (pc->itype != index_type_for_poscalc(pc->type))
-        {
-            fprintf(fp, " (");
-            switch (pc->itype)
-            {
-                case INDEX_UNKNOWN: fprintf(fp, "???");  break;
-                case INDEX_ATOM:    fprintf(fp, "ATOM"); break;
-                case INDEX_RES:     fprintf(fp, "RES");  break;
-                case INDEX_MOL:     fprintf(fp, "MOL");  break;
-                case INDEX_ALL:     fprintf(fp, "ALL");  break;
-            }
-            fprintf(fp, ")");
-        }
-        fprintf(fp, " flg=");
-        if (pc->flags & POS_MASS)
-        {
-            fprintf(fp, "M");
-        }
-        if (pc->flags & POS_DYNAMIC)
-        {
-            fprintf(fp, "D");
-        }
-        if (pc->flags & POS_MASKONLY)
-        {
-            fprintf(fp, "A");
-        }
-        if (pc->flags & POS_COMPLMAX)
-        {
-            fprintf(fp, "Cm");
-        }
-        if (pc->flags & POS_COMPLWHOLE)
-        {
-            fprintf(fp, "Cw");
-        }
-        if (!pc->flags)
-        {
-            fprintf(fp, "0");
-        }
-        fprintf(fp, " nr=%d nra=%d", pc->b.nr, pc->b.nra);
-        fprintf(fp, " refc=%d", pc->refcount);
-        fprintf(fp, "\n");
-        if (pc->gmax.nalloc_index > 0)
-        {
-            fprintf(fp, "   Group: ");
-            if (pc->gmax.isize > 20)
-            {
-                fprintf(fp, " %d atoms", pc->gmax.isize);
-            }
-            else
-            {
-                for (j = 0; j < pc->gmax.isize; ++j)
-                {
-                    fprintf(fp, " %d", pc->gmax.index[j] + 1);
-                }
-            }
-            fprintf(fp, "\n");
-        }
-        if (pc->b.nalloc_a > 0)
-        {
-            fprintf(fp, "   Atoms: ");
-            if (pc->b.nra > 20)
-            {
-                fprintf(fp, " %d atoms", pc->b.nra);
-            }
-            else
-            {
-                for (j = 0; j < pc->b.nra; ++j)
-                {
-                    fprintf(fp, " %d", pc->b.a[j] + 1);
-                }
-            }
-            fprintf(fp, "\n");
-        }
-        if (pc->b.nalloc_index > 0)
-        {
-            fprintf(fp, "   Blocks:");
-            if (pc->b.nr > 20)
-            {
-                fprintf(fp, " %d pcs", pc->b.nr);
-            }
-            else
-            {
-                for (j = 0; j <= pc->b.nr; ++j)
-                {
-                    fprintf(fp, " %d", pc->b.index[j]);
-                }
-            }
-            fprintf(fp, "\n");
-        }
-        if (pc->sbase)
-        {
-            gmx_ana_poscalc_t *base;
-
-            fprintf(fp, "   Base: ");
-            j = 1;
-            base = pcc->first;
-            while (base && base != pc->sbase)
-            {
-                ++j;
-                base = base->next;
-            }
-            fprintf(fp, "%d", j);
-            if (pc->baseid && pc->b.nr <= 20)
-            {
-                fprintf(fp, " id:");
-                for (j = 0; j < pc->b.nr; ++j)
-                {
-                    fprintf(fp, " %d", pc->baseid[j]+1);
-                }
-            }
-            fprintf(fp, "\n");
-        }
-        ++i;
-        pc = pc->next;
-    }
-}
-
-/*! \brief
- * Inserts a position calculation structure into its collection.
- *
- * \param pc     Data structure to insert.
- * \param before Data structure before which to insert
- *   (NULL = insert at end).
- *
- * Inserts \p pc to its collection before \p before.
- * If \p before is NULL, \p pc is appended to the list.
- */
-static void
-insert_poscalc(gmx_ana_poscalc_t *pc, gmx_ana_poscalc_t *before)
-{
-    if (before == NULL)
-    {
-        pc->next = NULL;
-        pc->prev = pc->coll->last;
-        if (pc->coll->last)
-        {
-            pc->coll->last->next = pc;
-        }
-        pc->coll->last = pc;
-    }
-    else
-    {
-        pc->prev     = before->prev;
-        pc->next     = before;
-        if (before->prev)
-        {
-            before->prev->next = pc;
-        }
-        before->prev = pc;
-    }
-    if (!pc->prev)
-    {
-        pc->coll->first = pc;
-    }
-}
-
-/*! \brief
- * Removes a position calculation structure from its collection.
- *
- * \param pc    Data structure to remove.
- *
- * Removes \p pc from its collection.
- */
-static void
-remove_poscalc(gmx_ana_poscalc_t *pc)
-{
-    if (pc->prev)
-    {
-        pc->prev->next = pc->next;
-    }
-    else if (pc == pc->coll->first)
-    {
-        pc->coll->first = pc->next;
-    }
-    if (pc->next)
-    {
-        pc->next->prev = pc->prev;
-    }
-    else if (pc == pc->coll->last)
-    {
-        pc->coll->last = pc->prev;
-    }
-    pc->prev = pc->next = NULL;
-}
-
-/*! \brief
- * Initializes position calculation using the maximum possible input index.
- *
- * \param[in,out] pc  Position calculation data structure.
- * \param[in]     g   Maximum index group for the calculation.
- * \param[in]     bBase Whether \p pc will be used as a base or not.
- *
- * \p bBase affects on how the \p pc->gmax field is initialized.
- */
-static void
-set_poscalc_maxindex(gmx_ana_poscalc_t *pc, gmx_ana_index_t *g, gmx_bool bBase)
-{
-    gmx_ana_index_make_block(&pc->b, pc->coll->top, g, pc->itype, pc->flags & POS_COMPLWHOLE);
-    /* Set the type to POS_ATOM if the calculation in fact is such. */
-    if (pc->b.nr == pc->b.nra)
-    {
-        pc->type   = POS_ATOM; 
-        pc->flags &= ~(POS_MASS | POS_COMPLMAX | POS_COMPLWHOLE);
-    }
-    /* Set the POS_COMPLWHOLE flag if the calculation in fact always uses
-     * complete residues and molecules. */
-    if (!(pc->flags & POS_COMPLWHOLE)
-        && (!(pc->flags & POS_DYNAMIC) || (pc->flags & POS_COMPLMAX))
-        && (pc->type == POS_RES || pc->type == POS_MOL)
-        && gmx_ana_index_has_complete_elems(g, pc->itype, pc->coll->top))
-    {
-        pc->flags &= ~POS_COMPLMAX;
-        pc->flags |= POS_COMPLWHOLE;
-    }
-    /* Setup the gmax field */
-    if ((pc->flags & POS_COMPLWHOLE) && !bBase && pc->b.nra > g->isize)
-    {
-        gmx_ana_index_copy(&pc->gmax, g, TRUE);
-        sfree(pc->gmax.name);
-        pc->gmax.name  = NULL;
-    }
-    else
-    {
-        gmx_ana_index_set(&pc->gmax, pc->b.nra, pc->b.a, NULL, 0);
-    }
-}
-
-/*! \brief
- * Checks whether a position calculation should use a base at all.
- *
- * \param[in] pc   Position calculation data to check.
- * \returns   TRUE if \p pc can use a base and gets some benefit out of it,
- *   FALSE otherwise.
- */
-static gmx_bool
-can_use_base(gmx_ana_poscalc_t *pc)
-{
-    /* For atoms, it should be faster to do a simple copy, so don't use a
-     * base. */
-    if (pc->type == POS_ATOM)
-    {
-        return FALSE;
-    }
-    /* For dynamic selections that do not use completion, it is not possible
-     * to use a base. */
-    if ((pc->type == POS_RES || pc->type == POS_MOL)
-        && (pc->flags & POS_DYNAMIC) && !(pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
-    {
-        return FALSE;
-    }
-    /* Dynamic calculations for a single position cannot use a base. */
-    if ((pc->type == POS_ALL || pc->type == POS_ALL_PBC)
-        && (pc->flags & POS_DYNAMIC))
-    {
-        return FALSE;
-    }
-    return TRUE;
-}
-
-/*! \brief
- * Checks whether two position calculations should use a common base.
- *
- * \param[in]     pc1 Calculation 1 to check for.
- * \param[in]     pc2 Calculation 2 to check for.
- * \param[in]     g1  Index group structure that contains the atoms from
- *   \p pc1.
- * \param[in,out] g   Working space, should have enough allocated memory to
- *   contain the intersection of the atoms in \p pc1 and \p pc2.
- * \returns   TRUE if the two calculations should be merged to use a common
- *   base, FALSE otherwise.
- */
-static gmx_bool
-should_merge(gmx_ana_poscalc_t *pc1, gmx_ana_poscalc_t *pc2,
-             gmx_ana_index_t *g1, gmx_ana_index_t *g)
-{
-    gmx_ana_index_t  g2;
-
-    /* Do not merge calculations with different mass weighting. */
-    if ((pc1->flags & POS_MASS) != (pc2->flags & POS_MASS))
-    {
-        return FALSE;
-    }
-    /* Avoid messing up complete calculations. */
-    if ((pc1->flags & POS_COMPLWHOLE) != (pc2->flags & POS_COMPLWHOLE))
-    {
-        return FALSE;
-    }
-    /* Find the overlap between the calculations. */
-    gmx_ana_index_set(&g2, pc2->b.nra, pc2->b.a, NULL, 0);
-    gmx_ana_index_intersection(g, g1, &g2);
-    /* Do not merge if there is no overlap. */
-    if (g->isize == 0)
-    {
-        return FALSE;
-    }
-    /* Full completion calculations always match if the type is correct. */
-    if ((pc1->flags & POS_COMPLWHOLE) && (pc2->flags & POS_COMPLWHOLE)
-        && pc1->type == pc2->type)
-    {
-        return TRUE;
-    }
-    /* The calculations also match if the intersection consists of full
-     * blocks. */
-    if (gmx_ana_index_has_full_ablocks(g, &pc1->b)
-        && gmx_ana_index_has_full_ablocks(g, &pc2->b))
-    {
-        return TRUE;
-    }
-    return FALSE;
-}
-
-/*! \brief
- * Creates a static base for position calculation.
- *
- * \param     pc  Data structure to copy.
- * \returns   Pointer to a newly allocated base for \p pc.
- *
- * Creates and returns a deep copy of \p pc, but clears the
- * \ref POS_DYNAMIC and \ref POS_MASKONLY flags.
- * The newly created structure is set as the base (\c gmx_ana_poscalc_t::sbase)
- * of \p pc and inserted in the collection before \p pc.
- */
-static gmx_ana_poscalc_t *
-create_simple_base(gmx_ana_poscalc_t *pc)
-{
-    gmx_ana_poscalc_t *base;
-    int                flags;
-    int                rc;
-
-    flags = pc->flags & ~(POS_DYNAMIC | POS_MASKONLY);
-    rc = gmx_ana_poscalc_create(&base, pc->coll, pc->type, flags);
-    if (rc != 0)
-    {
-        gmx_fatal(FARGS, "position calculation base creation failed");
-    }
-    set_poscalc_maxindex(base, &pc->gmax, TRUE);
-
-    snew(base->p, 1);
-
-    pc->sbase = base;
-    remove_poscalc(base);
-    insert_poscalc(base, pc);
-
-    return base;
-}
-
-/*! \brief
- * Merges a calculation into another calculation such that the new calculation
- * can be used as a base.
- *
- * \param[in,out] base Base calculation to merge to.
- * \param[in,out] pc   Position calculation to merge to \p base.
- *
- * After the call, \p base can be used as a base for \p pc (or any calculation
- * that used it as a base).
- * It is assumed that any overlap between \p base and \p pc is in complete
- * blocks, i.e., that the merge is possible.
- */
-static void
-merge_to_base(gmx_ana_poscalc_t *base, gmx_ana_poscalc_t *pc)
-{
-    gmx_ana_index_t  gp, gb, g;
-    int              isize, bnr;
-    int              i, j, bi, bj, bo;
-
-    base->flags |= pc->flags & (POS_VELOCITIES | POS_FORCES);
-    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
-    gmx_ana_index_set(&gb, base->b.nra, base->b.a, NULL, 0);
-    isize = gmx_ana_index_difference_size(&gp, &gb);
-    if (isize > 0)
-    {
-        gmx_ana_index_clear(&g);
-        gmx_ana_index_reserve(&g, base->b.nra + isize);
-        /* Find the new blocks */
-        gmx_ana_index_difference(&g, &gp, &gb);
-        /* Count the blocks in g */
-        i = bi = bnr = 0;
-        while (i < g.isize)
-        {
-            while (pc->b.a[pc->b.index[bi]] != g.index[i])
-            {
-                ++bi;
-            }
-            i += pc->b.index[bi+1] - pc->b.index[bi];
-            ++bnr;
-            ++bi;
-        }
-        /* Merge the atoms into a temporary structure */
-        gmx_ana_index_merge(&g, &gb, &g);
-        /* Merge the blocks */
-        srenew(base->b.index, base->b.nr + bnr + 1);
-        i  = g.isize - 1;
-        bi = base->b.nr - 1;
-        bj = pc->b.nr - 1;
-        bo = base->b.nr + bnr - 1;
-        base->b.index[bo+1] = i + 1;
-        while (bo >= 0)
-        {
-            if (bi < 0 || base->b.a[base->b.index[bi+1]-1] != g.index[i])
-            {
-                i -= pc->b.index[bj+1] - pc->b.index[bj];
-                --bj;
-            }
-            else
-            {
-                if (bj >= 0 && pc->b.a[pc->b.index[bj+1]-1] == g.index[i])
-                {
-                    --bj;
-                }
-                i -= base->b.index[bi+1] - base->b.index[bi];
-                --bi;
-            }
-            base->b.index[bo] = i + 1;
-            --bo;
-        }
-        base->b.nr           += bnr;
-        base->b.nalloc_index += bnr;
-        sfree(base->b.a);
-        base->b.nra      = g.isize;
-        base->b.a        = g.index;
-        base->b.nalloc_a = g.isize;
-        /* Refresh the gmax field */
-        gmx_ana_index_set(&base->gmax, base->b.nra, base->b.a, NULL, 0);
-    }
-}
-
-/*! \brief
- * Merges two bases into one.
- *
- * \param[in,out] tbase Base calculation to merge to.
- * \param[in]     mbase Base calculation to merge to \p tbase.
- *
- * After the call, \p mbase has been freed and \p tbase is used as the base
- * for all calculations that previously had \p mbase as their base.
- * It is assumed that any overlap between \p tbase and \p mbase is in complete
- * blocks, i.e., that the merge is possible.
- */
-static void
-merge_bases(gmx_ana_poscalc_t *tbase, gmx_ana_poscalc_t *mbase)
-{
-    gmx_ana_poscalc_t *pc;
-
-    merge_to_base(tbase, mbase);
-    remove_poscalc(mbase);
-    /* Set tbase as the base for all calculations that had mbase */
-    pc = tbase->coll->first;
-    while (pc)
-    {
-        if (pc->sbase == mbase)
-        {
-            pc->sbase = tbase;
-            tbase->refcount++;
-        }
-        pc = pc->next;
-    }
-    /* Free mbase */
-    mbase->refcount = 0;
-    gmx_ana_poscalc_free(mbase);
-}
-
-/*! \brief
- * Setups the static base calculation for a position calculation.
- *
- * \param[in,out] pc   Position calculation to setup the base for.
- */
-static void
-setup_base(gmx_ana_poscalc_t *pc)
-{
-    gmx_ana_poscalc_t *base, *pbase, *next;
-    gmx_ana_index_t    gp, g;
-
-    /* Exit immediately if pc should not have a base. */
-    if (!can_use_base(pc))
-    {
-        return;
-    }
-
-    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
-    gmx_ana_index_clear(&g);
-    gmx_ana_index_reserve(&g, pc->b.nra);
-    pbase = pc;
-    base = pc->coll->first;
-    while (base)
-    {
-        /* Save the next calculation so that we can safely delete base */
-        next = base->next;
-        /* Skip pc, calculations that already have a base (we should match the
-         * base instead), as well as calculations that should not have a base.
-         * If the above conditions are met, check whether we should do a
-         * merge.
-         */
-        if (base != pc && !base->sbase && can_use_base(base)
-            && should_merge(pbase, base, &gp, &g))
-        {
-            /* Check whether this is the first base found */
-            if (pbase == pc)
-            {
-                /* Create a real base if one is not present */
-                if (!base->p)
-                {
-                    pbase = create_simple_base(base);
-                }
-                else
-                {
-                    pbase = base;
-                }
-                /* Make it a base for pc as well */
-                merge_to_base(pbase, pc);
-                pc->sbase = pbase;
-                pbase->refcount++;
-            }
-            else /* This was not the first base */
-            {
-                if (!base->p)
-                {
-                    /* If it is not a real base, just make the new base as
-                     * the base for it as well. */
-                    merge_to_base(pbase, base);
-                    base->sbase = pbase;
-                    pbase->refcount++;
-                }
-                else
-                {
-                    /* If base is a real base, merge it with the new base
-                     * and delete it. */
-                    merge_bases(pbase, base);
-                }
-            }
-            gmx_ana_index_set(&gp, pbase->b.nra, pbase->b.a, NULL, 0);
-            gmx_ana_index_reserve(&g, pc->b.nra);
-        }
-        /* Proceed to the next unchecked calculation */
-        base = next;
-    }
-
-    gmx_ana_index_deinit(&g);
-
-    /* If no base was found, create one if one is required */
-    if (!pc->sbase && (pc->flags & POS_DYNAMIC)
-        && (pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
-    {
-        create_simple_base(pc);
-    }
-}
-
-/*!
- * \param[out] pcp   Position calculation data structure pointer to initialize.
- * \param[in,out] pcc   Position calculation collection.
- * \param[in]  type  Type of calculation.
- * \param[in]  flags Flags for setting calculation options
- *   (see \ref poscalc_flags "documentation of the flags").
- * \returns    0 on success.
- */
-int
-gmx_ana_poscalc_create(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
-                       e_poscalc_t type, int flags)
-{
-    gmx_ana_poscalc_t *pc;
-
-    snew(pc, 1);
-    pc->type     = type;
-    pc->itype    = index_type_for_poscalc(type);
-    gmx_ana_poscalc_set_flags(pc, flags);
-    pc->refcount = 1;
-    pc->coll     = pcc;
-    insert_poscalc(pc, NULL);
-    *pcp = pc;
-    return 0;
-}
-
-/*!
- * \param[out] pcp   Position calculation data structure pointer to initialize.
- * \param[in,out] pcc   Position calculation collection.
- * \param[in]  post  One of the strings acceptable for
- *   gmx_ana_poscalc_type_from_enum().
- * \param[in]  flags Flags for setting calculation options
- *   (see \ref poscalc_flags "documentation of the flags").
- * \returns    0 on success, a non-zero error value on error.
- *
- * This is a convenience wrapper for gmx_ana_poscalc_create().
- * \p flags sets the default calculation options if not overridden by \p post;
- * see gmx_ana_poscalc_type_from_enum().
- *
- * \see gmx_ana_poscalc_create(), gmx_ana_poscalc_type_from_enum()
- */
-int
-gmx_ana_poscalc_create_enum(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
-                            const char *post, int flags)
-{
-    e_poscalc_t  type;
-    int          cflags;
-    int          rc;
-
-    cflags = flags;
-    rc = gmx_ana_poscalc_type_from_enum(post, &type, &cflags);
-    if (rc != 0)
-    {
-        *pcp = NULL;
-        return rc;
-    }
-    return gmx_ana_poscalc_create(pcp, pcc, type, cflags);
-}
-
-/*!
- * \param[in,out] pc    Position calculation data structure.
- * \param[in]     flags New flags.
- *
- * \p flags are added to the old flags.
- * If calculation type is \ref POS_ATOM, \ref POS_MASS is automatically
- * cleared.
- * If both \ref POS_DYNAMIC and \ref POS_MASKONLY are provided,
- * \ref POS_DYNAMIC is cleared.
- * If calculation type is not \ref POS_RES or \ref POS_MOL,
- * \ref POS_COMPLMAX and \ref POS_COMPLWHOLE are automatically cleared.
- */
-void
-gmx_ana_poscalc_set_flags(gmx_ana_poscalc_t *pc, int flags)
-{
-    if (pc->type == POS_ATOM)
-    {
-        flags &= ~POS_MASS;
-    }
-    if (flags & POS_MASKONLY)
-    {
-        flags &= ~POS_DYNAMIC;
-    }
-    if (pc->type != POS_RES && pc->type != POS_MOL)
-    {
-        flags &= ~(POS_COMPLMAX | POS_COMPLWHOLE);
-    }
-    pc->flags |= flags;
-}
-
-/*!
- * \param[in,out] pc  Position calculation data structure.
- * \param[in]     g   Maximum index group for the calculation.
- *
- * Subsequent calls to gmx_ana_poscalc_update() should use only subsets of
- * \p g for evaluation.
- *
- * The topology should have been set for the collection of which \p pc is
- * a member.
- */
-void
-gmx_ana_poscalc_set_maxindex(gmx_ana_poscalc_t *pc, gmx_ana_index_t *g)
-{
-    set_poscalc_maxindex(pc, g, FALSE);
-    setup_base(pc);
-}
-
-/*!
- * \param[in]  pc  Position calculation data structure.
- * \param[out] p   Output positions.
- *
- * Calls to gmx_ana_poscalc_update() using \p pc should use only positions
- * initialized with this function.
- * The \c p->g pointer is initialized to point to an internal group that
- * contains the maximum index group set with gmx_ana_poscalc_set_maxindex().
- */
-void
-gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p)
-{
-    gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, pc->itype);
-    /* Only do the static optimization when there is no completion */
-    if (!(pc->flags & POS_DYNAMIC) && pc->b.nra == pc->gmax.isize)
-    {
-        gmx_ana_indexmap_set_static(&p->m, &pc->b);
-    }
-    gmx_ana_pos_reserve(p, p->m.nr, 0);
-    if (pc->flags & POS_VELOCITIES)
-    {
-        gmx_ana_pos_reserve_velocities(p);
-    }
-    if (pc->flags & POS_FORCES)
-    {
-        gmx_ana_pos_reserve_forces(p);
-    }
-    gmx_ana_pos_set_nr(p, p->m.nr);
-    gmx_ana_pos_set_evalgrp(p, &pc->gmax);
-}
-
-/*!
- * \param  pc  Position calculation data to be freed.
- *
- * The \p pc pointer is invalid after the call.
- */
-void
-gmx_ana_poscalc_free(gmx_ana_poscalc_t *pc)
-{
-    if (!pc)
-    {
-        return;
-    }
-
-    pc->refcount--;
-    if (pc->refcount > 0)
-    {
-        return;
-    }
-
-    remove_poscalc(pc);
-    if (pc->b.nalloc_index > 0)
-    {
-        sfree(pc->b.index);
-    }
-    if (pc->b.nalloc_a > 0)
-    {
-        sfree(pc->b.a);
-    }
-    if (pc->flags & POS_COMPLWHOLE)
-    {
-        gmx_ana_index_deinit(&pc->gmax);
-    }
-    if (pc->p)
-    {
-        gmx_ana_pos_free(pc->p);
-    }
-    if (pc->sbase)
-    {
-        gmx_ana_poscalc_free(pc->sbase);
-        sfree(pc->baseid);
-    }
-    sfree(pc);
-}
-
-/*!
- * \param[in] pc  Position calculation data to query.
- * \returns   TRUE if \p pc requires topology for initialization and/or
- *   evaluation, FALSE otherwise.
- */
-gmx_bool
-gmx_ana_poscalc_requires_top(gmx_ana_poscalc_t *pc)
-{
-    if ((pc->flags & POS_MASS) || pc->type == POS_RES || pc->type == POS_MOL)
-    {
-        return TRUE;
-    }
-    return FALSE;
-}
-
-/*!
- * \param[in,out] pcc Position calculation collection to initialize.
- *
- * This function does some final initialization of the data structures in the
- * collection to prepare them for evaluation.
- * After this function has been called, it is no longer possible to add new
- * calculations to the collection.
- *
- * This function is automatically called by gmx_ana_poscalc_init_frame() 
- * if not called by the user earlier.
- * Multiple calls to the function are ignored.
- */
-void
-gmx_ana_poscalc_init_eval(gmx_ana_poscalc_coll_t *pcc)
-{
-    gmx_ana_poscalc_t      *pc;
-    int                     bi, bj;
-
-    if (pcc->bInit)
-    {
-        return;
-    }
-    pc = pcc->first;
-    while (pc)
-    {
-        /* Initialize position storage for base calculations */
-        if (pc->p)
-        {
-            gmx_ana_poscalc_init_pos(pc, pc->p);
-        }
-        /* Construct the mapping of the base positions */
-        if (pc->sbase)
-        {
-            snew(pc->baseid, pc->b.nr);
-            for (bi = bj = 0; bi < pc->b.nr; ++bi, ++bj)
-            {
-                while (pc->sbase->b.a[pc->sbase->b.index[bj]] != pc->b.a[pc->b.index[bi]])
-                {
-                    ++bj;
-                }
-                pc->baseid[bi] = bj;
-            }
-        }
-        /* Free the block data for dynamic calculations */
-        if (pc->flags & POS_DYNAMIC)
-        {
-            if (pc->b.nalloc_index > 0)
-            {
-                sfree(pc->b.index);
-                pc->b.nalloc_index = 0;
-            }
-            if (pc->b.nalloc_a > 0)
-            {
-                sfree(pc->b.a);
-                pc->b.nalloc_a = 0;
-            }
-        }
-        pc = pc->next;
-    }
-    pcc->bInit = TRUE;
-}
-
-/*!
- * \param[in,out] pcc Position calculation collection to initialize.
- *
- * Clears the evaluation flag for all calculations.
- * Should be called for each frame before calling gmx_ana_poscalc_update().
- *
- * This function is automatically called by gmx_ana_do() for each
- * frame, and should not be called by the user unless gmx_ana_do() is
- * not being used.
- *
- * This function calls gmx_ana_poscalc_init_eval() automatically if it has
- * not been called earlier.
- */
-void
-gmx_ana_poscalc_init_frame(gmx_ana_poscalc_coll_t *pcc)
-{
-    gmx_ana_poscalc_t      *pc;
-
-    if (!pcc->bInit)
-    {
-        gmx_ana_poscalc_init_eval(pcc);
-    }
-    /* Clear the evaluation flags */
-    pc = pcc->first;
-    while (pc)
-    {
-        pc->bEval = FALSE;
-        pc = pc->next;
-    }
-}
-
-/*!
- * \param[in]     pc   Position calculation data.
- * \param[in,out] p    Output positions, initialized previously with
- *   gmx_ana_poscalc_init_pos() using \p pc.
- * \param[in]     g    Index group to use for the update.
- * \param[in]     fr   Current frame.
- * \param[in]     pbc  PBC data, or NULL if no PBC should be used.
- *
- * gmx_ana_poscalc_init_frame() should be called for each frame before calling
- * this function.
- */
-void
-gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p,
-                       gmx_ana_index_t *g, t_trxframe *fr, t_pbc *pbc)
-{
-    int  i, j, bi, bj;
-    
-    if (pc->bEval == TRUE && !(pc->flags & POS_MASKONLY))
-    {
-        return;
-    }
-    if (pc->sbase)
-    {
-        gmx_ana_poscalc_update(pc->sbase, NULL, NULL, fr, pbc);
-    }
-    if (!p)
-    {
-        p = pc->p;
-    }
-    if (!g)
-    {
-        g = &pc->gmax;
-    }
-    gmx_ana_pos_set_evalgrp(p, g);
-
-    /* Update the index map */
-    if (pc->flags & POS_DYNAMIC)
-    {
-        gmx_ana_indexmap_update(&p->m, g, FALSE);
-        p->nr = p->m.nr;
-    }
-    else if (pc->flags & POS_MASKONLY)
-    {
-        gmx_ana_indexmap_update(&p->m, g, TRUE);
-        if (pc->bEval)
-            return;
-    }
-    if (!(pc->flags & POS_DYNAMIC))
-    {
-        pc->bEval = TRUE;
-    }
-
-    /* Evaluate the positions */
-    if (pc->sbase)
-    {
-        /* TODO: It might be faster to evaluate the positions within this
-         * loop instead of in the beginning. */
-        if (pc->flags & POS_DYNAMIC)
-        {
-            for (bi = 0; bi < p->nr; ++bi)
-            {
-                bj = pc->baseid[p->m.refid[bi]];
-                copy_rvec(pc->sbase->p->x[bj], p->x[bi]);
-            }
-            if (p->v)
-            {
-                for (bi = 0; bi < p->nr; ++bi)
-                {
-                    bj = pc->baseid[p->m.refid[bi]];
-                    copy_rvec(pc->sbase->p->v[bj], p->v[bi]);
-                }
-            }
-            if (p->f)
-            {
-                for (bi = 0; bi < p->nr; ++bi)
-                {
-                    bj = pc->baseid[p->m.refid[bi]];
-                    copy_rvec(pc->sbase->p->f[bj], p->f[bi]);
-                }
-            }
-        }
-        else
-        {
-            for (bi = 0; bi < p->nr; ++bi)
-            {
-                bj = pc->baseid[bi];
-                copy_rvec(pc->sbase->p->x[bj], p->x[bi]);
-            }
-            if (p->v)
-            {
-                for (bi = 0; bi < p->nr; ++bi)
-                {
-                    bj = pc->baseid[bi];
-                    copy_rvec(pc->sbase->p->v[bj], p->v[bi]);
-                }
-            }
-            if (p->f)
-            {
-                for (bi = 0; bi < p->nr; ++bi)
-                {
-                    bj = pc->baseid[bi];
-                    copy_rvec(pc->sbase->p->f[bj], p->f[bi]);
-                }
-            }
-        }
-    }
-    else /* pc->sbase is NULL */
-    {
-        if (pc->flags & POS_DYNAMIC)
-        {
-            pc->b.nr    = p->m.mapb.nr;
-            pc->b.index = p->m.mapb.index;
-            pc->b.nra   = g->isize;
-            pc->b.a     = g->index;
-        }
-        if (p->v && !fr->bV)
-        {
-            for (i = 0; i < pc->b.nra; ++i)
-            {
-                clear_rvec(p->v[i]);
-            }
-        }
-        if (p->f && !fr->bF)
-        {
-            for (i = 0; i < pc->b.nra; ++i)
-            {
-                clear_rvec(p->f[i]);
-            }
-        }
-        /* Here, we assume that the topology has been properly initialized,
-         * and do not check the return values of gmx_calc_comg*(). */
-        switch (pc->type)
-        {
-        case POS_ATOM:
-            for (i = 0; i < pc->b.nra; ++i)
-            {
-                copy_rvec(fr->x[pc->b.a[i]], p->x[i]);
-            }
-            if (p->v && fr->bV)
-            {
-                for (i = 0; i < pc->b.nra; ++i)
-                {
-                    copy_rvec(fr->v[pc->b.a[i]], p->v[i]);
-                }
-            }
-            if (p->f && fr->bF)
-            {
-                for (i = 0; i < pc->b.nra; ++i)
-                {
-                    copy_rvec(fr->f[pc->b.a[i]], p->f[i]);
-                }
-            }
-            break;
-        case POS_ALL:
-            gmx_calc_comg(pc->coll->top, fr->x, pc->b.nra, pc->b.a,
-                          pc->flags & POS_MASS, p->x[0]);
-            if (p->v && fr->bV)
-            {
-                gmx_calc_comg(pc->coll->top, fr->v, pc->b.nra, pc->b.a,
-                              pc->flags & POS_MASS, p->v[0]);
-            }
-            if (p->f && fr->bF)
-            {
-                gmx_calc_comg_f(pc->coll->top, fr->f, pc->b.nra, pc->b.a,
-                                pc->flags & POS_MASS, p->f[0]);
-            }
-            break;
-        case POS_ALL_PBC:
-            gmx_calc_comg_pbc(pc->coll->top, fr->x, pbc, pc->b.nra, pc->b.a,
-                              pc->flags & POS_MASS, p->x[0]);
-            if (p->v && fr->bV)
-            {
-                gmx_calc_comg(pc->coll->top, fr->v, pc->b.nra, pc->b.a,
-                              pc->flags & POS_MASS, p->v[0]);
-            }
-            if (p->f && fr->bF)
-            {
-                gmx_calc_comg_f(pc->coll->top, fr->f, pc->b.nra, pc->b.a,
-                                pc->flags & POS_MASS, p->f[0]);
-            }
-            break;
-        default:
-            gmx_calc_comg_blocka(pc->coll->top, fr->x, &pc->b,
-                                 pc->flags & POS_MASS, p->x);
-            if (p->v && fr->bV)
-            {
-                gmx_calc_comg_blocka(pc->coll->top, fr->v, &pc->b,
-                                     pc->flags & POS_MASS, p->v);
-            }
-            if (p->f && fr->bF)
-            {
-                gmx_calc_comg_blocka(pc->coll->top, fr->f, &pc->b,
-                                     pc->flags & POS_MASS, p->f);
-            }
-            break;
-        }
-    }
-}
diff --git a/src/gmxlib/trajana/position.c b/src/gmxlib/trajana/position.c
deleted file mode 100644 (file)
index 4edcb46..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \internal \file
- * \brief Implementation of functions in position.h.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <string.h>
-
-#include <smalloc.h>
-#include <typedefs.h>
-#include <vec.h>
-
-#include <indexutil.h>
-#include <position.h>
-
-/*!
- * \param[out] pos      Output structure.
- *
- * Any contents of \p pos are discarded without freeing.
- */
-void
-gmx_ana_pos_clear(gmx_ana_pos_t *pos)
-{
-    pos->nr = 0;
-    pos->x  = NULL;
-    pos->v  = NULL;
-    pos->f  = NULL;
-    gmx_ana_indexmap_clear(&pos->m);
-    pos->g  = NULL;
-    pos->nalloc_x = 0;
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- * \param[in]     n     Maximum number of positions.
- * \param[in]     isize Maximum number of atoms.
- *
- * Ensures that enough memory is allocated in \p pos to calculate \p n
- * positions from \p isize atoms.
- */
-void
-gmx_ana_pos_reserve(gmx_ana_pos_t *pos, int n, int isize)
-{
-    if (pos->nalloc_x < n)
-    {
-        pos->nalloc_x = n;
-        srenew(pos->x, n);
-        if (pos->v)
-        {
-            srenew(pos->v, n);
-        }
-        if (pos->f)
-        {
-            srenew(pos->f, n);
-        }
-    }
-    if (isize > 0)
-    {
-        gmx_ana_indexmap_reserve(&pos->m, n, isize);
-    }
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Currently, this function can only be called after gmx_ana_pos_reserve()
- * has been called at least once with a \p n > 0.
- */
-void
-gmx_ana_pos_reserve_velocities(gmx_ana_pos_t *pos)
-{
-    assert(pos->nalloc_x > 0);
-    if (!pos->v)
-    {
-        snew(pos->v, pos->nalloc_x);
-    }
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Currently, this function can only be called after gmx_ana_pos_reserve()
- * has been called at least once with a \p n > 0.
- */
-void
-gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos)
-{
-    assert(pos->nalloc_x > 0);
-    if (!pos->f)
-    {
-        snew(pos->f, pos->nalloc_x);
-    }
-}
-
-/*!
- * \param[out]    pos  Position data structure to initialize.
- * \param[in]     x    Position vector to use.
- */
-void
-gmx_ana_pos_init_const(gmx_ana_pos_t *pos, rvec x)
-{
-    gmx_ana_pos_clear(pos);
-    pos->nr = 1;
-    snew(pos->x, 1);
-    snew(pos->v, 1);
-    snew(pos->f, 1);
-    pos->nalloc_x = 1;
-    copy_rvec(x, pos->x[0]);
-    clear_rvec(pos->v[0]);
-    clear_rvec(pos->f[0]);
-    gmx_ana_indexmap_init(&pos->m, NULL, NULL, INDEX_UNKNOWN);
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Frees any memory allocated within \p pos.
- * The pointer \p pos itself is not freed.
- *
- * \see gmx_ana_pos_free()
- */
-void
-gmx_ana_pos_deinit(gmx_ana_pos_t *pos)
-{
-    pos->nr = 0;
-    sfree(pos->x); pos->x = NULL;
-    sfree(pos->v); pos->v = NULL;
-    sfree(pos->f); pos->f = NULL;
-    pos->nalloc_x = 0;
-    gmx_ana_indexmap_deinit(&pos->m);
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Frees any memory allocated for \p pos.
- * The pointer \p pos is also freed, and is invalid after the call.
- *
- * \see gmx_ana_pos_deinit()
- */
-void
-gmx_ana_pos_free(gmx_ana_pos_t *pos)
-{
-    gmx_ana_pos_deinit(pos);
-    sfree(pos);
-}
-
-/*!
- * \param[in,out] dest   Destination positions.
- * \param[in]     src    Source positions.
- * \param[in]     bFirst If TRUE, memory is allocated for \p dest and a full
- *   copy is made; otherwise, only variable parts are copied, and no memory
- *   is allocated.
- *
- * \p dest should have been initialized somehow (calloc() is enough).
- */
-void
-gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, gmx_bool bFirst)
-{
-    if (bFirst)
-    {
-        gmx_ana_pos_reserve(dest, src->nr, 0);
-        if (src->v)
-        {
-            gmx_ana_pos_reserve_velocities(dest);
-        }
-        if (src->f)
-        {
-            gmx_ana_pos_reserve_forces(dest);
-        }
-    }
-    dest->nr = src->nr;
-    memcpy(dest->x, src->x, dest->nr*sizeof(*dest->x));
-    if (dest->v)
-    {
-        memcpy(dest->v, src->v, dest->nr*sizeof(*dest->v));
-    }
-    if (dest->f)
-    {
-        memcpy(dest->f, src->f, dest->nr*sizeof(*dest->f));
-    }
-    gmx_ana_indexmap_copy(&dest->m, &src->m, bFirst);
-    dest->g = src->g;
-}
-
-/*!
- * \param[in,out] pos  Position data structure.
- * \param[in]     nr   Number of positions.
- */
-void
-gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int nr)
-{
-    pos->nr = nr;
-}
-
-/*!
- * \param[in,out] pos  Position data structure.
- * \param         g    Evaluation group.
- *
- * The old group, if any, is discarded.
- * Note that only a pointer to \p g is stored; it is the responsibility of
- * the caller to ensure that \p g is not freed while it can be accessed
- * through \p pos.
- */
-void
-gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g)
-{
-    pos->g = g;
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Sets the number of positions to 0.
- */
-void
-gmx_ana_pos_empty_init(gmx_ana_pos_t *pos)
-{
-    pos->nr = 0;
-    pos->m.nr = 0;
-    pos->m.mapb.nr = 0;
-    pos->m.b.nr = 0;
-    pos->m.b.nra = 0;
-    /* This should not really be necessary, but do it for safety... */
-    pos->m.mapb.index[0] = 0;
-    pos->m.b.index[0] = 0;
-    /* This function should only be used to construct all the possible
-     * positions, so the result should always be static. */
-    pos->m.bStatic = TRUE;
-    pos->m.bMapStatic = TRUE;
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * Sets the number of positions to 0.
- */
-void
-gmx_ana_pos_empty(gmx_ana_pos_t *pos)
-{
-    pos->nr = 0;
-    pos->m.nr = 0;
-    pos->m.mapb.nr = 0;
-    /* This should not really be necessary, but do it for safety... */
-    pos->m.mapb.index[0] = 0;
-    /* We set the flags to TRUE, although really in the empty state they
-     * should be FALSE. This makes it possible to update the flags in
-     * gmx_ana_pos_append(), and just make a simple check in
-     * gmx_ana_pos_append_finish(). */
-    pos->m.bStatic = TRUE;
-    pos->m.bMapStatic = TRUE;
-}
-
-/*!
- * \param[in,out] dest  Data structure to which the new position is appended.
- * \param[in,out] g     Data structure to which the new atoms are appended.
- * \param[in]     src   Data structure from which the position is copied.
- * \param[in]     i     Index in \p from to copy.
- */
-void
-gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                        gmx_ana_pos_t *src, int i)
-{
-    int  j, k;
-
-    j = dest->nr;
-    copy_rvec(src->x[i], dest->x[j]);
-    if (dest->v)
-    {
-        if (src->v)
-        {
-            copy_rvec(src->v[i], dest->v[j]);
-        }
-        else
-        {
-            clear_rvec(dest->v[j]);
-        }
-    }
-    if (dest->f)
-    {
-        if (src->f)
-        {
-            copy_rvec(src->f[i], dest->f[j]);
-        }
-        else
-        {
-            clear_rvec(dest->f[j]);
-        }
-    }
-    dest->m.refid[j] = j;
-    dest->m.mapid[j] = src->m.mapid[i];
-    dest->m.orgid[j] = src->m.orgid[i];
-    for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
-    {
-        g->index[g->isize++]         = src->g->index[k];
-        dest->m.b.a[dest->m.b.nra++] = src->m.b.a[k];
-    }
-    dest->m.mapb.index[j+1] = g->isize;
-    dest->m.b.index[j+1]    = g->isize;
-    dest->nr++;
-    dest->m.nr = dest->nr;
-    dest->m.mapb.nr = dest->nr;
-    dest->m.b.nr = dest->nr;
-}
-
-/*!
- * \param[in,out] dest  Data structure to which the new position is appended
- *      (can be NULL, in which case only \p g is updated).
- * \param[in,out] g     Data structure to which the new atoms are appended.
- * \param[in]     src   Data structure from which the position is copied.
- * \param[in]     i     Index in \p src to copy.
- * \param[in]     refid Reference ID in \p out
- *   (all negative values are treated as -1).
- *
- * If \p dest is NULL, the value of \p refid is not used.
- */
-void
-gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                   gmx_ana_pos_t *src, int i, int refid)
-{
-    int  j, k;
-
-    for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
-    {
-        g->index[g->isize++] = src->g->index[k];
-    }
-    if (dest)
-    {
-        j = dest->nr;
-        if (dest->v)
-        {
-            if (src->v)
-            {
-                copy_rvec(src->v[i], dest->v[j]);
-            }
-            else
-            {
-                clear_rvec(dest->v[j]);
-            }
-        }
-        if (dest->f)
-        {
-            if (src->f)
-            {
-                copy_rvec(src->f[i], dest->f[j]);
-            }
-            else
-            {
-                clear_rvec(dest->f[j]);
-            }
-        }
-        copy_rvec(src->x[i], dest->x[j]);
-        if (refid < 0)
-        {
-            dest->m.refid[j] = -1;
-            dest->m.bStatic = FALSE;
-            /* If we are using masks, there is no need to alter the
-             * mapid field. */
-        }
-        else
-        {
-            if (refid != j)
-            {
-                dest->m.bStatic = FALSE;
-                dest->m.bMapStatic = FALSE;
-            }
-            dest->m.refid[j] = refid;
-            /* Use the original IDs from the output structure to correctly
-             * handle user customization. */
-            dest->m.mapid[j] = dest->m.orgid[refid];
-        }
-        dest->m.mapb.index[j+1] = g->isize;
-        dest->nr++;
-        dest->m.nr = dest->nr;
-        dest->m.mapb.nr = dest->nr;
-    }
-}
-
-/*!
- * \param[in,out] pos   Position data structure.
- *
- * After gmx_ana_pos_empty(), internal state of the position data structure
- * is not consistent before this function is called. This function should be
- * called after any gmx_ana_pos_append() calls have been made.
- */
-void
-gmx_ana_pos_append_finish(gmx_ana_pos_t *pos)
-{
-    if (pos->m.nr != pos->m.b.nr)
-    {
-        pos->m.bStatic = FALSE;
-        pos->m.bMapStatic = FALSE;
-    }
-}
diff --git a/src/gmxlib/trajana/trajana.c b/src/gmxlib/trajana/trajana.c
deleted file mode 100644 (file)
index 4dde161..0000000
+++ /dev/null
@@ -1,1701 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \page libtrajana Library for trajectory analysis
- *
- * This is a trajectory analysis library for Gromacs.
- *
- * The main features of the library are:
- *  - \subpage selengine "Flexible handling of textual selections" that can
- *    also be dynamic, i.e., depend of the trajectory frame through
- *    positions of the particles.
- *    Selections evaluate directly to positions, which can then be used in
- *    the analysis program.
- *  - \subpage selmethods "Custom selection keywords" can also be easily
- *    implemented, also on a tool-by-tool basis.
- *  - Efficient \subpage nbsearch "neighborhood searching"
- *    (currently not very efficient...).
- *  - \subpage displacements "On-the-fly calculation of displacement vectors"
- *    during a single pass over the trajectory.
- *  - \subpage histograms "Calculation of histograms" with error estimates
- *    through block averaging.
- *
- * The functions also automate several things common to most analysis programs
- * such as making molecules whole if required, reading input files, and
- * setting up index groups for analysis.
- * The library unifies the structure of analysis programs (at least a bit)
- * and makes it easier to add common functionality to all analysis programs.
- *
- *
- * \section main_using Using the library
- *
- * There is a \ref share/template/template.c "template" for writing
- * analysis programs, the documentation for it and links from there should
- * help getting started.
- *
- *
- * \internal
- * \section libtrajana_impl Implementation details
- *
- * Some internal implementation details of the library are documented on
- * separate pages:
- *  - \subpage poscalcengine
- *  - \subpage selparser
- *  - \subpage selcompiler
- */
-/*! \page selengine Text-based selections
- *
- * \section selection_basics Basics
- *
- * Selections are enabled automatically for an analysis program that uses
- * the library. The selection syntax is described in an online help that is
- * accessible from all tools that use the library.
- * By default, dynamic selections are allowed, and the user can freely
- * choose whether to analyze atoms or centers of mass/geometry of
- * residues/molecules.
- * These defaults, as well as some others, can be changed by specifying
- * flags for gmx_ana_traj_create().
- *
- * The analysis program can then access the selected positions for each frame
- * through a \p gmx_ana_selection_t array that is passed to the frame
- * analysis function (see gmx_analysisfunc()).
- * As long as the analysis program is written such that it does not assume
- * that the number of positions or the atoms in the groups groups remain
- * constant, any kind of selection expression can be used.
- *
- * Some analysis programs may require a special structure for the index groups
- * (e.g., \c g_angle requires the index group to be made of groups of three or
- * four atoms).
- * For such programs, it is up to the user to provide a proper selection
- * expression that always returns such positions.
- * Such analysis program can define \ref ANA_REQUIRE_WHOLE to make the
- * default behavior appropriate for the most common uses where the groups
- * should consist of atoms within a single residue/molecule.
- *
- * \section selection_methods Implementing new keywords
- *
- * New selection keywords can be easily implemented, either directly into the
- * library or as part of analysis programs (the latter may be useful for
- * testing or methods very specific to some analysis).
- * For both cases, you should first create a \c gmx_ana_selmethod_t structure
- * and fill it with the necessary information.
- * Details can be found on a separate page: \ref selmethods.
- */
-/*! \internal \file
- * \brief Implementation of functions in trajana.h.
- */
-/*! \internal \dir src/gmxlib/trajana
- * \brief Source code for common trajectory analysis functions.
- *
- * Selection handling is found in \ref src/gmxlib/selection.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <filenm.h>
-#include <futil.h>
-#include <macros.h>
-#include <pbc.h>
-#include <rmpbc.h>
-#include <smalloc.h>
-#include <statutil.h>
-#include <typedefs.h>
-#include <tpxio.h>
-#include <vec.h>
-
-#include <poscalc.h>
-#include <selection.h>
-#include <selmethod.h>
-#include <trajana.h>
-
-/*! \internal \brief
- * Data structure for trajectory analysis tools.
- */
-struct gmx_ana_traj_t
-{
-    /*! \brief
-     * Flags that alter the behavior of the analysis library.
-     *
-     * This variable stores the flags passed to gmx_ana_traj_create() for use
-     * in the other functions.
-     */
-    unsigned long             flags;
-    /** Number of input reference groups. */
-    int                       nrefgrps;
-    /*! \brief
-     * Number of input analysis groups.
-     *
-     * This is the number of groups in addition to the reference groups
-     * that are required.
-     * If -1, any number of groups (at least one) is acceptable.
-     */
-    int                       nanagrps;
-    /*! \brief
-     * Flags for init_first_frame() to specify what to read from the
-     * trajectory.
-     */
-    int                       frflags;
-    /** TRUE if molecules should be made whole for each frame. */
-    gmx_bool                      bRmPBC;
-    /*! \brief
-     * TRUE if periodic boundary conditions should be used.
-     *
-     * If the flag is FALSE, the \p pbc pointer passed to gmx_analysisfunc()
-     * is NULL.
-     */
-    gmx_bool                      bPBC;
-
-    /** Name of the trajectory file (NULL if not provided). */
-    char                     *trjfile;
-    /** Name of the topology file (NULL if no topology loaded). */
-    char                     *topfile;
-    /** Non-NULL name of the topology file. */
-    char                     *topfile_notnull;
-    /** Name of the index file (NULL if no index file provided). */
-    char                     *ndxfile;
-    /** Name of the selection file (NULL if no file provided). */
-    char                     *selfile;
-    /** The selection string (NULL if not provided). */
-    char                     *selection;
-
-    /** The topology structure, or \p NULL if no topology loaded. */
-    t_topology               *top;
-    /** TRUE if full tpx file was loaded, FALSE otherwise. */
-    gmx_bool                      bTop;
-    /** Coordinates from the topology (see \p bTopX). */
-    rvec                     *xtop;
-    /** The box loaded from the topology file. */
-    matrix                    boxtop;
-    /** The ePBC field loaded from the topology file. */
-    int                       ePBC;
-
-    /** The current frame, or \p NULL if no frame loaded yet. */
-    t_trxframe               *fr;
-    /** Used to store the status variable from read_first_frame(). */
-    t_trxstatus              *status;
-    /** The number of frames read. */
-    int                       nframes;
-
-    /** Number of elements in the \p sel array. */
-    int                       ngrps;
-    /*! \brief
-     * Array of selection information (one element for each index group).
-     *
-     * After the call to gmx_ana_init_selections(), this array contains
-     * information about the selections the user has provided.
-     * The array contains \p ngrps elements;
-     * if \p nanagrps was -1, the number may vary.
-     * See \c gmx_ana_selection_t for details of the contents.
-     *
-     * The largest possible index groups for dynamic selections can be found
-     * in \p sel[i]->g, i.e., the program can assume that any index group
-     * passed to gmx_analysisfunc() is a subset of the provided group.
-     * After gmx_ana_do(), the same groups can be used in post-processing.
-     */
-    gmx_ana_selection_t     **sel;
-    /** Array of names of the selections for convenience. */
-    char                    **grpnames;
-    /** Position calculation data. */
-    gmx_ana_poscalc_coll_t   *pcc;
-    /** Selection data. */
-    gmx_ana_selcollection_t  *sc;
-
-    /** Data for statutil.c utilities. */
-    output_env_t              oenv;
-};
-
-/** Loads the topology. */
-static int load_topology(gmx_ana_traj_t *d, gmx_bool bReq);
-/** Loads the first frame and does some checks. */
-static int init_first_frame(gmx_ana_traj_t *d);
-
-static int add_fnmarg(int nfile, t_filenm *fnm, t_filenm *fnm_add)
-{
-    memcpy(&(fnm[nfile]), fnm_add, sizeof(*fnm_add));
-    return nfile + 1;
-}
-
-/* Copied from src/gmxlib/statutil.c */
-static int
-add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
-{
-    memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
-    return npargs + 1;
-}
-
-/*!
- * \param[out] data  Trajectory analysis data structure poitner to initialize.
- * \param[in]  flags Combination of flags (see \ref analysis_flags).
- * \returns    0 on success.
- */
-int
-gmx_ana_traj_create(gmx_ana_traj_t **data, unsigned long flags)
-{
-    gmx_ana_traj_t     *d;
-    int                 rc;
-
-    snew(d, 1);
-
-    d->nrefgrps        = 0;
-    d->nanagrps        = 1;
-    d->frflags         = TRX_NEED_X;
-    d->bRmPBC          = TRUE;
-    d->bPBC            = TRUE;
-
-    d->trjfile         = NULL;
-    d->topfile         = NULL;
-    d->ndxfile         = NULL;
-    d->selfile         = NULL;
-    d->selection       = NULL;
-
-    d->top             = NULL;
-    d->bTop            = FALSE;
-    d->xtop            = NULL;
-    d->ePBC            = -1;
-    d->fr              = NULL;
-    d->nframes         = 0;
-
-    d->ngrps           = 0;
-    d->sel             = NULL;
-    d->grpnames        = NULL;
-
-    d->flags           = flags;
-    d->topfile_notnull = NULL;
-    rc = gmx_ana_poscalc_coll_create(&d->pcc);
-    if (rc != 0)
-    {
-        sfree(d);
-        *data = NULL;
-        return rc;
-    }
-    rc = gmx_ana_selcollection_create(&d->sc, d->pcc);
-    if (rc != 0)
-    {
-        gmx_ana_poscalc_coll_free(d->pcc);
-        sfree(d);
-        *data = NULL;
-        return rc;
-    }
-    d->status          = NULL;
-    d->oenv            = NULL;
-
-    *data              = d;
-    return 0;
-}
-
-/*!
- * \param   d  Trajectory analysis data to free.
- */
-void
-gmx_ana_traj_free(gmx_ana_traj_t *d)
-{
-    int                 i;
-
-    sfree(d->trjfile);
-    sfree(d->topfile);
-    sfree(d->topfile_notnull);
-    sfree(d->ndxfile);
-    sfree(d->selfile);
-    if (d->top)
-    {
-        done_top(d->top);
-        sfree(d->top);
-    }
-    if (d->fr)
-    {
-        /* Gromacs does not seem to have a function for freeing frame data */
-        sfree(d->fr->x);
-        sfree(d->fr->v);
-        sfree(d->fr->f);
-        sfree(d->fr);
-    }
-    sfree(d->xtop);
-    sfree(d->sel);
-    gmx_ana_selcollection_free(d->sc);
-    gmx_ana_poscalc_coll_free(d->pcc);
-    sfree(d->grpnames);
-    output_env_done(d->oenv);
-    sfree(d);
-}
-
-/*!
- * \param[in,out] d      Trajectory analysis data structure.
- * \param[in]     flags  Additional flags to set.
- * \returns       0 on success, a non-zero error code on error.
- *
- * Currently there are no checks whether the flags make sense or not.
- */
-int
-gmx_ana_add_flags(gmx_ana_traj_t *d, unsigned long flags)
-{
-    d->flags |= flags;
-    return 0;
-}
-
-/*!
- * \param[in,out] d      Trajectory analysis data structure.
- * \param[in]     bPBC   TRUE if periodic boundary conditions should be used.
- * \returns       0 on success.
- * 
- * If this function is called before parse_trjana_args(), it sets the default
- * for whether PBC are used in the analysis or not.
- * If \ref ANA_NOUSER_PBC is not set, a command-line option is provided for the
- * user to override the default value.
- * If called after parse_trjana_args(), it overrides the setting provided by
- * the user or an earlier call.
- *
- * If this function is not called, the default is to use PBC.
- *
- * If PBC are not used, the \p pbc pointer passed to gmx_analysisfunc()
- * is NULL.
- *
- * \see \ref ANA_NOUSER_PBC
- */
-int
-gmx_ana_set_pbc(gmx_ana_traj_t *d, gmx_bool bPBC)
-{
-    d->bPBC = bPBC;
-    return 0;
-}
-
-/*!
- * \param[in] d      Trajectory analysis data structure.
- * \returns   TRUE if periodic boundary conditions are set to be used.
- */
-gmx_bool
-gmx_ana_has_pbc(gmx_ana_traj_t *d)
-{
-    return d->bPBC;
-}
-
-/*!
- * \param[in,out] d      Trajectory analysis data structure.
- * \param[in]     bRmPBC TRUE if molecules should be made whole.
- * \returns       0 on success.
- * 
- * If this function is called before parse_trjana_args(), it sets the default
- * for whether molecules are made whole.
- * If \ref ANA_NOUSER_RMPBC is not set, a command-line option is provided for
- * the user to override the default value.
- * If called after parse_trjana_args(), it overrides the setting provided by
- * the user or an earlier call.
- *
- * If this function is not called, the default is to make molecules whole.
- *
- * The main use of this function is to call it with FALSE if your analysis
- * program does not require whole molecules as this can increase the
- * performance.
- * In such a case, you can also specify \ref ANA_NOUSER_RMPBC to not to
- * confuse the user with an option that would only slow the program
- * down.
- *
- * \see \ref ANA_NOUSER_RMPBC
- */
-int
-gmx_ana_set_rmpbc(gmx_ana_traj_t *d, gmx_bool bRmPBC)
-{
-    d->bRmPBC = bRmPBC;
-    return 0;
-}
-
-/*!
- * \param[in,out] d       Trajectory analysis data structure.
- * \param[in]     frflags Flags for what to read from the trajectory file.
- * \returns       0 on success, an error code on error.
- *
- * The TRX_NEED_X flag is always set.
- * If the analysis tools needs some other information (velocities, forces),
- * it can call this function to load additional information from the
- * trajectory.
- */
-int
-gmx_ana_set_frflags(gmx_ana_traj_t *d, int frflags)
-{
-    if (d->sel)
-    {
-        gmx_call("cannot set trajectory flags after initializing selections");
-        return -1;
-    }
-    if (d->fr)
-    {
-        gmx_call("cannot set trajectory flags after the first frame has been read");
-        return -1;
-    }
-    frflags |= TRX_NEED_X;
-    d->frflags = frflags;
-    return 0;
-}
-
-/*!
- * \param[in,out] d        Trajectory analysis data structure.
- * \param[in]     nrefgrps Number of reference groups required.
- * \returns       0 on success, a non-zero error code on error.
- *
- * \p nrefgrps should be a non-negative integer.
- * If this function is not called (or \p nrefgrps is 0), all selections are
- * treated as reference groups.
- */
-int
-gmx_ana_set_nrefgrps(gmx_ana_traj_t *d, int nrefgrps)
-{
-    if (nrefgrps < 0)
-    {
-        d->nrefgrps = 0;
-        gmx_incons("number of reference groups is negative");
-        return EINVAL;
-    }
-    d->nrefgrps = nrefgrps;
-    return 0;
-}
-
-/*!
- * \param[in,out] d        Trajectory analysis data structure.
- * \param[in]     nanagrps Number of analysis groups required
- *   (-1 stands for any number of analysis groups).
- * \returns       0 on success, a non-zero error code on error.
- *
- * \p nanagrps should be a positive integer or -1.
- * In the latter case, any number of groups (but at least one) is acceptable.
- * gmx_ana_get_nanagrps() can be used to access the actual value after
- * gmx_ana_init_selections() has been called.
- * If this function is not called, a single analysis group is expected.
- */
-int
-gmx_ana_set_nanagrps(gmx_ana_traj_t *d, int nanagrps)
-{
-    if (nanagrps <= 0 && nanagrps != -1)
-    {
-        d->nanagrps = 1;
-        gmx_incons("number of analysis groups is invalid");
-        return EINVAL;
-    }
-    d->nanagrps = nanagrps;
-    return 0;
-}
-
-/*!
- * \param[in]  d     Trajectory analysis data structure.
- * \param[out] ngrps Total number of selections specified by the user.
- * \returns    0 on success, a non-zero error code on error.
- *
- * The value stored in \p *ngrps is the sum of the number of reference groups
- * and the number of analysis groups.
- * If a specific number (not -1) of analysis groups has been set with
- * gmx_ana_set_nanagrps(), the value is always the sum of the values provided
- * to gmx_ana_set_nrefgrps() and gmx_ana_set_nanagrps().
- *
- * Should only be called after gmx_ana_init_selections().
- */
-int
-gmx_ana_get_ngrps(gmx_ana_traj_t *d, int *ngrps)
-{
-    if (d->nanagrps == -1)
-    {
-        *ngrps = 0;
-        gmx_call("gmx_ana_init_selections() not called");
-        return EINVAL;
-    }
-    *ngrps = d->nrefgrps + d->nanagrps;
-    return 0;
-}
-
-/*!
- * \param[in]  d        Trajectory analysis data structure.
- * \param[out] nanagrps Number of analysis groups specified by the user.
- * \returns    0 on success, a non-zero error code on error.
- *
- * If a specific number (not -1) of analysis groups has been set with
- * gmx_ana_set_nanagrps(), the value is always the same value.
- * Hence, you only need to call this function if gmx_ana_set_nanagrps() has
- * been called with \p nanagrps set to -1.
- *
- * Should only be called after gmx_ana_init_selections().
- */
-int
-gmx_ana_get_nanagrps(gmx_ana_traj_t *d, int *nanagrps)
-{
-    if (d->nanagrps == -1)
-    {
-        *nanagrps = 0;
-        gmx_call("gmx_ana_init_selections() not called");
-        return EINVAL;
-    }
-    *nanagrps = d->nanagrps;
-    return 0;
-}
-
-/*!
- * \param[in]  d   Trajectory analysis data structure.
- * \param[in]  i   Ordinal number of the reference selection to get.
- * \param[out] sel Selection object for the \p i'th reference group.
- * \returns    0 on success, a non-zero error code on error.
- *
- * The pointer returned in \p *sel should not be freed.
- * Should only be called after gmx_ana_init_selections().
- */
-int
-gmx_ana_get_refsel(gmx_ana_traj_t *d, int i, gmx_ana_selection_t **sel)
-{
-    if (i < 0 || i >= d->nrefgrps)
-    {
-        *sel = NULL;
-        gmx_call("invalid reference group number");
-        return EINVAL;
-    }
-    *sel = gmx_ana_selcollection_get_selection(d->sc, i);
-    if (!*sel)
-    {
-        gmx_incons("gmx_ana_init_selections() not called");
-        return EINVAL;
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  d   Trajectory analysis data structure.
- * \param[out] sel Array of analysis selections.
- * \returns    0 on success, a non-zero error code on error.
- *
- * The pointer returned in \p *sel should not be freed.
- * Should only be called after gmx_ana_init_selections().
- */
-int
-gmx_ana_get_anagrps(gmx_ana_traj_t *d, gmx_ana_selection_t ***sel)
-{
-    if (!d->sel)
-    {
-        *sel = NULL;
-        gmx_incons("gmx_ana_init_selections() not called");
-        return EINVAL;
-    }
-    *sel = d->sel;
-    return 0;
-}
-
-/*!
- * \param[in]  d        Trajectory analysis data structure.
- * \param[out] grpnames Array of selection names.
- * \returns    0 on success, a non-zero error code on error.
- *
- * The pointer returned in \p *grpnames should not be freed.
- * Should only be called after gmx_ana_init_selections().
- */
-int
-gmx_ana_get_grpnames(gmx_ana_traj_t *d, char ***grpnames)
-{
-    if (!d->grpnames)
-    {
-        *grpnames = NULL;
-        gmx_call("gmx_ana_init_selections() not called");
-        return EINVAL;
-    }
-    *grpnames = d->grpnames;
-    return 0;
-}
-
-/*!
- * \param[in]  d   Trajectory analysis data structure.
- * \param[out] sc  Selection collection object.
- * \returns    0 on success.
- *
- * This function is mostly useful for debugging purposes.
- * The information commonly required in analysis programs is accessible
- * more conveniently through other means.
- *
- * The pointer returned in \p *sc should not be freed.
- * Can be called at any point.
- */
-int
-gmx_ana_get_selcollection(gmx_ana_traj_t *d, gmx_ana_selcollection_t **sc)
-{
-    *sc = d->sc;
-    return 0;
-}
-
-/*!
- * \param[in,out] d     Trajectory analysis data structure.
- * \returns    0 on success, a non-zero error code on error.
- *
- * This function should be called first in the analysis program, much in
- * the same way as parse_common_args() in traditional Gromacs analysis
- * programs. It adds some command-line arguments of its own, and uses
- * parse_common_args() to parse the command-line arguments.
- * It also loads topology information if required or if a topology is
- * provided on the command line.
- * Selection handling is also initialized if it is enabled and
- * the user has selected it on the command line.
- *
- * The rest of the parameters are passed on to the Gromacs routine
- * parse_common_args(), and the use of this function should be identical
- * to parse_common_args(), with the exception that for \p pca_flags,
- * \p PCA_CAN_TIME and \p PCA_BE_NICE flags are automatically added.
- * \param      argc
- * \param      argv
- * \param      pca_flags
- * \param      nfile
- * \param      fnm
- * \param      npargs
- * \param      pa
- * \param      ndesc
- * \param      desc
- * \param      nbugs
- * \param      bugs
- * \param      oenv
- */
-int
-parse_trjana_args(gmx_ana_traj_t *d,
-                  int *argc, char *argv[], unsigned long pca_flags,
-                  int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
-                  int ndesc, const char **desc,
-                 int nbugs, const char **bugs,
-                  output_env_t *oenv)
-{
-    t_filenm           *all_fnm = NULL;
-    int                 max_fnm, nfall;
-    int                *fnm_map;
-    t_pargs            *all_pa = NULL;
-    int                 max_pa, npall;
-    size_t              i;
-    int                 k;
-    int                 rc;
-    const char         *tmp_fnm;
-
-    t_filenm            def_fnm[] = {
-        {efTRX, NULL,  NULL,        ffOPTRD},
-        {efTPS, NULL,  NULL,        ffREAD},
-        {efDAT, "-sf", "selection", ffOPTRD},
-        {efNDX, NULL,  NULL,        ffOPTRD},
-    };
-    gmx_bool                bPBC = TRUE;
-    t_pargs             pbc_pa[] = {
-        {"-pbc",      FALSE, etBOOL, {&bPBC},
-         "Use periodic boundary conditions for distance calculation"},
-    };
-    gmx_bool                bRmPBC = TRUE;
-    t_pargs             rmpbc_pa[] = {
-        {"-rmpbc",    FALSE, etBOOL, {&bRmPBC},
-         "Make molecules whole for each frame"},
-    };
-    char               *selection = NULL;
-    const char        **rpost     = NULL;
-    gmx_bool                bSelDump  = FALSE;
-    t_pargs             sel_pa[] = {
-        {"-select",   FALSE, etSTR,  {&selection},
-         "Selection string (use 'help' for help)"},
-        {"-seldebug", FALSE, etBOOL, {&bSelDump},
-         "HIDDENPrint out the parsed and compiled selection trees"},
-    };
-    t_pargs             dsel_pa[] = {
-        {"-selrpos",  FALSE, etENUM, {NULL},
-         "Selection reference position"},
-    };
-    const char        **spost = NULL;
-    t_pargs             selpt_pa[] = {
-        {"-seltype",  FALSE, etENUM, {NULL},
-         "Default analysis positions"},
-    };
-#define MAX_PA asize(sel_pa)+asize(dsel_pa)+5
-
-    if (d->nrefgrps < 0)
-    {
-        gmx_incons("number of reference groups is negative");
-        return EINVAL;
-    }
-
-    if (d->flags & ANA_DEBUG_SELECTION)
-    {
-        bSelDump = TRUE;
-    }
-
-    rpost = gmx_ana_poscalc_create_type_enum(!(d->flags & ANA_REQUIRE_WHOLE));
-    if (rpost == NULL)
-    {
-        return ENOMEM;
-    }
-    spost = gmx_ana_poscalc_create_type_enum(TRUE);
-    if (spost == NULL)
-    {
-        sfree(rpost);
-        return ENOMEM;
-    }
-
-    /* Construct the file name argument array */
-    max_fnm = nfile + asize(def_fnm);
-    snew(all_fnm, max_fnm);
-    nfall = 0;
-    if (!(d->flags & ANA_REQUIRE_TOP))
-    {
-        def_fnm[1].flag |= ffOPT;
-    }
-    snew(fnm_map, nfile);
-    for (k = 0; k < nfile; ++k)
-    {
-        fnm_map[k] = -1;
-    }
-
-    for (i = 0; i < asize(def_fnm); ++i)
-    {
-        for (k = 0; k < nfile; ++k)
-        {
-            if (fnm_map[k] == -1 && def_fnm[i].opt == NULL
-                && fnm[k].opt == NULL && fnm[k].ftp == def_fnm[i].ftp)
-            {
-                break;
-            }
-        }
-        if (k < nfile)
-        {
-            fnm_map[k] = nfall;
-            nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
-        }
-        else
-        {
-            nfall = add_fnmarg(nfall, all_fnm, &(def_fnm[i]));
-        }
-    }
-
-    for (k = 0; k < nfile; ++k)
-    {
-        if (fnm_map[k] == -1)
-        {
-            fnm_map[k] = nfall;
-            nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
-        }
-    }
-
-    /* Construct the argument array */
-    max_pa = npargs + MAX_PA;
-    snew(all_pa, max_pa);
-    npall = 0;
-
-    if (!(d->flags & ANA_NOUSER_RMPBC))
-    {
-        for (i = 0; i < asize(rmpbc_pa); ++i)
-        {
-            npall = add_parg(npall, all_pa, &(rmpbc_pa[i]));
-        }
-    }
-    if (!(d->flags & ANA_NOUSER_PBC))
-    {
-        for (i = 0; i < asize(pbc_pa); ++i)
-        {
-            npall = add_parg(npall, all_pa, &(pbc_pa[i]));
-        }
-    }
-
-    for (i = 0; i < asize(sel_pa); ++i)
-    {
-        npall = add_parg(npall, all_pa, &(sel_pa[i]));
-    }
-    if (!(d->flags & ANA_NO_DYNSEL))
-    {
-        dsel_pa[0].u.c = rpost;
-        for (i = 0; i < asize(dsel_pa); ++i)
-        {
-            npall = add_parg(npall, all_pa, &(dsel_pa[i]));
-        }
-    }
-
-    if (!(d->flags & ANA_ONLY_ATOMPOS))
-    {
-        selpt_pa[0].u.c = spost;
-        for (i = 0; i < asize(selpt_pa); ++i)
-        {
-            npall = add_parg(npall, all_pa, &(selpt_pa[i]));
-        }
-    }
-
-    for (k = 0; k < npargs; ++k)
-    {
-        npall = add_parg(npall, all_pa, &(pa[k]));
-    }
-
-    pca_flags |= PCA_CAN_TIME | PCA_BE_NICE;
-    parse_common_args(argc, argv, pca_flags, nfall, all_fnm, npall, all_pa,
-                      ndesc, desc, nbugs, bugs,oenv);
-    d->oenv = *oenv;
-
-    /* Process our own options.
-     * Make copies of file names for easier memory management. */
-    tmp_fnm            = ftp2fn_null(efTRX, nfall, all_fnm);
-    d->trjfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
-    tmp_fnm            = ftp2fn_null(efTPS, nfall, all_fnm);
-    d->topfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
-    d->topfile_notnull = strdup(ftp2fn(efTPS, nfall, all_fnm));
-    tmp_fnm            = ftp2fn_null(efNDX, nfall, all_fnm);
-    d->ndxfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
-    if (!(d->flags & ANA_NOUSER_RMPBC))
-    {
-        d->bRmPBC      = bRmPBC;
-    }
-    if (!(d->flags & ANA_NOUSER_PBC))
-    {
-        d->bPBC        = bPBC;
-    }
-    d->selection       = selection;
-    tmp_fnm            = opt2fn_null("-sf", nfall, all_fnm);
-    d->selfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
-
-    /* Copy the results back */
-    for (k = 0; k < nfile; ++k)
-    {
-        memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
-        /* Delegate responsibility of freeing the file names to caller. */
-        all_fnm[fnm_map[k]].nfiles = 0;
-        all_fnm[fnm_map[k]].fns    = NULL;
-    }
-    for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
-    {
-        memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
-    }
-
-    /* Free memory we have allocated. */
-    done_filenms(nfall, all_fnm);
-    sfree(all_fnm);
-    sfree(fnm_map);
-    sfree(all_pa);
-
-    if (!(d->flags & ANA_NO_DYNSEL))
-    {
-        gmx_ana_selcollection_set_refpostype(d->sc, rpost[0]);
-    }
-    else
-    {
-        gmx_ana_selcollection_set_refpostype(d->sc, rpost[1]);
-    }
-    sfree(rpost);
-    if (bSelDump)
-    {
-        d->flags |= ANA_DEBUG_SELECTION;
-    }
-    else
-    {
-        d->flags &= ~ANA_DEBUG_SELECTION;
-    }
-
-    if (!(d->flags & ANA_ONLY_ATOMPOS))
-    {
-        gmx_ana_selcollection_set_outpostype(d->sc, spost[0], d->flags & ANA_USE_POSMASK);
-    }
-    else
-    {
-        gmx_ana_selcollection_set_outpostype(d->sc, spost[1], d->flags & ANA_USE_POSMASK);
-    }
-    sfree(spost);
-
-    /* Check if the user requested help on selections.
-     * If so, call gmx_ana_init_selections() to print the help and exit. */
-    if (selection && strncmp(selection, "help", 4) == 0)
-    {
-        gmx_ana_init_selections(d);
-    }
-
-    /* If no trajectory file is given, we need to set some flags to be able
-     * to prepare a frame from the loaded topology information. Also, check
-     * that a topology is provided. */
-    if (!d->trjfile)
-    {
-        if (!d->topfile)
-        {
-            gmx_input("No trajectory or topology provided, nothing to do!");
-            return -1;
-        }
-        d->flags |= ANA_REQUIRE_TOP;
-        d->flags |= ANA_USE_TOPX;
-    }
-
-    /* Load the topology if so requested. */
-    rc = load_topology(d, (d->flags & ANA_REQUIRE_TOP));
-    if (rc != 0)
-    {
-        return rc;
-    }
-
-    /* Initialize the selections/index groups */
-    if (!(d->flags & ANA_USER_SELINIT))
-    {
-        rc = gmx_ana_init_selections(d);
-    }
-
-    return rc;
-}
-
-/*!
- * \param[in,out] d     Trajectory analysis data structure.
- * \param[in]     bReq  If TRUE, topology loading is forced.
- * \returns       0 on success, a non-zero error code on error.
- *
- * Initializes the \c gmx_ana_traj_t::top, \c gmx_ana_traj_t::bTop,
- * \c gmx_ana_traj_t::boxtop and \c gmx_ana_traj_t::ePBC fields of the
- * analysis structure.
- * If \p bReq is TRUE, the topology is loaded even if it is not given on
- * the command line.
- *
- * The function can be called multiple times safely; extra calls are
- * ignored.
- */
-static int load_topology(gmx_ana_traj_t *d, gmx_bool bReq)
-{
-    char                title[STRLEN];
-
-    /* Return if topology already loaded */
-    if (d->top)
-    {
-        return 0;
-    }
-
-    if (d->topfile || bReq)
-    {
-        snew(d->top, 1);
-        d->bTop = read_tps_conf(d->topfile_notnull, title, d->top,
-                                &d->ePBC, &d->xtop, NULL, d->boxtop, TRUE);
-        if (!(d->flags & ANA_USE_TOPX))
-        {
-            sfree(d->xtop);
-            d->xtop = NULL;
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  d     Trajectory analysis data structure.
- * \param[in]  bReq  If TRUE, topology loading is forced.
- * \param[out] top   Topology data pointer to initialize.
- * \param[out] bTop  TRUE if a full tpx file was loaded, FALSE otherwise
- *   (can be NULL, in which case it is not used).
- * \returns    0 on success, a non-zero error code on error.
- *
- * If \ref ANA_REQUIRE_TOP has not been specified and \p bReq is FALSE,
- * the pointer stored in \p *top may be NULL if no topology has been provided
- * on the command line.
- *
- * The pointer returned in \p *top should not be freed.
- */
-int
-gmx_ana_get_topology(gmx_ana_traj_t *d, gmx_bool bReq, t_topology **top, gmx_bool *bTop)
-{
-    int rc;
-
-    rc = load_topology(d, bReq);
-    if (rc != 0)
-    {
-        *top = NULL;
-        return rc;
-    }
-    *top = d->top;
-    if (bTop)
-    {
-        *bTop = d->bTop;
-    }
-    return 0;
-}
-
-/*!
- * \param[in]  d     Trajectory analysis data structure.
- * \param[out] x     Topology data pointer to initialize.
- *   (can be NULL, in which case it is not used).
- * \param[out] box   Box size from the topology file
- *   (can be NULL, in which case it is not used).
- * \param[out] ePBC  The ePBC field from the topology
- *   (can be NULL, in which case it is not used).
- * \returns    0 on success, a non-zero error code on error.
- *
- * If \ref ANA_USE_TOPX has not been specified, the \p x parameter should be
- * NULL.
- *
- * The pointer returned in \p *x should not be freed.
- */
-int
-gmx_ana_get_topconf(gmx_ana_traj_t *d, rvec **x, matrix box, int *ePBC)
-{
-    if (box)
-    {
-        copy_mat(d->boxtop, box);
-    }
-    if (ePBC)
-    {
-        *ePBC = d->ePBC;
-    }
-    if (x)
-    {
-        if (!(d->flags & ANA_USE_TOPX))
-        {
-            gmx_incons("topology coordinates requested by ANA_USE_TOPX not set");
-            *x = NULL;
-            return EINVAL;
-        }
-        *x = d->xtop;
-    }
-    return 0;
-}
-
-/*! \brief
- * Loads default index groups from a selection file.
- *
- * \param[in,out] d     Trajectory analysis data structure.
- * \param[out]    grps  Pointer to receive the default groups.
- * \returns       0 on success, a non-zero error code on error.
- */
-static int
-init_default_selections(gmx_ana_traj_t *d, gmx_ana_indexgrps_t **grps)
-{
-    gmx_ana_selcollection_t  *sc;
-    char                     *fnm;
-    int                       nr, nr_notempty, i;
-    int                       rc;
-
-    /* If an index file is provided, just load it and exit. */
-    if (d->ndxfile)
-    {
-        gmx_ana_indexgrps_init(grps, d->top, d->ndxfile);
-        return 0;
-    }
-    /* Initialize groups to NULL if we return prematurely. */
-    *grps = NULL;
-    /* Return immediately if no topology provided. */
-    if (!d->top)
-    {
-        return 0;
-    }
-
-    /* Find the default selection file, return if none found. */
-    fnm = low_gmxlibfn("defselection.dat", TRUE, FALSE);
-    if (fnm == NULL)
-    {
-        return 0;
-    }
-
-    /* Create a temporary selection collection. */
-    rc = gmx_ana_selcollection_create(&sc, d->pcc);
-    if (rc != 0)
-    {
-        sfree(fnm);
-        return rc;
-    }
-    rc = gmx_ana_selmethod_register_defaults(sc);
-    if (rc != 0)
-    {
-        gmx_ana_selcollection_free(sc);
-        sfree(fnm);
-        gmx_fatal(FARGS, "default selection method registration failed");
-        return rc;
-    }
-    /* FIXME: It would be better to not have the strings here hard-coded. */
-    gmx_ana_selcollection_set_refpostype(sc, "atom");
-    gmx_ana_selcollection_set_outpostype(sc, "atom", FALSE);
-
-    /* Parse and compile the file with no external groups. */
-    rc = gmx_ana_selcollection_parse_file(sc, fnm, NULL);
-    sfree(fnm);
-    if (rc != 0)
-    {
-        gmx_ana_selcollection_free(sc);
-        fprintf(stderr, "\nWARNING: default selection(s) could not be parsed\n");
-        return rc;
-    }
-    gmx_ana_selcollection_set_topology(sc, d->top, -1);
-    rc = gmx_ana_selcollection_compile(sc);
-    if (rc != 0)
-    {
-        gmx_ana_selcollection_free(sc);
-        fprintf(stderr, "\nWARNING: default selection(s) could not be compiled\n");
-        return rc;
-    }
-
-    /* Count the non-empty groups and check that there are no dynamic
-     * selections. */
-    nr = gmx_ana_selcollection_get_count(sc);
-    nr_notempty = 0;
-    for (i = 0; i < nr; ++i)
-    {
-        gmx_ana_selection_t  *sel;
-
-        sel = gmx_ana_selcollection_get_selection(sc, i);
-        if (sel->bDynamic)
-        {
-            fprintf(stderr, "\nWARNING: dynamic default selection ignored\n");
-        }
-        else if (sel->g->isize > 0)
-        {
-            ++nr_notempty;
-        }
-    }
-
-    /* Copy the groups to the output structure */
-    gmx_ana_indexgrps_alloc(grps, nr_notempty);
-    nr_notempty = 0;
-    for (i = 0; i < nr; ++i)
-    {
-        gmx_ana_selection_t  *sel;
-
-        sel = gmx_ana_selcollection_get_selection(sc, i);
-        if (!sel->bDynamic && sel->g->isize > 0)
-        {
-            gmx_ana_index_t  *g;
-
-            g = gmx_ana_indexgrps_get_grp(*grps, nr_notempty);
-            gmx_ana_index_copy(g, sel->g, TRUE);
-            g->name = strdup(sel->name);
-            ++nr_notempty;
-        }
-    }
-
-    gmx_ana_selcollection_free(sc);
-    return 0;
-}
-
-/*!
- * \param[in,out] d     Trajectory analysis data structure.
- * \returns       0 on success, a non-zero error code on error.
- *
- * Initializes the selection data in \c gmx_ana_traj_t based on
- * the selection options and/or index files provided on the command line.
- *
- * This function is called automatically by parse_trjana_args() and should
- * not be called directly unless \ref ANA_USER_SELINIT is specified.
- *
- * \see ANA_USER_SELINIT
- */
-int
-gmx_ana_init_selections(gmx_ana_traj_t *d)
-{
-    int                  rc;
-    int                  i;
-    int                  nr;
-    gmx_ana_indexgrps_t *grps;
-    int                  natoms;
-    gmx_bool                 bStdIn;
-    gmx_bool                 bInteractive;
-    gmx_bool                 bOk;
-
-    if (d->sel)
-    {
-        gmx_call("init_selections called more than once\n"
-                 "perhaps you forgot ANA_USER_SELINIT");
-        return -1;
-    }
-
-    gmx_ana_selcollection_set_veloutput(d->sc,
-            d->frflags & (TRX_READ_V | TRX_NEED_V));
-    gmx_ana_selcollection_set_forceoutput(d->sc,
-            d->frflags & (TRX_READ_F | TRX_NEED_F));
-    /* Check if we need some information from the topology */
-    if (gmx_ana_selcollection_requires_top(d->sc))
-    {
-        rc = load_topology(d, TRUE);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    /* Initialize the default selection methods */
-    rc = gmx_ana_selmethod_register_defaults(d->sc);
-    if (rc != 0)
-    {
-        gmx_fatal(FARGS, "default selection method registration failed");
-        return rc;
-    }
-    /* Initialize index groups.
-     * We ignore the return value to continue without the default groups if
-     * there is an error there. */
-    init_default_selections(d, &grps);
-    /* Parse the selections */
-    bStdIn = (d->selfile && d->selfile[0] == '-' && d->selfile[1] == 0)
-             || (d->selection && d->selection[0] == 0)
-             || (!d->selfile && !d->selection);
-    /* Behavior is not very pretty if we cannot check for interactive input,
-     * but at least it should compile and work in most cases. */
-#ifdef HAVE_UNISTD_H
-    bInteractive = bStdIn && isatty(fileno(stdin));
-#else
-    bInteractive = bStdIn;
-#endif
-    if (bStdIn && bInteractive)
-    {
-        /* Parse from stdin */
-        /* First we parse the reference groups if there are any */
-        if (d->nrefgrps > 0)
-        {
-            fprintf(stderr, "\nSpecify ");
-            if (d->nrefgrps == 1)
-            {
-                fprintf(stderr, "a reference selection");
-            }
-            else
-            {
-                fprintf(stderr, "%d reference selections", d->nrefgrps);
-            }
-            fprintf(stderr, ":\n");
-            fprintf(stderr, "(one selection per line, 'help' for help)\n");
-            rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nrefgrps, grps, TRUE);
-            nr = gmx_ana_selcollection_get_count(d->sc);
-            if (rc != 0 || nr != d->nrefgrps)
-            {
-                gmx_ana_traj_free(d);
-                gmx_input("unrecoverable error in selection parsing");
-                return rc;
-            }
-        }
-        /* Then, we parse the analysis groups */
-        fprintf(stderr, "\nSpecify ");
-        if (d->nanagrps == 1)
-        {
-            fprintf(stderr, "a selection");
-        }
-        else if (d->nanagrps == -1)
-        {
-            fprintf(stderr, "any number of selections");
-        }
-        else
-        {
-            fprintf(stderr, "%d selections", d->nanagrps);
-        }
-        fprintf(stderr, " for analysis:\n");
-        fprintf(stderr, "(one selection per line, 'help' for help%s)\n",
-                d->nanagrps == -1 ? ", Ctrl-D to end" : "");
-        rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nanagrps, grps, TRUE);
-        fprintf(stderr, "\n");
-    }
-    else if (bStdIn)
-    {
-        rc = gmx_ana_selcollection_parse_stdin(d->sc, -1, grps, FALSE);
-    }
-    else if (d->selection)
-    {
-        rc = gmx_ana_selcollection_parse_str(d->sc, d->selection, grps);
-    }
-    else
-    {
-        rc = gmx_ana_selcollection_parse_file(d->sc, d->selfile, grps);
-    }
-    if (grps)
-    {
-        gmx_ana_indexgrps_free(grps);
-    }
-    if (rc != 0)
-    {
-        /* Free memory for memory leak checking */
-        gmx_ana_traj_free(d);
-        gmx_input("selection(s) could not be parsed");
-        return rc;
-    }
-
-    /* Check the number of groups */
-    nr = gmx_ana_selcollection_get_count(d->sc);
-    if (nr == 0)
-    {
-        /* TODO: Don't print this if the user has requested help */
-        fprintf(stderr, "Nothing selected, finishing up.\n");
-        gmx_ana_traj_free(d);
-        /* TODO: It would be better to return some code that tells the caller
-         * that one should exit. */
-        exit(0);
-    }
-    if (nr <= d->nrefgrps)
-    {
-        gmx_input("selection does not specify enough index groups");
-        return -1;
-    }
-    if (d->nanagrps <= 0)
-    {
-        d->nanagrps = nr - d->nrefgrps;
-    }
-    else if (nr != d->nrefgrps + d->nanagrps)
-    {
-        gmx_input("selection does not specify the correct number of index groups");
-        return -1;
-    }
-
-    if (d->flags & ANA_DEBUG_SELECTION)
-    {
-        gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
-    }
-    if (gmx_ana_selcollection_requires_top(d->sc))
-    {
-        rc = load_topology(d, TRUE);
-        if (rc != 0)
-        {
-            return rc;
-        }
-    }
-    if (d->top)
-    {
-        natoms = -1;
-    }
-    else
-    {
-        rc = init_first_frame(d);
-        if (rc != 0)
-        {
-            return rc;
-        }
-        natoms = d->fr->natoms;
-    }
-    gmx_ana_selcollection_set_topology(d->sc, d->top, natoms);
-    rc = gmx_ana_selcollection_compile(d->sc);
-    if (rc != 0)
-    {
-        /* Free memory for memory leak checking */
-        gmx_ana_traj_free(d);
-        gmx_input("selection could not be compiled");
-        return rc;
-    }
-    /* Create the selection array */
-    d->ngrps = gmx_ana_selcollection_get_count(d->sc);
-    if (!(d->flags & ANA_USE_FULLGRPS))
-    {
-        d->ngrps -= d->nrefgrps;
-    }
-    snew(d->sel, d->ngrps);
-    for (i = 0; i < d->ngrps; ++i)
-    {
-        if (d->flags & ANA_USE_FULLGRPS)
-        {
-            d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i);
-        }
-        else
-        {
-            d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
-        }
-    }
-    if (d->flags & ANA_DEBUG_SELECTION)
-    {
-        fprintf(stderr, "\n");
-        gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
-        fprintf(stderr, "\n");
-        gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
-        fprintf(stderr, "\n");
-    }
-
-    /* Initialize the position evaluation */
-    gmx_ana_poscalc_init_eval(d->pcc);
-    if (d->flags & ANA_DEBUG_SELECTION)
-    {
-        gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
-        fprintf(stderr, "\n");
-    }
-
-    /* Check that dynamic selections are not provided if not allowed */
-    if (d->flags & ANA_NO_DYNSEL)
-    {
-        for (i = 0; i < d->nrefgrps + d->nanagrps; ++i)
-        {
-            gmx_ana_selection_t *sel;
-
-            sel = gmx_ana_selcollection_get_selection(d->sc, i);
-            if (sel->bDynamic)
-            {
-                gmx_fatal(FARGS, "%s does not support dynamic selections",
-                          ShortProgram());
-                return -1;
-            }
-        }
-    }
-    /* Check that non-atom positions are not provided if not allowed.
-     * TODO: It would be better to have these checks in the parser. */
-    if (d->flags & ANA_ONLY_ATOMPOS)
-    {
-        for (i = 0; i < d->nanagrps; ++i)
-        {
-            gmx_ana_selection_t *sel;
-
-            sel = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
-            if (sel->p.m.type != INDEX_ATOM)
-            {
-                gmx_fatal(FARGS, "%s does not support non-atom positions",
-                          ShortProgram());
-                return -1;
-            }
-        }
-    }
-    /* Create the names array */
-    snew(d->grpnames, d->ngrps);
-    for (i = 0; i < d->ngrps; ++i)
-    {
-        d->grpnames[i] = gmx_ana_selection_name(d->sel[i]);
-    }
-
-    return 0;
-}
-
-/*!
- * \param[in,out] d       Trajectory analysis data structure.
- * \param[in]     type    Type of covered fractions to calculate.
- * \returns       0 on success, a non-zero error code on error.
- *
- * By default, covered fractions are not calculated.
- * If this function is called, the covered fraction calculation is
- * initialize to calculate the fractions of type \p type for each selection.
- * The function must be called after gmx_ana_init_selections() has been
- * called.
- *
- * For more fine-grained control of the calculation, you can use
- * gmx_ana_selection_init_coverfrac(): if you initialize some selections
- * this function to something else than CFRAC_NONE before calling
- * gmx_ana_init_coverfrac(), these settings are not overwritten.
- *
- * You only need to call this function if your program needs to have
- * information about the covered fractions, e.g., for normalization.
- *
- * \see gmx_ana_selection_init_coverfrac()
- */
-int
-gmx_ana_init_coverfrac(gmx_ana_traj_t *d, e_coverfrac_t type)
-{
-    int                 g;
-
-    if (type == CFRAC_NONE)
-    {
-        return 0;
-    }
-
-    for (g = 0; g < d->ngrps; ++g)
-    {
-        if (d->sel[g]->cfractype == CFRAC_NONE)
-        {
-            gmx_ana_selection_init_coverfrac(d->sel[g], type);
-        }
-    }
-    return 0;
-}
-
-/*!
- * \param[in] out  Output file.
- * \param[in] d    Trajectory analysis data structure.
- * \returns   0 on success, a non-zero error code on error.
- */
-int xvgr_selections(FILE *out, gmx_ana_traj_t *d)
-{
-    xvgr_selcollection(out, d->sc, d->oenv);
-    return 0;
-}
-
-/*!
- * \param[in,out] d       Trajectory analysis data structure.
- * \returns       0 on success, a non-zero error code on error.
- */
-static int init_first_frame(gmx_ana_traj_t *d)
-{
-    int                 i;
-
-    /* Return if we have already initialized the trajectory */
-    if (d->fr)
-    {
-        return 0;
-    }
-
-    d->frflags |= TRX_NEED_X;
-
-    snew(d->fr, 1);
-
-    if (d->trjfile)
-    {
-        if (!read_first_frame(d->oenv, &d->status, d->trjfile, d->fr, d->frflags))
-        {
-            gmx_input("could not read coordinates from trajectory");
-            return EIO;
-        }
-
-        if (d->top && d->fr->natoms > d->top->atoms.nr)
-        {
-            gmx_fatal(FARGS, "Trajectory (%d atoms) does not match topology (%d atoms)",
-                      d->fr->natoms, d->top->atoms.nr);
-            return -1;
-        }
-        /* check index groups */
-        for (i = 0; i < d->ngrps; ++i)
-        {
-            gmx_ana_index_check(d->sel[i]->g, d->fr->natoms);
-        }
-    }
-    else
-    {
-        /* Prepare a frame from topology information */
-        /* TODO: Initialize more of the fields */
-        if (d->frflags & (TRX_NEED_V))
-        {
-            gmx_impl("Velocity reading from a topology not implemented");
-            return -1;
-        }
-        if (d->frflags & (TRX_NEED_F))
-        {
-            gmx_input("Forces cannot be read from a topology");
-            return -1;
-        }
-        d->fr->flags  = d->frflags;
-        d->fr->natoms = d->top->atoms.nr;
-        d->fr->bX     = TRUE;
-        snew(d->fr->x, d->fr->natoms);
-        memcpy(d->fr->x, d->xtop, sizeof(*d->fr->x)*d->fr->natoms);
-        d->fr->bBox   = TRUE;
-        copy_mat(d->boxtop, d->fr->box);
-    }
-
-    set_trxframe_ePBC(d->fr, d->ePBC);
-
-    return 0;
-}
-
-/*!
- * \param[in,out] d       Trajectory analysis data structure.
- * \param[out]    fr      First frame in the trajectory.
- * \returns       0 on success, a non-zero error code on error.
- *
- * The pointer stored in \p *fr should not be freed by the caller.
- *
- * You only need to call this function if your program needs to do some
- * initialization for which it requires data from the first frame.
- *
- * \see gmx_ana_do()
- */
-int gmx_ana_get_first_frame(gmx_ana_traj_t *d, t_trxframe **fr)
-{
-    int rc;
-
-    rc = init_first_frame(d);
-    if (rc != 0)
-    {
-        *fr = NULL;
-        return rc;
-    }
-    *fr = d->fr;
-    return 0;
-}
-
-/*!
- * \param[in,out] d   Trajectory analysis data structure.
- * \param[in] flags   Combination of flags
- *      (currently, there are no flags defined).
- * \param[in] analyze Pointer to frame analysis function.
- * \param     data    User data to be passed to \p analyze.
- * \returns   0 on success, a non-zero error code on error.
- *
- * This function performs the actual analysis of the trajectory.
- * It loops through all the frames in the trajectory, and calls
- * \p analyze for each frame to perform the actual analysis.
- * Before calling \p analyze, selections are updated (if there are any).
- * See gmx_analysisfunc() for description of \p analyze parameters.
- *
- * This function also calculates the number of frames during the run.
- */
-int gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *data)
-{
-    t_pbc               pbc;
-    t_pbc              *ppbc;
-    int                 rc;
-    gmx_rmpbc_t         gpbc=NULL;
-    
-    rc = init_first_frame(d);
-    if (rc != 0)
-    {
-        return rc;
-    }
-
-    ppbc = d->bPBC ? &pbc : 0;
-    if (!d->top)
-    {
-        d->bRmPBC = FALSE;
-    }
-    if (d->bRmPBC) 
-    {
-       gpbc = gmx_rmpbc_init(&d->top->idef,d->ePBC,d->fr->natoms,d->fr->box);
-    }
-    d->nframes = 0;
-    do
-    {
-        if (d->bRmPBC)
-        {
-           gmx_rmpbc_trxfr(gpbc,d->fr);
-        }
-        if (ppbc)
-        {
-            set_pbc(&pbc, d->ePBC, d->fr->box);
-        }
-
-        gmx_ana_poscalc_init_frame(d->pcc);
-        rc = gmx_ana_selcollection_evaluate(d->sc, d->fr, ppbc);
-        if (rc != 0)
-        {
-            close_trj(d->status);
-            gmx_fatal(FARGS, "selection evaluation failed");
-            return rc;
-        }
-        rc = analyze(d->top, d->fr, ppbc, d->ngrps, d->sel, data);
-        if (rc != 0)
-        {
-            close_trj(d->status);
-            return rc;
-        }
-
-        d->nframes++;
-    }
-    while (d->trjfile && read_next_frame(d->oenv, d->status, d->fr));
-    if (d->bRmPBC)
-    {
-        gmx_rmpbc_done(gpbc);
-    }
-    if (d->trjfile)
-    {
-        close_trj(d->status);
-        fprintf(stderr, "Analyzed %d frames, last time %.3f\n",
-                d->nframes, d->fr->time);
-    }
-    else
-    {
-        fprintf(stderr, "Analyzed topology coordinates\n");
-    }
-
-    /* Restore the maximal groups for dynamic selections */
-    rc = gmx_ana_selcollection_evaluate_fin(d->sc, d->nframes);
-    if (rc != 0)
-    {
-        gmx_fatal(FARGS, "selection evaluation failed");
-    }
-
-    return rc;
-}
-
-/*!
- * \param[in,out] d       Trajectory analysis data structure.
- * \param[out]    nframes Number of frames.
- * \returns   0 on success, a non-zero error code on error.
- *
- * If called before gmx_ana_do(), the behavior is currently undefined.
- */
-extern int
-gmx_ana_get_nframes(gmx_ana_traj_t *d, int *nframes)
-{
-    *nframes = d->nframes;
-    return 0;
-}
diff --git a/src/gmxlib/txtdump.c b/src/gmxlib/txtdump.c
deleted file mode 100644 (file)
index 0221e2f..0000000
+++ /dev/null
@@ -1,1465 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROningen Mixture of Alchemy and Childrens' Stories
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* This file is completely threadsafe - please keep it that way! */
-#ifdef GMX_THREADS
-#include <thread_mpi.h>
-#endif
-
-
-#include <stdio.h>
-#include "smalloc.h"
-#include "typedefs.h"
-#include "names.h"
-#include "txtdump.h"
-#include "string2.h"
-#include "vec.h"
-
-
-int pr_indent(FILE *fp,int n)
-{
-  int i;
-
-  for (i=0; i<n; i++) (void) fprintf(fp," ");
-  return n;
-}
-
-int available(FILE *fp,void *p,int indent,const char *title)
-{
-  if (!p) {
-    if (indent > 0)
-      pr_indent(fp,indent);
-    (void) fprintf(fp,"%s: not available\n",title);
-  }
-  return (p!=NULL);
-}
-
-int pr_title(FILE *fp,int indent,const char *title)
-{
-  (void) pr_indent(fp,indent);
-  (void) fprintf(fp,"%s:\n",title);
-  return (indent+INDENT);
-}
-
-int pr_title_n(FILE *fp,int indent,const char *title,int n)
-{
-  (void) pr_indent(fp,indent);
-  (void) fprintf(fp,"%s (%d):\n",title,n);
-  return (indent+INDENT);
-}
-
-int pr_title_nxn(FILE *fp,int indent,const char *title,int n1,int n2)
-{
-  (void) pr_indent(fp,indent);
-  (void) fprintf(fp,"%s (%dx%d):\n",title,n1,n2);
-  return (indent+INDENT);
-}
-
-void pr_ivec(FILE *fp,int indent,const char *title,int vec[],int n, gmx_bool bShowNumbers)
-{
-  int i;
-
-  if (available(fp,vec,indent,title))
-    {
-      indent=pr_title_n(fp,indent,title,n);
-      for (i=0; i<n; i++)
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"%s[%d]=%d\n",title,bShowNumbers?i:-1,vec[i]);
-        }
-    }
-}
-
-void pr_ivec_block(FILE *fp,int indent,const char *title,int vec[],int n, gmx_bool bShowNumbers)
-{
-    int i,j;
-    
-    if (available(fp,vec,indent,title))
-    {
-        indent=pr_title_n(fp,indent,title,n);
-        i = 0;
-        while (i < n)
-        {
-            j = i+1;
-            while (j < n && vec[j] == vec[j-1]+1)
-            {
-                j++;
-            }
-            /* Print consecutive groups of 3 or more as blocks */
-            if (j - i < 3)
-            {
-                while(i < j)
-                {
-                    (void) pr_indent(fp,indent);
-                    (void) fprintf(fp,"%s[%d]=%d\n",
-                                   title,bShowNumbers?i:-1,vec[i]);
-                    i++;
-                }
-            }
-            else
-            {
-                (void) pr_indent(fp,indent);
-                (void) fprintf(fp,"%s[%d,...,%d] = {%d,...,%d}\n",
-                               title,
-                               bShowNumbers?i:-1,
-                               bShowNumbers?j-1:-1,
-                               vec[i],vec[j-1]); 
-                i = j;
-            }
-        }
-    }
-}
-
-void pr_bvec(FILE *fp,int indent,const char *title,gmx_bool vec[],int n, gmx_bool bShowNumbers)
-{
-  int i;
-
-  if (available(fp,vec,indent,title))
-    {
-      indent=pr_title_n(fp,indent,title,n);
-      for (i=0; i<n; i++)
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"%s[%d]=%s\n",title,bShowNumbers?i:-1,
-                        BOOL(vec[i]));
-        }
-    }
-}
-
-void pr_ivecs(FILE *fp,int indent,const char *title,ivec vec[],int n, gmx_bool bShowNumbers)
-{
-  int i,j;
-
-  if (available(fp,vec,indent,title))
-    {  
-      indent=pr_title_nxn(fp,indent,title,n,DIM);
-      for (i=0; i<n; i++)
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"%s[%d]={",title,bShowNumbers?i:-1);
-          for (j=0; j<DIM; j++)
-            {
-              if (j!=0) (void) fprintf(fp,", ");
-              fprintf(fp,"%d",vec[i][j]);
-            }
-          (void) fprintf(fp,"}\n");
-        }
-    }
-}
-
-void pr_rvec(FILE *fp,int indent,const char *title,real vec[],int n, gmx_bool bShowNumbers)
-{
-  int i;
-
-  if (available(fp,vec,indent,title))
-    {  
-      indent=pr_title_n(fp,indent,title,n);
-      for (i=0; i<n; i++)
-        {
-          pr_indent(fp,indent);
-          fprintf(fp,"%s[%d]=%12.5e\n",title,bShowNumbers?i:-1,vec[i]);
-        }
-    }
-}
-
-void pr_dvec(FILE *fp,int indent,const char *title,double vec[],int n, gmx_bool bShowNumbers)
-{
-       int i;
-       
-       if (available(fp,vec,indent,title))
-    {  
-               indent=pr_title_n(fp,indent,title,n);
-               for (i=0; i<n; i++)
-        {
-                       pr_indent(fp,indent);
-                       fprintf(fp,"%s[%d]=%12.5e\n",title,bShowNumbers?i:-1,vec[i]);
-        }
-    }
-}
-
-
-/*
-void pr_mat(FILE *fp,int indent,char *title,matrix m)
-{
-  int i,j;
-  
-  if (available(fp,m,indent,title)) {  
-    indent=pr_title_n(fp,indent,title,n);
-    for(i=0; i<n; i++) {
-      pr_indent(fp,indent);
-      fprintf(fp,"%s[%d]=%12.5e %12.5e %12.5e\n",
-             title,bShowNumbers?i:-1,m[i][XX],m[i][YY],m[i][ZZ]);
-    }
-  }
-}
-*/
-
-void pr_rvecs_len(FILE *fp,int indent,const char *title,rvec vec[],int n)
-{
-  int i,j;
-
-  if (available(fp,vec,indent,title)) {  
-    indent=pr_title_nxn(fp,indent,title,n,DIM);
-    for (i=0; i<n; i++) {
-      (void) pr_indent(fp,indent);
-      (void) fprintf(fp,"%s[%5d]={",title,i);
-      for (j=0; j<DIM; j++) {
-       if (j != 0) 
-         (void) fprintf(fp,", ");
-       (void) fprintf(fp,"%12.5e",vec[i][j]);
-      }
-      (void) fprintf(fp,"} len=%12.5e\n",norm(vec[i]));
-    }
-  }
-}
-
-void pr_rvecs(FILE *fp,int indent,const char *title,rvec vec[],int n)
-{
-  const char *fshort = "%12.5e";
-  const char *flong  = "%15.8e";
-  const char *format;
-  int i,j;
-
-  if (getenv("LONGFORMAT") != NULL)
-    format = flong;
-  else
-    format = fshort;
-    
-  if (available(fp,vec,indent,title)) {  
-    indent=pr_title_nxn(fp,indent,title,n,DIM);
-    for (i=0; i<n; i++) {
-      (void) pr_indent(fp,indent);
-      (void) fprintf(fp,"%s[%5d]={",title,i);
-      for (j=0; j<DIM; j++) {
-       if (j != 0) 
-         (void) fprintf(fp,", ");
-       (void) fprintf(fp,format,vec[i][j]);
-      }
-      (void) fprintf(fp,"}\n");
-    }
-  }
-}
-
-
-void pr_reals(FILE *fp,int indent,const char *title,real *vec,int n)
-{
-  int i;
-    
-  if (available(fp,vec,indent,title)) {  
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"%s:\t",title);
-    for(i=0; i<n; i++)
-      fprintf(fp,"  %10g",vec[i]);
-    (void) fprintf(fp,"\n");
-  }
-}
-
-void pr_doubles(FILE *fp,int indent,const char *title,double *vec,int n)
-{
-  int i;
-    
-  if (available(fp,vec,indent,title)) {  
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"%s:\t",title);
-    for(i=0; i<n; i++)
-      fprintf(fp,"  %10g",vec[i]);
-    (void) fprintf(fp,"\n");
-  }
-}
-
-static void pr_int(FILE *fp,int indent,const char *title,int i)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"%-20s = %d\n",title,i);
-}
-
-static void pr_gmx_large_int(FILE *fp,int indent,const char *title,gmx_large_int_t i)
-{
-  char buf[STEPSTRSIZE];
-
-  pr_indent(fp,indent);
-  fprintf(fp,"%-20s = %s\n",title,gmx_step_str(i,buf));
-}
-
-static void pr_real(FILE *fp,int indent,const char *title,real r)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"%-20s = %g\n",title,r);
-}
-
-static void pr_double(FILE *fp,int indent,const char *title,double d)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"%-20s = %g\n",title,d);
-}
-
-static void pr_str(FILE *fp,int indent,const char *title,const char *s)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"%-20s = %s\n",title,s);
-}
-
-void pr_qm_opts(FILE *fp,int indent,const char *title,t_grpopts *opts)
-{
-  int i,m,j;
-
-  fprintf(fp,"%s:\n",title);
-  
-  pr_int(fp,indent,"ngQM",opts->ngQM);
-  if (opts->ngQM > 0) {
-    pr_ivec(fp,indent,"QMmethod",opts->QMmethod,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"QMbasis",opts->QMbasis,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"QMcharge",opts->QMcharge,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"QMmult",opts->QMmult,opts->ngQM,FALSE);
-    pr_bvec(fp,indent,"bSH",opts->bSH,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"CASorbitals",opts->CASorbitals,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"CASelectrons",opts->CASelectrons,opts->ngQM,FALSE);
-    pr_rvec(fp,indent,"SAon",opts->SAon,opts->ngQM,FALSE);
-    pr_rvec(fp,indent,"SAon",opts->SAon,opts->ngQM,FALSE);
-    pr_ivec(fp,indent,"SAsteps",opts->SAsteps,opts->ngQM,FALSE);
-    pr_bvec(fp,indent,"bOPT",opts->bOPT,opts->ngQM,FALSE);
-    pr_bvec(fp,indent,"bTS",opts->bTS,opts->ngQM,FALSE);
-  }
-}
-
-static void pr_grp_opts(FILE *out,int indent,const char *title,t_grpopts *opts,
-                       gmx_bool bMDPformat)
-{
-  int i,m,j;
-
-  if (!bMDPformat)
-    fprintf(out,"%s:\n",title);
-  
-  pr_indent(out,indent);
-  fprintf(out,"nrdf%s",bMDPformat ? " = " : ":");
-  for(i=0; (i<opts->ngtc); i++)
-    fprintf(out,"  %10g",opts->nrdf[i]);
-  fprintf(out,"\n");
-  
-  pr_indent(out,indent);
-  fprintf(out,"ref-t%s",bMDPformat ? " = " : ":");
-  for(i=0; (i<opts->ngtc); i++)
-    fprintf(out,"  %10g",opts->ref_t[i]);
-  fprintf(out,"\n");
-
-  pr_indent(out,indent);
-  fprintf(out,"tau-t%s",bMDPformat ? " = " : ":");
-  for(i=0; (i<opts->ngtc); i++)
-    fprintf(out,"  %10g",opts->tau_t[i]);
-  fprintf(out,"\n");  
-  
-  /* Pretty-print the simulated annealing info */
-  fprintf(out,"anneal%s",bMDPformat ? " = " : ":");
-  for(i=0; (i<opts->ngtc); i++)
-    fprintf(out,"  %10s",EANNEAL(opts->annealing[i]));
-  fprintf(out,"\n");  
-  fprintf(out,"ann-npoints%s",bMDPformat ? " = " : ":");
-  for(i=0; (i<opts->ngtc); i++)
-    fprintf(out,"  %10d",opts->anneal_npoints[i]);
-  fprintf(out,"\n");  
-  for(i=0; (i<opts->ngtc); i++) {
-    if(opts->anneal_npoints[i]>0) {
-      fprintf(out,"ann. times [%d]:\t",i);
-      for(j=0; (j<opts->anneal_npoints[i]); j++)
-       fprintf(out,"  %10.1f",opts->anneal_time[i][j]);
-      fprintf(out,"\n");  
-      fprintf(out,"ann. temps [%d]:\t",i);
-      for(j=0; (j<opts->anneal_npoints[i]); j++)
-       fprintf(out,"  %10.1f",opts->anneal_temp[i][j]);
-      fprintf(out,"\n");  
-    }
-  }
-  
-  pr_indent(out,indent);
-  fprintf(out,"acc:\t");
-  for(i=0; (i<opts->ngacc); i++)
-    for(m=0; (m<DIM); m++)
-      fprintf(out,"  %10g",opts->acc[i][m]);
-  fprintf(out,"\n");
-
-  pr_indent(out,indent);
-  fprintf(out,"nfreeze:");
-  for(i=0; (i<opts->ngfrz); i++)
-    for(m=0; (m<DIM); m++)
-      fprintf(out,"  %10s",opts->nFreeze[i][m] ? "Y" : "N");
-  fprintf(out,"\n");
-
-
-  for(i=0; (i<opts->ngener); i++) {
-    pr_indent(out,indent);
-    fprintf(out,"energygrp-flags[%3d]:",i);
-    for(m=0; (m<opts->ngener); m++)
-      fprintf(out," %d",opts->egp_flags[opts->ngener*i+m]);
-    fprintf(out,"\n");
-  }
-
-  fflush(out);
-}
-
-static void pr_matrix(FILE *fp,int indent,const char *title,rvec *m,
-                     gmx_bool bMDPformat)
-{
-  if (bMDPformat)
-    fprintf(fp,"%-10s    = %g %g %g %g %g %g\n",title,
-           m[XX][XX],m[YY][YY],m[ZZ][ZZ],m[XX][YY],m[XX][ZZ],m[YY][ZZ]);
-  else
-    pr_rvecs(fp,indent,title,m,DIM);
-}
-
-static void pr_cosine(FILE *fp,int indent,const char *title,t_cosines *cos,
-                     gmx_bool bMDPformat)
-{
-  int j;
-  
-  if (bMDPformat) {
-    fprintf(fp,"%s = %d\n",title,cos->n);
-  }
-  else {
-    indent=pr_title(fp,indent,title);
-    (void) pr_indent(fp,indent);
-    fprintf(fp,"n = %d\n",cos->n);
-    if (cos->n > 0) {
-      (void) pr_indent(fp,indent+2);
-      fprintf(fp,"a =");
-      for(j=0; (j<cos->n); j++)
-       fprintf(fp," %e",cos->a[j]);
-      fprintf(fp,"\n");
-      (void) pr_indent(fp,indent+2);
-      fprintf(fp,"phi =");
-      for(j=0; (j<cos->n); j++)
-       fprintf(fp," %e",cos->phi[j]);
-      fprintf(fp,"\n");
-    }
-  }
-}
-
-#define PS(t,s) pr_str(fp,indent,t,s)
-#define PI(t,s) pr_int(fp,indent,t,s)
-#define PSTEP(t,s) pr_gmx_large_int(fp,indent,t,s)
-#define PR(t,s) pr_real(fp,indent,t,s)
-#define PD(t,s) pr_double(fp,indent,t,s)
-
-static void pr_pullgrp(FILE *fp,int indent,int g,t_pullgrp *pg)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"pull-group %d:\n",g);
-  indent += 2;
-  pr_ivec_block(fp,indent,"atom",pg->ind,pg->nat,TRUE);
-  pr_rvec(fp,indent,"weight",pg->weight,pg->nweight,TRUE);
-  PI("pbcatom",pg->pbcatom);
-  pr_rvec(fp,indent,"vec",pg->vec,DIM,TRUE);
-  pr_rvec(fp,indent,"init",pg->init,DIM,TRUE);
-  PR("rate",pg->rate);
-  PR("k",pg->k);
-  PR("kB",pg->kB);
-}
-
-static void pr_pull(FILE *fp,int indent,t_pull *pull)
-{
-  int g;
-
-  PS("pull-geometry",EPULLGEOM(pull->eGeom));
-  pr_ivec(fp,indent,"pull-dim",pull->dim,DIM,TRUE);
-  PR("pull-r1",pull->cyl_r1);
-  PR("pull-r0",pull->cyl_r0);
-  PR("pull-constr-tol",pull->constr_tol);
-  PI("pull-nstxout",pull->nstxout);
-  PI("pull-nstfout",pull->nstfout);
-  PI("pull-ngrp",pull->ngrp);
-  for(g=0; g<pull->ngrp+1; g++)
-    pr_pullgrp(fp,indent,g,&pull->grp[g]);
-}
-
-void pr_inputrec(FILE *fp,int indent,const char *title,t_inputrec *ir,
-                 gmx_bool bMDPformat)
-{
-  const char *infbuf="inf";
-  int  i;
-  
-  if (available(fp,ir,indent,title)) {
-    if (!bMDPformat)
-      indent=pr_title(fp,indent,title);
-    PS("integrator",EI(ir->eI));
-    PSTEP("nsteps",ir->nsteps);
-    PSTEP("init-step",ir->init_step);
-    PS("ns-type",ENS(ir->ns_type));
-    PI("nstlist",ir->nstlist);
-    PI("ndelta",ir->ndelta);
-    PI("nstcomm",ir->nstcomm);
-    PS("comm-mode",ECOM(ir->comm_mode));
-    PI("nstlog",ir->nstlog);
-    PI("nstxout",ir->nstxout);
-    PI("nstvout",ir->nstvout);
-    PI("nstfout",ir->nstfout);
-    PI("nstcalcenergy",ir->nstcalcenergy);
-    PI("nstenergy",ir->nstenergy);
-    PI("nstxtcout",ir->nstxtcout);
-    PR("init-t",ir->init_t);
-    PR("delta-t",ir->delta_t);
-    
-    PR("xtcprec",ir->xtcprec);
-    PI("nkx",ir->nkx);
-    PI("nky",ir->nky);
-    PI("nkz",ir->nkz);
-    PI("pme-order",ir->pme_order);
-    PR("ewald-rtol",ir->ewald_rtol);
-    PR("ewald-geometry",ir->ewald_geometry);
-    PR("epsilon-surface",ir->epsilon_surface);
-    PS("optimize-fft",BOOL(ir->bOptFFT));
-    PS("ePBC",EPBC(ir->ePBC));
-    PS("bPeriodicMols",BOOL(ir->bPeriodicMols));
-    PS("bContinuation",BOOL(ir->bContinuation));
-    PS("bShakeSOR",BOOL(ir->bShakeSOR));
-    PS("etc",ETCOUPLTYPE(ir->etc));
-    PI("nsttcouple",ir->nsttcouple);
-    PS("epc",EPCOUPLTYPE(ir->epc));
-    PS("epctype",EPCOUPLTYPETYPE(ir->epct));
-    PI("nstpcouple",ir->nstpcouple);
-    PR("tau-p",ir->tau_p);
-    pr_matrix(fp,indent,"ref-p",ir->ref_p,bMDPformat);
-    pr_matrix(fp,indent,"compress",ir->compress,bMDPformat);
-    PS("refcoord-scaling",EREFSCALINGTYPE(ir->refcoord_scaling));
-    if (bMDPformat)
-      fprintf(fp,"posres-com  = %g %g %g\n",ir->posres_com[XX],
-             ir->posres_com[YY],ir->posres_com[ZZ]);
-    else
-      pr_rvec(fp,indent,"posres-com",ir->posres_com,DIM,TRUE);
-    if (bMDPformat)
-      fprintf(fp,"posres-comB = %g %g %g\n",ir->posres_comB[XX],
-             ir->posres_comB[YY],ir->posres_comB[ZZ]);
-    else
-      pr_rvec(fp,indent,"posres-comB",ir->posres_comB,DIM,TRUE);
-    PI("andersen-seed",ir->andersen_seed);
-    PR("rlist",ir->rlist);
-    PR("rlistlong",ir->rlistlong);
-    PR("rtpi",ir->rtpi);
-    PS("coulombtype",EELTYPE(ir->coulombtype));
-    PR("rcoulomb-switch",ir->rcoulomb_switch);
-    PR("rcoulomb",ir->rcoulomb);
-    PS("vdwtype",EVDWTYPE(ir->vdwtype));
-    PR("rvdw-switch",ir->rvdw_switch);
-    PR("rvdw",ir->rvdw);
-    if (ir->epsilon_r != 0)
-      PR("epsilon-r",ir->epsilon_r);
-    else
-      PS("epsilon-r",infbuf);
-    if (ir->epsilon_rf != 0)
-      PR("epsilon-rf",ir->epsilon_rf);
-    else
-      PS("epsilon-rf",infbuf);
-    PR("tabext",ir->tabext);
-    PS("implicit-solvent",EIMPLICITSOL(ir->implicit_solvent));
-    PS("gb-algorithm",EGBALGORITHM(ir->gb_algorithm));
-    PR("gb-epsilon-solvent",ir->gb_epsilon_solvent);
-    PI("nstgbradii",ir->nstgbradii);
-    PR("rgbradii",ir->rgbradii);
-    PR("gb-saltconc",ir->gb_saltconc);
-    PR("gb-obc-alpha",ir->gb_obc_alpha);
-    PR("gb-obc-beta",ir->gb_obc_beta);
-    PR("gb-obc-gamma",ir->gb_obc_gamma);
-    PR("gb-dielectric-offset",ir->gb_dielectric_offset);
-    PS("sa-algorithm",ESAALGORITHM(ir->gb_algorithm));
-    PR("sa-surface-tension",ir->sa_surface_tension);
-         
-    PS("DispCorr",EDISPCORR(ir->eDispCorr));
-    PS("free-energy",EFEPTYPE(ir->efep));
-    PR("init-lambda",ir->init_lambda);
-    PR("delta-lambda",ir->delta_lambda);
-    if (!bMDPformat)
-    {
-        PI("n-foreign-lambda",ir->n_flambda);
-    }
-    if (ir->n_flambda > 0)
-    {
-        pr_indent(fp,indent);
-        fprintf(fp,"foreign-lambda%s",bMDPformat ? " = " : ":");
-        for(i=0; i<ir->n_flambda; i++)
-        {
-            fprintf(fp,"  %10g",ir->flambda[i]);
-        }
-        fprintf(fp,"\n");
-    }
-    PR("sc-alpha",ir->sc_alpha);
-    PI("sc-power",ir->sc_power);
-    PR("sc-sigma",ir->sc_sigma);
-    PR("sc-sigma-min",ir->sc_sigma_min);
-    PI("nstdhdl", ir->nstdhdl);
-    PS("separate-dhdl-file", SEPDHDLFILETYPE(ir->separate_dhdl_file));
-    PS("dhdl-derivatives", DHDLDERIVATIVESTYPE(ir->dhdl_derivatives));
-    PI("dh-hist-size", ir->dh_hist_size);
-    PD("dh-hist-spacing", ir->dh_hist_spacing);
-
-    PI("nwall",ir->nwall);
-    PS("wall-type",EWALLTYPE(ir->wall_type));
-    PI("wall-atomtype[0]",ir->wall_atomtype[0]);
-    PI("wall-atomtype[1]",ir->wall_atomtype[1]);
-    PR("wall-density[0]",ir->wall_density[0]);
-    PR("wall-density[1]",ir->wall_density[1]);
-    PR("wall-ewald-zfac",ir->wall_ewald_zfac);
-
-    PS("pull",EPULLTYPE(ir->ePull));
-    if (ir->ePull != epullNO)
-      pr_pull(fp,indent,ir->pull);
-
-    PS("disre",EDISRETYPE(ir->eDisre));
-    PS("disre-weighting",EDISREWEIGHTING(ir->eDisreWeighting));
-    PS("disre-mixed",BOOL(ir->bDisreMixed));
-    PR("dr-fc",ir->dr_fc);
-    PR("dr-tau",ir->dr_tau);
-    PR("nstdisreout",ir->nstdisreout);
-    PR("orires-fc",ir->orires_fc);
-    PR("orires-tau",ir->orires_tau);
-    PR("nstorireout",ir->nstorireout);
-
-    PR("dihre-fc",ir->dihre_fc);
-    
-    PR("em-stepsize",ir->em_stepsize);
-    PR("em-tol",ir->em_tol);
-    PI("niter",ir->niter);
-    PR("fc-stepsize",ir->fc_stepsize);
-    PI("nstcgsteep",ir->nstcgsteep);
-    PI("nbfgscorr",ir->nbfgscorr);
-
-    PS("ConstAlg",ECONSTRTYPE(ir->eConstrAlg));
-    PR("shake-tol",ir->shake_tol);
-    PI("lincs-order",ir->nProjOrder);
-    PR("lincs-warnangle",ir->LincsWarnAngle);
-    PI("lincs-iter",ir->nLincsIter);
-    PR("bd-fric",ir->bd_fric);
-    PI("ld-seed",ir->ld_seed);
-    PR("cos-accel",ir->cos_accel);
-    pr_matrix(fp,indent,"deform",ir->deform,bMDPformat);
-    PI("userint1",ir->userint1);
-    PI("userint2",ir->userint2);
-    PI("userint3",ir->userint3);
-    PI("userint4",ir->userint4);
-    PR("userreal1",ir->userreal1);
-    PR("userreal2",ir->userreal2);
-    PR("userreal3",ir->userreal3);
-    PR("userreal4",ir->userreal4);
-    pr_grp_opts(fp,indent,"grpopts",&(ir->opts),bMDPformat);
-    pr_cosine(fp,indent,"efield-x",&(ir->ex[XX]),bMDPformat);
-    pr_cosine(fp,indent,"efield-xt",&(ir->et[XX]),bMDPformat);
-    pr_cosine(fp,indent,"efield-y",&(ir->ex[YY]),bMDPformat);
-    pr_cosine(fp,indent,"efield-yt",&(ir->et[YY]),bMDPformat);
-    pr_cosine(fp,indent,"efield-z",&(ir->ex[ZZ]),bMDPformat);
-    pr_cosine(fp,indent,"efield-zt",&(ir->et[ZZ]),bMDPformat);
-    PS("bQMMM",BOOL(ir->bQMMM));
-    PI("QMconstraints",ir->QMconstraints);
-    PI("QMMMscheme",ir->QMMMscheme);
-    PR("scalefactor",ir->scalefactor);
-    pr_qm_opts(fp,indent,"qm-opts",&(ir->opts));
-  }
-}
-#undef PS
-#undef PR
-#undef PI
-
-static void pr_harm(FILE *fp,t_iparams *iparams,const char *r,const char *kr)
-{
-  fprintf(fp,"%sA=%12.5e, %sA=%12.5e, %sB=%12.5e, %sB=%12.5e\n",
-         r,iparams->harmonic.rA,kr,iparams->harmonic.krA,
-         r,iparams->harmonic.rB,kr,iparams->harmonic.krB);
-}
-
-void pr_iparams(FILE *fp,t_functype ftype,t_iparams *iparams)
-{
-  int i;
-  real VA[4],VB[4],*rbcA,*rbcB;
-
-  switch (ftype) {
-  case F_ANGLES:
-  case F_G96ANGLES:
-    pr_harm(fp,iparams,"th","ct");
-    break;
-  case F_CROSS_BOND_BONDS:
-    fprintf(fp,"r1e=%15.8e, r2e=%15.8e, krr=%15.8e\n",
-           iparams->cross_bb.r1e,iparams->cross_bb.r2e,
-           iparams->cross_bb.krr);
-    break;
-  case F_CROSS_BOND_ANGLES:
-    fprintf(fp,"r1e=%15.8e, r1e=%15.8e, r3e=%15.8e, krt=%15.8e\n",
-           iparams->cross_ba.r1e,iparams->cross_ba.r2e,
-           iparams->cross_ba.r3e,iparams->cross_ba.krt);
-    break;
-  case F_UREY_BRADLEY:
-    fprintf(fp,"theta=%15.8e, ktheta=%15.8e, r13=%15.8e, kUB=%15.8e\n",
-           iparams->u_b.theta,iparams->u_b.ktheta,iparams->u_b.r13,iparams->u_b.kUB);
-    break;
-  case F_QUARTIC_ANGLES:
-    fprintf(fp,"theta=%15.8e",iparams->qangle.theta);
-    for(i=0; i<5; i++)
-      fprintf(fp,", c%c=%15.8e",'0'+i,iparams->qangle.c[i]);
-    fprintf(fp,"\n");
-    break;
-  case F_BHAM:
-    fprintf(fp,"a=%15.8e, b=%15.8e, c=%15.8e\n",
-           iparams->bham.a,iparams->bham.b,iparams->bham.c);
-    break;
-  case F_BONDS:
-  case F_G96BONDS:
-  case F_HARMONIC:
-    pr_harm(fp,iparams,"b0","cb");
-    break;
-  case F_IDIHS:
-    pr_harm(fp,iparams,"xi","cx");
-    break;
-  case F_MORSE:
-    fprintf(fp,"b0=%15.8e, cb=%15.8e, beta=%15.8e\n",
-           iparams->morse.b0,iparams->morse.cb,iparams->morse.beta);
-    break;
-  case F_CUBICBONDS:
-    fprintf(fp,"b0=%15.8e, kb=%15.8e, kcub=%15.8e\n",
-           iparams->cubic.b0,iparams->cubic.kb,iparams->cubic.kcub);
-    break;
-  case F_CONNBONDS:
-    fprintf(fp,"\n");
-    break;
-  case F_FENEBONDS:
-    fprintf(fp,"bm=%15.8e, kb=%15.8e\n",iparams->fene.bm,iparams->fene.kb);
-    break;
-  case F_RESTRBONDS:
-      fprintf(fp,"lowA=%15.8e, up1A=%15.8e, up2A=%15.8e, kA=%15.8e, lowB=%15.8e, up1B=%15.8e, up2B=%15.8e, kB=%15.8e,\n",
-              iparams->restraint.lowA,iparams->restraint.up1A,
-              iparams->restraint.up2A,iparams->restraint.kA,
-              iparams->restraint.lowB,iparams->restraint.up1B,
-              iparams->restraint.up2B,iparams->restraint.kB);
-      break;
-  case F_TABBONDS:
-  case F_TABBONDSNC:
-  case F_TABANGLES:
-  case F_TABDIHS:
-    fprintf(fp,"tab=%d, kA=%15.8e, kB=%15.8e\n",
-           iparams->tab.table,iparams->tab.kA,iparams->tab.kB);
-    break;
-  case F_POLARIZATION:
-    fprintf(fp,"alpha=%15.8e\n",iparams->polarize.alpha);
-    break;
-  case F_THOLE_POL:
-    fprintf(fp,"a=%15.8e, alpha1=%15.8e, alpha2=%15.8e, rfac=%15.8e\n",
-           iparams->thole.a,iparams->thole.alpha1,iparams->thole.alpha2,
-           iparams->thole.rfac);
-    break;
-  case F_WATER_POL:
-    fprintf(fp,"al_x=%15.8e, al_y=%15.8e, al_z=%15.8e, rOH=%9.6f, rHH=%9.6f, rOD=%9.6f\n",
-           iparams->wpol.al_x,iparams->wpol.al_y,iparams->wpol.al_z,
-           iparams->wpol.rOH,iparams->wpol.rHH,iparams->wpol.rOD);
-    break;
-  case F_LJ:
-    fprintf(fp,"c6=%15.8e, c12=%15.8e\n",iparams->lj.c6,iparams->lj.c12);
-    break;
-  case F_LJ14:
-    fprintf(fp,"c6A=%15.8e, c12A=%15.8e, c6B=%15.8e, c12B=%15.8e\n",
-           iparams->lj14.c6A,iparams->lj14.c12A,
-           iparams->lj14.c6B,iparams->lj14.c12B);
-    break;
-  case F_LJC14_Q:
-    fprintf(fp,"fqq=%15.8e, qi=%15.8e, qj=%15.8e, c6=%15.8e, c12=%15.8e\n",
-           iparams->ljc14.fqq,
-           iparams->ljc14.qi,iparams->ljc14.qj,
-           iparams->ljc14.c6,iparams->ljc14.c12);
-    break;
-  case F_LJC_PAIRS_NB:
-    fprintf(fp,"qi=%15.8e, qj=%15.8e, c6=%15.8e, c12=%15.8e\n",
-           iparams->ljcnb.qi,iparams->ljcnb.qj,
-           iparams->ljcnb.c6,iparams->ljcnb.c12);
-    break;
-  case F_PDIHS:
-  case F_PIDIHS:
-  case F_ANGRES:
-  case F_ANGRESZ:
-    fprintf(fp,"phiA=%15.8e, cpA=%15.8e, phiB=%15.8e, cpB=%15.8e, mult=%d\n",
-           iparams->pdihs.phiA,iparams->pdihs.cpA,
-           iparams->pdihs.phiB,iparams->pdihs.cpB,
-           iparams->pdihs.mult);
-    break;
-  case F_DISRES:
-    fprintf(fp,"label=%4d, type=%1d, low=%15.8e, up1=%15.8e, up2=%15.8e, fac=%15.8e)\n",
-           iparams->disres.label,iparams->disres.type,
-           iparams->disres.low,iparams->disres.up1,
-           iparams->disres.up2,iparams->disres.kfac);
-    break;
-  case F_ORIRES:
-    fprintf(fp,"ex=%4d, label=%d, power=%4d, c=%15.8e, obs=%15.8e, kfac=%15.8e)\n",
-           iparams->orires.ex,iparams->orires.label,iparams->orires.power,
-           iparams->orires.c,iparams->orires.obs,iparams->orires.kfac);
-    break;
-  case F_DIHRES:
-    fprintf(fp,"label=%d, power=%4d phi=%15.8e, dphi=%15.8e, kfac=%15.8e)\n",
-           iparams->dihres.label,iparams->dihres.power,
-           iparams->dihres.phi,iparams->dihres.dphi,iparams->dihres.kfac);
-    break;
-  case F_POSRES:
-    fprintf(fp,"pos0A=(%15.8e,%15.8e,%15.8e), fcA=(%15.8e,%15.8e,%15.8e), pos0B=(%15.8e,%15.8e,%15.8e), fcB=(%15.8e,%15.8e,%15.8e)\n",
-           iparams->posres.pos0A[XX],iparams->posres.pos0A[YY],
-           iparams->posres.pos0A[ZZ],iparams->posres.fcA[XX],
-           iparams->posres.fcA[YY],iparams->posres.fcA[ZZ],
-           iparams->posres.pos0B[XX],iparams->posres.pos0B[YY],
-           iparams->posres.pos0B[ZZ],iparams->posres.fcB[XX],
-           iparams->posres.fcB[YY],iparams->posres.fcB[ZZ]);
-    break;
-  case F_RBDIHS:
-    for (i=0; i<NR_RBDIHS; i++) 
-      fprintf(fp,"%srbcA[%d]=%15.8e",i==0?"":", ",i,iparams->rbdihs.rbcA[i]);
-    fprintf(fp,"\n");
-    for (i=0; i<NR_RBDIHS; i++) 
-      fprintf(fp,"%srbcB[%d]=%15.8e",i==0?"":", ",i,iparams->rbdihs.rbcB[i]);
-    fprintf(fp,"\n");
-    break;
-  case F_FOURDIHS:
-    /* Use the OPLS -> Ryckaert-Bellemans formula backwards to get the
-     * OPLS potential constants back.
-     */
-    rbcA = iparams->rbdihs.rbcA;
-    rbcB = iparams->rbdihs.rbcB;
-
-    VA[3] = -0.25*rbcA[4];
-    VA[2] = -0.5*rbcA[3];
-    VA[1] = 4.0*VA[3]-rbcA[2];
-    VA[0] = 3.0*VA[2]-2.0*rbcA[1];
-
-    VB[3] = -0.25*rbcB[4];
-    VB[2] = -0.5*rbcB[3];
-    VB[1] = 4.0*VB[3]-rbcB[2];
-    VB[0] = 3.0*VB[2]-2.0*rbcB[1];
-
-    for (i=0; i<NR_FOURDIHS; i++) 
-      fprintf(fp,"%sFourA[%d]=%15.8e",i==0?"":", ",i,VA[i]);
-    fprintf(fp,"\n");
-    for (i=0; i<NR_FOURDIHS; i++) 
-      fprintf(fp,"%sFourB[%d]=%15.8e",i==0?"":", ",i,VB[i]);
-    fprintf(fp,"\n");
-    break;
-   
-  case F_CONSTR:
-  case F_CONSTRNC:
-    fprintf(fp,"dA=%15.8e, dB=%15.8e\n",iparams->constr.dA,iparams->constr.dB);
-    break;
-  case F_SETTLE:
-    fprintf(fp,"doh=%15.8e, dhh=%15.8e\n",iparams->settle.doh,
-           iparams->settle.dhh);
-    break;
-  case F_VSITE2:
-    fprintf(fp,"a=%15.8e\n",iparams->vsite.a);
-    break;
-  case F_VSITE3:
-  case F_VSITE3FD:
-  case F_VSITE3FAD:
-    fprintf(fp,"a=%15.8e, b=%15.8e\n",iparams->vsite.a,iparams->vsite.b);
-    break;
-  case F_VSITE3OUT:
-  case F_VSITE4FD:
-  case F_VSITE4FDN:
-    fprintf(fp,"a=%15.8e, b=%15.8e, c=%15.8e\n",
-           iparams->vsite.a,iparams->vsite.b,iparams->vsite.c);
-    break;
-  case F_VSITEN:
-    fprintf(fp,"n=%2d, a=%15.8e\n",iparams->vsiten.n,iparams->vsiten.a);
-    break;
-  case F_GB12:
-  case F_GB13:
-  case F_GB14:
-    fprintf(fp, "sar=%15.8e, st=%15.8e, pi=%15.8e, gbr=%15.8e, bmlt=%15.8e\n",iparams->gb.sar,iparams->gb.st,iparams->gb.pi,iparams->gb.gbr,iparams->gb.bmlt);
-    break;               
-  case F_CMAP:
-    fprintf(fp, "cmapA=%1d, cmapB=%1d\n",iparams->cmap.cmapA, iparams->cmap.cmapB);
-    break;               
-  default:
-    gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
-             ftype,interaction_function[ftype].name,__FILE__,__LINE__);
-  }
-}
-
-void pr_ilist(FILE *fp,int indent,const char *title,
-              t_functype *functype,t_ilist *ilist, gmx_bool bShowNumbers)
-{
-    int i,j,k,type,ftype;
-    t_iatom *iatoms;
-    
-    if (available(fp,ilist,indent,title) && ilist->nr > 0)
-    {  
-        indent=pr_title(fp,indent,title);
-        (void) pr_indent(fp,indent);
-        fprintf(fp,"nr: %d\n",ilist->nr);
-        if (ilist->nr > 0) {
-            (void) pr_indent(fp,indent);
-            fprintf(fp,"iatoms:\n");
-            iatoms=ilist->iatoms;
-            for (i=j=0; i<ilist->nr;) {
-#ifndef DEBUG
-                (void) pr_indent(fp,indent+INDENT);
-                type=*(iatoms++);
-                ftype=functype[type];
-                (void) fprintf(fp,"%d type=%d (%s)",
-                               bShowNumbers?j:-1,bShowNumbers?type:-1,
-                               interaction_function[ftype].name);
-                j++;
-                for (k=0; k<interaction_function[ftype].nratoms; k++)
-                    (void) fprintf(fp," %u",*(iatoms++));
-                (void) fprintf(fp,"\n");
-                i+=1+interaction_function[ftype].nratoms;
-#else
-                fprintf(fp,"%5d%5d\n",i,iatoms[i]);
-                i++;
-#endif
-            }
-        }
-    }
-}
-
-static void pr_cmap(FILE *fp, int indent, const char *title,
-                    gmx_cmap_t *cmap_grid, gmx_bool bShowNumbers)
-{
-    int i,j,nelem;
-    real dx,idx;
-       
-    dx    = 360.0 / cmap_grid->grid_spacing;
-    nelem = cmap_grid->grid_spacing*cmap_grid->grid_spacing;
-       
-    if(available(fp,cmap_grid,indent,title))
-    {
-        fprintf(fp,"%s\n",title);
-               
-        for(i=0;i<cmap_grid->ngrid;i++)
-        {
-            idx = -180.0;
-            fprintf(fp,"%8s %8s %8s %8s\n","V","dVdx","dVdy","d2dV");
-                       
-            fprintf(fp,"grid[%3d]={\n",bShowNumbers?i:-1);
-                       
-            for(j=0;j<nelem;j++)
-            {
-                if( (j%cmap_grid->grid_spacing)==0)
-                {
-                    fprintf(fp,"%8.1f\n",idx);
-                    idx+=dx;
-                }
-                               
-                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4]);
-                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4+1]);
-                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4+2]);
-                fprintf(fp,"%8.3f\n",cmap_grid->cmapdata[i].cmap[j*4+3]);
-            }
-            fprintf(fp,"\n");
-        }
-    }
-       
-}
-
-void pr_ffparams(FILE *fp,int indent,const char *title,
-                 gmx_ffparams_t *ffparams,
-                 gmx_bool bShowNumbers)
-{
-  int i,j;
-  
-  indent=pr_title(fp,indent,title);
-  (void) pr_indent(fp,indent);
-  (void) fprintf(fp,"atnr=%d\n",ffparams->atnr);
-  (void) pr_indent(fp,indent);
-  (void) fprintf(fp,"ntypes=%d\n",ffparams->ntypes);
-  for (i=0; i<ffparams->ntypes; i++) {
-      (void) pr_indent(fp,indent+INDENT);
-      (void) fprintf(fp,"functype[%d]=%s, ",
-                     bShowNumbers?i:-1,
-                     interaction_function[ffparams->functype[i]].name);
-      pr_iparams(fp,ffparams->functype[i],&ffparams->iparams[i]);
-  }
-  (void) pr_double(fp,indent,"reppow",ffparams->reppow);
-  (void) pr_real(fp,indent,"fudgeQQ",ffparams->fudgeQQ);
-  pr_cmap(fp,indent,"cmap",&ffparams->cmap_grid,bShowNumbers);
-}
-
-void pr_idef(FILE *fp,int indent,const char *title,t_idef *idef, gmx_bool bShowNumbers)
-{
-  int i,j;
-  
-  if (available(fp,idef,indent,title)) {  
-    indent=pr_title(fp,indent,title);
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"atnr=%d\n",idef->atnr);
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"ntypes=%d\n",idef->ntypes);
-    for (i=0; i<idef->ntypes; i++) {
-      (void) pr_indent(fp,indent+INDENT);
-      (void) fprintf(fp,"functype[%d]=%s, ",
-                    bShowNumbers?i:-1,
-                    interaction_function[idef->functype[i]].name);
-      pr_iparams(fp,idef->functype[i],&idef->iparams[i]);
-    }
-    (void) pr_real(fp,indent,"fudgeQQ",idef->fudgeQQ);
-
-    for(j=0; (j<F_NRE); j++)
-      pr_ilist(fp,indent,interaction_function[j].longname,
-               idef->functype,&idef->il[j],bShowNumbers);
-  }
-}
-
-static int pr_block_title(FILE *fp,int indent,const char *title,t_block *block)
-{
-  int i;
-
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_title(fp,indent,title);
-      (void) pr_indent(fp,indent);
-      (void) fprintf(fp,"nr=%d\n",block->nr);
-    }
-  return indent;
-}
-
-static int pr_blocka_title(FILE *fp,int indent,const char *title,t_blocka *block)
-{
-  int i;
-
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_title(fp,indent,title);
-      (void) pr_indent(fp,indent);
-      (void) fprintf(fp,"nr=%d\n",block->nr);
-      (void) pr_indent(fp,indent);
-      (void) fprintf(fp,"nra=%d\n",block->nra);
-    }
-  return indent;
-}
-
-static void low_pr_block(FILE *fp,int indent,const char *title,t_block *block, gmx_bool bShowNumbers)
-{
-  int i;
-  
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_block_title(fp,indent,title,block);
-      for (i=0; i<=block->nr; i++)
-        {
-          (void) pr_indent(fp,indent+INDENT);
-          (void) fprintf(fp,"%s->index[%d]=%u\n",
-                        title,bShowNumbers?i:-1,block->index[i]);
-        }
-    }
-}
-
-static void low_pr_blocka(FILE *fp,int indent,const char *title,t_blocka *block, gmx_bool bShowNumbers)
-{
-  int i;
-  
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_blocka_title(fp,indent,title,block);
-      for (i=0; i<=block->nr; i++)
-        {
-          (void) pr_indent(fp,indent+INDENT);
-          (void) fprintf(fp,"%s->index[%d]=%u\n",
-                        title,bShowNumbers?i:-1,block->index[i]);
-        }
-      for (i=0; i<block->nra; i++)
-        {
-          (void) pr_indent(fp,indent+INDENT);
-          (void) fprintf(fp,"%s->a[%d]=%u\n",
-                        title,bShowNumbers?i:-1,block->a[i]);
-        }
-    }
-}
-
-void pr_block(FILE *fp,int indent,const char *title,t_block *block,gmx_bool bShowNumbers)
-{
-  int i,j,ok,size,start,end;
-  
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_block_title(fp,indent,title,block);
-      start=0;
-      end=start;
-      if ((ok=(block->index[start]==0))==0)
-        (void) fprintf(fp,"block->index[%d] should be 0\n",start);
-      else
-        for (i=0; i<block->nr; i++)
-          {
-            end=block->index[i+1];
-            size=pr_indent(fp,indent);
-            if (end<=start)
-              size+=fprintf(fp,"%s[%d]={}\n",title,i);
-            else
-              size+=fprintf(fp,"%s[%d]={%d..%d}\n",
-                           title,bShowNumbers?i:-1,
-                           bShowNumbers?start:-1,bShowNumbers?end-1:-1);
-            start=end;
-          }
-    }
-}
-
-void pr_blocka(FILE *fp,int indent,const char *title,t_blocka *block,gmx_bool bShowNumbers)
-{
-  int i,j,ok,size,start,end;
-  
-  if (available(fp,block,indent,title))
-    {
-      indent=pr_blocka_title(fp,indent,title,block);
-      start=0;
-      end=start;
-      if ((ok=(block->index[start]==0))==0)
-        (void) fprintf(fp,"block->index[%d] should be 0\n",start);
-      else
-        for (i=0; i<block->nr; i++)
-          {
-            end=block->index[i+1];
-            size=pr_indent(fp,indent);
-            if (end<=start)
-              size+=fprintf(fp,"%s[%d]={",title,i);
-            else
-              size+=fprintf(fp,"%s[%d][%d..%d]={",
-                           title,bShowNumbers?i:-1,
-                           bShowNumbers?start:-1,bShowNumbers?end-1:-1);
-            for (j=start; j<end; j++)
-              {
-                if (j>start) size+=fprintf(fp,", ");
-                if ((size)>(USE_WIDTH))
-                  {
-                    (void) fprintf(fp,"\n");
-                    size=pr_indent(fp,indent+INDENT);
-                  }
-                size+=fprintf(fp,"%u",block->a[j]);
-              }
-            (void) fprintf(fp,"}\n");
-            start=end;
-          }
-      if ((end!=block->nra)||(!ok)) 
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"tables inconsistent, dumping complete tables:\n");
-          low_pr_blocka(fp,indent,title,block,bShowNumbers);
-        }
-    }
-}
-
-static void pr_strings(FILE *fp,int indent,const char *title,char ***nm,int n, gmx_bool bShowNumbers)
-{
-  int i;
-
-  if (available(fp,nm,indent,title))
-    {  
-      indent=pr_title_n(fp,indent,title,n);
-      for (i=0; i<n; i++)
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"%s[%d]={name=\"%s\"}\n",
-                        title,bShowNumbers?i:-1,*(nm[i]));
-        }
-    }
-}
-
-static void pr_strings2(FILE *fp,int indent,const char *title,
-                       char ***nm,char ***nmB,int n, gmx_bool bShowNumbers)
-{
-  int i;
-
-  if (available(fp,nm,indent,title))
-    {  
-      indent=pr_title_n(fp,indent,title,n);
-      for (i=0; i<n; i++)
-        {
-          (void) pr_indent(fp,indent);
-          (void) fprintf(fp,"%s[%d]={name=\"%s\",nameB=\"%s\"}\n",
-                        title,bShowNumbers?i:-1,*(nm[i]),*(nmB[i]));
-        }
-    }
-}
-
-static void pr_resinfo(FILE *fp,int indent,const char *title,t_resinfo *resinfo,int n, gmx_bool bShowNumbers)
-{
-    int i;
-    
-    if (available(fp,resinfo,indent,title))
-    {  
-        indent=pr_title_n(fp,indent,title,n);
-        for (i=0; i<n; i++)
-        {
-            (void) pr_indent(fp,indent);
-            (void) fprintf(fp,"%s[%d]={name=\"%s\", nr=%d, ic='%c'}\n",
-                           title,bShowNumbers?i:-1,
-                           *(resinfo[i].name),resinfo[i].nr,
-                           (resinfo[i].ic == '\0') ? ' ' : resinfo[i].ic);
-        }
-    }
-}
-
-static void pr_atom(FILE *fp,int indent,const char *title,t_atom *atom,int n)
-{
-  int i,j;
-  
-  if (available(fp,atom,indent,title)) {  
-    indent=pr_title_n(fp,indent,title,n);
-    for (i=0; i<n; i++) {
-      (void) pr_indent(fp,indent);
-      fprintf(fp,"%s[%6d]={type=%3d, typeB=%3d, ptype=%8s, m=%12.5e, "
-              "q=%12.5e, mB=%12.5e, qB=%12.5e, resind=%5d, atomnumber=%3d}\n",
-              title,i,atom[i].type,atom[i].typeB,ptype_str[atom[i].ptype],
-              atom[i].m,atom[i].q,atom[i].mB,atom[i].qB,
-              atom[i].resind,atom[i].atomnumber);
-    }
-  }
-}
-
-static void pr_grps(FILE *fp,int indent,const char *title,t_grps grps[],
-                   char **grpname[], gmx_bool bShowNumbers)
-{
-    int i,j;
-
-    for(i=0; (i<egcNR); i++)
-    {
-        fprintf(fp,"%s[%-12s] nr=%d, name=[",title,gtypes[i],grps[i].nr);
-        for(j=0; (j<grps[i].nr); j++)
-        {
-            fprintf(fp," %s",*(grpname[grps[i].nm_ind[j]]));
-        }
-        fprintf(fp,"]\n");
-    }
-}
-
-static void pr_groups(FILE *fp,int indent,const char *title,
-                      gmx_groups_t *groups,
-                      gmx_bool bShowNumbers)
-{
-    int grpnr[egcNR];
-    int nat_max,i,g;
-
-    pr_grps(fp,indent,"grp",groups->grps,groups->grpname,bShowNumbers);
-    pr_strings(fp,indent,"grpname",groups->grpname,groups->ngrpname,bShowNumbers);
-
-    (void) pr_indent(fp,indent);
-    fprintf(fp,"groups          ");
-    for(g=0; g<egcNR; g++)
-    {
-       printf(" %5.5s",gtypes[g]);
-    }
-    printf("\n");
-
-    (void) pr_indent(fp,indent);
-    fprintf(fp,"allocated       ");
-    nat_max = 0;
-    for(g=0; g<egcNR; g++)
-    {
-        printf(" %5d",groups->ngrpnr[g]);
-        nat_max = max(nat_max,groups->ngrpnr[g]);
-    }
-    printf("\n");
-
-    if (nat_max == 0)
-    {
-        (void) pr_indent(fp,indent);
-        fprintf(fp,"groupnr[%5s] =","*");
-        for(g=0; g<egcNR; g++)
-        {
-            fprintf(fp,"  %3d ",0);
-        }
-        fprintf(fp,"\n");
-    }
-    else
-    {
-        for(i=0; i<nat_max; i++)
-        {
-            (void) pr_indent(fp,indent);
-            fprintf(fp,"groupnr[%5d] =",i);
-            for(g=0; g<egcNR; g++)
-            {
-                fprintf(fp,"  %3d ",
-                        groups->grpnr[g] ? groups->grpnr[g][i] : 0);
-            }
-            fprintf(fp,"\n");
-        }
-    }
-}
-
-void pr_atoms(FILE *fp,int indent,const char *title,t_atoms *atoms, 
-             gmx_bool bShownumbers)
-{
-  if (available(fp,atoms,indent,title))
-    {
-      indent=pr_title(fp,indent,title);
-      pr_atom(fp,indent,"atom",atoms->atom,atoms->nr);
-      pr_strings(fp,indent,"atom",atoms->atomname,atoms->nr,bShownumbers);
-      pr_strings2(fp,indent,"type",atoms->atomtype,atoms->atomtypeB,atoms->nr,bShownumbers);
-      pr_resinfo(fp,indent,"residue",atoms->resinfo,atoms->nres,bShownumbers);
-    }
-}
-
-
-void pr_atomtypes(FILE *fp,int indent,const char *title,t_atomtypes *atomtypes, 
-                 gmx_bool bShowNumbers)
-{
-  int i;
-  if (available(fp,atomtypes,indent,title)) 
-  {
-    indent=pr_title(fp,indent,title);
-    for(i=0;i<atomtypes->nr;i++) {
-      pr_indent(fp,indent);
-               fprintf(fp,
-                               "atomtype[%3d]={radius=%12.5e, volume=%12.5e, gb_radius=%12.5e, surftens=%12.5e, atomnumber=%4d, S_hct=%12.5e)}\n",
-                               bShowNumbers?i:-1,atomtypes->radius[i],atomtypes->vol[i],
-                               atomtypes->gb_radius[i],
-                               atomtypes->surftens[i],atomtypes->atomnumber[i],atomtypes->S_hct[i]);
-    }
-  }
-}
-
-static void pr_moltype(FILE *fp,int indent,const char *title,
-                       gmx_moltype_t *molt,int n,
-                       gmx_ffparams_t *ffparams,
-                       gmx_bool bShowNumbers)
-{
-    int j;
-
-    indent = pr_title_n(fp,indent,title,n);
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"name=\"%s\"\n",*(molt->name));
-    pr_atoms(fp,indent,"atoms",&(molt->atoms),bShowNumbers);
-    pr_block(fp,indent,"cgs",&molt->cgs, bShowNumbers);
-    pr_blocka(fp,indent,"excls",&molt->excls, bShowNumbers);
-    for(j=0; (j<F_NRE); j++) {
-        pr_ilist(fp,indent,interaction_function[j].longname,
-                 ffparams->functype,&molt->ilist[j],bShowNumbers);
-    }
-}
-
-static void pr_molblock(FILE *fp,int indent,const char *title,
-                        gmx_molblock_t *molb,int n,
-                        gmx_moltype_t *molt,
-                        gmx_bool bShowNumbers)
-{
-    indent = pr_title_n(fp,indent,title,n);
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"%-20s = %d \"%s\"\n",
-                   "moltype",molb->type,*(molt[molb->type].name));
-    pr_int(fp,indent,"#molecules",molb->nmol);
-    pr_int(fp,indent,"#atoms_mol",molb->natoms_mol);
-    pr_int(fp,indent,"#posres_xA",molb->nposres_xA);
-    if (molb->nposres_xA > 0) {
-        pr_rvecs(fp,indent,"posres_xA",molb->posres_xA,molb->nposres_xA);
-    }
-    pr_int(fp,indent,"#posres_xB",molb->nposres_xB);
-    if (molb->nposres_xB > 0) {
-        pr_rvecs(fp,indent,"posres_xB",molb->posres_xB,molb->nposres_xB);
-    }
-}
-
-void pr_mtop(FILE *fp,int indent,const char *title,gmx_mtop_t *mtop,
-             gmx_bool bShowNumbers)
-{
-    int mt,mb;
-
-    if (available(fp,mtop,indent,title)) {
-        indent=pr_title(fp,indent,title);
-        (void) pr_indent(fp,indent);
-        (void) fprintf(fp,"name=\"%s\"\n",*(mtop->name));
-        pr_int(fp,indent,"#atoms",mtop->natoms);
-        for(mb=0; mb<mtop->nmolblock; mb++) {
-            pr_molblock(fp,indent,"molblock",&mtop->molblock[mb],mb,
-                        mtop->moltype,bShowNumbers);
-        }
-        pr_ffparams(fp,indent,"ffparams",&(mtop->ffparams),bShowNumbers);
-        pr_atomtypes(fp,indent,"atomtypes",&(mtop->atomtypes),bShowNumbers);
-        for(mt=0; mt<mtop->nmoltype; mt++) {
-            pr_moltype(fp,indent,"moltype",&mtop->moltype[mt],mt,
-                       &mtop->ffparams,bShowNumbers);
-        }
-        pr_groups(fp,indent,"groups",&mtop->groups,bShowNumbers);
-    }
-}
-
-void pr_top(FILE *fp,int indent,const char *title,t_topology *top, gmx_bool bShowNumbers)
-{
-  if (available(fp,top,indent,title)) {
-    indent=pr_title(fp,indent,title);
-    (void) pr_indent(fp,indent);
-    (void) fprintf(fp,"name=\"%s\"\n",*(top->name));
-    pr_atoms(fp,indent,"atoms",&(top->atoms),bShowNumbers);
-    pr_atomtypes(fp,indent,"atomtypes",&(top->atomtypes),bShowNumbers);
-    pr_block(fp,indent,"cgs",&top->cgs, bShowNumbers);
-    pr_block(fp,indent,"mols",&top->mols, bShowNumbers);
-    pr_blocka(fp,indent,"excls",&top->excls, bShowNumbers);
-    pr_idef(fp,indent,"idef",&top->idef,bShowNumbers);
-  }
-}
-
-void pr_header(FILE *fp,int indent,const char *title,t_tpxheader *sh)
-{
-  char buf[22];
-    
-  if (available(fp,sh,indent,title))
-    {
-      indent=pr_title(fp,indent,title);
-      pr_indent(fp,indent);
-      fprintf(fp,"bIr    = %spresent\n",sh->bIr?"":"not ");
-      pr_indent(fp,indent);
-      fprintf(fp,"bBox   = %spresent\n",sh->bBox?"":"not ");
-      pr_indent(fp,indent);
-      fprintf(fp,"bTop   = %spresent\n",sh->bTop?"":"not ");
-      pr_indent(fp,indent);
-      fprintf(fp,"bX     = %spresent\n",sh->bX?"":"not ");
-      pr_indent(fp,indent);
-      fprintf(fp,"bV     = %spresent\n",sh->bV?"":"not ");
-      pr_indent(fp,indent);
-      fprintf(fp,"bF     = %spresent\n",sh->bF?"":"not ");
-      
-      pr_indent(fp,indent);
-      fprintf(fp,"natoms = %d\n",sh->natoms);
-      pr_indent(fp,indent);
-      fprintf(fp,"lambda = %e\n",sh->lambda);
-    }
-}
-
-void pr_commrec(FILE *fp,int indent,t_commrec *cr)
-{
-  pr_indent(fp,indent);
-  fprintf(fp,"commrec:\n");
-  indent+=2;
-  pr_indent(fp,indent);
-  fprintf(fp,"nodeid    = %d\n",cr->nodeid);
-  pr_indent(fp,indent);
-  fprintf(fp,"nnodes    = %d\n",cr->nnodes);
-  pr_indent(fp,indent);
-  fprintf(fp,"npmenodes = %d\n",cr->npmenodes);
-  /*
-  pr_indent(fp,indent);
-  fprintf(fp,"threadid  = %d\n",cr->threadid);
-  pr_indent(fp,indent);
-  fprintf(fp,"nthreads  = %d\n",cr->nthreads);
-  */
-}
diff --git a/src/gmxlib/version.c.cmakein b/src/gmxlib/version.c.cmakein
deleted file mode 100644 (file)
index 8aa4895..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "version.h"
-const char _gmx_ver_string[] = "VERSION @GMX_PROJECT_VERSION_STR@";
-const char _gmx_full_git_hash[] = "@GMX_GIT_HEAD_HASH@";
-const char _gmx_central_base_hash[] = "@GMX_GIT_REMOTE_HASH@";
diff --git a/src/gromacs/CMakeLists.txt b/src/gromacs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b8310c0
--- /dev/null
@@ -0,0 +1,86 @@
+set(LIBGROMACS_SOURCES)
+
+add_subdirectory(legacyheaders)
+add_subdirectory(gmxlib)
+add_subdirectory(mdlib)
+add_subdirectory(gmxpreprocess)
+add_subdirectory(analysisdata)
+add_subdirectory(fatalerror)
+add_subdirectory(options)
+add_subdirectory(selection)
+add_subdirectory(trajectoryanalysis)
+add_subdirectory(utility)
+
+file(GLOB LIBGROMACS_HEADERS *.h)
+install(FILES ${LIBGROMACS_HEADERS} DESTINATION ${INCL_INSTALL_DIR}/gromacs
+        COMPONENT development)
+
+# only fiddle with assembly kernels if we're not doing OpenMM build
+if(NOT GMX_OPENMM) 
+if(GMX_ASM_USEASM-NASM)
+  enable_language(ASM-NASM)
+  # if NASM is used, we need a special build command for windows...
+  FOREACH(SRC ${GMX_SSEKERNEL_ASM_SRC})
+    GET_FILENAME_COMPONENT(FILE_BASE ${SRC} NAME_WE)
+    SET(OBJ ${CMAKE_CURRENT_BINARY_DIR}/${FILE_BASE}${CMAKE_C_OUTPUT_EXTENSION})
+
+    ADD_CUSTOM_COMMAND(OUTPUT ${OBJ}
+                       MAIN_DEPENDENCY ${SRC}
+                       COMMAND ${CMAKE_ASM-NASM_COMPILER} -f ${CMAKE_ASM-NASM_OBJECT_FORMAT} -o ${OBJ} ${SRC})
+
+    SET(ALL_ASM_OBJS ${ALL_ASM_OBJS} ${OBJ})
+  ENDFOREACH(SRC ${GMX_SSEKERNEL_ASM_SRC})
+  set(GMX_SSEKERNEL_ASM_SRC ${ALL_ASM_OBJS})
+else(GMX_ASM_USEASM-NASM)
+  enable_language(ASM-ATT)
+  SET(CMAKE_ASM-ATT_COMPILER ${CMAKE_C_COMPILER})
+  if(GMX_IA32_ASM)
+    set_source_files_properties(${GMX_SSEKERNEL_ASM_SRC} PROPERTIES COMPILE_FLAGS "-c -m32")
+  else()
+    set_source_files_properties(${GMX_SSEKERNEL_ASM_SRC} PROPERTIES COMPILE_FLAGS "-c -m64")
+  endif()
+endif(GMX_ASM_USEASM-NASM)
+endif(NOT GMX_OPENMM)
+
+list(APPEND LIBGROMACS_SOURCES ${GMXLIB_SOURCES} ${GMX_SSEKERNEL_ASM_SRC} ${MDLIB_SOURCES})
+
+# add target that generates version.c every time a make is run
+# only do this if we generate the version
+if (USE_VERSION_H)
+    add_custom_target(gmx_version ALL
+            COMMAND ${CMAKE_COMMAND} 
+                -D GIT_EXECUTABLE="${GIT_EXECUTABLE}"
+                -D GIT_VERSION="${GIT_VERSION}"
+                -D PROJECT_VERSION="${PROJECT_VERSION}"
+                -D PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}"
+                -D VERSION_C_CMAKEIN="${CMAKE_CURRENT_SOURCE_DIR}/version.c.cmakein"
+                -D VERSION_C_OUT="${CMAKE_CURRENT_BINARY_DIR}/version.c"
+                -P ${CMAKE_SOURCE_DIR}/cmake/gmxGenerateVersionInfo.cmake 
+            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/gmxlib 
+            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.c.cmakein
+            COMMENT "Generating version information")
+    list(APPEND LIBGROMACS_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/version.c) # auto-generated
+    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/version.c 
+                                PROPERTIES GENERATED true)
+endif (USE_VERSION_H)
+
+add_library(libgromacs ${LIBGROMACS_SOURCES})
+if (USE_VERSION_H)
+    add_dependencies(libgromacs gmx_version)
+endif (USE_VERSION_H)
+target_link_libraries(libgromacs
+                      ${GMX_EXTRA_LIBRARIES} ${FFT_LIBRARIES} ${XML_LIBRARIES}
+                      ${THREAD_LIB})
+set_target_properties(libgromacs PROPERTIES
+                      OUTPUT_NAME "gromacs${GMX_LIBS_SUFFIX}"
+                      SOVERSION ${SOVERSION}
+                      INSTALL_NAME_DIR "${LIB_INSTALL_DIR}")
+
+install(TARGETS libgromacs DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libgromacs.pc.cmakein
+               ${CMAKE_CURRENT_BINARY_DIR}/libgromacs.pc @ONLY)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgromacs.pc
+        DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
+        RENAME "libgromacs${GMX_LIBS_SUFFIX}.pc"
+        COMPONENT development)
diff --git a/src/gromacs/analysisdata.h b/src/gromacs/analysisdata.h
new file mode 100644 (file)
index 0000000..0af48c6
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \defgroup module_analysisdata Parallelizable Handling of Output Data
+ * \ingroup group_analysismodules
+ * \brief
+ * Provides functionality for handling and processing output data from
+ * analysis.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \file
+ * \brief
+ * Public API convenience header for analysis data handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_H
+#define GMX_ANALYSISDATA_H
+
+#include "analysisdata/analysisdata.h"
+#include "analysisdata/arraydata.h"
+#include "analysisdata/modules/average.h"
+#include "analysisdata/modules/displacement.h"
+#include "analysisdata/modules/histogram.h"
+#include "analysisdata/modules/plot.h"
+
+#endif
diff --git a/src/gromacs/analysisdata/CMakeLists.txt b/src/gromacs/analysisdata/CMakeLists.txt
new file mode 100644 (file)
index 0000000..69419af
--- /dev/null
@@ -0,0 +1,17 @@
+file(GLOB ANALYSISDATA_SOURCES *.cpp modules/*.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${ANALYSISDATA_SOURCES} PARENT_SCOPE)
+
+set(ANALYSISDATA_PUBLIC_HEADERS
+    abstractdata.h
+    analysisdata.h
+    arraydata.h
+    datamodule.h)
+install(FILES ${ANALYSISDATA_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/analysisdata
+        COMPONENT development)
+
+add_subdirectory(modules)
+
+if (BUILD_TESTING)
+    add_subdirectory(tests)
+endif (BUILD_TESTING)
diff --git a/src/gromacs/analysisdata/abstractdata-impl.h b/src/gromacs/analysisdata/abstractdata-impl.h
new file mode 100644 (file)
index 0000000..eb76827
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares internal implementation classes for gmx::AbstractAnalysisData and
+ * gmx::AbstractAnalysisDataStored.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_ABSTRACTDATA_IMPL_H
+#define GMX_ANALYSISDATA_ABSTRACTDATA_IMPL_H
+
+#include <vector>
+
+#include "types/simple.h"
+#include "abstractdata.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Private implementation class for AbstractAnalysisData.
+ *
+ * \ingroup module_analysisdata
+ */
+class AbstractAnalysisData::Impl
+{
+    public:
+        //! Shorthand for list of modules added to the data.
+        typedef std::vector<AnalysisDataModuleInterface *> ModuleList;
+
+        Impl();
+        ~Impl();
+
+        /*! \brief
+         * Present data already added to the data object to a module.
+         *
+         * \param[in] data   Data object to read data from.
+         * \param[in] module Module to present the data to.
+         * \retval ::eeInvalidValue if \p module is not compatible with the
+         *      data object.
+         * \retval ::eedataDataNotAvailable if all data is not  available
+         *      through getData().
+         *
+         * Uses getData() in \p data to access all data in the object, and
+         * calls the notification functions in \p module as if the module had
+         * been registered to the data object when the data was added.
+         */
+        void presentData(AbstractAnalysisData *data,
+                         AnalysisDataModuleInterface *module);
+
+        //! List of modules added to the data.
+        ModuleList              _modules;
+        //! Whether notifyDataStart() has been called.
+        bool                    _bDataStart;
+        //! Whether new data is being added.
+        bool                    _bInData;
+        //! Whether data for a frame is being added.
+        bool                    _bInFrame;
+        //! true if all modules support missing data.
+        bool                    _bAllowMissing;
+        //! x value for the current frame.
+        real                    _currx;
+        //! dx value for the current frame.
+        real                    _currdx;
+};
+
+/*! \internal \brief
+ * Internal implementation class for storing a single data frame.
+ *
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataFrame
+{
+    public:
+        AnalysisDataFrame();
+        ~AnalysisDataFrame();
+
+        //! Allocate memory for a given number of columns.
+        void allocate(int ncol);
+
+        //! Zero-based global index of the frame.
+        int                     _index;
+        //! x value of the frame.
+        real                    _x;
+        //! Error of x for the frame.
+        real                    _dx;
+        //! Array of column values for the frame.
+        real                   *_y;
+        //! Array of column error values for the frame.
+        real                   *_dy;
+        //! Array of flags that tell whether a value is present.
+        bool                   *_present;
+};
+
+/*! \internal \brief
+ * Private implementation class for AbstractAnalysisDataStored.
+ *
+ * \ingroup module_analysisdata
+ */
+class AbstractAnalysisDataStored::Impl
+{
+    public:
+        //! Shorthand for a list of data frames that are currently stored.
+        typedef std::vector<AnalysisDataFrame *> FrameList;
+
+        Impl();
+        ~Impl();
+
+        /*! \brief
+         * Calculates the index of a frame in the storage vector.
+         *
+         * \param[in] index  Zero-based index for the frame to query.
+         *      Negative value counts backwards from the current frame.
+         * \returns Index in \a _store corresponding to \p index,
+         *      or -1 if not available.
+         */
+        int getStoreIndex(int index) const;
+
+        /*! \brief
+         * Total number of complete frames in the data.
+         */
+        int                     _nframes;
+        /*! \brief
+         * Number of elements in \a _store.
+         *
+         * Also holds the number of frames that should be stored, even before
+         * \a _store has been allocated.
+         */
+        int                     _nalloc;
+        //! Whether all frames should be stored.
+        bool                    _bStoreAll;
+        //! List of data frames that are currently stored.
+        FrameList               _store;
+        /*! \brief
+         * Index in \a _store where the next frame will be stored.
+         *
+         * This counter is incremented after notifyPointsAdd() has been called
+         * for the frame.
+         */
+        int                     _nextind;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/abstractdata.cpp b/src/gromacs/analysisdata/abstractdata.cpp
new file mode 100644 (file)
index 0000000..3b00ede
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::AbstractAnalysisData and gmx::AbstractAnalysisDataStored.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/abstractdata.h"
+
+#include <memory>
+
+// Legacy header.
+#include "smalloc.h"
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+#include "abstractdata-impl.h"
+#include "dataproxy.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AbstractAnalysisData::Impl
+ */
+
+AbstractAnalysisData::Impl::Impl()
+    : _bDataStart(false), _bInData(false), _bInFrame(false),
+      _bAllowMissing(true)
+{
+}
+
+AbstractAnalysisData::Impl::~Impl()
+{
+    ModuleList::const_iterator i;
+    for (i = _modules.begin(); i != _modules.end(); ++i)
+    {
+        delete *i;
+    }
+}
+
+
+void
+AbstractAnalysisData::Impl::presentData(AbstractAnalysisData *data,
+                                        AnalysisDataModuleInterface *module)
+{
+    module->dataStarted(data);
+    bool bCheckMissing = _bAllowMissing
+        && !(module->flags() & AnalysisDataModuleInterface::efAllowMissing);
+    int ncol = data->columnCount();
+    for (int i = 0; i < data->frameCount(); ++i)
+    {
+        real        x, dx;
+        const real *y, *dy;
+        const bool *present;
+
+        if (!data->getDataWErr(i, &x, &dx, &y, &dy, &present))
+        {
+            GMX_THROW(APIError("Data not available when module added"));
+        }
+        if (bCheckMissing && present)
+        {
+            for (int j = 0; j < ncol; ++j)
+            {
+                if (!present[j])
+                {
+                    GMX_THROW(APIError("Missing data not supported by a module"));
+                }
+            }
+        }
+        module->frameStarted(x, dx);
+        module->pointsAdded(x, dx, 0, ncol, y, dy, present);
+        module->frameFinished();
+    }
+    if (!_bInData)
+    {
+        module->dataFinished();
+    }
+}
+
+
+/********************************************************************
+ * AbstractAnalysisData
+ */
+
+AbstractAnalysisData::AbstractAnalysisData()
+    : _impl(new Impl()), _ncol(0), _bMultiPoint(false)
+{
+}
+
+
+AbstractAnalysisData::~AbstractAnalysisData()
+{
+    delete _impl;
+}
+
+
+bool
+AbstractAnalysisData::getData(int index, real *x, const real **y,
+                              const bool **missing) const
+{
+    return getDataWErr(index, x, 0, y, 0, missing);
+}
+
+
+bool
+AbstractAnalysisData::getErrors(int index, real *dx, const real **dy) const
+{
+    return getDataWErr(index, 0, dx, 0, dy, 0);
+}
+
+
+void
+AbstractAnalysisData::addModule(AnalysisDataModuleInterface *module)
+{
+    std::auto_ptr<AnalysisDataModuleInterface> module_ptr(module);
+    if ((columnCount() > 1 && !(module->flags() & AnalysisDataModuleInterface::efAllowMulticolumn))
+        || (isMultipoint() && !(module->flags() & AnalysisDataModuleInterface::efAllowMultipoint))
+        || (!isMultipoint() && (module->flags() & AnalysisDataModuleInterface::efOnlyMultipoint)))
+    {
+        GMX_THROW(APIError("Data module not compatible with data object properties"));
+    }
+
+    if (_impl->_bDataStart)
+    {
+        GMX_RELEASE_ASSERT(!_impl->_bInFrame,
+                           "Cannot add data modules in mid-frame");
+        _impl->presentData(this, module);
+    }
+    if (!(module->flags() & AnalysisDataModuleInterface::efAllowMissing))
+    {
+        _impl->_bAllowMissing = false;
+    }
+    _impl->_modules.push_back(module);
+    module_ptr.release();
+}
+
+
+void
+AbstractAnalysisData::addColumnModule(int col, int span,
+                                      AnalysisDataModuleInterface *module)
+{
+    std::auto_ptr<AnalysisDataModuleInterface> module_ptr(module);
+    GMX_RELEASE_ASSERT(col >= 0 && span >= 1 && col + span <= _ncol,
+                       "Invalid columns specified for a column module");
+    if (_impl->_bDataStart)
+    {
+        GMX_THROW(NotImplementedError("Cannot add column modules after data"));
+    }
+
+    std::auto_ptr<AnalysisDataProxy> proxy(new AnalysisDataProxy(col, span, this));
+    proxy->addModule(module_ptr.release());
+    addModule(proxy.release());
+}
+
+
+void
+AbstractAnalysisData::applyModule(AnalysisDataModuleInterface *module)
+{
+    if ((columnCount() > 1 && !(module->flags() & AnalysisDataModuleInterface::efAllowMulticolumn))
+        || (isMultipoint() && !(module->flags() & AnalysisDataModuleInterface::efAllowMultipoint))
+        || (!isMultipoint() && (module->flags() & AnalysisDataModuleInterface::efOnlyMultipoint)))
+    {
+        GMX_THROW(APIError("Data module not compatible with data object properties"));
+    }
+    GMX_RELEASE_ASSERT(_impl->_bDataStart && !_impl->_bInData,
+                       "Data module can only be applied to ready data");
+
+    _impl->presentData(this, module);
+}
+
+
+void
+AbstractAnalysisData::setColumnCount(int ncol)
+{
+    GMX_RELEASE_ASSERT(ncol > 0, "Invalid data column count");
+    GMX_RELEASE_ASSERT(_ncol == 0 || _impl->_modules.empty(),
+                       "Data column count cannot be changed after modules are added");
+    GMX_RELEASE_ASSERT(!_impl->_bDataStart,
+                       "Data column count cannot be changed after data has been added");
+    _ncol = ncol;
+}
+
+
+void
+AbstractAnalysisData::setMultipoint(bool multipoint)
+{
+    GMX_RELEASE_ASSERT(_impl->_modules.empty(),
+                       "Data type cannot be changed after modules are added");
+    GMX_RELEASE_ASSERT(!_impl->_bDataStart,
+                       "Data type cannot be changed after data has been added");
+    _bMultiPoint = multipoint;
+}
+
+
+/*! \internal
+ * This method is not const because the dataStarted() methods of the attached
+ * modules can request storage of the data.
+ */
+void
+AbstractAnalysisData::notifyDataStart()
+{
+    GMX_RELEASE_ASSERT(!_impl->_bDataStart,
+                       "notifyDataStart() called more than once");
+    GMX_RELEASE_ASSERT(_ncol > 0, "Data column count is not set");
+    _impl->_bDataStart = _impl->_bInData = true;
+
+    Impl::ModuleList::const_iterator i;
+
+    for (i = _impl->_modules.begin(); i != _impl->_modules.end(); ++i)
+    {
+        if (_ncol > 1 && !((*i)->flags() & AnalysisDataModuleInterface::efAllowMulticolumn))
+        {
+            GMX_THROW(APIError("Data module not compatible with data object properties"));
+        }
+        (*i)->dataStarted(this);
+    }
+}
+
+
+void
+AbstractAnalysisData::notifyFrameStart(real x, real dx) const
+{
+    GMX_ASSERT(_impl->_bInData, "notifyDataStart() not called");
+    GMX_ASSERT(!_impl->_bInFrame,
+               "notifyFrameStart() called while inside a frame");
+    _impl->_bInFrame = true;
+    _impl->_currx  = x;
+    _impl->_currdx = dx;
+
+    Impl::ModuleList::const_iterator i;
+    for (i = _impl->_modules.begin(); i != _impl->_modules.end(); ++i)
+    {
+        (*i)->frameStarted(x, dx);
+    }
+}
+
+
+void
+AbstractAnalysisData::notifyPointsAdd(int firstcol, int n,
+                                      const real *y, const real *dy,
+                                      const bool *present) const
+{
+    GMX_ASSERT(_impl->_bInData, "notifyDataStart() not called");
+    GMX_ASSERT(_impl->_bInFrame, "notifyFrameStart() not called");
+    GMX_ASSERT(firstcol >= 0 && n > 0 && firstcol + n <= _ncol, "Invalid column");
+    if (present && !_impl->_bAllowMissing)
+    {
+        for (int i = 0; i < n; ++i)
+        {
+            if (!present[i])
+            {
+                GMX_THROW(APIError("Missing data not supported by a module"));
+            }
+        }
+    }
+
+    Impl::ModuleList::const_iterator i;
+    for (i = _impl->_modules.begin(); i != _impl->_modules.end(); ++i)
+    {
+        (*i)->pointsAdded(_impl->_currx, _impl->_currdx, firstcol, n,
+                          y, dy, present);
+    }
+}
+
+
+void
+AbstractAnalysisData::notifyFrameFinish() const
+{
+    GMX_ASSERT(_impl->_bInData, "notifyDataStart() not called");
+    GMX_ASSERT(_impl->_bInFrame, "notifyFrameStart() not called");
+    _impl->_bInFrame = false;
+
+    Impl::ModuleList::const_iterator i;
+
+    for (i = _impl->_modules.begin(); i != _impl->_modules.end(); ++i)
+    {
+        (*i)->frameFinished();
+    }
+}
+
+
+void
+AbstractAnalysisData::notifyDataFinish() const
+{
+    GMX_RELEASE_ASSERT(_impl->_bInData, "notifyDataStart() not called");
+    GMX_RELEASE_ASSERT(!_impl->_bInFrame,
+                       "notifyDataFinish() called while inside a frame");
+    _impl->_bInData = false;
+
+    Impl::ModuleList::const_iterator i;
+
+    for (i = _impl->_modules.begin(); i != _impl->_modules.end(); ++i)
+    {
+        (*i)->dataFinished();
+    }
+}
+
+
+/********************************************************************
+ * AnalysisDataFrame
+ */
+
+AnalysisDataFrame::AnalysisDataFrame()
+    : _y(NULL), _dy(NULL), _present(NULL)
+{
+}
+
+AnalysisDataFrame::~AnalysisDataFrame()
+{
+    sfree(_y);
+    sfree(_dy);
+    sfree(_present);
+}
+
+
+void AnalysisDataFrame::allocate(int ncol)
+{
+    snew(_y, ncol);
+    snew(_dy, ncol);
+    snew(_present, ncol);
+}
+
+
+/********************************************************************
+ * AbstractAnalysisDataStored::Impl
+ */
+
+AbstractAnalysisDataStored::Impl::Impl()
+    : _nframes(0), _nalloc(0), _bStoreAll(false), _nextind(-1)
+{
+}
+
+
+AbstractAnalysisDataStored::Impl::~Impl()
+{
+    FrameList::const_iterator i;
+    for (i = _store.begin(); i != _store.end(); ++i)
+    {
+        delete *i;
+    }
+}
+
+
+int
+AbstractAnalysisDataStored::Impl::getStoreIndex(int index) const
+{
+    // Check that the requested index is available.
+    if ((index < 0 && (-index > _nalloc || -index > _nframes))
+        || index >= _nframes || (index >= 0 && index < _nframes - _nalloc))
+    {
+        return -1;
+    }
+    // Calculate the index into the storage array.
+    if (index < 0)
+    {
+        index = _nextind + index;
+        if (index < 0)
+        {
+            index += _nalloc;
+        }
+    }
+    else if (_nframes > _nalloc)
+    {
+        index %= _nalloc;
+    }
+    return index;
+}
+
+
+/********************************************************************
+ * AbstractAnalysisDataStored
+ */
+
+AbstractAnalysisDataStored::AbstractAnalysisDataStored()
+    : _impl(new Impl())
+{
+}
+
+
+AbstractAnalysisDataStored::~AbstractAnalysisDataStored()
+{
+    delete _impl;
+}
+
+
+int
+AbstractAnalysisDataStored::frameCount() const
+{
+    return _impl->_nframes;
+}
+
+
+bool
+AbstractAnalysisDataStored::getDataWErr(int index, real *x, real *dx,
+                                        const real **y, const real **dy,
+                                        const bool **present) const
+{
+    index = _impl->getStoreIndex(index);
+    if (index < 0)
+    {
+        return false;
+    }
+
+    // Retrieve the data.
+    AnalysisDataFrame *fr = _impl->_store[index];
+    if (x)
+    {
+        *x = fr->_x;
+    }
+    if (dx)
+    {
+        *dx = fr->_dx;
+    }
+    if (y)
+    {
+        *y = fr->_y;
+    }
+    if (dy)
+    {
+        *dy = fr->_dy;
+    }
+    if (present)
+    {
+        *present = fr->_present;
+    }
+    return true;
+}
+
+
+bool
+AbstractAnalysisDataStored::requestStorage(int nframes)
+{
+    GMX_RELEASE_ASSERT(nframes >= -1, "Invalid number of frames requested");
+    if (nframes == 0)
+    {
+        return true;
+    }
+    GMX_RELEASE_ASSERT(!isMultipoint(), "Storage of multipoint data not supported");
+
+    // Handle the case when everything needs to be stored.
+    if (nframes == -1)
+    {
+        _impl->_bStoreAll = true;
+        _impl->_nalloc = 1;
+        return true;
+    }
+    // Check whether an earier call has requested more storage.
+    if (_impl->_bStoreAll || nframes < _impl->_nalloc)
+    {
+        return true;
+    }
+    _impl->_nalloc = nframes;
+    return true;
+}
+
+
+void
+AbstractAnalysisDataStored::setMultipoint(bool multipoint)
+{
+    GMX_RELEASE_ASSERT(_impl->_nalloc == 0 || !multipoint,
+                       "Storage of multipoint data not supported");
+    AbstractAnalysisData::setMultipoint(multipoint);
+}
+
+
+void
+AbstractAnalysisDataStored::startDataStore()
+{
+    // We first notify any attached modules, because they also might request
+    // some storage.
+    notifyDataStart();
+
+    int ncol = columnCount();
+
+    // If any storage has been requested, preallocate it.
+    if (_impl->_nalloc > 0)
+    {
+        _impl->_store.resize(_impl->_nalloc);
+        for (int i = 0; i < _impl->_nalloc; ++i)
+        {
+            _impl->_store[i] = new AnalysisDataFrame();
+            _impl->_store[i]->allocate(ncol);
+        }
+        _impl->_nextind = 0;
+    }
+}
+
+
+void
+AbstractAnalysisDataStored::startNextFrame(real x, real dx)
+{
+    // Start storing the frame if needed.
+    if (_impl->_nalloc > 0)
+    {
+        if (_impl->_nextind >= _impl->_nalloc)
+        {
+            if (_impl->_bStoreAll)
+            {
+                int ncol = columnCount();
+
+                _impl->_nalloc = _impl->_nextind + 1;
+                _impl->_store.resize(_impl->_nalloc);
+                for (int i = _impl->_nextind; i < _impl->_nalloc; ++i)
+                {
+                    _impl->_store[i] = new AnalysisDataFrame();
+                    _impl->_store[i]->allocate(ncol);
+                }
+            }
+            else
+            {
+                _impl->_nextind = 0;
+            }
+        }
+
+        _impl->_store[_impl->_nextind]->_x  = x;
+        _impl->_store[_impl->_nextind]->_dx = dx;
+    }
+
+    // Notify any modules.
+    notifyFrameStart(x, dx);
+}
+
+
+void
+AbstractAnalysisDataStored::storeThisFrame(const real *y, const real *dy,
+                                           const bool *present)
+{
+    int ncol = columnCount();
+
+    // Store the values if required.
+    if (_impl->_nextind >= 0)
+    {
+        AnalysisDataFrame *fr = _impl->_store[_impl->_nextind];
+
+        for (int i = 0; i < ncol; ++i)
+        {
+            fr->_y[i] = y[i];
+            if (dy)
+            {
+                fr->_dy[i] = dy[i];
+            }
+            if (present)
+            {
+                fr->_present[i] = present[i];
+            }
+        }
+    }
+    ++_impl->_nframes;
+
+    // Notify modules of new data.
+    notifyPointsAdd(0, ncol, y, dy, present);
+    // The index needs to be incremented after the notifications to allow
+    // the modules to use getData() properly.
+    if (_impl->_nextind >= 0)
+    {
+        ++_impl->_nextind;
+    }
+    notifyFrameFinish();
+}
+
+
+void
+AbstractAnalysisDataStored::storeNextFrame(real x, real dx, const real *y,
+                                           const real *dy, const bool *present)
+{
+    startNextFrame(x, dx);
+    storeThisFrame(y, dy, present);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/abstractdata.h b/src/gromacs/analysisdata/abstractdata.h
new file mode 100644 (file)
index 0000000..a55af2f
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AbstractAnalysisData and gmx::AbstractAnalysisDataStored.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_ABSTRACTDATA_H
+#define GMX_ANALYSISDATA_ABSTRACTDATA_H
+
+#include "../legacyheaders/types/simple.h"
+
+namespace gmx
+{
+
+class AnalysisDataModuleInterface;
+
+/*! \brief
+ * Abstract base class for all objects that provide data.
+ *
+ * The public interface includes functions for querying the data
+ * (isMultipoint(), columnCount(), frameCount(), getDataWErr(), getData(),
+ * getErrors(), requestStorage()) and functions for using modules for
+ * processing the data (addModule(), addColumnModule(), applyModule()).
+ *
+ * \if libapi
+ * There are also protected functions for use in derived classes:
+ * setting the properties returned by isMultipoint() and columnCount()
+ * through setMultipoint() and setColumnCount(), and notifying attached
+ * modules of added data.
+ * \endif
+ *
+ * Notice that even for non-const objects, the interface does not provide
+ * any means of altering the data. It is only possible to add modules,
+ * making it relatively safe to return a non-const pointer of this type
+ * pointing to an internal data structure without worrying about possible
+ * modifications of the data.
+ *
+ * \if libapi
+ * It is up to subclasses to ensure that the protected functions are called
+ * in a correct sequence (the functions will assert in most incorrect use
+ * cases), and that the data provided through the public interface matches
+ * that passed to the modules with the notify methods.
+ * \endif
+ *
+ * Currently, it is not possible to continue using the data object if an
+ * attached module throws an exception during data processing; it is only safe
+ * to destroy such data object.
+ *
+ * \todo
+ * Improve the exception-handling semantics.  In most cases, it doesn't make
+ * much sense to continue data processing after one module fails, but having
+ * the alternative would not hurt.
+ *
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+class AbstractAnalysisData
+{
+    public:
+        virtual ~AbstractAnalysisData();
+
+        /*! \brief
+         * Whether the data can have multiple points in the same column
+         * in the same frame.
+         *
+         * \returns \c true if multiple points in the same column are
+         *     allowed within a single frame.
+         *
+         * This kind of data can appear in many histogramming applications
+         * (e.g., RDFs), where each trajectory frame has several data points
+         * (possibly a different number for each frame). The current interface
+         * doesn't support storing such data, but this should rarely be
+         * necessary.
+         *
+         * \if libapi
+         * Derived classes can change the type by calling setMultipoint().
+         * If this is not done, the function always returns false.
+         * \endif
+         */
+        bool isMultipoint() const { return _bMultiPoint; }
+        /*! \brief
+         * Returns the number of columns in the data.
+         *
+         * \returns The number of columns in the data.
+         *
+         * If the number of columns is yet known, returns 0.
+         * \if libapi
+         * Derived classes should set the number of columns with
+         * setColumnCount().
+         * \endif
+         */
+        int columnCount() const { return _ncol; }
+        /*! \brief
+         * Returns the total number of frames in the data.
+         *
+         * \returns The total number of frames in the data.
+         *
+         * This function returns the number of frames that the object has
+         * produced. If requestStorage() has been successfully called,
+         * getData() can be used to access some or all of these frames.
+         */
+        virtual int frameCount() const = 0;
+        /*! \brief
+         * Access stored data.
+         *
+         * \param[in]  index   Frame index to access
+         *      (negative indices count backwards from the current frame).
+         * \param[out] x
+         * \param[out] dx
+         * \param[out] y
+         * \param[out] dy
+         * \param[out] present Returns a pointer to an array that tells
+         *      whether the corresponding column is present in that frame.
+         *      If NULL, no missing information is returned.
+         * \retval \c false if data for the requested frame is no longer
+         *      available.
+         *
+         * \if libapi
+         * Derived classes can choose to return false if requestStorage() has
+         * not been called at all, or if the frame is too old (compared to the
+         * value given to requestStorage()).
+         * \endif
+         *
+         * \todo
+         * For more flexibility, it would be better to return a data row/frame
+         * object from this method, which could then be used to access all the
+         * data for that frame.
+         */
+        virtual bool getDataWErr(int index, real *x, real *dx,
+                                 const real **y, const real **dy,
+                                 const bool **present = 0) const = 0;
+        /*! \brief
+         * Convenience function for accessing stored data.
+         *
+         * \see getDataWErr()
+         */
+        bool getData(int index, real *x, const real **y,
+                     const bool **present = 0) const;
+        /*! \brief
+         * Convenience function for accessing errors for stored data.
+         *
+         * \see getDataWErr()
+         */
+        bool getErrors(int index, real *dx, const real **dy) const;
+        /*! \brief
+         * Request storage of frames.
+         *
+         * \param[in] nframes  Request storing at least \c nframes previous
+         *     frames (-1 = request storing all).
+         * \retval true if the request could be satisfied.
+         *
+         * If called multiple times, the largest request should be honored.
+         *
+         * \see getData()
+         */
+        virtual bool requestStorage(int nframes = -1) = 0;
+
+        /*! \brief
+         * Adds a module to process the data.
+         *
+         * \param  module  Module to add.
+         * \exception APIError if
+         *      - \p module is not compatible with the data object
+         *      - data has already been added to the data object and everything
+         *        is not available through getData().
+         *
+         * If data has already been added to the module, the new module
+         * immediately processes all existing data.  APIError is thrown
+         * if all data is not available through getData().
+         *
+         * When this function is entered, the data object takes ownership of the
+         * module, and automatically destructs it when the data object itself
+         * is destroyed.
+         *
+         * \todo
+         * Provide additional semantics that does not acquire ownership of the
+         * data object.
+         */
+        void addModule(AnalysisDataModuleInterface *module);
+        /*! \brief
+         * Adds a module that processes only a subset of the columns.
+         *
+         * \param[in] col     First column.
+         * \param[in] span    Number of columns.
+         * \param     module  Module to add.
+         *
+         * \see addModule()
+         */
+        void addColumnModule(int col, int span, AnalysisDataModuleInterface *module);
+        /*! \brief
+         * Applies a module to process data that is ready.
+         *
+         * \param  module  Module to apply.
+         *
+         * This function works as addModule(), except that it does not take
+         * ownership of \p module. Also, it can only be called after the data
+         * is ready, and only if getData() gives access to all of the data.
+         * It is provided for additional flexibility in postprocessing
+         * in-memory data.
+         */
+        void applyModule(AnalysisDataModuleInterface *module);
+
+    protected:
+        /*! \cond libapi */
+        AbstractAnalysisData();
+
+        /*! \brief
+         * Sets the number of columns.
+         *
+         * \param[in] ncol  Number of columns in the data (must be > 0).
+         *
+         * Can be called only before notifyDataStart(), otherwise asserts.
+         * Multiple calls are only allowed if all of them occur before
+         * addModule() has been called, otherwise asserts (a single call
+         * can occur after addModule() if no calls have been made earlier).
+         *
+         * \see columnCount()
+         */
+        void setColumnCount(int ncol);
+        /*! \brief
+         * Sets whether the data has multiple points per column in a frame.
+         *
+         * \param[in] multipoint  Whether multiple points per column are
+         *     possible.
+         *
+         * Can be called only before addModule() or notifyDataStart(),
+         * otherwise asserts.
+         *
+         * \see isMultipoint()
+         */
+        void setMultipoint(bool multipoint);
+
+        /*! \brief
+         * Notifies attached modules of the start of data.
+         *
+         * Should be called once, after data properties have been set with
+         * setColumnCount() and isMultipoint(), and before any of the
+         * notification functions. The derived class should prepare for
+         * requestStorage() calls from the attached modules.
+         */
+        void notifyDataStart();
+        /*! \brief
+         * Notifies attached modules of the start of a frame.
+         *
+         * Should be called once for each frame, before notifyPointsAdd() calls
+         * for thet frame.
+         */
+        void notifyFrameStart(real x, real dx) const;
+        /*! \brief
+         * Notifies attached modules of the addition of points to the
+         * current frame.
+         *
+         * Can be called zero or more times for each frame.
+         * The caller should ensure that any column occurs at most once in the
+         * calls, unless the data is multipoint.
+         * For efficiency reasons, calls to this method should be aggregated
+         * whenever possible, i.e., it's better to handle multiple columns or
+         * even the whole frame in a single call rather than calling the method
+         * for each column separately.
+         */
+        void notifyPointsAdd(int firstcol, int n,
+                             const real *y, const real *dy,
+                             const bool *present) const;
+        /*! \brief
+         * Notifies attached modules of the end of a frame.
+         *
+         * Should be called once for each call of notifyFrameStart(), after any
+         * notifyPointsAdd() calls for the frame.
+         */
+        void notifyFrameFinish() const;
+        /*! \brief
+         * Notifies attached modules of the end of data.
+         *
+         * Should be called once, after all the other notification calls.
+         */
+        void notifyDataFinish() const;
+        //! \endcond
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+        int                     _ncol;
+        bool                    _bMultiPoint;
+
+        // Disallow copy and assign.
+        AbstractAnalysisData(const AbstractAnalysisData &);
+        void operator =(const AbstractAnalysisData &);
+};
+
+
+/*! \brief
+ * Abstract class that implements storage of data.
+ *
+ * \if libapi
+ * This class implements a standard way of storing data, to avoid implementing
+ * storage in each derived class separately. All the pure virtual methods of
+ * AbstractData are implemented, and protected methods are provided to add data
+ * to the storage. These protected methods automatically call notifyDataStart(),
+ * notifyFrameStart(), notifyPointsAdd() and notifyFrameFinish()
+ * functions in AbstractAnalysisData, but the derived class should still
+ * call notifyDataFinish().
+ *
+ * Additional protected functions could be implemented to allow optimization:
+ * in the current interface, some data copying is unavoidable.
+ * Some changes could make it possible to obtain a pointer to the
+ * storage, allowing the calculated values to be stored there directly
+ * instead of a temporary array.
+ * \endif
+ *
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+class AbstractAnalysisDataStored : public AbstractAnalysisData
+{
+    public:
+        virtual ~AbstractAnalysisDataStored();
+
+        virtual int frameCount() const;
+        virtual bool getDataWErr(int index, real *x, real *dx,
+                                 const real **y, const real **dy,
+                                 const bool **present = 0) const;
+        virtual bool requestStorage(int nframes = -1);
+
+    protected:
+        /*! \cond libapi */
+        AbstractAnalysisDataStored();
+
+        /*! \copydoc AbstractAnalysisData::setMultipoint()
+         *
+         * The overridden method also asserts if
+         * storage has been requested and \p multipoint is \c true.
+         */
+        void setMultipoint(bool multipoint);
+
+        //! Start storing data.
+        void startDataStore();
+        //! Starts storing a next frame.
+        void startNextFrame(real x, real dx);
+        //! Stores the whole frame in a single call after start_next_frame().
+        void storeThisFrame(const real *y, const real *dy, const bool *present);
+        //! Convenience function for storing a whole frame in a single call.
+        void storeNextFrame(real x, real dx, const real *y, const real *dy,
+                            const bool *present);
+        //! \endcond
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Copy and assign disallowed by base class.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/analysisdata-impl.h b/src/gromacs/analysisdata/analysisdata-impl.h
new file mode 100644 (file)
index 0000000..7af2b58
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::AnalysisData.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_ANALYSISDATA_IMPL_H
+#define GMX_ANALYSISDATA_ANALYSISDATA_IMPL_H
+
+#include <memory>
+#include <vector>
+
+#include "analysisdata.h"
+
+#include "abstractdata-impl.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Private implementation class for AnalysisData.
+ *
+ * \ingroup module_analysisdata
+ */
+class AnalysisData::Impl
+{
+    public:
+        //! Shorthand for a list of data handles.
+        typedef std::vector<AnalysisDataHandle *> HandleList;
+        //! Shorthand for a list of frames.
+        typedef std::vector<AnalysisDataFrame *>  FrameList;
+
+        //! Creates an implementation class associated with the given object.
+        explicit Impl(AnalysisData *data);
+        ~Impl();
+
+        /*! \brief
+         * Handles a new frame.
+         *
+         * If all earlier frames are ready, the data is directly passed to
+         * AbstractStoredData.  Otherwise, it is put into the correct location
+         * in \a _pending.  Calls processPendingFrame() after processing \p fr.
+         */
+        void addPendingFrame(AnalysisDataFrame *fr);
+        /*! \brief
+         * Passes pending frames to base class if all earlier frames are ready.
+         */
+        void processPendingFrames();
+        //! Increments \a _pstart.
+        void incrementPStart();
+
+        //! The data object that uses this implementation class.
+        AnalysisData           &_data;
+        //! List of handles for this data object.
+        HandleList              _handles;
+        /*! \brief
+         * Index into \a _pending that points to the location where the current
+         * frame would go.
+         */
+        size_t                  _pstart;
+        /*! \brief
+         * Circular buffer for frames that are ready but waiting for earlier
+         * frames.
+         */
+        FrameList               _pending;
+};
+
+/*! \internal \brief
+ * Private implementation class for AnalysisDataHandle.
+ *
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataHandle::Impl
+{
+    public:
+        //! Creates a handle associated with the given data object.
+        explicit Impl(AnalysisData *data);
+        ~Impl();
+
+        //! The data object that this handle belongs to.
+        AnalysisData            &_data;
+        //! Frame object where the current frame is being accumulated.
+        // Could be scoped_ptr
+        std::auto_ptr<AnalysisDataFrame> _frame;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/analysisdata.cpp b/src/gromacs/analysisdata/analysisdata.cpp
new file mode 100644 (file)
index 0000000..6beb1b3
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in analysisdata.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/analysisdata.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+#include "abstractdata-impl.h"
+#include "analysisdata-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AnalysisData::Impl
+ ********************************************************************/
+
+static bool
+frame_index_gtr(AnalysisDataFrame *a, AnalysisDataFrame *b)
+{
+    return a->_index > b->_index;
+}
+
+
+AnalysisData::Impl::Impl(AnalysisData *data)
+    : _data(*data), _pstart(0)
+{
+}
+
+
+AnalysisData::Impl::~Impl()
+{
+    HandleList::const_iterator i;
+    for (i = _handles.begin(); i != _handles.end(); ++i)
+    {
+        delete *i;
+    }
+
+    FrameList::const_iterator j;
+    for (j = _pending.begin(); j != _pending.end(); ++j)
+    {
+        delete *j;
+    }
+}
+
+
+void
+AnalysisData::Impl::addPendingFrame(AnalysisDataFrame *fr)
+{
+    GMX_ASSERT(fr->_index >= _data.frameCount(),
+               "addPendingFrame() called for too old frame");
+    size_t pindex = fr->_index - _data.frameCount();
+    if (pindex == 0)
+    {
+        // Just store our frame if it is the next one.
+        _data.storeNextFrame(fr->_x, fr->_dx, fr->_y, fr->_dy, fr->_present);
+        incrementPStart();
+    }
+    else
+    {
+        if (pindex >= _pending.size())
+        {
+            // TODO: We need to wait until earlier frames are ready...
+        }
+        // TODO: This is not thread-safe.
+        pindex += _pstart;
+        if (pindex > _pending.size())
+        {
+            pindex -= _pending.size();
+        }
+
+        int ncol = _data.columnCount();
+        _pending[pindex]->_x     = fr->_x;
+        _pending[pindex]->_dx    = fr->_dx;
+        for (int i = 0; i < ncol; ++i)
+        {
+            _pending[pindex]->_y[i]       = fr->_y[i];
+            _pending[pindex]->_dy[i]      = fr->_dy[i];
+            _pending[pindex]->_present[i] = fr->_present[i];
+        }
+        _pending[pindex]->_index = fr->_index;
+    }
+    processPendingFrames();
+}
+
+
+void
+AnalysisData::Impl::processPendingFrames()
+{
+    while (_pending[_pstart]->_index != -1)
+    {
+        AnalysisDataFrame *fr = _pending[_pstart];
+
+        _data.storeNextFrame(fr->_x, fr->_dx, fr->_y, fr->_dy, fr->_present);
+        fr->_index = -1;
+        incrementPStart();
+    }
+}
+
+
+void
+AnalysisData::Impl::incrementPStart()
+{
+    size_t val = _pstart;
+
+    ++val;
+    if (val >= _pending.size())
+    {
+        val -= _pending.size();
+    }
+    _pstart = val;
+}
+
+
+/********************************************************************
+ * AnalysisData
+ */
+
+AnalysisData::AnalysisData()
+    : _impl(new Impl(this))
+{
+}
+
+
+AnalysisData::~AnalysisData()
+{
+    delete _impl;
+}
+
+
+void
+AnalysisData::setColumns(int ncol, bool multipoint)
+{
+    GMX_RELEASE_ASSERT(ncol > 0, "Number of columns must be positive");
+    GMX_RELEASE_ASSERT(_impl->_handles.empty(),
+                       "Cannot change data dimensionality after creating handles");
+    setColumnCount(ncol);
+    setMultipoint(multipoint);
+}
+
+
+AnalysisDataHandle *
+AnalysisData::startData(AnalysisDataParallelOptions opt)
+{
+    if (_impl->_handles.empty())
+    {
+        startDataStore();
+    }
+    else if (isMultipoint())
+    {
+        GMX_THROW(NotImplementedError("Parallelism not supported for multipoint data"));
+    }
+
+    std::auto_ptr<AnalysisDataHandle> handle(new AnalysisDataHandle(this));
+    _impl->_handles.push_back(handle.get());
+
+    _impl->_pending.resize(2 * _impl->_handles.size() - 1);
+    Impl::FrameList::iterator i;
+    for (i = _impl->_pending.begin(); i != _impl->_pending.end(); ++i)
+    {
+        *i = new AnalysisDataFrame();
+        (*i)->allocate(columnCount());
+        (*i)->_index = -1;
+    }
+
+    return handle.release();
+}
+
+
+void
+AnalysisData::finishData(AnalysisDataHandle *handle)
+{
+    Impl::HandleList::iterator i;
+
+    i = std::find(_impl->_handles.begin(), _impl->_handles.end(), handle);
+    GMX_RELEASE_ASSERT(i != _impl->_handles.end(),
+                       "finishData() called for an unknown handle");
+
+    _impl->_handles.erase(i);
+    delete handle;
+
+    if (_impl->_handles.empty())
+    {
+        notifyDataFinish();
+    }
+}
+
+
+/********************************************************************
+ * AnalysisDataHandle::Impl
+ */
+
+AnalysisDataHandle::Impl::Impl(AnalysisData *data)
+    : _data(*data)
+{
+    if (!_data.isMultipoint())
+    {
+        _frame.reset(new AnalysisDataFrame());
+        _frame->allocate(_data.columnCount());
+    }
+}
+
+
+AnalysisDataHandle::Impl::~Impl()
+{
+}
+
+
+/********************************************************************
+ * AnalysisDataHandle
+ */
+
+AnalysisDataHandle::AnalysisDataHandle(AnalysisData *data)
+    : _impl(new Impl(data))
+{
+}
+
+
+AnalysisDataHandle::~AnalysisDataHandle()
+{
+    delete _impl;
+}
+
+
+void
+AnalysisDataHandle::startFrame(int index, real x, real dx)
+{
+    if (_impl->_data.isMultipoint())
+    {
+        _impl->_data.notifyFrameStart(x, dx);
+    }
+    else
+    {
+        _impl->_frame->_index = index;
+        _impl->_frame->_x  = x;
+        _impl->_frame->_dx = dx;
+        for (int i = 0; i < _impl->_data.columnCount(); ++i)
+        {
+            _impl->_frame->_y[i]  = 0.0;
+            _impl->_frame->_dy[i] = 0.0;
+            _impl->_frame->_present[i] = false;
+        }
+    }
+}
+
+
+void
+AnalysisDataHandle::addPoint(int col, real y, real dy, bool present)
+{
+    if (_impl->_data.isMultipoint())
+    {
+        _impl->_data.notifyPointsAdd(col, 1, &y, &dy, &present);
+    }
+    else
+    {
+        GMX_ASSERT(!_impl->_frame->_present[col],
+                   "Data for a column set multiple times");
+        _impl->_frame->_y[col] = y;
+        _impl->_frame->_dy[col] = dy;
+        _impl->_frame->_present[col] = present;
+    }
+}
+
+
+void
+AnalysisDataHandle::addPoints(int firstcol, int n,
+                              const real *y, const real *dy,
+                              const bool *present)
+{
+    if (_impl->_data.isMultipoint())
+    {
+        _impl->_data.notifyPointsAdd(firstcol, n, y, dy, present);
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+        {
+            addPoint(firstcol + i, y[i], dy ? dy[i] : 0.0,
+                     present ? present[i] : true);
+        }
+    }
+}
+
+
+void
+AnalysisDataHandle::finishFrame()
+{
+    if (_impl->_data.isMultipoint())
+    {
+        _impl->_data.notifyFrameFinish();
+    }
+    else
+    {
+        _impl->_data._impl->addPendingFrame(_impl->_frame.get());
+    }
+}
+
+
+void
+AnalysisDataHandle::addFrame(int index, real x, const real *y, const real *dy,
+                             const bool *present)
+{
+    addFrame(index, x, 0.0, y, dy, present);
+}
+
+
+void
+AnalysisDataHandle::addFrame(int index, real x, real dx,
+                             const real *y, const real *dy,
+                             const bool *present)
+{
+    startFrame(index, x, dx);
+    addPoints(0, _impl->_data.columnCount(), y, dy, present);
+    finishFrame();
+}
+
+
+void
+AnalysisDataHandle::finishData()
+{
+    // Calls delete this
+    _impl->_data.finishData(this);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/analysisdata.h b/src/gromacs/analysisdata/analysisdata.h
new file mode 100644 (file)
index 0000000..61f81c7
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AnalysisData and related classes.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_ANALYSISDATA_H
+#define GMX_ANALYSISDATA_ANALYSISDATA_H
+
+#include "abstractdata.h"
+
+namespace gmx
+{
+
+class AnalysisDataHandle;
+
+//! Placeholder type for parallelization options.
+typedef void *AnalysisDataParallelOptions;
+
+/*! \brief
+ * Parallelizable data container for raw data.
+ *
+ * This is the only data object (in addition to the tightly coupled
+ * \c AnalysisDataHandle object) that needs explicit parallelization.
+ *
+ * Special note for MPI implementation: assuming that the initialization of
+ * data objects is identical in all processes, associating the data objects
+ * in different MPI processes should be possible without changes in the
+ * interface.
+ * Alternative, more robust implementation could get a unique ID as parameter
+ * to the constructor or a separate function, but would require all tools to
+ * provide it.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisData : public AbstractAnalysisDataStored
+{
+    public:
+        //! Creates an empty analysis data object.
+        AnalysisData();
+        virtual ~AnalysisData();
+
+        /*! \brief
+         * Sets the number of columns in the data and type of the data.
+         *
+         * \see isMultipoint()
+         */
+        void setColumns(int ncol, bool multipoint = false);
+
+        /*! \brief
+         * Create a handle for adding data.
+         *
+         * \param[in]  opt     Options for setting how this handle will be
+         *     used.
+         * \returns The created handle.
+         */
+        AnalysisDataHandle *startData(AnalysisDataParallelOptions opt);
+        /*! \brief
+         * Destroy a handle after all data has been added.
+         *
+         * \param[in]  handle  Handle to destroy.
+         *
+         * The pointer \p handle is invalid after the call.
+         */
+        void finishData(AnalysisDataHandle *handle);
+
+    private:
+        class Impl;
+
+        Impl                *_impl;
+
+        friend class Impl;
+        friend class AnalysisDataHandle;
+
+        // Copy and assign disallowed by base class.
+};
+
+
+/*! \brief
+ * Handle for inserting data into AnalysisData.
+ *
+ * Several handles can exist concurrently.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataHandle
+{
+    public:
+        /*! \brief
+         * Frees memory allocated for the internal implementation.
+         *
+         * Should not be called directly, but through finishData() or
+         * AnalysisData::finishData().
+         */
+        ~AnalysisDataHandle();
+
+        //! Start data for a new frame.
+        void startFrame(int index, real x, real dx = 0.0);
+        //! Add a data point for in single column for the current frame.
+        void addPoint(int col, real y, real dy = 0.0, bool present = true);
+        //! Add multiple data points in neighboring columns for the current frame.
+        void addPoints(int firstcol, int n,
+                       const real *y, const real *dy = 0,
+                       const bool *present = 0);
+        //! Finish data for the current frame.
+        void finishFrame();
+        //! Convenience function for adding a complete frame.
+        void addFrame(int index, real x, const real *y, const real *dy = 0,
+                      const bool *present = 0);
+        //! Convenience function for adding a complete frame.
+        void addFrame(int index, real x, real dx,
+                      const real *y, const real *dy = 0,
+                      const bool *present = 0);
+        //! Calls AnalysisData::finishData() for this handle.
+        void finishData();
+
+    private:
+        /*! \brief
+         * Creates a new data handle associated with \p data.
+         *
+         * \param  data Data to associate the handle with.
+         *
+         * The constructor is private because data handles should only be
+         * constructed through AnalysisData::startData().
+         */
+        explicit AnalysisDataHandle(AnalysisData *data);
+
+        class Impl;
+
+        Impl                *_impl;
+
+        friend class AnalysisData;
+
+        // Disallow copy and assign.
+        AnalysisDataHandle(const AnalysisDataHandle &);
+        void operator =(const AnalysisDataHandle &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/arraydata.cpp b/src/gromacs/analysisdata/arraydata.cpp
new file mode 100644 (file)
index 0000000..f1f2411
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in arraydata.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/arraydata.h"
+
+// Legacy header.
+#include "smalloc.h"
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+namespace gmx
+{
+
+AbstractAnalysisArrayData::AbstractAnalysisArrayData()
+    : _nrows(0), _value(NULL), _xstart(0.0), _xstep(1.0), _bReady(false)
+{
+}
+
+AbstractAnalysisArrayData::~AbstractAnalysisArrayData()
+{
+    sfree(_value);
+}
+
+
+int
+AbstractAnalysisArrayData::frameCount() const
+{
+    return _bReady ? _nrows : 0;
+}
+
+
+bool
+AbstractAnalysisArrayData::getDataWErr(int index, real *x, real *dx,
+                                       const real **y, const real **dy,
+                                       const bool **present) const
+{
+    if (index < 0)
+    {
+        index += _nrows;
+        if (index < 0)
+        {
+            return false;
+        }
+    }
+    if (index >= frameCount())
+    {
+        return false;
+    }
+    if (x != NULL)
+    {
+        *x = _xstart + index * _xstep;
+    }
+    if (dx != NULL)
+    {
+        *dx = 0.0;
+    }
+    if (y != NULL)
+    {
+        *y = _value + (index * columnCount());
+    }
+    if (dy != NULL)
+    {
+        // TODO: Implement
+        *dy = NULL;
+    }
+    if (present != NULL)
+    {
+        // TODO: Implement
+        *present = NULL;
+    }
+    return true;
+}
+
+
+bool
+AbstractAnalysisArrayData::requestStorage(int /*nframes*/)
+{
+    return true;
+}
+
+
+void
+AbstractAnalysisArrayData::setColumnCount(int ncols)
+{
+    GMX_RELEASE_ASSERT(!_value,
+                       "Cannot change column count after data has been allocated");
+    AbstractAnalysisData::setColumnCount(ncols);
+}
+
+
+void
+AbstractAnalysisArrayData::setRowCount(int nrows)
+{
+    GMX_RELEASE_ASSERT(nrows > 0, "Invalid number of rows");
+    GMX_RELEASE_ASSERT(!_value,
+                       "Cannot change row count after data has been allocated");
+    GMX_RELEASE_ASSERT(columnCount() > 0, "Column count must be set before row count");
+    _nrows = nrows;
+    snew(_value, _nrows * columnCount());
+}
+
+
+void
+AbstractAnalysisArrayData::setXAxis(real start, real step)
+{
+    GMX_RELEASE_ASSERT(!_bReady, "X axis cannot be set after data is finished");
+    _xstart = start;
+    _xstep = step;
+}
+
+
+void
+AbstractAnalysisArrayData::valuesReady()
+{
+    GMX_RELEASE_ASSERT(columnCount() > 0 && _nrows > 0 && _value,
+                       "There must be some data");
+    if (_bReady)
+    {
+        return;
+    }
+    _bReady = true;
+
+    notifyDataStart();
+    for (int i = 0; i < _nrows; ++i)
+    {
+        notifyFrameStart(_xstart + i * _xstep, 0);
+        notifyPointsAdd(0, columnCount(), _value + (i * columnCount()),
+                        NULL, NULL);
+        notifyFrameFinish();
+    }
+    notifyDataFinish();
+}
+
+
+void
+AbstractAnalysisArrayData::copyContents(const AbstractAnalysisArrayData *src,
+                                        AbstractAnalysisArrayData *dest)
+{
+    GMX_RELEASE_ASSERT(src->columnCount() > 0 && src->_nrows > 0 && src->_value,
+                       "Source data must not be empty");
+    GMX_RELEASE_ASSERT(!dest->_value, "Destination data must not be allocated");
+    dest->setColumnCount(src->columnCount());
+    dest->setRowCount(src->_nrows);
+    dest->setXAxis(src->_xstart, src->_xstep);
+    for (int i = 0; i < src->_nrows * src->columnCount(); ++i)
+    {
+        dest->_value[i] = src->_value[i];
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/arraydata.h b/src/gromacs/analysisdata/arraydata.h
new file mode 100644 (file)
index 0000000..5405bdf
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AbstractAnalysisArrayData and gmx::AnalysisArrayData.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_ARRAYDATA_H
+#define GMX_ANALYSISDATA_ARRAYDATA_H
+
+#include <cstddef>
+
+#include "../fatalerror/gmxassert.h"
+
+#include "abstractdata.h"
+
+namespace gmx
+{
+
+/*! \brief
+ * Abstract base class for data objects that present in-memory data.
+ *
+ * This class implements a subclass of AbstractAnalysisData that presents an
+ * in-memory array through the AbstractAnalysisData interface.  Subclasses
+ * should initialize the in-memory array through the provided protected member
+ * functions.
+ *
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+class AbstractAnalysisArrayData : public AbstractAnalysisData
+{
+    public:
+        virtual ~AbstractAnalysisArrayData();
+
+        virtual int frameCount() const;
+        virtual bool getDataWErr(int index, real *x, real *dx,
+                                 const real **y, const real **dy,
+                                 const bool **present = 0) const;
+        virtual bool requestStorage(int nframes = -1);
+
+    protected:
+        AbstractAnalysisArrayData();
+
+        /*! \brief
+         * Returns the number of rows in the data array.
+         *
+         * This function is identical to frameCount(), except that frameCount()
+         * returns 0 before valuesReady() has been called.
+         */
+        int rowCount() const { return _nrows; }
+        /*! \brief
+         * Sets the number of columns in the data array.
+         */
+        void setColumnCount(int ncols);
+        /*! \brief
+         * Sets the number of rows in the data array.
+         */
+        void setRowCount(int nrows);
+        //! Returns the x value of the first frame.
+        real xstart() const { return _xstart; }
+        //! Returns the step between frame x values.
+        real xstep() const { return _xstep; }
+        /*! \brief
+         * Sets the values reported as x values for frames.
+         */
+        void setXAxis(real start, real step);
+        //! Returns a reference to a given array element.
+        real &value(int row, int col)
+        {
+            GMX_ASSERT(row >= 0 && row < _nrows, "Row index out of range");
+            GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
+            GMX_ASSERT(_value != NULL, "Data array not allocated");
+            return _value[row * columnCount() + col];
+        }
+        //! Returns a given array element.
+        const real &value(int row, int col) const
+        {
+            GMX_ASSERT(row >= 0 && row < _nrows, "Row index out of range");
+            GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
+            GMX_ASSERT(_value != NULL, "Data array not allocated");
+            return _value[row * columnCount() + col];
+        }
+        /*! \brief
+         * Sets the value of an element in the array.
+         */
+        void setValue(int row, int col, real val)
+        {
+            value(row, col) = val;
+        }
+        /*! \brief
+         * Notifies modules of the data.
+         *
+         * This function should be called once the values in the array
+         * have been initialized. The values should not be changed after this
+         * function has been called.
+         */
+        void valuesReady();
+
+        /*! \brief
+         * Copies the contents into a new object.
+         *
+         * \param[in]     src  Object to copy data from.
+         * \param[in,out] dest Empty array data object to copy data to.
+         *
+         * \p dest should not have previous contents.
+         */
+        static void copyContents(const AbstractAnalysisArrayData *src,
+                                 AbstractAnalysisArrayData *dest);
+
+    private:
+        int                  _nrows;
+        real                *_value;
+        real                 _xstart;
+        real                 _xstep;
+        bool                 _bReady;
+
+        // Copy and assign disallowed by base.
+};
+
+/*! \brief
+ * Simple in-memory data array.
+ *
+ * This class simply exposes the protected functions of
+ * AbstractAnalysisArrayData to allow construction of simple in-memory data
+ * arrays for input into data modules.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisArrayData : public AbstractAnalysisArrayData
+{
+    public:
+        AnalysisArrayData() {}
+
+        // TODO: These statements cause Doxygen to generate confusing
+        // documentation.
+        using AbstractAnalysisArrayData::rowCount;
+        using AbstractAnalysisArrayData::setColumnCount;
+        using AbstractAnalysisArrayData::setRowCount;
+        using AbstractAnalysisArrayData::xstart;
+        using AbstractAnalysisArrayData::xstep;
+        using AbstractAnalysisArrayData::setXAxis;
+        using AbstractAnalysisArrayData::value;
+        using AbstractAnalysisArrayData::setValue;
+        using AbstractAnalysisArrayData::valuesReady;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/datamodule.h b/src/gromacs/analysisdata/datamodule.h
new file mode 100644 (file)
index 0000000..107877f
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AnalysisDataModuleInterface.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_DATAMODULE_H
+#define GMX_ANALYSISDATA_DATAMODULE_H
+
+#include "../legacyheaders/types/simple.h"
+
+namespace gmx
+{
+
+class AbstractAnalysisData;
+
+/*! \brief
+ * Interface for a module that gets notified whenever data is added.
+ *
+ * The interface provides one method (flags()) that describes features of
+ * data objects the module supports. Only most common features are included
+ * in the flags; custom checks can be implemented in the dataStarted() method
+ * (see below).
+ * All other methods in the interface are callbacks that are called by the
+ * data object to which the module is attached to describe the data.
+ *
+ * \inlibraryapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataModuleInterface
+{
+    public:
+        /*! \brief
+         * Possible flags for flags().
+         */
+        enum {
+            //! The module can process multipoint data.
+            efAllowMultipoint    = 0x01,
+            //! The module does not make sense for non-multipoint data.
+            efOnlyMultipoint     = 0x02,
+            //! The module can process data with more than one column.
+            efAllowMulticolumn   = 0x04,
+            //! The module can process data with missing points.
+            efAllowMissing       = 0x08,
+        };
+
+        virtual ~AnalysisDataModuleInterface() {};
+
+        /*! \brief
+         * Returns properties supported by the module.
+         *
+         * The return value of this method should not change after the module
+         * has been added to a data (this responsibility can, and in most cases
+         * must, be delegated to the user of the module).
+         *
+         * The purpose of this method is to remove the need for common checks
+         * for data compatibility in the classes that implement the interface.
+         * Instead, AbstractAnalysisData performs these checks based on the
+         * flags provided.
+         */
+        virtual int flags() const = 0;
+
+        /*! \brief
+         * Called (once) when the data has been set up properly.
+         *
+         * The data to which the module is attached is passed as an argument
+         * to provide access to properties of the data for initialization
+         * and/or validation.
+         * This is the only place where the module gets access to the data;
+         * if properties of the data are required later, the module should
+         * store them internally. It is guaranteed that the data properties
+         * (column count, whether it's multipoint) do not change once this
+         * method has been called.
+         */
+        virtual void dataStarted(AbstractAnalysisData *data) = 0;
+        /*! \brief
+         * Called at the start of each data frame.
+         */
+        virtual void frameStarted(real x, real dx) = 0;
+        /*! \brief
+         * Called one or more times during each data frame.
+         *
+         * For convenience, the \p x and \p dx values for the frame are
+         * passed to each call of this function.
+         *
+         * \todo
+         * For more flexibility, this function should take a data row/frame
+         * object, which could be used to access all relevant data.
+         */
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present) = 0;
+        /*! \brief
+         * Called when a data frame is finished.
+         */
+        virtual void frameFinished() = 0;
+        /*! \brief
+         * Called (once) when no more data is available.
+         */
+        virtual void dataFinished() = 0;
+
+    protected:
+        AnalysisDataModuleInterface() {}
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/dataproxy.cpp b/src/gromacs/analysisdata/dataproxy.cpp
new file mode 100644 (file)
index 0000000..60828b6
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::AnalysisDataProxy.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "dataproxy.h"
+
+#include "gromacs/fatalerror/gmxassert.h"
+
+namespace gmx
+{
+
+AnalysisDataProxy::AnalysisDataProxy(int col, int span,
+                                     AbstractAnalysisData *data)
+    : _source(*data), _col(col), _span(span)
+{
+    GMX_RELEASE_ASSERT(data, "Source data must not be NULL");
+    GMX_RELEASE_ASSERT(col >= 0 && span > 0, "Invalid proxy column");
+    setColumnCount(span);
+    setMultipoint(_source.isMultipoint());
+}
+
+
+int
+AnalysisDataProxy::frameCount() const
+{
+    return _source.frameCount();
+}
+
+
+bool
+AnalysisDataProxy::getDataWErr(int index, real *x, real *dx,
+                               const real **y, const real **dy,
+                               const bool **missing) const
+{
+    bool bExists = _source.getDataWErr(index, x, dx, y, dy, missing);
+    if (bExists)
+    {
+        if (y && *y)
+        {
+            *y += _col;
+        }
+        if (dy && *dy)
+        {
+            *dy += _col;
+        }
+        if (missing && *missing)
+        {
+            *missing += _col;
+        }
+    }
+    return bExists;
+}
+
+
+bool
+AnalysisDataProxy::requestStorage(int nframes)
+{
+    return _source.requestStorage(nframes);
+}
+
+
+int
+AnalysisDataProxy::flags() const
+{
+    return efAllowMultipoint | efAllowMulticolumn | efAllowMissing;
+}
+
+
+void
+AnalysisDataProxy::dataStarted(AbstractAnalysisData *data)
+{
+    GMX_RELEASE_ASSERT(data == &_source, "Source data mismatch");
+    GMX_RELEASE_ASSERT(_col + _span <= _source.columnCount(),
+                       "Invalid column(s) specified");
+    notifyDataStart();
+}
+
+
+void
+AnalysisDataProxy::frameStarted(real x, real dx)
+{
+    notifyFrameStart(x, dx);
+}
+
+
+void
+AnalysisDataProxy::pointsAdded(real x, real dx, int firstcol, int n,
+                               const real *y, const real *dy,
+                               const bool *missing)
+{
+    if (firstcol + n <= _col || firstcol >= _col + _span)
+    {
+        return;
+    }
+    firstcol -= _col;
+    if (firstcol < 0)
+    {
+        if (y)
+        {
+            y +=  -firstcol;
+        }
+        if (dy)
+        {
+            dy += -firstcol;
+        }
+        if (missing)
+        {
+            missing += -firstcol;
+        }
+        n -= -firstcol;
+        firstcol = 0;
+    }
+    if (firstcol + n > _span)
+    {
+        n = _span - firstcol;
+    }
+    notifyPointsAdd(firstcol, n, y, dy, missing);
+}
+
+
+void
+AnalysisDataProxy::frameFinished()
+{
+    notifyFrameFinish();
+}
+
+
+void
+AnalysisDataProxy::dataFinished()
+{
+    notifyDataFinish();
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/dataproxy.h b/src/gromacs/analysisdata/dataproxy.h
new file mode 100644 (file)
index 0000000..d9237cf
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares gmx::AnalysisDataProxy.
+ *
+ * This header is only meant for internal use of the gmx::AbstractAnalysisData
+ * class to implement modules that handle only a subset of columns.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_DATAPROXY_H
+#define GMX_ANALYSISDATA_DATAPROXY_H
+
+#include "abstractdata.h"
+#include "datamodule.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Internal implementation class used to implement column modules.
+ *
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataProxy : public AbstractAnalysisData,
+                          public AnalysisDataModuleInterface
+{
+    public:
+        /*! \brief
+         * Creates a proxy object that only presents certain columns.
+         *
+         * \param[in] col   First column to present.
+         * \param[in] span  Number of columns to present.
+         * \param[in] data  Data object that should be wrapped.
+         */
+        AnalysisDataProxy(int col, int span, AbstractAnalysisData *data);
+
+        virtual int frameCount() const;
+        virtual bool getDataWErr(int index, real *x, real *dx,
+                                 const real **y, const real **dy,
+                                 const bool **missing = 0) const;
+        virtual bool requestStorage(int nframes = -1);
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *missing);
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+    private:
+        AbstractAnalysisData   &_source;
+        int                     _col;
+        int                     _span;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/CMakeLists.txt b/src/gromacs/analysisdata/modules/CMakeLists.txt
new file mode 100644 (file)
index 0000000..61b3e75
--- /dev/null
@@ -0,0 +1,8 @@
+set(ANALYSISDATA_MODULES_PUBLIC_HEADERS
+    average.h
+    displacement.h
+    histogram.h
+    plot.h)
+install(FILES ${ANALYSISDATA_MODULES_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/analysisdata/modules
+        COMPONENT development)
diff --git a/src/gromacs/analysisdata/modules/average.cpp b/src/gromacs/analysisdata/modules/average.cpp
new file mode 100644 (file)
index 0000000..93327b2
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::AnalysisDataAverageModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/modules/average.h"
+
+#include <cmath>
+
+// Legacy include
+#include "smalloc.h"
+
+#include "gromacs/basicmath.h"
+
+namespace gmx
+{
+
+AnalysisDataAverageModule::AnalysisDataAverageModule()
+    : _nsamples(NULL)
+{
+    setColumnCount(2);
+}
+
+
+AnalysisDataAverageModule::~AnalysisDataAverageModule()
+{
+    sfree(_nsamples);
+}
+
+
+int
+AnalysisDataAverageModule::flags() const
+{
+    return efAllowMultipoint | efAllowMulticolumn | efAllowMissing;
+}
+
+
+void
+AnalysisDataAverageModule::dataStarted(AbstractAnalysisData *data)
+{
+    int nrows = data->columnCount();
+    setRowCount(nrows);
+    snew(_nsamples, nrows);
+}
+
+
+void
+AnalysisDataAverageModule::frameStarted(real x, real dx)
+{
+}
+
+
+void
+AnalysisDataAverageModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                       const real *y, const real *dy,
+                                       const bool *present)
+{
+    for (int i = 0; i < n; ++i)
+    {
+        if (!present || present[i])
+        {
+            value(firstcol + i, 0)  += y[i];
+            value(firstcol + i, 1)  += y[i] * y[i];
+            _nsamples[firstcol + i] += 1;
+        }
+    }
+}
+
+
+void
+AnalysisDataAverageModule::frameFinished()
+{
+}
+
+
+void
+AnalysisDataAverageModule::dataFinished()
+{
+    for (int i = 0; i < rowCount(); ++i)
+    {
+        real ave = value(i, 0) / _nsamples[i];
+        real std = sqrt(value(i, 1) / _nsamples[i] - ave * ave);
+        setValue(i, 0, ave);
+        setValue(i, 1, std);
+    }
+    valuesReady();
+}
+
+
+real
+AnalysisDataAverageModule::average(int index) const
+{
+    return value(index, 0);
+}
+
+
+real
+AnalysisDataAverageModule::stddev(int index) const
+{
+    return value(index, 1);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/modules/average.h b/src/gromacs/analysisdata/modules/average.h
new file mode 100644 (file)
index 0000000..644ddaa
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AnalysisDataAverageModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_AVERAGE_H
+#define GMX_ANALYSISDATA_MODULES_AVERAGE_H
+
+#include "../arraydata.h"
+#include "../datamodule.h"
+
+namespace gmx
+{
+
+/*! \brief
+ * Data module for simple averaging of columns.
+ *
+ * Output data contains a frame for each column of input data.
+ * There are two columns: the average and standard deviation of
+ * that column.
+ * The data becomes available only after the original data has been
+ * finished.
+ *
+ * Multipoint data and missing data points are both supported. The average
+ * is always calculated over all data points present in a column.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataAverageModule : public AbstractAnalysisArrayData,
+                                  public AnalysisDataModuleInterface
+{
+    public:
+        AnalysisDataAverageModule();
+        virtual ~AnalysisDataAverageModule();
+
+        using AbstractAnalysisArrayData::setXAxis;
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+        //! Convenience access to the average of a data column.
+        real average(int index) const;
+        //! Convenience access to the standard deviation of a data column.
+        real stddev(int index) const;
+
+    private:
+        int                    *_nsamples;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/displacement-impl.h b/src/gromacs/analysisdata/modules/displacement-impl.h
new file mode 100644 (file)
index 0000000..3d6b0f6
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for
+ * gmx::AnalysisDataDisplacementModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_DISPLACEMENT_IMPL_H
+#define GMX_ANALYSISDATA_MODULES_DISPLACEMENT_IMPL_H
+
+#include "displacement.h"
+
+namespace gmx
+{
+
+class AbstractHistogramModule;
+
+/*! \internal \brief
+ * Private implementation class for AnalysisDataDisplacementModule.
+ *
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataDisplacementModule::Impl
+{
+    public:
+        Impl();
+        ~Impl();
+
+        //! Maximum number of particles for which the displacements are calculated.
+        int                     nmax;
+        //! Maximum time for which the displacements are needed.
+        real                    tmax;
+        //! Number of dimensions per data point.
+        int                     ndim;
+
+        //! TRUE if no frames have been read.
+        bool                    bFirst;
+        //! Stores the time of the first frame.
+        real                    t0;
+        //! Stores the time interval between frames.
+        real                    dt;
+        //! Stores the time of the current frame.
+        real                    t;
+        //! Stores the index in the store for the current positions.
+        int                     ci;
+
+        //! Maximum number of positions to store for a particle.
+        int                     max_store;
+        //! The total number of positions ever stored (can be larger than \p max_store).
+        int                     nstored;
+        //! Old values.
+        real                   *oldval;
+        //! The most recently calculated displacements.
+        real                   *currd;
+
+        //! Histogram module for calculating MSD histograms, or NULL if not set.
+        AbstractHistogramModule *histm;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/displacement.cpp b/src/gromacs/analysisdata/modules/displacement.cpp
new file mode 100644 (file)
index 0000000..a799522
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::AnalysisDataDisplacementModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/modules/displacement.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// Legacy include.
+#include "smalloc.h"
+
+#include "gromacs/analysisdata/modules/histogram.h"
+#include "gromacs/basicmath.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+#include "displacement-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AnalysisDataDisplacementModule::Impl
+ */
+
+AnalysisDataDisplacementModule::Impl::Impl()
+    : nmax(0), tmax(0.0), ndim(3),
+      bFirst(true), t0(0.0), dt(0.0), t(0.0),
+      max_store(-1), nstored(0), oldval(NULL), currd(NULL),
+      histm(NULL)
+{
+}
+
+AnalysisDataDisplacementModule::Impl::~Impl()
+{
+    sfree(oldval);
+    sfree(currd);
+}
+
+/********************************************************************
+ * AnalysisDataDisplacementModule
+ */
+
+AnalysisDataDisplacementModule::AnalysisDataDisplacementModule()
+    : _impl(new Impl())
+{
+    setMultipoint(true);
+}
+
+
+AnalysisDataDisplacementModule::~AnalysisDataDisplacementModule()
+{
+    delete _impl;
+}
+
+
+void
+AnalysisDataDisplacementModule::setMaxTime(real tmax)
+{
+    _impl->tmax = tmax;
+}
+
+
+void
+AnalysisDataDisplacementModule::setMSDHistogram(AnalysisDataBinAverageModule *histm)
+{
+    GMX_RELEASE_ASSERT(!_impl->histm, "Can only set MSD histogram once");
+    _impl->histm = histm;
+    histm->setIgnoreMissing(true);
+    addModule(histm);
+}
+
+
+int
+AnalysisDataDisplacementModule::frameCount() const
+{
+    return _impl->nstored > 1 ? _impl->nstored - 1 : 0;
+}
+
+
+bool
+AnalysisDataDisplacementModule::getDataWErr(int index, real *x, real *dx,
+                                            const real **y, const real **dy,
+                                            const bool **present) const
+{
+    return false;
+}
+
+
+bool
+AnalysisDataDisplacementModule::requestStorage(int nframes)
+{
+    return false;
+}
+
+
+int
+AnalysisDataDisplacementModule::flags() const
+{
+    return efAllowMulticolumn;
+}
+
+
+void
+AnalysisDataDisplacementModule::dataStarted(AbstractAnalysisData *data)
+{
+    if (data->columnCount() % _impl->ndim != 0)
+    {
+        GMX_THROW(APIError("Data has incorrect number of columns"));
+    }
+    _impl->nmax = data->columnCount();
+    snew(_impl->oldval, _impl->nmax);
+    _impl->ci = -_impl->nmax;
+
+    int ncol = _impl->nmax / _impl->ndim + 1;
+    snew(_impl->currd, ncol);
+    setColumnCount(ncol);
+}
+
+
+void
+AnalysisDataDisplacementModule::frameStarted(real x, real dx)
+{
+    // Initialize times.
+    if (_impl->bFirst)
+    {
+        _impl->t0 = x;
+    }
+    else if (_impl->dt <= 0)
+    {
+        _impl->dt = x - _impl->t0;
+        if (_impl->dt < 0 || gmx_within_tol(_impl->dt, 0.0, GMX_REAL_EPS))
+        {
+            GMX_THROW(APIError("Identical or decreasing frame times"));
+        }
+    }
+    else
+    {
+        if (!gmx_within_tol(x - _impl->t, _impl->dt, GMX_REAL_EPS))
+        {
+            GMX_THROW(APIError("Frames not evenly spaced"));
+        }
+    }
+    _impl->t = x;
+
+    // Allocate memory for all the positions once it is possible.
+    if (_impl->max_store == -1 && !_impl->bFirst)
+    {
+        _impl->max_store = _impl->nmax * (int)(_impl->tmax/_impl->dt + 1);
+        srenew(_impl->oldval, _impl->max_store);
+    }
+
+    // Increment the index where current positions are stored.
+    _impl->ci += _impl->nmax;
+    if (_impl->ci >= _impl->max_store)
+    {
+        _impl->ci = 0;
+    }
+
+/*
+    for (int i = 0; i < _impl->nmax; ++i)
+    {
+        _impl->p[_impl->ci + i].bPres = false;
+    }
+*/
+    _impl->nstored++;
+    _impl->bFirst = false;
+}
+
+
+void
+AnalysisDataDisplacementModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                            const real *y, const real *dy,
+                                            const bool *present)
+{
+    if (firstcol % _impl->ndim != 0 || n % _impl->ndim != 0)
+    {
+        GMX_THROW(APIError("Partial data points"));
+    }
+    for (int i = firstcol; i < firstcol + n; ++i)
+    {
+        _impl->oldval[_impl->ci + i] = y[i];
+    }
+}
+
+
+void
+AnalysisDataDisplacementModule::frameFinished()
+{
+    if (_impl->nstored <= 1)
+    {
+        return;
+    }
+
+    int step, i;
+    int rc;
+
+    if (_impl->nstored == 2)
+    {
+        if (_impl->histm)
+        {
+            _impl->histm->initNBins(0, _impl->dt,
+                                    _impl->max_store / _impl->nmax, true);
+        }
+        notifyDataStart();
+    }
+    notifyFrameStart(_impl->t, 0);
+
+    for (i = _impl->ci - _impl->nmax, step = 1;
+         step < _impl->nstored && i != _impl->ci;
+         i -= _impl->nmax, ++step)
+    {
+        if (i < 0)
+        {
+            i += _impl->max_store;
+        }
+        _impl->currd[0] = step * _impl->dt;
+        int k = 1;
+        for (int j = 0; j < _impl->nmax; j += _impl->ndim, ++k)
+        {
+            real dist2 = 0.0;
+
+            for (int d = 0; d < _impl->ndim; ++d)
+            {
+                dist2 += sqr(_impl->oldval[_impl->ci + j + d]
+                             - _impl->oldval[i + j + d]);
+            }
+            _impl->currd[k] = dist2;
+        }
+        notifyPointsAdd(0, k, _impl->currd, NULL, NULL);
+    }
+
+    notifyFrameFinish();
+}
+
+
+void
+AnalysisDataDisplacementModule::dataFinished()
+{
+    if (_impl->nstored >= 2)
+    {
+        notifyDataFinish();
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/modules/displacement.h b/src/gromacs/analysisdata/modules/displacement.h
new file mode 100644 (file)
index 0000000..9c44dc0
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AnalysisDataDisplacementModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_DISPLACEMENT_H
+#define GMX_ANALYSISDATA_MODULES_DISPLACEMENT_H
+
+#include "../analysisdata.h"
+#include "../datamodule.h"
+
+namespace gmx
+{
+
+class AnalysisDataBinAverageModule;
+
+/*! \brief
+ * Data module for calculating displacements.
+ *
+ * Output data contains a frame for each frame in the input data except the
+ * first one.  For each frame, there can be multiple points, each of which
+ * describes displacement for a certain time difference ending that that frame.
+ * The first column contains the time difference (backwards from the current
+ * frame), and the remaining columns the sizes of the displacements.
+ *
+ * Current implementation is not very generic, but should be easy to extend.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataDisplacementModule : public AbstractAnalysisData,
+                                       public AnalysisDataModuleInterface
+{
+    public:
+        AnalysisDataDisplacementModule();
+        virtual ~AnalysisDataDisplacementModule();
+
+        /*! \brief
+         * Sets the largest displacement time to be calculated.
+         */
+        void setMaxTime(real tmax);
+        /*! \brief
+         * Sets an histogram module that will receive a MSD histogram.
+         *
+         * If this function is not called, no histogram is calculated.
+         */
+        void setMSDHistogram(AnalysisDataBinAverageModule *histm);
+
+        virtual int frameCount() const;
+        virtual bool getDataWErr(int index, real *x, real *dx,
+                                 const real **y, const real **dy,
+                                 const bool **present = 0) const;
+        virtual bool requestStorage(int nframes = -1);
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/histogram.cpp b/src/gromacs/analysisdata/modules/histogram.cpp
new file mode 100644 (file)
index 0000000..220bfe3
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in histogram.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include "gromacs/analysisdata/modules/histogram.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cmath>
+
+#include <memory>
+
+// Legacy include.
+#include "smalloc.h"
+
+#include "gromacs/basicmath.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AbstractHistogramModule
+ */
+
+AbstractHistogramModule::AbstractHistogramModule()
+    : _hist(NULL), _averager(NULL), _nbins(0)
+{
+}
+
+AbstractHistogramModule::~AbstractHistogramModule()
+{
+    sfree(_hist);
+}
+
+
+void
+AbstractHistogramModule::initNBins(real miny, real binw, int nbins,
+                                   bool bIntegerBins)
+{
+    GMX_RELEASE_ASSERT(nbins > 0 && binw > 0, "Invalid histogram parameters");
+    if (bIntegerBins)
+    {
+        miny -= 0.5*binw;
+    }
+    _nbins    = nbins;
+    _miny     = miny;
+    _binwidth = binw;
+    _maxy     = miny + nbins * binw;
+    _invbw    = 1.0/binw;
+    setColumnCount(_nbins);
+}
+
+
+void
+AbstractHistogramModule::initRange(real miny, real maxy, real binw,
+                                   bool bIntegerBins)
+{
+    GMX_RELEASE_ASSERT(miny < maxy && binw > 0, "Invalid histogram parameters");
+    if (bIntegerBins)
+    {
+        _nbins = (int)ceil((maxy - miny) / binw) + 1;
+        miny -= 0.5 * binw;
+        maxy  = miny + _nbins * binw;
+    }
+    else
+    {
+        miny = binw * floor(miny / binw);
+        maxy = binw * ceil(maxy / binw);
+        if (miny != 0)
+        {
+            miny -= binw;
+        }
+        maxy += binw;
+        _nbins = (int)((maxy - miny) / binw + 0.5);
+    }
+    _miny     = miny;
+    _maxy     = maxy;
+    _binwidth = binw;
+    _invbw    = 1.0/binw;
+    setColumnCount(_nbins);
+}
+
+
+void
+AbstractHistogramModule::setAll(bool bAll)
+{
+    _bAll = bAll;
+}
+
+
+int
+AbstractHistogramModule::findBin(real y) const
+{
+    if (y < _miny)
+    {
+        return _bAll ? 0 : -1;
+    }
+    else if (y >= _maxy)
+    {
+        return _bAll ? _nbins-1 : -1;
+    }
+    return (int)((y - _miny) * _invbw);
+}
+
+
+HistogramAverageModule *
+AbstractHistogramModule::averager()
+{
+    if (!_averager)
+    {
+        createAverager();
+    }
+    return _averager;
+}
+
+
+int
+AbstractHistogramModule::flags() const
+{
+    return efAllowMultipoint;
+}
+
+
+void
+AbstractHistogramModule::dataStarted(AbstractAnalysisData *data)
+{
+    if (!_averager)
+    {
+        createAverager();
+    }
+    _averager->setXAxis(_miny + 0.5 * _binwidth, _binwidth);
+    snew(_hist, nbins());
+    startDataStore();
+}
+
+
+void
+AbstractHistogramModule::frameStarted(real x, real dx)
+{
+    for (int i = 0; i < nbins(); ++i)
+    {
+        _hist[i] = 0.0;
+    }
+    startNextFrame(x, dx);
+}
+
+
+void
+AbstractHistogramModule::frameFinished()
+{
+    storeThisFrame(_hist, NULL, NULL);
+}
+
+
+void
+AbstractHistogramModule::dataFinished()
+{
+    notifyDataFinish();
+}
+
+
+void
+AbstractHistogramModule::createAverager()
+{
+    _averager = new HistogramAverageModule();
+    addModule(_averager);
+    _averager->setXAxis(_miny + 0.5 * _binwidth, _binwidth);
+}
+
+
+/********************************************************************
+ * HistogramAverageModule
+ */
+
+HistogramAverageModule::HistogramAverageModule()
+    : _nframes(0), _bIgnoreMissing(false)
+{
+    setColumnCount(2);
+}
+
+
+void
+HistogramAverageModule::setIgnoreMissing(bool bIgnoreMissing)
+{
+    _bIgnoreMissing = bIgnoreMissing;
+    setColumnCount(bIgnoreMissing ? 3 : 2);
+}
+
+
+int
+HistogramAverageModule::flags() const
+{
+    return efAllowMulticolumn | efAllowMissing;
+}
+
+
+void
+HistogramAverageModule::dataStarted(AbstractAnalysisData *data)
+{
+    setRowCount(data->columnCount());
+}
+
+
+void
+HistogramAverageModule::frameStarted(real /*x*/, real /*dx*/)
+{
+}
+
+
+void
+HistogramAverageModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                    const real *y, const real *dy,
+                                    const bool *present)
+{
+    for (int i = 0; i < n; ++i)
+    {
+        value(firstcol + i, 0) += y[i];
+        value(firstcol + i, 1) += y[i] * y[i];
+    }
+    if (_bIgnoreMissing)
+    {
+        GMX_ASSERT(present != NULL, "Required data not available");
+        for (int i = 0; i < n; ++i)
+        {
+            if (present[i])
+            {
+                value(firstcol + i, 2) += 1;
+            }
+        }
+    }
+}
+
+
+void
+HistogramAverageModule::frameFinished()
+{
+    ++_nframes;
+}
+
+
+void
+HistogramAverageModule::dataFinished()
+{
+    for (int i = 0; i < rowCount(); ++i)
+    {
+        real ave = 0.0;
+        real std = 0.0;
+        if (_bIgnoreMissing)
+        {
+            if (value(i, 2) > 0)
+            {
+                ave = value(i, 0) / value(i, 2);
+                std = sqrt(value(i, 1) / value(i, 2) - ave * ave);
+            }
+        }
+        else
+        {
+            ave = value(i, 0) / _nframes;
+            std = sqrt(value(i, 1) / _nframes - ave * ave);
+        }
+        setValue(i, 0, ave);
+        setValue(i, 1, std);
+    }
+}
+
+
+HistogramAverageModule *
+HistogramAverageModule::resampleDoubleBinWidth(bool bIntegerBins) const
+{
+    std::auto_ptr<HistogramAverageModule> dest(new HistogramAverageModule());
+    int nbins = rowCount() / 2;
+    dest->setRowCount(nbins);
+    real minx = xstart() + xstep() / 2;
+    if (bIntegerBins)
+    {
+        minx -= xstep();
+    }
+    dest->setXAxis(minx, xstep() * 2);
+
+    int  i, j;
+    for (i = j = 0; i < nbins; ++i)
+    {
+        real  v, ve;
+        if (bIntegerBins && i == 0)
+        {
+            v  = value(0, 0);
+            ve = sqr(value(0, 1));
+            ++j;
+        }
+        else
+        {
+            v  =     value(j, 0)  +     value(j+1, 0);
+            ve = sqr(value(j, 1)) + sqr(value(j+1, 1));
+            j += 2;
+        }
+        ve = sqrt(ve);
+        dest->setValue(i, 0, v);
+        dest->setValue(i, 1, ve);
+    }
+    return dest.release();
+}
+
+
+HistogramAverageModule *
+HistogramAverageModule::clone() const
+{
+    std::auto_ptr<HistogramAverageModule> dest(new HistogramAverageModule());
+    copyContents(this, dest.get());
+    return dest.release();
+}
+
+
+void
+HistogramAverageModule::normalizeProbability()
+{
+    real sum = 0;
+    for (int i = 0; i < rowCount(); ++i)
+    {
+        sum += value(i, 0);
+    }
+    scale(1.0 / (sum * xstep()));
+}
+
+
+void
+HistogramAverageModule::scale(real norm)
+{
+    for (int i = 0; i < rowCount(); ++i)
+    {
+        value(i, 0) *= norm;
+        value(i, 1) *= norm;
+    }
+}
+
+
+void
+HistogramAverageModule::scaleVector(real norm[])
+{
+    for (int i = 0; i < rowCount(); ++i)
+    {
+        value(i, 0) *= norm[i];
+        value(i, 1) *= norm[i];
+    }
+}
+
+
+/********************************************************************
+ * AnalysisDataSimpleHistogramModule
+ */
+
+void
+AnalysisDataSimpleHistogramModule::pointsAdded(real /*x*/, real /*dx*/,
+                                               int /*firstcol*/, int n,
+                                               const real *y, const real * /*dy*/,
+                                               const bool * /*present*/)
+{
+    for (int i = 0; i < n; ++i)
+    {
+        int bin = findBin(y[i]);
+        _hist[bin] += 1;
+    }
+}
+
+
+/********************************************************************
+ * AnalysisDataWeightedHistogramModule
+ */
+
+int
+AnalysisDataWeightedHistogramModule::flags() const
+{
+    return AbstractHistogramModule::flags() | efAllowMulticolumn;
+}
+
+
+void
+AnalysisDataWeightedHistogramModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                                 const real *y, const real *dy,
+                                                 const bool *present)
+{
+    if (firstcol != 0 || n < 2)
+    {
+        GMX_THROW(APIError("Invalid data layout"));
+    }
+    int bin = findBin(y[0]);
+    for (int i = 1; i < n; ++i)
+    {
+        _hist[bin] += y[i];
+    }
+}
+
+
+/********************************************************************
+ * AnalysisDataBinAverageModule
+ */
+
+AnalysisDataBinAverageModule::AnalysisDataBinAverageModule()
+    : _n(NULL), _present(NULL), _bIgnoreMissing(false)
+{
+}
+
+AnalysisDataBinAverageModule::~AnalysisDataBinAverageModule()
+{
+    sfree(_n);
+    sfree(_present);
+}
+
+
+void
+AnalysisDataBinAverageModule::setIgnoreMissing(bool bIgnoreMissing)
+{
+    // Changes can only be made before there is data.
+    GMX_RELEASE_ASSERT(_n == NULL, "Cannot make changes after data is allocated");
+    _bIgnoreMissing = bIgnoreMissing;
+    averager()->setIgnoreMissing(bIgnoreMissing);
+}
+
+
+int
+AnalysisDataBinAverageModule::flags() const
+{
+    return AbstractHistogramModule::flags() | efAllowMulticolumn;
+}
+
+
+void
+AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData *data)
+{
+    snew(_n, nbins());
+    snew(_present, nbins());
+    AbstractHistogramModule::dataStarted(data);
+}
+
+
+void
+AnalysisDataBinAverageModule::frameStarted(real x, real dx)
+{
+    for (int i = 0; i < nbins(); ++i)
+    {
+        _n[i] = 0;
+    }
+    AbstractHistogramModule::frameStarted(x, dx);
+}
+
+
+void
+AnalysisDataBinAverageModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                          const real *y, const real *dy,
+                                          const bool *present)
+{
+    if (firstcol != 0 || n < 2)
+    {
+        GMX_THROW(APIError("Invalid data layout"));
+    }
+    int bin = findBin(y[0]);
+    for (int i = 1; i < n; ++i)
+    {
+        _hist[bin] += y[i];
+    }
+    _n[bin] += n - 1;
+}
+
+
+void
+AnalysisDataBinAverageModule::frameFinished()
+{
+    for (int i = 0; i < nbins(); ++i)
+    {
+        _present[i] = (_n[i] > 0);
+        if (_n[i] > 0)
+        {
+            _hist[i] /= _n[i];
+        }
+    }
+    if (!_bIgnoreMissing)
+    {
+        AbstractHistogramModule::frameFinished();
+    }
+    storeThisFrame(_hist, NULL, _present);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/modules/histogram.h b/src/gromacs/analysisdata/modules/histogram.h
new file mode 100644 (file)
index 0000000..e6bc67e
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares analysis data modules for calculating histograms.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_HISTOGRAM_H
+#define GMX_ANALYSISDATA_MODULES_HISTOGRAM_H
+
+#include "../analysisdata.h"
+#include "../arraydata.h"
+#include "../datamodule.h"
+
+namespace gmx
+{
+
+class HistogramAverageModule;
+
+/*! \brief
+ * Abstract base class for per-frame histogram modules.
+ *
+ * \ingroup module_analysisdata
+ */
+class AbstractHistogramModule : public AbstractAnalysisDataStored,
+                                public AnalysisDataModuleInterface
+{
+    public:
+        virtual ~AbstractHistogramModule();
+
+        /*! \brief
+         * Initializes the histogram using bin width and the number of bins.
+         */
+        void initNBins(real miny, real binw, int nbins,
+                       bool bIntegerBins = false);
+        /*! \brief
+         * Initializes the histogram using a range and a bin width.
+         */
+        void initRange(real miny, real maxy, real binw,
+                       bool bIntegerBins = false);
+        /*! \brief
+         * Sets the histogram to match all values.
+         *
+         * If \p bAll is true, the histogram behaves as if the bins at the ends
+         * extended to +-infinity.
+         */
+        void setAll(bool bAll);
+
+        /*! \brief
+         * Returns the average histogram over all frames.
+         *
+         * Can be called already before the histogram is calculated to
+         * customize the way the average histogram is calculated.
+         *
+         * \see HistogramAverageModule
+         */
+        HistogramAverageModule *averager();
+
+        //! Returns the number of bins in the histogram.
+        int nbins() const { return _nbins; }
+        //! Returns the width of a bin in the histogram.
+        real binwidth() const { return _binwidth; }
+        //! Returns a zero-based bin index for a value, or -1 if not in range.
+        int findBin(real y) const;
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present) = 0;
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+    protected:
+        AbstractHistogramModule();
+
+        //! Actual histogram data.
+        real                   *_hist;
+
+    private:
+        void createAverager();
+
+        HistogramAverageModule *_averager;
+        int                     _nbins;
+        real                    _miny;
+        real                    _maxy;
+        real                    _binwidth;
+        real                    _invbw;
+        bool                    _bAll;
+
+        // Copy and assign disallowed by base.
+};
+
+
+/*! \brief
+ * Data module for averaging histograms over frames.
+ *
+ * The averaging module for a per-frame histogram is always created by the
+ * AbstractHistogramModule class, and can be accessed using
+ * AbstractHistogramModule::averager().
+ * The user can alter some properties of the average histogram directly, but
+ * the main use of the object is to postprocess the histogram once the
+ * calculation is finished.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class HistogramAverageModule : public AbstractAnalysisArrayData,
+                               public AnalysisDataModuleInterface
+{
+    public:
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+        /*! \brief
+         * Sets the averager to ignore missing values.
+         */
+        void setIgnoreMissing(bool bIgnoreMissing);
+
+        /*! \brief
+         * Creates a copy of the histogram with double the bin width.
+         */
+        HistogramAverageModule *resampleDoubleBinWidth(bool bIntegerBins) const;
+        //! Creates a deep copy of the histogram.
+        HistogramAverageModule *clone() const;
+        //! Normalizes the histogram such that the integral over it is one.
+        void normalizeProbability();
+        //! Scales the value of each bin by an uniform scaling factor.
+        void scale(real norm);
+        //! Scales the value of each bin by a different scaling factor.
+        void scaleVector(real norm[]);
+        /*! \brief
+         * Notifies attached modules of the histogram data.
+         *
+         * After this function has been called, it is no longer possible to
+         * alter the histogram.
+         */
+        void done() { AbstractAnalysisArrayData::valuesReady(); }
+
+    private:
+        HistogramAverageModule();
+
+        int                     _nframes;
+        bool                    _bIgnoreMissing;
+
+        friend class AbstractHistogramModule;
+
+        // Copy and assign disallowed by base.
+};
+
+
+/*! \brief
+ * Data module for per-frame histograms.
+ *
+ * Output data contains the same number of frames as the input data.
+ * Each frame contains the histogram for the points in that frame.
+ * All input columns are averaged into the same histogram.
+ * The number of columns equals the number of bins in the histogram.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataSimpleHistogramModule : public AbstractHistogramModule
+{
+    public:
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+
+        // Copy and assign disallowed by base.
+};
+
+
+/*! \brief
+ * Data module for per-frame weighted histograms.
+ *
+ * Output data contains the same number of frames as the input data.
+ * Each frame contains the histogram for the points in that frame, interpreted
+ * such that the first column passed to pointsAdded() determines the bin and
+ * the rest give weights to be added to that bin (input data should have at
+ * least two colums, and at least two columns should be added at the same time).
+ * All input columns are averaged into the same histogram.
+ * The number of columns equals the number of bins in the histogram.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataWeightedHistogramModule : public AbstractHistogramModule
+{
+    public:
+        virtual int flags() const;
+
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+
+        // Copy and assign disallowed by base.
+};
+
+
+/*! \brief
+ * Data module for per-frame bin averages.
+ *
+ * Output data contains the same number of frames as the input data.
+ * Each frame contains the average for the points in that frame within each bin.
+ * The input data is interpreted such that the first column passed to
+ * pointsAdded() determines the bin and the rest give values to be added to
+ * that bin (input data should have at least two colums, and at least two
+ * columns should be added at the same time).
+ * All input columns are averaged into the same histogram.
+ * The number of columns equals the number of bins.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataBinAverageModule : public AbstractHistogramModule
+{
+    public:
+        AnalysisDataBinAverageModule();
+        virtual ~AnalysisDataBinAverageModule();
+
+        //! Ignore missing bins in the average histogram.
+        void setIgnoreMissing(bool bIgnoreMissing);
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+        virtual void frameFinished();
+
+    private:
+        int                    *_n;
+        bool                   *_present;
+        bool                    _bIgnoreMissing;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/plot-impl.h b/src/gromacs/analysisdata/modules/plot-impl.h
new file mode 100644 (file)
index 0000000..c46c387
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::AbstractPlotModule.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_PLOT_IMPL_H
+#define GMX_ANALYSISDATA_MODULES_PLOT_IMPL_H
+
+#include <string>
+#include <vector>
+
+#include "plot.h"
+
+namespace gmx
+{
+
+class Options;
+
+class AbstractPlotModule::Impl
+{
+    public:
+        explicit Impl(const Options &options);
+        ~Impl();
+
+        void closeFile();
+
+        std::string             fnm;
+        FILE                   *fp;
+
+        bool                    bPlain;
+        bool                    bOmitX;
+        output_env_t            oenv;
+        SelectionCollection    *sel;
+        std::string             title;
+        std::string             subtitle;
+        std::string             xlabel;
+        std::string             ylabel;
+        std::vector<std::string>  leg;
+        char                    xfmt[15];
+        char                    yfmt[15];
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/modules/plot.cpp b/src/gromacs/analysisdata/modules/plot.cpp
new file mode 100644 (file)
index 0000000..a378261
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in plot.h.
+ *
+ * \ingroup module_analysisdata
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#include "gromacs/analysisdata/modules/plot.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string>
+#include <vector>
+
+#include <cstdio>
+#include <cstring>
+
+#include <gmxfio.h>
+#include <statutil.h>
+#include <vec.h>
+#include <xvgr.h>
+
+// FIXME: This kind of trickery should not be necessary...
+#undef min
+#undef max
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/selection/selectioncollection.h"
+
+#include "plot-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AbstractPlotModule::Impl
+ */
+
+AbstractPlotModule::Impl::Impl(const Options &options)
+    : fp(NULL), bPlain(false), bOmitX(false),
+      oenv(options.globalProperties().output_env()),
+      sel(options.globalProperties().selectionCollection())
+{
+    strcpy(xfmt, "%11.3f");
+    strcpy(yfmt, " %8.3f");
+}
+
+AbstractPlotModule::Impl::~Impl()
+{
+    closeFile();
+}
+
+
+void
+AbstractPlotModule::Impl::closeFile()
+{
+    if (fp != NULL)
+    {
+        if (bPlain)
+        {
+            gmx_fio_fclose(fp);
+        }
+        else
+        {
+            xvgrclose(fp);
+        }
+        fp = NULL;
+    }
+}
+
+
+/********************************************************************
+ * AbstractPlotModule
+ */
+
+AbstractPlotModule::AbstractPlotModule(const Options &options)
+    : _impl(new Impl(options))
+{
+}
+
+
+AbstractPlotModule::~AbstractPlotModule()
+{
+    delete _impl;
+}
+
+
+void
+AbstractPlotModule::setFileName(const std::string &fnm)
+{
+    _impl->fnm = fnm;
+}
+
+
+void
+AbstractPlotModule::setPlainOutput(bool bPlain)
+{
+    _impl->bPlain = bPlain;
+}
+
+
+void
+AbstractPlotModule::setOmitX(bool bOmitX)
+{
+    _impl->bOmitX = bOmitX;
+}
+
+
+void
+AbstractPlotModule::setTitle(const char *title)
+{
+    _impl->title = title;
+}
+
+
+void
+AbstractPlotModule::setSubtitle(const char *subtitle)
+{
+    _impl->subtitle = subtitle;
+}
+
+
+void
+AbstractPlotModule::setXLabel(const char *label)
+{
+    _impl->xlabel = label;
+}
+
+
+void
+AbstractPlotModule::setXTimeLabel()
+{
+    _impl->xlabel = output_env_get_xvgr_tlabel(_impl->oenv);
+}
+
+
+void
+AbstractPlotModule::setYLabel(const char *label)
+{
+    _impl->ylabel = label;
+}
+
+
+void
+AbstractPlotModule::setLegend(int nsets, const char * const *setname)
+{
+    _impl->leg.reserve(_impl->leg.size() + nsets);
+    for (int i = 0; i < nsets; ++i)
+    {
+        appendLegend(setname[i]);
+    }
+}
+
+
+void
+AbstractPlotModule::appendLegend(const char *setname)
+{
+    _impl->leg.push_back(setname);
+}
+
+
+void
+AbstractPlotModule::setXFormat(int width, int prec, char fmt)
+{
+    GMX_RELEASE_ASSERT(width >= 0 && prec >= 0 && width <= 99 && prec <= 99,
+                       "Invalid width or precision");
+    GMX_RELEASE_ASSERT(strchr("eEfFgG", fmt) != NULL,
+                       "Invalid format specifier");
+    sprintf(_impl->xfmt, "%%%d.%d%c", width, prec, fmt);
+}
+
+
+void
+AbstractPlotModule::setYFormat(int width, int prec, char fmt)
+{
+    GMX_RELEASE_ASSERT(width >= 0 && prec >= 0 && width <= 99 && prec <= 99,
+                       "Invalid width or precision");
+    GMX_RELEASE_ASSERT(strchr("eEfFgG", fmt) != NULL,
+                       "Invalid format specifier");
+    sprintf(_impl->yfmt, " %%%d.%d%c", width, prec, fmt);
+}
+
+
+int
+AbstractPlotModule::flags() const
+{
+    return efAllowMulticolumn | efAllowMultipoint;
+}
+
+
+void
+AbstractPlotModule::dataStarted(AbstractAnalysisData *data)
+{
+    if (!_impl->fnm.empty())
+    {
+        if (_impl->bPlain)
+        {
+            _impl->fp = gmx_fio_fopen(_impl->fnm.c_str(), "w");
+        }
+        else
+        {
+            _impl->fp = xvgropen(_impl->fnm.c_str(), _impl->title.c_str(),
+                                 _impl->xlabel.c_str(), _impl->ylabel.c_str(),
+                                 _impl->oenv);
+            if (_impl->sel != NULL)
+            {
+                _impl->sel->printXvgrInfo(_impl->fp, _impl->oenv);
+            }
+            if (!_impl->subtitle.empty())
+            {
+                xvgr_subtitle(_impl->fp, _impl->subtitle.c_str(), _impl->oenv);
+            }
+            if (output_env_get_print_xvgr_codes(_impl->oenv)
+                && !_impl->leg.empty())
+            {
+                const char **leg;
+
+                leg = new const char *[_impl->leg.size()];
+                for (size_t i = 0; i < _impl->leg.size(); ++i)
+                {
+                    leg[i] = _impl->leg[i].c_str();
+                }
+                xvgr_legend(_impl->fp, _impl->leg.size(), leg, _impl->oenv);
+                delete [] leg;
+            }
+        }
+    }
+}
+
+
+void
+AbstractPlotModule::frameStarted(real x, real dx)
+{
+    if (!isFileOpen())
+    {
+        return;
+    }
+    if (!_impl->bOmitX)
+    {
+        std::fprintf(_impl->fp, _impl->xfmt, x);
+    }
+}
+
+
+void
+AbstractPlotModule::frameFinished()
+{
+    if (!isFileOpen())
+    {
+        return;
+    }
+    std::fprintf(_impl->fp, "\n");
+}
+
+
+void
+AbstractPlotModule::dataFinished()
+{
+    _impl->closeFile();
+}
+
+
+bool
+AbstractPlotModule::isFileOpen() const
+{
+    return _impl->fp != NULL;
+}
+
+
+void
+AbstractPlotModule::writeValue(real value) const
+{
+    GMX_ASSERT(isFileOpen(), "File not opened, but write attempted");
+    std::fprintf(_impl->fp, _impl->yfmt, value);
+}
+
+
+/********************************************************************
+ * DataPlotModule
+ */
+
+AnalysisDataPlotModule::AnalysisDataPlotModule(const Options &options)
+    : AbstractPlotModule(options)
+{
+}
+
+
+void
+AnalysisDataPlotModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                    const real *y, const real *dy,
+                                    const bool *present)
+{
+    if (!isFileOpen())
+    {
+        return;
+    }
+    for (int i = 0; i < n; ++i)
+    {
+        writeValue(y[i]);
+    }
+}
+
+
+/********************************************************************
+ * DataVectorPlotModule
+ */
+
+AnalysisDataVectorPlotModule::AnalysisDataVectorPlotModule(const Options &options)
+    : AbstractPlotModule(options)
+{
+    for (int i = 0; i < DIM; ++i)
+    {
+        _bWrite[i] = true;
+    }
+    _bWrite[DIM] = false;
+}
+
+
+void
+AnalysisDataVectorPlotModule::setWriteX(bool bWrite)
+{
+    _bWrite[XX] = bWrite;
+}
+
+
+void
+AnalysisDataVectorPlotModule::setWriteY(bool bWrite)
+{
+    _bWrite[YY] = bWrite;
+}
+
+
+void
+AnalysisDataVectorPlotModule::setWriteZ(bool bWrite)
+{
+    _bWrite[ZZ] = bWrite;
+}
+
+
+void
+AnalysisDataVectorPlotModule::setWriteNorm(bool bWrite)
+{
+    _bWrite[DIM] = bWrite;
+}
+
+
+void
+AnalysisDataVectorPlotModule::setWriteMask(bool bWrite[DIM + 1])
+{
+    for (int i = 0; i < DIM + 1; ++i)
+    {
+        _bWrite[i] = bWrite[i];
+    }
+}
+
+
+void
+AnalysisDataVectorPlotModule::pointsAdded(real x, real dx, int firstcol, int n,
+                                          const real *y, const real *dy,
+                                          const bool *present)
+{
+    if (firstcol % DIM != 0)
+    {
+        GMX_THROW(APIError("Partial data points"));
+    }
+    if (!isFileOpen())
+    {
+        return;
+    }
+    for (int i = 0; i < n; i += 3)
+    {
+        for (int d = 0; d < DIM; ++d)
+        {
+            if (_bWrite[i])
+            {
+                writeValue(y[i + d]);
+            }
+        }
+        if (_bWrite[DIM])
+        {
+            writeValue(norm(&y[i]));
+        }
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/analysisdata/modules/plot.h b/src/gromacs/analysisdata/modules/plot.h
new file mode 100644 (file)
index 0000000..6145117
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AnalysisDataPlotModule for plotting data (into a file).
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#ifndef GMX_ANALYSISDATA_MODULES_PLOT_H
+#define GMX_ANALYSISDATA_MODULES_PLOT_H
+
+#include <string>
+
+#include "../datamodule.h"
+
+namespace gmx
+{
+
+class Options;
+
+/*! \brief
+ * Abstract data module for writing data into a file.
+ *
+ * Implements features common to all plotting modules.  Subclasses implement
+ * features specific to certain applications (AnalysisDataPlotModule implements
+ * straightforward plotting).
+ *
+ * By default, the data is written into an xvgr file, according to the
+ * options read from the Options object given to the constructor.
+ * For non-xvgr data, it's possible to skip all headers by calling
+ * setPlainOutput().
+ *
+ * Multipoint data is supported, in which case all the points are written to
+ * the output, in the order in which they are added to the data.  A single
+ * output line corresponds to a single frame.  In most cases with multipoint
+ * data, setPlainOutput() should be called since the output does not make sense
+ * as an xvgr file, but this is not enforced.
+ *
+ * \ingroup module_analysisdata
+ */
+class AbstractPlotModule : public AnalysisDataModuleInterface
+{
+    public:
+        virtual ~AbstractPlotModule();
+
+        /*! \brief
+         * Set the output file name.
+         *
+         * If no file name is set (or if \p fnm is NULL), no output occurs.
+         */
+        void setFileName(const std::string &fnm);
+        /*! \brief
+         * Set plain output.
+         *
+         * If \p bPlain is true, no xvgr headers are written to the file.
+         * In this case, only setOmitX(), setXFormat(), and setYFormat()
+         * methods have any effect on the output.
+         */
+        void setPlainOutput(bool bPlain);
+        /*! \brief
+         * Omit the X coordinates from the output.
+         *
+         * This method only makes sense when combined with setPlainOutput().
+         */
+        void setOmitX(bool bOmitX);
+        /*! \brief
+         * Set plot title.
+         */
+        void setTitle(const char *title);
+        /*! \brief
+         * Set plot subtitle.
+         */
+        void setSubtitle(const char *subtitle);
+        /*! \brief
+         * Set X axis label.
+         */
+        void setXLabel(const char *label);
+        /*! \brief
+         * Set X axis label for time.
+         */
+        void setXTimeLabel();
+        /*! \brief
+         * Set Y axis label.
+         */
+        void setYLabel(const char *label);
+        /*! \brief
+         * Add legend from an array of strings.
+         *
+         * Multiple calls to setLegend() and/or appendLegend() are added
+         * together.
+         */
+        void setLegend(int nsets, const char * const *setname);
+        /*! \brief
+         * Add a legend string for the next data set.
+         *
+         * Multiple calls to setLegend() and/or appendLegend() are added
+         * together.
+         */
+        void appendLegend(const char *setname);
+        /*! \brief
+         * Set field width and precision for X value output.
+         */
+        void setXFormat(int width, int prec, char fmt = 'f');
+        /*! \brief
+         * Set field width and precision for Y value output.
+         */
+        void setYFormat(int width, int prec, char fmt = 'f');
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present) = 0;
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+    protected:
+        /*! \cond libapi */
+        explicit AbstractPlotModule(const Options &options);
+
+        bool isFileOpen() const;
+        void writeValue(real value) const;
+        //! \endcond
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        AbstractPlotModule(const AbstractPlotModule &);
+        void operator =(const AbstractPlotModule &);
+};
+
+
+/*! \brief
+ * Plotting module for straightforward plotting of data.
+ *
+ * See AbstractPlotModule for common plotting options.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataPlotModule : public AbstractPlotModule
+{
+    public:
+        explicit AnalysisDataPlotModule(const Options &options);
+
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+
+        // Copy and assign disallowed by base.
+};
+
+
+/*! \brief
+ * Plotting module specifically for data consisting of vectors.
+ *
+ * See AbstractPlotModule for common plotting options.
+ *
+ * \inpublicapi
+ * \ingroup module_analysisdata
+ */
+class AnalysisDataVectorPlotModule : public AbstractPlotModule
+{
+    public:
+        explicit AnalysisDataVectorPlotModule(const Options &options);
+
+        /*! \brief
+         * Set whether to write X component.
+         */
+        void setWriteX(bool bWrite);
+        /*! \brief
+         * Set whether to write Y component.
+         */
+        void setWriteY(bool bWrite);
+        /*! \brief
+         * Set whether to write Z component.
+         */
+        void setWriteZ(bool bWrite);
+        /*! \brief
+         * Set whether to write norm of the vector.
+         */
+        void setWriteNorm(bool bWrite);
+        /*! \brief
+         * Set mask for what to write.
+         */
+        void setWriteMask(bool bWrite[4]);
+
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+
+    private:
+        bool                    _bWrite[4];
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/analysisdata/tests/.gitignore b/src/gromacs/analysisdata/tests/.gitignore
new file mode 100644 (file)
index 0000000..0e75d4c
--- /dev/null
@@ -0,0 +1 @@
+analysisdata-tests
diff --git a/src/gromacs/analysisdata/tests/CMakeLists.txt b/src/gromacs/analysisdata/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..cb52398
--- /dev/null
@@ -0,0 +1,2 @@
+add_gmock_test(AnalysisDataUnitTests analysisdata-test
+               analysisdata.cpp)
diff --git a/src/gromacs/analysisdata/tests/analysisdata.cpp b/src/gromacs/analysisdata/tests/analysisdata.cpp
new file mode 100644 (file)
index 0000000..aeb294a
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests for analysis data functionality.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/fatalerror/exceptions.h"
+
+#include "mock_module.h"
+
+namespace
+{
+
+/********************************************************************
+ * Tests for gmx::AnalysisData.
+ */
+
+TEST(AnalysisDataTest, BasicInitialization)
+{
+    gmx::AnalysisData data;
+    EXPECT_EQ(0, data.columnCount());
+    EXPECT_FALSE(data.isMultipoint());
+    EXPECT_EQ(0, data.frameCount());
+
+    data.setColumns(1);
+    EXPECT_EQ(1, data.columnCount());
+    EXPECT_FALSE(data.isMultipoint());
+
+    data.setColumns(3, true);
+    EXPECT_EQ(3, data.columnCount());
+    EXPECT_TRUE(data.isMultipoint());
+
+    data.setColumns(1);
+    EXPECT_EQ(1, data.columnCount());
+    EXPECT_FALSE(data.isMultipoint());
+}
+
+
+TEST(AnalysisDataTest, ChecksMultiColumnModules)
+{
+    gmx::AnalysisData data;
+    data.setColumns(2);
+
+    std::auto_ptr<MockModule> mod(new MockModule(0));
+    EXPECT_THROW(data.addModule(mod.release()), gmx::APIError);
+
+    mod.reset(new MockModule(gmx::AnalysisDataModuleInterface::efAllowMulticolumn));
+    EXPECT_NO_THROW(data.addModule(mod.release()));
+}
+
+
+TEST(AnalysisDataTest, ChecksMultiPointModules)
+{
+    gmx::AnalysisData data;
+    data.setColumns(1, true);
+
+    std::auto_ptr<MockModule> mod(new MockModule(0));
+    EXPECT_THROW(data.addModule(mod.release()), gmx::APIError);
+
+    mod.reset(new MockModule(gmx::AnalysisDataModuleInterface::efAllowMultipoint));
+    EXPECT_NO_THROW(data.addModule(mod.release()));
+}
+
+
+TEST(AnalysisDataTest, CallsModuleCorrectly)
+{
+    gmx::AnalysisData data;
+    data.setColumns(1);
+
+    std::auto_ptr<MockModule> mod(new MockModule(0));
+    {
+        ::testing::InSequence dummy;
+        using ::testing::_;
+
+        EXPECT_CALL(*mod, dataStarted(&data));
+        EXPECT_CALL(*mod, frameStarted(1.0, 0.0));
+        EXPECT_CALL(*mod, pointsAdded(1.0, 0.0, 0, 1, _, _, _));
+        EXPECT_CALL(*mod, frameFinished());
+        EXPECT_CALL(*mod, frameStarted(2.0, 0.0));
+        EXPECT_CALL(*mod, pointsAdded(2.0, 0.0, 0, 1, _, _, _));
+        EXPECT_CALL(*mod, frameFinished());
+        EXPECT_CALL(*mod, frameStarted(3.0, 0.0));
+        EXPECT_CALL(*mod, pointsAdded(3.0, 0.0, 0, 1, _, _, _));
+        EXPECT_CALL(*mod, frameFinished());
+        EXPECT_CALL(*mod, dataFinished());
+    }
+    ASSERT_NO_THROW(data.addModule(mod.release()));
+
+    gmx::AnalysisDataHandle *dh = NULL;
+    ASSERT_NO_THROW(dh = data.startData(NULL));
+
+    ASSERT_NO_THROW(dh->startFrame(0, 1.0));
+    EXPECT_NO_THROW(dh->addPoint(0, 1.5));
+    EXPECT_NO_THROW(dh->finishFrame());
+    EXPECT_EQ(1, data.frameCount());
+
+    ASSERT_NO_THROW(dh->startFrame(1, 2.0));
+    EXPECT_NO_THROW(dh->addPoint(0, 2.5));
+    EXPECT_NO_THROW(dh->finishFrame());
+    EXPECT_EQ(2, data.frameCount());
+
+    ASSERT_NO_THROW(dh->startFrame(2, 3.0));
+    EXPECT_NO_THROW(dh->addPoint(0, 3.5));
+    EXPECT_NO_THROW(dh->finishFrame());
+    EXPECT_EQ(3, data.frameCount());
+
+    EXPECT_NO_THROW(data.finishData(dh));
+}
+
+} // namespace
diff --git a/src/gromacs/analysisdata/tests/mock_module.h b/src/gromacs/analysisdata/tests/mock_module.h
new file mode 100644 (file)
index 0000000..7d5062e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares mock implementation of gmx::AnalysisDataModuleInterface.
+ *
+ * Requires Google Mock.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_analysisdata
+ */
+#ifndef GMX_ANALYSISDATA_TESTS_MOCK_MODULE_H
+#define GMX_ANALYSISDATA_TESTS_MOCK_MODULE_H
+
+#include <gmock/gmock.h>
+
+#include "gromacs/analysisdata/datamodule.h"
+
+class MockModule : public gmx::AnalysisDataModuleInterface
+{
+    public:
+        explicit MockModule(int flags) : _flags(flags) {}
+
+        int flags() const { return _flags; }
+
+        MOCK_METHOD1(dataStarted, void(gmx::AbstractAnalysisData *data));
+        MOCK_METHOD2(frameStarted, void(real x, real dx));
+        MOCK_METHOD7(pointsAdded, void(real x, real dx, int firstcol, int n,
+                                       const real *y, const real *dy,
+                                       const bool *present));
+        MOCK_METHOD0(frameFinished, void());
+        MOCK_METHOD0(dataFinished, void());
+
+    private:
+        int         _flags;
+};
+
+#endif
diff --git a/src/gromacs/basicmath.h b/src/gromacs/basicmath.h
new file mode 100644 (file)
index 0000000..673b7fd
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+#ifndef GMX_BASICMATH_H
+#define GMX_BASICMATH_H
+
+#include <cmath>
+
+#include "types/simple.h"
+
+namespace gmx
+{
+
+template <typename T> static inline
+T sqr(const T &value)
+{
+    return value * value;
+}
+
+/*! \brief
+ * Check if two numbers are within a tolerance
+ *
+ * This routine checks if the relative difference between two numbers is
+ * approximately within the given tolerance, defined as
+ * fabs(f1-f2)<=tolerance*fabs(f1+f2).
+ *
+ * To check if two floating-point numbers are almost identical, use this routine
+ * with the tolerance GMX_REAL_EPS, or GMX_DOUBLE_EPS if the check should be
+ * done in double regardless of Gromacs precision.
+ *
+ * To check if two algorithms produce similar results you will normally need
+ * to relax the tolerance significantly since many operations (e.g. summation)
+ * accumulate floating point errors.
+ *
+ * \param f1  First number to compare
+ * \param f2  Second number to compare
+ * \param tol Tolerance to use
+ *
+ * \return 1 if the relative difference is within tolerance, 0 if not.
+ */
+static int
+gmx_within_tol(double   f1,
+               double   f2,
+               double   tol)
+{
+    /* The or-equal is important - otherwise we return false if f1==f2==0 */
+    if (std::fabs(f1-f2) <= tol * 0.5 * (std::fabs(f1) + std::fabs(f2)))
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+
+
+/*! \brief
+ * Check if a number is smaller than some preset safe minimum
+ * value, currently defined as GMX_REAL_MIN/GMX_REAL_EPS.
+ *
+ * If a number is smaller than this value we risk numerical overflow
+ * if any number larger than 1.0/GMX_REAL_EPS is divided by it.
+ *
+ * \return 1  if 'almost' numerically zero, 0 otherwise.
+ */
+static int
+gmx_numzero(double a)
+{
+  return gmx_within_tol(a,0.0,GMX_REAL_MIN/GMX_REAL_EPS);
+}
+
+}
+
+#endif
diff --git a/src/gromacs/fatalerror.h b/src/gromacs/fatalerror.h
new file mode 100644 (file)
index 0000000..ca611c3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \defgroup module_fatalerror Handling of Fatal Errors
+ * \ingroup group_utilitymodules
+ * \brief
+ * Provides functions for handling fatal errors.
+ *
+ * Exception classes used in the library are defined in the exceptions.h header
+ * file.  This header also declares a ::GMX_THROW macro that should be used for
+ * throwing exceptions.  It also declares helper functions formatErrorMessage()
+ * and translateException() for creating standard error messages and
+ * translating exceptions to error return codes.
+ *
+ * Use of error return codes should be avoided in new code except in C wrappers
+ * and similar, but for compatibility, facilities for handling them are
+ * provided by the errorcodes.h header file.  It provides a set of error codes
+ * (the enum ::ErrorCode) that should be used for return codes in functions.
+ * It also provides macros ::GMX_ERROR and ::GMX_ERROR_NORET that should be
+ * used for returning an error code.  setFatalErrorHandler() is provided to
+ * alter the behavior of ::GMX_ERROR and ::GMX_ERROR_NORET.  The default
+ * handler prints the reason of the error to standard error and aborts the
+ * execution.
+ *
+ * Header file gmxassert.h is also provided for assertions.  It declares macros
+ * ::GMX_ASSERT and ::GMX_RELEASE_ASSERT that should be used for assertions.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \file
+ * \brief
+ * Public API convenience header for fatal error handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_H
+#define GMX_FATALERROR_H
+
+#include "fatalerror/errorcodes.h"
+#include "fatalerror/exceptions.h"
+#include "fatalerror/gmxassert.h"
+
+#endif
diff --git a/src/gromacs/fatalerror/CMakeLists.txt b/src/gromacs/fatalerror/CMakeLists.txt
new file mode 100644 (file)
index 0000000..19efdfb
--- /dev/null
@@ -0,0 +1,8 @@
+file(GLOB FATALERROR_SOURCES *.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${FATALERROR_SOURCES} PARENT_SCOPE)
+
+set(FATALERROR_PUBLIC_HEADERS
+    errorcodes.h exceptions.h gmxassert.h)
+install(FILES ${FATALERROR_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/fatalerror
+        COMPONENT development)
diff --git a/src/gromacs/fatalerror/errorcodes.cpp b/src/gromacs/fatalerror/errorcodes.cpp
new file mode 100644 (file)
index 0000000..20ecf7c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in errorcodes.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#include "gromacs/fatalerror/errorcodes.h"
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+#include "errorformat.h"
+
+// This has to match the enum in fatalerror.h
+static const char *const error_names[] =
+{
+    "No error",
+    "Out of memory",
+    "File not found",
+    "System I/O error",
+    "Error in user input",
+    "Inconsistency in user input",
+    "Simulation instability detected",
+
+    "Feature not implemented",
+    "Invalid value (bug)",
+    "Invalid call (bug)",
+    "Internal error (bug)",
+    "API error (bug)",
+    "Range checking error (possible bug)",
+    "Communication error (possible bug)",
+
+    "Unknown error",
+};
+
+namespace gmx
+{
+
+const char *getErrorCodeString(int errorcode)
+{
+    if (errorcode < 0 || errorcode >= eeUnknownError)
+    {
+        errorcode = eeUnknownError;
+    }
+    return error_names[errorcode];
+}
+
+static void standardErrorHandler(int retcode, const char *msg,
+                                 const char *file, int line)
+{
+    const char *title = getErrorCodeString(retcode);
+    fprintf(stderr, "%s",
+            internal::formatFatalError(title, msg, NULL, file, line).c_str());
+    std::exit(1);
+}
+
+static ErrorHandlerFunc error_handler = standardErrorHandler;
+
+ErrorHandlerFunc setFatalErrorHandler(ErrorHandlerFunc handler)
+{
+    // TODO: Acquire a mutex here
+    ErrorHandlerFunc old_handler = error_handler;
+    error_handler = handler;
+    // TODO: Release the mutex here
+    return old_handler;
+}
+
+namespace internal
+{
+
+void fatalError(int retcode, const char *msg, const char *file, int line)
+{
+    // TODO: Acquire a mutex here
+    ErrorHandlerFunc handler = error_handler;
+    // TODO: Release the mutex here
+    if (handler != NULL)
+    {
+        handler(retcode, msg, file, line);
+    }
+}
+
+} // namespace internal
+
+} // namespace gmx
diff --git a/src/gromacs/fatalerror/errorcodes.h b/src/gromacs/fatalerror/errorcodes.h
new file mode 100644 (file)
index 0000000..366afa4
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares error codes and related functions for fatal error handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_ERRORCODES_H
+#define GMX_FATALERROR_ERRORCODES_H
+
+namespace gmx
+{
+
+/*! \addtopublicapi
+ * \{
+ */
+
+/*! \brief
+ * Possible error return codes from Gromacs functions.
+ */
+enum ErrorCode
+{
+    //! Zero for successful return.
+    eeOK,
+    //! Not enough memory to complete operation.
+    eeOutOfMemory,
+    //! Provided file could not be opened.
+    eeFileNotFound,
+    //! System I/O error.
+    eeFileIO,
+    //! Invalid user input (could not be understood).
+    eeInvalidInput,
+    //! Invalid user input (conflicting or unsupported settings).
+    eeInconsistentInput,
+    //! Simulation instability detected.
+    eeInstability,
+
+    // Error codes below are for internal error checking; if triggered, they
+    // should indicate a bug in the code.
+    //! Requested feature not yet implemented.
+    eeNotImplemented,
+    //! Input value violates API specification.
+    eeInvalidValue,
+    //! Invalid routine called or wrong calling sequence detected.
+    eeInvalidCall,
+    //! Internal consistency check failed.
+    eeInternalError,
+    //! API specification was violated.
+    eeAPIError,
+    //! Range consistency check failed.
+    eeRange,
+    //! Communication consistency check failed.
+    eeCommunication,
+
+    //! Unknown error detected.
+    eeUnknownError,
+};
+
+/*! \brief
+ * Returns a short string description of an error code.
+ *
+ * \param[in] errorcode Error code to retrieve the string for.
+ * \returns   A constant string corresponding to \p errorcode.
+ *
+ * If \p errorcode is not one of those defined for ::gmx::ErrorCode,
+ * the string corresponding to ::eeUnknownError is returned.
+ *
+ * This function does not throw.
+ */
+const char *getErrorCodeString(int errorcode);
+
+/*! \brief
+ * Callback function pointer type for error handlers.
+ *
+ * \param[in] retcode Code of the error that has occurred.
+ * \param[in] msg     More detailed description of the error.
+ * \param[in] file    Name of the file where the error occurred.
+ * \param[in] line    Line in \p file on which the error occurred.
+ */
+typedef void (*ErrorHandlerFunc)(int retcode, const char *msg,
+                                 const char *file, int line);
+
+/*! \brief
+ * Sets callback function for handling errors.
+ *
+ * \param[in] handler New error handler function.
+ * \returns   Old error handler function.
+ *
+ * The default error handler prints out the location and reason of the error to
+ * stderr, and then calls abort().
+ */
+ErrorHandlerFunc setFatalErrorHandler(ErrorHandlerFunc handler);
+
+/*! \brief
+ * Macro for raising an error and returning from a function.
+ *
+ * The function should return \c int ; if it doesn't, use GMX_ERROR_NORET.
+ */
+#define GMX_ERROR(retcode, msg) \
+    do { \
+        int _rc_internal = (retcode); \
+        ::gmx::internal::fatalError(_rc_internal, msg, __FILE__, __LINE__); \
+        return _rc_internal; \
+    } while (0)
+
+/*! \brief
+ * Macro for raising an error in a function that does not return \c int.
+ *
+ * \see GMX_ERROR
+ */
+#define GMX_ERROR_NORET(retcode, msg) \
+        ::gmx::internal::fatalError(retcode, msg, __FILE__, __LINE__)
+
+/*!\}*/
+
+/*! \cond internal */
+namespace internal
+{
+
+/*! \brief
+ * Raises a fatal error.
+ *
+ * \param[in] retcode Error code to raise.
+ * \param[in] msg     More detailed description of the error.
+ * \param[in] file    Name of the source file where the error occurred.
+ * \param[in] line    Line in \p file on which the error occurred.
+ *
+ * Should not be called directly, but instead through ::GMX_ERROR or
+ * ::GMX_ERROR_NORET.
+ *
+ * \ingroup module_fatalerror
+ */
+void fatalError(int retcode, const char *msg, const char *file, int line);
+
+} // namespace internal
+//! \endcond
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/fatalerror/errorformat.cpp b/src/gromacs/fatalerror/errorformat.cpp
new file mode 100644 (file)
index 0000000..4fe09b3
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions declared in errorformat.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#include "gromacs/fatalerror/errorformat.h"
+
+#include <string>
+
+#include "gromacs/legacyheaders/copyrite.h"
+#include "gromacs/legacyheaders/statutil.h"
+
+#include "gromacs/utility/format.h"
+
+namespace gmx
+{
+
+namespace internal
+{
+
+std::string formatFatalError(const char *title, const char *details,
+                             const char *func, const char *file, int line)
+{
+    std::string result;
+    result.append("\n-------------------------------------------------------\n");
+    // TODO: Make the program name work also for unit tests
+    result.append(formatString("Program %s, %s\n", "TEST", GromacsVersion()));
+    if (func != NULL)
+    {
+        result.append(formatString("In function %s\n", func));
+    }
+    // TODO: Strip away absolute paths from file names (CMake seems to generate those)
+    if (file != NULL)
+    {
+        result.append(formatString("Source file %s, line %d\n\n", file, line));
+    }
+    else
+    {
+        result.append("\n");
+    }
+    result.append(formatString("%s:\n%s\n", title, details));
+    result.append("For more information and tips for troubleshooting, please check the GROMACS\n"
+                  "website at http://www.gromacs.org/Documentation/Errors");
+    result.append("\n-------------------------------------------------------\n");
+    return result;
+}
+
+} // namespace internal
+
+} // namespace gmx
diff --git a/src/gromacs/fatalerror/errorformat.h b/src/gromacs/fatalerror/errorformat.h
new file mode 100644 (file)
index 0000000..36ab81d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares an internal helper function for formatting standard error messages.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_ERRORFORMAT_H
+#define GMX_FATALERROR_ERRORFORMAT_H
+
+#include <string>
+
+namespace gmx
+{
+
+namespace internal
+{
+
+/*! \internal \brief
+ * Formats common headers and footers for error messages.
+ *
+ * \ingroup module_fatalerror
+ */
+std::string formatFatalError(const char *title, const char *details,
+                             const char *func, const char *file, int line);
+
+} // namespace internal
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/fatalerror/exceptions.cpp b/src/gromacs/fatalerror/exceptions.cpp
new file mode 100644 (file)
index 0000000..3925af0
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes and functions in exceptions.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#include "gromacs/fatalerror/exceptions.h"
+
+#include <boost/exception/get_error_info.hpp>
+
+#include "gromacs/fatalerror/errorcodes.h"
+
+#include "errorformat.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * GromacsException
+ */
+
+GromacsException::GromacsException(const std::string &reason)
+{
+    *this << errinfo_message(reason);
+}
+
+const char *GromacsException::what() const throw()
+{
+    const std::string *msg = boost::get_error_info<errinfo_message>(*this);
+    return msg != NULL ? msg->c_str() : "No reason provided";
+}
+
+/********************************************************************
+ * Derived exception classes
+ */
+
+int FileIOError::errorCode() const
+{
+    return eeFileIO;
+}
+
+int InvalidInputError::errorCode() const
+{
+    return eeInvalidInput;
+}
+
+int InconsistentInputError::errorCode() const
+{
+    return eeInconsistentInput;
+}
+
+int SimulationInstabilityError::errorCode() const
+{
+    return eeInstability;
+}
+
+int InternalError::errorCode() const
+{
+    return eeInternalError;
+}
+
+int APIError::errorCode() const
+{
+    return eeAPIError;
+}
+
+int NotImplementedError::errorCode() const
+{
+    return eeNotImplemented;
+}
+
+
+/********************************************************************
+ * Global functions
+ */
+
+std::string formatErrorMessage(const std::exception &ex)
+{
+    const char *title = "Unknown exception";
+    const char *func = NULL;
+    const char *file = NULL;
+    int line = 0;
+    const GromacsException *gmxEx = dynamic_cast<const GromacsException *>(&ex);
+    // TODO: Also treat common standard exceptions
+    if (gmxEx != NULL)
+    {
+        title = getErrorCodeString(gmxEx->errorCode());
+        func = *boost::get_error_info<boost::throw_function>(*gmxEx);
+        file = *boost::get_error_info<boost::throw_file>(*gmxEx);
+        line = *boost::get_error_info<boost::throw_line>(*gmxEx);
+    }
+    return internal::formatFatalError(title, ex.what(), func, file, line);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/fatalerror/exceptions.h b/src/gromacs/fatalerror/exceptions.h
new file mode 100644 (file)
index 0000000..bdee78e
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares common exception classes for fatal error handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_EXCEPTIONS_H
+#define GMX_FATALERROR_EXCEPTIONS_H
+
+#include <exception>
+#include <string>
+
+#include <boost/exception/exception.hpp>
+#include <boost/exception/info.hpp>
+#include <boost/throw_exception.hpp>
+
+namespace gmx
+{
+
+/*! \brief
+ * Stores a user-friendly explanation for the reason of an exception.
+ *
+ * Typically, should not be used directly, but through the GromacsException
+ * class: it is initialized by the constructor, and can be accessed with
+ * GromacsException::what().
+ *
+ * \inlibraryapi
+ */
+typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;
+
+/*! \addtopublicapi
+ * \{
+ */
+
+/*! \brief
+ * Base class for all exception objects in Gromacs.
+ *
+ * Although boost recommends using virtual inheritance in exception hiearchies,
+ * it is not used here for two reasons:
+ * -# It is only useful when there is diamond inheritance, and that should
+ *    never occur in this exception hierarchy because this class is the only
+ *    instance of multiple inheritance (Gromacs programming guidelines prohibit
+ *    multiple inheritance from concrete classes, but it is unavoidable here
+ *    because of the design of boost::exception).
+ * -# Because the constructor takes an argument, virtual inheritance would
+ *    complicate any classes that inherit indirectly from this class.
+ *
+ * \ingroup module_fatalerror
+ */
+class GromacsException : public std::exception, public boost::exception
+{
+    public:
+        /*! \brief
+         * Returns the reason string for the exception.
+         *
+         * The return value is the string that was passed to the constructor.
+         */
+        virtual const char *what() const throw();
+        /*! \brief
+         * Returns the error code corresponding to the exception type.
+         */
+        virtual int errorCode() const = 0;
+
+    protected:
+        /*! \brief
+         * Creates an exception object with the provided detailed reason.
+         *
+         * \param[in] reason Detailed reason for the exception.
+         */
+        explicit GromacsException(const std::string &reason);
+};
+
+/*! \brief
+ * Exception class for file I/O errors.
+ *
+ * \ingroup module_fatalerror
+ */
+class FileIOError : public GromacsException
+{
+    public:
+        /*! \brief
+         * Creates an exception object with the provided detailed reason.
+         *
+         * \param[in] reason Detailed reason for the exception.
+         */
+        explicit FileIOError(const std::string &reason)
+            : GromacsException(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for user input errors.
+ *
+ * Derived classes should be used to indicate the nature of the error instead
+ * of throwing this class directly.
+ *
+ * \ingroup module_fatalerror
+ */
+class UserInputError : public GromacsException
+{
+    protected:
+        //! \copydoc FileIOError::FileIOError()
+        explicit UserInputError(const std::string &reason)
+            : GromacsException(reason) {}
+};
+
+/*! \brief
+ * Exception class for situations where user input cannot be parsed/understood.
+ *
+ * \ingroup module_fatalerror
+ */
+class InvalidInputError : public UserInputError
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit InvalidInputError(const std::string &reason)
+            : UserInputError(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for situations where user input is inconsistent.
+ *
+ * \ingroup module_fatalerror
+ */
+class InconsistentInputError : public UserInputError
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit InconsistentInputError(const std::string &reason)
+            : UserInputError(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for simulation instabilities.
+ *
+ * \ingroup module_fatalerror
+ */
+class SimulationInstabilityError : public GromacsException
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit SimulationInstabilityError(const std::string &reason)
+            : GromacsException(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for internal errors.
+ *
+ * \ingroup module_fatalerror
+ */
+class InternalError : public GromacsException
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit InternalError(const std::string &reason)
+            : GromacsException(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for incorrect use of an API.
+ *
+ * \ingroup module_fatalerror
+ */
+class APIError : public GromacsException
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit APIError(const std::string &reason)
+            : GromacsException(reason) {}
+
+        virtual int errorCode() const;
+};
+
+/*! \brief
+ * Exception class for use of an unimplemented feature.
+ *
+ * \ingroup module_fatalerror
+ */
+class NotImplementedError : public APIError
+{
+    public:
+        //! \copydoc FileIOError::FileIOError()
+        explicit NotImplementedError(const std::string &reason)
+            : APIError(reason) {}
+
+        virtual int errorCode() const;
+};
+
+
+/*! \brief
+ * Macro for throwing an exception.
+ *
+ * \param[in] e    Exception object to throw.
+ *
+ * Using this macro instead of \c throw directly makes it possible to uniformly
+ * attach information into the exception objects.
+ * \p e should evaluate to an instance of an object derived from
+ * GromacsException.
+ *
+ * Basic usage:
+ * \code
+if (value < 0)
+{
+    GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
+}
+ * \endcode
+ */
+#define GMX_THROW(e) \
+    BOOST_THROW_EXCEPTION((e))
+
+/*! \brief
+ * Formats a standard error message for reporting an error.
+ *
+ * Normal usage in Gromacs command-line programs is like this:
+ * \code
+int main(int argc, char *argv[])
+{
+    try
+    {
+        // The actual code for the program
+        return 0;
+    }
+    catch (std::exception &ex)
+    {
+        fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
+        return 1;
+    }
+}
+ * \endcode
+ */
+std::string formatErrorMessage(const std::exception &ex);
+
+/*! \brief
+ * Converts an exception into a return code.
+ */
+int translateException(const std::exception &ex);
+
+/*!\}*/
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/fatalerror/gmxassert.cpp b/src/gromacs/fatalerror/gmxassert.cpp
new file mode 100644 (file)
index 0000000..b8bb7f2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements assertion handlers.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#include "gromacs/fatalerror/gmxassert.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <string>
+
+#include "gromacs/utility/format.h"
+
+#include "errorformat.h"
+
+namespace gmx
+{
+
+namespace internal
+{
+
+void assertHandler(const char *condition, const char *msg,
+                   const char *func, const char *file, int line)
+{
+    std::string text =
+        formatFatalError("Assertion failed",
+                         formatString("Condition: %s\n%s", condition, msg).c_str(),
+                         func, file, line);
+    std::fprintf(stderr, "%s", text.c_str());
+    std::abort();
+}
+
+} // namespace internal
+
+} // namespace gmx
diff --git a/src/gromacs/fatalerror/gmxassert.h b/src/gromacs/fatalerror/gmxassert.h
new file mode 100644 (file)
index 0000000..24a8589
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Defines assert macros customized for Gromacs.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_GMXASSERT_H
+#define GMX_FATALERROR_GMXASSERT_H
+
+#include <boost/current_function.hpp>
+
+/*! \addtopublicapi
+ * \{
+ */
+
+/*! \brief
+ * Macro for asserts that should also be present in the release version.
+ *
+ * Regardless of NDEBUG, this macro checks \p condition, and if it is not true,
+ * it calls the assert handler.
+ *
+ * Although this macro currently calls abort() if the assertion fails, it
+ * should only be used in a context where it is safe to throw an exception to
+ * keep the option open.
+ */
+#define GMX_RELEASE_ASSERT(condition, msg) \
+    ((void) ((condition) ? (void)0 : \
+        ::gmx::internal::assertHandler(#condition, msg, \
+            BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)))
+/*! \def GMX_ASSERT
+ * \brief
+ * Macro for debug asserts.
+ *
+ * If NDEBUG is defined, this macro expands to nothing.
+ * If it is not defined, it will work exactly like ::GMX_RELEASE_ASSERT.
+ *
+ * \see ::GMX_RELEASE_ASSERT
+ */
+#ifdef NDEBUG
+#define GMX_ASSERT(condition, msg)
+#else
+#define GMX_ASSERT(condition, msg) GMX_RELEASE_ASSERT(condition, msg)
+#endif
+
+/*!\}*/
+
+namespace gmx
+{
+
+/*! \cond internal */
+namespace internal
+{
+
+/*! \brief
+ * Called when an assert fails.
+ *
+ * Should not be called directly, but instead through ::GMX_ASSERT or
+ * ::GMX_RELEASE_ASSERT.
+ *
+ * \ingroup module_fatalerror
+ */
+void assertHandler(const char *condition, const char *msg,
+                   const char *func, const char *file, int line);
+
+} // namespace internal
+//! \endcond
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/fatalerror/messagestringcollector.cpp b/src/gromacs/fatalerror/messagestringcollector.cpp
new file mode 100644 (file)
index 0000000..1016b81
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::MessageStringCollector.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_fatalerror
+ */
+#include "gromacs/fatalerror/messagestringcollector.h"
+
+#include <vector>
+
+#include "gromacs/fatalerror/gmxassert.h"
+
+namespace gmx
+{
+
+class MessageStringCollector::Impl
+{
+    public:
+        Impl() : prevContext_(0) {}
+
+        std::vector<std::string> contexts_;
+        std::string              text_;
+        size_t                   prevContext_;
+};
+
+MessageStringCollector::MessageStringCollector()
+    : impl_(new Impl)
+{
+}
+
+MessageStringCollector::~MessageStringCollector()
+{
+    delete impl_;
+}
+
+void MessageStringCollector::startContext(const char *name)
+{
+    impl_->contexts_.push_back(name);
+}
+
+void MessageStringCollector::append(const std::string &message)
+{
+    int indent = static_cast<int>(impl_->prevContext_ * 2);
+    if (!impl_->contexts_.empty())
+    {
+        std::vector<std::string>::const_iterator ci;
+        for (ci = impl_->contexts_.begin() + impl_->prevContext_;
+             ci != impl_->contexts_.end(); ++ci)
+        {
+            impl_->text_.append(indent, ' ');
+            impl_->text_.append(*ci);
+            impl_->text_.append("\n");
+            indent += 2;
+        }
+    }
+    impl_->prevContext_ = impl_->contexts_.size();
+
+    // TODO: Put this into a more generic helper, could be useful elsewhere
+    size_t pos = 0;
+    while (pos < message.size())
+    {
+        size_t nextpos = message.find_first_of('\n', pos);
+        impl_->text_.append(indent, ' ');
+        impl_->text_.append(message.substr(pos, nextpos - pos));
+        impl_->text_.append("\n");
+        if (nextpos == std::string::npos)
+        {
+            break;
+        }
+        pos = nextpos + 1;
+    }
+}
+
+void MessageStringCollector::finishContext()
+{
+    GMX_RELEASE_ASSERT(!impl_->contexts_.empty(),
+                       "finishContext() called without context");
+    impl_->contexts_.pop_back();
+    if (impl_->prevContext_ > impl_->contexts_.size())
+    {
+        impl_->prevContext_ = impl_->contexts_.size();
+    }
+}
+
+void MessageStringCollector::clear()
+{
+    impl_->contexts_.clear();
+    impl_->text_.clear();
+    impl_->prevContext_ = 0;
+}
+
+bool MessageStringCollector::isEmpty() const
+{
+    return impl_->text_.empty();
+}
+
+std::string MessageStringCollector::toString() const
+{
+    return impl_->text_;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/fatalerror/messagestringcollector.h b/src/gromacs/fatalerror/messagestringcollector.h
new file mode 100644 (file)
index 0000000..e84cd11
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares ::gmx::MessageStringCollector.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_fatalerror
+ */
+#ifndef GMX_FATALERROR_MESSAGESTRINGCOLLECTOR_H
+#define GMX_FATALERROR_MESSAGESTRINGCOLLECTOR_H
+
+#include <string>
+
+namespace gmx
+{
+
+/*! \libinternal \brief
+ * Helper class for collecting message strings, optionally with context.
+ *
+ * After strings have been collected, they can be formatted into one long
+ * string for, e.g., printing out or for including in an exception.
+ *
+ * \inlibraryapi
+ * \ingroup module_fatalerror
+ */
+class MessageStringCollector
+{
+    public:
+        MessageStringCollector();
+        ~MessageStringCollector();
+
+        /*! \brief
+         * Starts a context for messages.
+         *
+         * \param[in] name  Short description of the context.
+         *
+         * \see finishContext()
+         * \see MessageStringContext
+         */
+        void startContext(const char *name);
+        /*! \brief
+         * Convenience wrapper for startContext(const char *).
+         */
+        void startContext(const std::string &name)
+        { startContext(name.c_str()); }
+        /*! \brief
+         * Adds a new message.
+         */
+        void append(const char *message)
+        { append(std::string(message)); }
+        /*! \brief
+         * Adds a new message.
+         */
+        void append(const std::string &message);
+        /*! \brief
+         * Ends a context started with startContext().
+         *
+         * \see MessageStringContext
+         */
+        void finishContext();
+        /*! \brief
+         * Clears all collected messages.
+         */
+        void clear();
+
+        /*! \brief
+         * Returns true if any messages have been added.
+         *
+         * \returns true if append() has been called at least once.
+         *
+         * The return value is identical to \c toString().empty().
+         * Calls to startContext()/finishContext() only do not cause this
+         * function to return true.
+         */
+        bool isEmpty() const;
+        /*! \brief
+         * Returns all collected messages as one string.
+         */
+        std::string toString() const;
+
+    private:
+        class Impl;
+
+        Impl                   *impl_;
+};
+
+/*! \libinternal \brief
+ * Convenience class for creating a message context.
+ *
+ * This class provides a RAII-style interface to the
+ * MessageStringCollector::startContext() and
+ * MessageStringCollector::finishContext() methods: finishContext() is called
+ * upon destruction of the object.  This avoids the need to call
+ * MessageStringCollector::finishContext() on every possible exit point.
+ *
+ * Example usage:
+ * \code
+bool function(::gmx::MessageStringCollector *errors)
+{
+    ::gmx::MessageStringContext errcontext(errors, "In function()");
+    bool bOk = function2(errors);
+    bOk = function3(errors) && bOk;
+    // <more processing>
+    return bOk;
+}
+ * \endcode
+ *
+ * \see MessageStringCollector
+ * \inlibraryapi
+ * \ingroup module_fatalerror
+ */
+class MessageStringContext
+{
+    public:
+        /*! \brief
+         * Adds a context for the given object.
+         */
+        MessageStringContext(MessageStringCollector *collector, const char *name)
+            : collector_(*collector)
+        {
+            collector_.startContext(name);
+        }
+        /*! \brief
+         * Adds a context for the given object.
+         */
+        MessageStringContext(MessageStringCollector *collector,
+                       const std::string &name)
+            : collector_(*collector)
+        {
+            collector_.startContext(name);
+        }
+        /*! \brief
+         * Calls MessageStringCollector::finishContext() on the wrapped object.
+         */
+        ~MessageStringContext()
+        {
+            collector_.finishContext();
+        }
+
+    private:
+        //! The wrapped object.
+        MessageStringCollector &collector_;
+
+        // Disallow copy and assign.
+        MessageStringContext(const MessageStringContext &);
+        void operator =(const MessageStringContext &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/gmxlib/CMakeLists.txt b/src/gromacs/gmxlib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..17cea60
--- /dev/null
@@ -0,0 +1,79 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+# The nonbonded directory contains subdirectories that are only
+# conditionally built, so we cannot use a GLOB_RECURSE here.
+file(GLOB GMXLIB_SOURCES *.c 
+     statistics/*.c nonbonded/*.c nonbonded/nb_kernel_c/*.c)
+
+if(GMX_DOUBLE)
+  set(SSETYPE sse2)
+else()
+  set(SSETYPE sse)
+endif()
+
+if(GMX_IA32_ASM)
+  file(GLOB GMX_SSEKERNEL_C_SRC   nonbonded/nb_kernel_ia32_${SSETYPE}/*.c)
+  if(GMX_ASM_USEASM-NASM)
+    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_ia32_${SSETYPE}/*intel_syntax*.s)    
+  else()
+    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_ia32_${SSETYPE}/*${SSETYPE}.s nonbonded/nb_kernel_ia32_${SSETYPE}/*asm.s)
+  endif()
+endif(GMX_IA32_ASM)
+
+if(GMX_X86_64_ASM)
+  file(GLOB GMX_SSEKERNEL_C_SRC   nonbonded/nb_kernel_x86_64_${SSETYPE}/*.c)
+  if(GMX_ASM_USEASM-NASM)
+    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_x86_64_${SSETYPE}/*intel_syntax*.s)
+  else()
+    file(GLOB GMX_SSEKERNEL_ASM_SRC nonbonded/nb_kernel_x86_64_${SSETYPE}/*${SSETYPE}.s nonbonded/nb_kernel_x86_64_${SSETYPE}/*asm.s)
+  endif()
+endif(GMX_X86_64_ASM)
+
+if(GMX_FORTRAN)
+  if (GMX_DOUBLE)
+    file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_f77_double/*.[cf])
+  else(GMX_DOUBLE)
+    file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_f77_single/*.[cf])
+  endif(GMX_DOUBLE)
+endif(GMX_FORTRAN)
+
+if(GMX_POWER6)
+  file(GLOB FORTRAN_SOURCES nonbonded/nb_kernel_power6/*.[cF])
+endif(GMX_POWER6)
+
+if(GMX_BLUEGENE)
+  file(GLOB GMX_BLUEGENE_C_SRC nonbonded/nb_kernel_bluegene/*.c)
+endif(GMX_BLUEGENE)
+
+if(GMX_PPC_ALTIVEC)
+  file(GLOB GMX_PPC_ALTIVEC_SRC nonbonded/nb_kernel_ppc_altivec/*.c)
+endif(GMX_PPC_ALTIVEC)
+
+if(NOT GMX_EXTERNAL_BLAS)
+  file(GLOB BLAS_SOURCES gmx_blas/*.c)
+endif(NOT GMX_EXTERNAL_BLAS)
+
+if(NOT GMX_EXTERNAL_LAPACK)
+  file(GLOB LAPACK_SOURCES gmx_lapack/*.c)
+endif(NOT GMX_EXTERNAL_LAPACK)
+
+# This would be the standard way to include thread_mpi, but we want libgmx
+# to link the functions directly
+#if(GMX_THREADS)
+#    add_subdirectory(thread_mpi)
+#endif(GMX_THREADS)
+#target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES} ${THREAD_MPI_LIB})
+
+# Files called xxx_test.c are test drivers with a main() function for module xxx.c,
+# so they should not be included in the library
+file(GLOB_RECURSE NOT_GMXLIB_SOURCES *_test.c *\#*)
+list(REMOVE_ITEM GMXLIB_SOURCES ${NOT_GMXLIB_SOURCES})  
+
+# An ugly hack to get absolute paths...
+file(GLOB THREAD_MPI_SOURCES ${THREAD_MPI_SRC})
+
+set(GMX_SSEKERNEL_ASM_SRC ${GMX_SSEKERNEL_ASM_SRC} PARENT_SCOPE)
+set(GMXLIB_SOURCES ${GMXLIB_SOURCES} ${BLAS_SOURCES} ${LAPACK_SOURCES}
+    ${GMX_SSEKERNEL_C_SRC} ${FORTRAN_SOURCES}
+    ${GMX_BLUEGENE_C_SRC} ${GMX_PPC_ALTIVEC_SRC} ${THREAD_MPI_SOURCES}
+    PARENT_SCOPE)
similarity index 100%
rename from src/gmxlib/dlb.h
rename to src/gromacs/gmxlib/dlb.h
similarity index 100%
rename from src/gmxlib/main.c
rename to src/gromacs/gmxlib/main.c
similarity index 100%
rename from src/gmxlib/md5.c
rename to src/gromacs/gmxlib/md5.c
diff --git a/src/gromacs/gmxlib/mvdata.c b/src/gromacs/gmxlib/mvdata.c
new file mode 100644 (file)
index 0000000..5b2df26
--- /dev/null
@@ -0,0 +1,593 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+/* This file is completely threadsafe - keep it that way! */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sysstuff.h>
+#include <string.h>
+#include "typedefs.h"
+#include "main.h"
+#include "mvdata.h"
+#include "network.h"
+#include "smalloc.h"
+#include "gmx_fatal.h"
+#include "symtab.h"
+#include "vec.h"
+#include "tgroup.h"
+
+#define   block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
+/* Probably the test for (nr) > 0 in the next macro is only needed
+ * on BlueGene(/L), where IBM's MPI_Bcast will segfault after
+ * dereferencing a null pointer, even when no data is to be transferred. */
+#define  nblock_bc(cr,nr,d) { if ((nr) > 0) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr)); }
+#define    snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
+/* Dirty macro with bAlloc not as an argument */
+#define nblock_abc(cr,nr,d) { if (bAlloc) snew((d),(nr)); nblock_bc(cr,(nr),(d)); }
+
+static void bc_string(const t_commrec *cr,t_symtab *symtab,char ***s)
+{
+  int handle;
+  
+  if (MASTER(cr)) {
+    handle = lookup_symtab(symtab,*s);
+  }
+  block_bc(cr,handle);
+  if (!MASTER(cr)) {
+    *s = get_symtab_handle(symtab,handle);
+  }
+}
+
+static void bc_strings(const t_commrec *cr,t_symtab *symtab,int nr,char ****nm)
+{
+  int  i;
+  int  *handle;
+  char ***NM;
+
+  snew(handle,nr);
+  if (MASTER(cr)) {
+    NM = *nm;
+    for(i=0; (i<nr); i++)
+      handle[i] = lookup_symtab(symtab,NM[i]);
+  }
+  nblock_bc(cr,nr,handle);
+
+  if (!MASTER(cr)) {
+    snew_bc(cr,*nm,nr);
+    NM = *nm;
+    for (i=0; (i<nr); i++) 
+      (*nm)[i] = get_symtab_handle(symtab,handle[i]);
+  }
+  sfree(handle);
+}
+
+static void bc_strings_resinfo(const t_commrec *cr,t_symtab *symtab,
+                              int nr,t_resinfo *resinfo)
+{
+  int  i;
+  int  *handle;
+
+  snew(handle,nr);
+  if (MASTER(cr)) {
+    for(i=0; (i<nr); i++)
+      handle[i] = lookup_symtab(symtab,resinfo[i].name);
+  }
+  nblock_bc(cr,nr,handle);
+
+  if (!MASTER(cr)) {
+    for (i=0; (i<nr); i++) 
+      resinfo[i].name = get_symtab_handle(symtab,handle[i]);
+  }
+  sfree(handle);
+}
+
+static void bc_symtab(const t_commrec *cr,t_symtab *symtab)
+{
+  int i,nr,len;
+  t_symbuf *symbuf;
+
+  block_bc(cr,symtab->nr);
+  nr = symtab->nr;
+  snew_bc(cr,symtab->symbuf,1);
+  symbuf = symtab->symbuf;
+  symbuf->bufsize = nr;
+  snew_bc(cr,symbuf->buf,nr);
+  for (i=0; i<nr; i++) {
+    if (MASTER(cr))
+      len = strlen(symbuf->buf[i]) + 1;
+    block_bc(cr,len);
+    snew_bc(cr,symbuf->buf[i],len);
+    nblock_bc(cr,len,symbuf->buf[i]);
+  }
+}
+
+static void bc_block(const t_commrec *cr,t_block *block)
+{
+  block_bc(cr,block->nr);
+  snew_bc(cr,block->index,block->nr+1);
+  nblock_bc(cr,block->nr+1,block->index);
+}
+
+static void bc_blocka(const t_commrec *cr,t_blocka *block)
+{
+  block_bc(cr,block->nr);
+  snew_bc(cr,block->index,block->nr+1);
+  nblock_bc(cr,block->nr+1,block->index);
+  block_bc(cr,block->nra);
+  if (block->nra) {
+    snew_bc(cr,block->a,block->nra);
+    nblock_bc(cr,block->nra,block->a);
+  }
+}
+
+static void bc_grps(const t_commrec *cr,t_grps grps[])
+{
+  int i;
+  
+  for(i=0; (i<egcNR); i++) {
+    block_bc(cr,grps[i].nr);
+    snew_bc(cr,grps[i].nm_ind,grps[i].nr);
+    nblock_bc(cr,grps[i].nr,grps[i].nm_ind);
+  }
+}
+
+static void bc_atoms(const t_commrec *cr,t_symtab *symtab,t_atoms *atoms)
+{
+  int dummy;
+
+  block_bc(cr,atoms->nr);
+  snew_bc(cr,atoms->atom,atoms->nr);
+  nblock_bc(cr,atoms->nr,atoms->atom);
+  bc_strings(cr,symtab,atoms->nr,&atoms->atomname);
+  block_bc(cr,atoms->nres);
+  snew_bc(cr,atoms->resinfo,atoms->nres);
+  nblock_bc(cr,atoms->nres,atoms->resinfo);
+  bc_strings_resinfo(cr,symtab,atoms->nres,atoms->resinfo);
+  /* QMMM requires atomtypes to be known on all nodes as well */
+  bc_strings(cr,symtab,atoms->nr,&atoms->atomtype);
+  bc_strings(cr,symtab,atoms->nr,&atoms->atomtypeB);
+}
+
+static void bc_groups(const t_commrec *cr,t_symtab *symtab,
+                     int natoms,gmx_groups_t *groups)
+{
+  int dummy;
+  int g,n;
+
+  bc_grps(cr,groups->grps);
+  block_bc(cr,groups->ngrpname);
+  bc_strings(cr,symtab,groups->ngrpname,&groups->grpname);
+  for(g=0; g<egcNR; g++) {
+    if (MASTER(cr)) {
+      if (groups->grpnr[g]) {
+       n = natoms;
+      } else {
+       n = 0;
+      }
+    }
+    block_bc(cr,n);
+    if (n == 0) {
+      groups->grpnr[g] = NULL;
+    } else {
+      snew_bc(cr,groups->grpnr[g],n);
+      nblock_bc(cr,n,groups->grpnr[g]);
+    }
+  }
+  if (debug) fprintf(debug,"after bc_groups\n");
+}
+
+void bcast_state_setup(const t_commrec *cr,t_state *state)
+{
+  block_bc(cr,state->natoms);
+  block_bc(cr,state->ngtc);
+  block_bc(cr,state->nnhpres);
+  block_bc(cr,state->nhchainlength);
+  block_bc(cr,state->nrng);
+  block_bc(cr,state->nrngi);
+  block_bc(cr,state->flags);
+}
+
+void bcast_state(const t_commrec *cr,t_state *state,gmx_bool bAlloc)
+{
+  int i,nnht,nnhtp;
+
+  bcast_state_setup(cr,state);
+
+  nnht = (state->ngtc)*(state->nhchainlength); 
+  nnhtp = (state->nnhpres)*(state->nhchainlength); 
+
+  if (MASTER(cr)) {
+    bAlloc = FALSE;
+  }
+  if (bAlloc) {
+    state->nalloc = state->natoms;
+  }
+  for(i=0; i<estNR; i++) {
+    if (state->flags & (1<<i)) {
+      switch (i) {
+      case estLAMBDA:  block_bc(cr,state->lambda); break;
+      case estBOX:     block_bc(cr,state->box); break;
+      case estBOX_REL: block_bc(cr,state->box_rel); break;
+      case estBOXV:    block_bc(cr,state->boxv); break;
+      case estPRES_PREV: block_bc(cr,state->pres_prev); break;
+      case estSVIR_PREV: block_bc(cr,state->svir_prev); break;
+      case estFVIR_PREV: block_bc(cr,state->fvir_prev); break;
+      case estNH_XI:   nblock_abc(cr,nnht,state->nosehoover_xi); break;
+      case estNH_VXI:  nblock_abc(cr,nnht,state->nosehoover_vxi); break;
+      case estNHPRES_XI:   nblock_abc(cr,nnhtp,state->nhpres_xi); break;
+      case estNHPRES_VXI:  nblock_abc(cr,nnhtp,state->nhpres_vxi); break;
+      case estTC_INT:  nblock_abc(cr,state->ngtc,state->therm_integral); break;
+      case estVETA:    block_bc(cr,state->veta); break;
+      case estVOL0:    block_bc(cr,state->vol0); break;
+      case estX:       nblock_abc(cr,state->natoms,state->x); break;
+      case estV:       nblock_abc(cr,state->natoms,state->v); break;
+      case estSDX:     nblock_abc(cr,state->natoms,state->sd_X); break;
+      case estCGP:     nblock_abc(cr,state->natoms,state->cg_p); break;
+         case estLD_RNG:  if(state->nrngi == 1) nblock_abc(cr,state->nrng,state->ld_rng); break;
+         case estLD_RNGI: if(state->nrngi == 1) nblock_abc(cr,state->nrngi,state->ld_rngi); break;
+      case estDISRE_INITF: block_bc(cr,state->hist.disre_initf); break;
+      case estDISRE_RM3TAV:
+          block_bc(cr,state->hist.ndisrepairs);
+          nblock_abc(cr,state->hist.ndisrepairs,state->hist.disre_rm3tav);
+          break;
+      case estORIRE_INITF: block_bc(cr,state->hist.orire_initf); break;
+      case estORIRE_DTAV:
+          block_bc(cr,state->hist.norire_Dtav);
+          nblock_abc(cr,state->hist.norire_Dtav,state->hist.orire_Dtav);
+          break;
+      default:
+          gmx_fatal(FARGS,
+                    "Communication is not implemented for %s in bcast_state",
+                    est_names[i]);
+      }
+    }
+  }
+}
+
+static void bc_ilists(const t_commrec *cr,t_ilist *ilist)
+{
+  int ftype;
+
+  /* Here we only communicate the non-zero length ilists */
+  if (MASTER(cr)) {
+    for(ftype=0; ftype<F_NRE; ftype++) {
+      if (ilist[ftype].nr > 0) {
+       block_bc(cr,ftype);
+       block_bc(cr,ilist[ftype].nr);
+       nblock_bc(cr,ilist[ftype].nr,ilist[ftype].iatoms);
+      }
+    }
+    ftype = -1;
+    block_bc(cr,ftype);
+  } else {
+    for(ftype=0; ftype<F_NRE; ftype++) {
+      ilist[ftype].nr = 0;
+    }
+    do {
+      block_bc(cr,ftype);
+      if (ftype >= 0) {
+       block_bc(cr,ilist[ftype].nr);
+       snew_bc(cr,ilist[ftype].iatoms,ilist[ftype].nr);
+       nblock_bc(cr,ilist[ftype].nr,ilist[ftype].iatoms);
+      }
+    } while (ftype >= 0);
+  }
+
+  if (debug) fprintf(debug,"after bc_ilists\n");
+}
+
+static void bc_idef(const t_commrec *cr,t_idef *idef)
+{
+  block_bc(cr,idef->ntypes);
+  block_bc(cr,idef->atnr);
+  snew_bc(cr,idef->functype,idef->ntypes);
+  snew_bc(cr,idef->iparams,idef->ntypes);
+  nblock_bc(cr,idef->ntypes,idef->functype);
+  nblock_bc(cr,idef->ntypes,idef->iparams);
+  block_bc(cr,idef->fudgeQQ);
+  bc_ilists(cr,idef->il);
+  block_bc(cr,idef->ilsort);
+}
+
+static void bc_cmap(const t_commrec *cr, gmx_cmap_t *cmap_grid)
+{
+       int i,j,nelem,ngrid;
+       
+       block_bc(cr,cmap_grid->ngrid);
+       block_bc(cr,cmap_grid->grid_spacing);
+       
+       ngrid = cmap_grid->ngrid;
+       nelem = cmap_grid->grid_spacing * cmap_grid->grid_spacing;
+       
+       if(ngrid>0)
+       {
+               snew_bc(cr,cmap_grid->cmapdata,ngrid);
+               
+               for(i=0;i<ngrid;i++)
+               {
+                       snew_bc(cr,cmap_grid->cmapdata[i].cmap,4*nelem);
+                       nblock_bc(cr,4*nelem,cmap_grid->cmapdata[i].cmap);
+               }
+       }
+}
+
+static void bc_ffparams(const t_commrec *cr,gmx_ffparams_t *ffp)
+{
+  int i;
+  
+  block_bc(cr,ffp->ntypes);
+  block_bc(cr,ffp->atnr);
+  snew_bc(cr,ffp->functype,ffp->ntypes);
+  snew_bc(cr,ffp->iparams,ffp->ntypes);
+  nblock_bc(cr,ffp->ntypes,ffp->functype);
+  nblock_bc(cr,ffp->ntypes,ffp->iparams);
+  block_bc(cr,ffp->reppow);
+  block_bc(cr,ffp->fudgeQQ);
+  bc_cmap(cr,&ffp->cmap_grid);
+}
+
+static void bc_grpopts(const t_commrec *cr,t_grpopts *g)
+{
+    int i,n;
+    
+    block_bc(cr,g->ngtc);
+    block_bc(cr,g->ngacc);
+    block_bc(cr,g->ngfrz);
+    block_bc(cr,g->ngener);
+    snew_bc(cr,g->nrdf,g->ngtc);
+    snew_bc(cr,g->tau_t,g->ngtc);
+    snew_bc(cr,g->ref_t,g->ngtc);
+    snew_bc(cr,g->acc,g->ngacc);
+    snew_bc(cr,g->nFreeze,g->ngfrz);
+    snew_bc(cr,g->egp_flags,g->ngener*g->ngener);
+    
+    nblock_bc(cr,g->ngtc,g->nrdf);
+    nblock_bc(cr,g->ngtc,g->tau_t);
+    nblock_bc(cr,g->ngtc,g->ref_t);
+    nblock_bc(cr,g->ngacc,g->acc);
+    nblock_bc(cr,g->ngfrz,g->nFreeze);
+    nblock_bc(cr,g->ngener*g->ngener,g->egp_flags);
+    snew_bc(cr,g->annealing,g->ngtc);
+    snew_bc(cr,g->anneal_npoints,g->ngtc);
+    snew_bc(cr,g->anneal_time,g->ngtc);
+    snew_bc(cr,g->anneal_temp,g->ngtc);
+    nblock_bc(cr,g->ngtc,g->annealing);
+    nblock_bc(cr,g->ngtc,g->anneal_npoints);
+    for(i=0;(i<g->ngtc); i++) {
+        n = g->anneal_npoints[i];
+        if (n > 0) {
+         snew_bc(cr,g->anneal_time[i],n);
+         snew_bc(cr,g->anneal_temp[i],n);
+         nblock_bc(cr,n,g->anneal_time[i]);
+         nblock_bc(cr,n,g->anneal_temp[i]);
+        }
+    }
+    
+    /* QMMM stuff, see inputrec */
+    block_bc(cr,g->ngQM);
+    snew_bc(cr,g->QMmethod,g->ngQM);
+    snew_bc(cr,g->QMbasis,g->ngQM);
+    snew_bc(cr,g->QMcharge,g->ngQM);
+    snew_bc(cr,g->QMmult,g->ngQM);
+    snew_bc(cr,g->bSH,g->ngQM);
+    snew_bc(cr,g->CASorbitals,g->ngQM);
+    snew_bc(cr,g->CASelectrons,g->ngQM);
+    snew_bc(cr,g->SAon,g->ngQM);
+    snew_bc(cr,g->SAoff,g->ngQM);
+    snew_bc(cr,g->SAsteps,g->ngQM);
+    
+    if (g->ngQM)
+    {
+        nblock_bc(cr,g->ngQM,g->QMmethod);
+        nblock_bc(cr,g->ngQM,g->QMbasis);
+        nblock_bc(cr,g->ngQM,g->QMcharge);
+        nblock_bc(cr,g->ngQM,g->QMmult);
+        nblock_bc(cr,g->ngQM,g->bSH);
+        nblock_bc(cr,g->ngQM,g->CASorbitals);
+        nblock_bc(cr,g->ngQM,g->CASelectrons);
+        nblock_bc(cr,g->ngQM,g->SAon);
+        nblock_bc(cr,g->ngQM,g->SAoff);
+        nblock_bc(cr,g->ngQM,g->SAsteps);
+        /* end of QMMM stuff */
+    }
+}
+
+static void bc_cosines(const t_commrec *cr,t_cosines *cs)
+{
+  block_bc(cr,cs->n);
+  snew_bc(cr,cs->a,cs->n);
+  snew_bc(cr,cs->phi,cs->n);
+  if (cs->n > 0) {
+    nblock_bc(cr,cs->n,cs->a);
+    nblock_bc(cr,cs->n,cs->phi);
+  }
+}
+
+static void bc_pullgrp(const t_commrec *cr,t_pullgrp *pgrp)
+{
+  block_bc(cr,*pgrp);
+  if (pgrp->nat > 0) {
+    snew_bc(cr,pgrp->ind,pgrp->nat);
+    nblock_bc(cr,pgrp->nat,pgrp->ind);
+  }
+  if (pgrp->nweight > 0) {
+    snew_bc(cr,pgrp->weight,pgrp->nweight);
+    nblock_bc(cr,pgrp->nweight,pgrp->weight);
+  }
+}
+
+static void bc_pull(const t_commrec *cr,t_pull *pull)
+{
+  int g;
+
+  block_bc(cr,*pull);
+  snew_bc(cr,pull->grp,pull->ngrp+1);
+  for(g=0; g<pull->ngrp+1; g++)
+  {
+      bc_pullgrp(cr,&pull->grp[g]);
+  }
+}
+
+static void bc_rotgrp(const t_commrec *cr,t_rotgrp *rotg)
+{
+  block_bc(cr,*rotg);
+  if (rotg->nat > 0) {
+    snew_bc(cr,rotg->ind,rotg->nat);
+    nblock_bc(cr,rotg->nat,rotg->ind);
+    snew_bc(cr,rotg->x_ref,rotg->nat);
+    nblock_bc(cr,rotg->nat,rotg->x_ref);
+  }
+}
+
+static void bc_rot(const t_commrec *cr,t_rot *rot)
+{
+  int g;
+
+  block_bc(cr,*rot);
+  snew_bc(cr,rot->grp,rot->ngrp);
+  for(g=0; g<rot->ngrp; g++)
+    bc_rotgrp(cr,&rot->grp[g]);
+}
+
+static void bc_inputrec(const t_commrec *cr,t_inputrec *inputrec)
+{
+  gmx_bool bAlloc=TRUE;
+  int i;
+  
+  block_bc(cr,*inputrec);
+  snew_bc(cr,inputrec->flambda,inputrec->n_flambda);
+  nblock_bc(cr,inputrec->n_flambda,inputrec->flambda);
+  bc_grpopts(cr,&(inputrec->opts));
+  if (inputrec->ePull != epullNO) {
+    snew_bc(cr,inputrec->pull,1);
+    bc_pull(cr,inputrec->pull);
+  }
+  if (inputrec->bRot) {
+    snew_bc(cr,inputrec->rot,1);
+    bc_rot(cr,inputrec->rot);
+  }
+  for(i=0; (i<DIM); i++) {
+    bc_cosines(cr,&(inputrec->ex[i]));
+    bc_cosines(cr,&(inputrec->et[i]));
+  }
+}
+
+static void bc_moltype(const t_commrec *cr,t_symtab *symtab,
+                      gmx_moltype_t *moltype)
+{
+  bc_string(cr,symtab,&moltype->name);
+  bc_atoms(cr,symtab,&moltype->atoms);
+  if (debug) fprintf(debug,"after bc_atoms\n");
+
+  bc_ilists(cr,moltype->ilist);
+  bc_block(cr,&moltype->cgs);
+  bc_blocka(cr,&moltype->excls);
+}
+
+static void bc_molblock(const t_commrec *cr,gmx_molblock_t *molb)
+{
+  gmx_bool bAlloc=TRUE;
+  
+  block_bc(cr,molb->type);
+  block_bc(cr,molb->nmol);
+  block_bc(cr,molb->natoms_mol);
+  block_bc(cr,molb->nposres_xA);
+  if (molb->nposres_xA > 0) {
+    snew_bc(cr,molb->posres_xA,molb->nposres_xA);
+    nblock_bc(cr,molb->nposres_xA*DIM,molb->posres_xA[0]);
+  }
+  block_bc(cr,molb->nposres_xB);
+  if (molb->nposres_xB > 0) {
+    snew_bc(cr,molb->posres_xB,molb->nposres_xB);
+    nblock_bc(cr,molb->nposres_xB*DIM,molb->posres_xB[0]);
+  }
+  if (debug) fprintf(debug,"after bc_molblock\n");
+}
+
+static void bc_atomtypes(const t_commrec *cr, t_atomtypes *atomtypes)
+{
+  int nr;
+
+  block_bc(cr,atomtypes->nr);
+
+  nr = atomtypes->nr;
+
+  snew_bc(cr,atomtypes->radius,nr);
+  snew_bc(cr,atomtypes->vol,nr);
+  snew_bc(cr,atomtypes->surftens,nr);
+  snew_bc(cr,atomtypes->gb_radius,nr);
+  snew_bc(cr,atomtypes->S_hct,nr);
+
+  nblock_bc(cr,nr,atomtypes->radius);
+  nblock_bc(cr,nr,atomtypes->vol);
+  nblock_bc(cr,nr,atomtypes->surftens);
+  nblock_bc(cr,nr,atomtypes->gb_radius);
+  nblock_bc(cr,nr,atomtypes->S_hct);
+}
+
+
+void bcast_ir_mtop(const t_commrec *cr,t_inputrec *inputrec,gmx_mtop_t *mtop)
+{
+  int i; 
+  if (debug) fprintf(debug,"in bc_data\n");
+  bc_inputrec(cr,inputrec);
+  if (debug) fprintf(debug,"after bc_inputrec\n");
+  bc_symtab(cr,&mtop->symtab);
+  if (debug) fprintf(debug,"after bc_symtab\n");
+  bc_string(cr,&mtop->symtab,&mtop->name);
+  if (debug) fprintf(debug,"after bc_name\n");
+
+  bc_ffparams(cr,&mtop->ffparams);
+
+  block_bc(cr,mtop->nmoltype);
+  snew_bc(cr,mtop->moltype,mtop->nmoltype);
+  for(i=0; i<mtop->nmoltype; i++) {
+    bc_moltype(cr,&mtop->symtab,&mtop->moltype[i]);
+  }
+
+  block_bc(cr,mtop->nmolblock);
+  snew_bc(cr,mtop->molblock,mtop->nmolblock);
+  for(i=0; i<mtop->nmolblock; i++) {
+    bc_molblock(cr,&mtop->molblock[i]);
+  }
+
+  block_bc(cr,mtop->natoms);
+
+  bc_atomtypes(cr,&mtop->atomtypes);
+
+  bc_block(cr,&mtop->mols);
+  bc_groups(cr,&mtop->symtab,mtop->natoms,&mtop->groups);
+}
diff --git a/src/gromacs/gmxlib/names.c b/src/gromacs/gmxlib/names.c
new file mode 100644 (file)
index 0000000..470a0c1
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "typedefs.h"
+#include "names.h"
+
+/* note: these arrays should correspond to enums in include/types/enums.h */
+
+const char *epbc_names[epbcNR+1]=
+{
+  "xyz", "no", "xy", "screw", NULL
+};
+
+const char *ens_names[ensNR+1]=
+{
+  "Grid","Simple", NULL
+};
+
+const char *ei_names[eiNR+1]=
+{
+  "md", "steep", "cg", "bd", "sd", "nm", "l-bfgs", "tpi", "tpic", "sd1", "md-vv", "md-vv-avek",NULL 
+};
+
+const char *bool_names[BOOL_NR+1]=
+{
+  "FALSE","TRUE", NULL
+};
+
+const char *yesno_names[BOOL_NR+1]=
+{
+  "no","yes", NULL
+};
+
+const char *ptype_str[eptNR+1] = {
+  "Atom", "Nucleus", "Shell", "Bond", "VSite", NULL
+};
+
+const char *eel_names[eelNR+1] = {
+  "Cut-off", "Reaction-Field", "Generalized-Reaction-Field",
+  "PME", "Ewald", "PPPM", "Poisson", "Switch", "Shift", "User", 
+  "Generalized-Born", "Reaction-Field-nec", "Encad-shift", 
+  "PME-User", "PME-Switch", "PME-User-Switch", 
+  "Reaction-Field-zero", NULL
+};
+
+const char *eewg_names[eewgNR+1] = {
+  "3d", "3dc", NULL
+};
+
+const char *evdw_names[evdwNR+1] = {
+  "Cut-off", "Switch", "Shift", "User", "Encad-shift", NULL
+};
+
+const char *econstr_names[econtNR+1] = {
+  "Lincs", "Shake", NULL
+};
+
+const char *egrp_nm[egNR+1] = { 
+  "Coul-SR","LJ-SR","Buck-SR", "Coul-LR", "LJ-LR", "Buck-LR",
+  "Coul-14", "LJ-14", NULL
+};
+
+const char *etcoupl_names[etcNR+1] = {
+  "No", "Berendsen", "Nose-Hoover", "yes", "Andersen", "Andersen-interval", "V-rescale", NULL
+}; /* yes is alias for berendsen */
+
+const char *epcoupl_names[epcNR+1] = {
+  "No", "Berendsen", "Parrinello-Rahman", "Isotropic", "MTTK", NULL
+}; /* isotropic is alias for berendsen */
+
+const char *epcoupltype_names[epctNR+1] = {
+  "Isotropic", "Semiisotropic", "Anisotropic", "Surface-Tension", NULL
+};
+
+const char *erefscaling_names[erscNR+1] = {
+  "No", "All", "COM", NULL
+};
+
+const char *edisre_names[edrNR+1] = {
+  "No", "Simple", "Ensemble", NULL
+};
+
+const char *edisreweighting_names[edrwNR+1] = {
+  "Conservative", "Equal", NULL
+};
+
+const char *enbf_names[eNBF_NR+1] = {
+  "", "LJ", "Buckingham", NULL
+};
+
+const char *ecomb_names[eCOMB_NR+1] = {
+  "", "Geometric", "Arithmetic", "GeomSigEps", NULL
+};
+
+const char *gtypes[egcNR+1] = {
+  "T-Coupling", "Energy Mon.", "Acceleration", "Freeze",
+  "User1", "User2", "VCM", "XTC", "Or. Res. Fit", "QMMM", NULL
+};
+
+const char *efep_names[efepNR+1] = {
+  "no", "yes", NULL
+};
+
+const char *separate_dhdl_file_names[sepdhdlfileNR+1] = {
+  "yes", "no", NULL
+};
+
+const char *dhdl_derivatives_names[dhdlderivativesNR+1] = {
+  "yes", "no", NULL
+};
+
+const char *esol_names[esolNR+1] = {
+  "No", "SPC", "TIP4p", NULL
+};
+
+const char *enlist_names[enlistNR+1] = {
+  "Atom-Atom", "SPC-Atom", "SPC-SPC", "TIP4p-Atom", "TIP4p-TIP4p", "CG-CG", NULL
+};
+
+const char *edispc_names[edispcNR+1] = {
+  "No", "EnerPres", "Ener", "AllEnerPres", "AllEner", NULL
+};
+
+const char *ecm_names[ecmNR+1] = { 
+  "Linear", "Angular", "None", NULL 
+};
+
+const char *eann_names[eannNR+1] = {
+  "No", "Single", "Periodic", NULL
+};
+
+const char *eis_names[eisNR+1] = {
+       "No", "GBSA", NULL
+};
+
+const char *egb_names[egbNR+1] = {
+  "Still", "HCT", "OBC", NULL
+};
+
+const char *esa_names[esaNR+1] = {
+  "Ace-approximation", "None", "Still", NULL
+};
+
+const char *ewt_names[ewtNR+1] = {
+  "9-3", "10-4", "table", "12-6", NULL
+};
+
+const char *epull_names[epullNR+1] = { 
+  "no", "umbrella", "constraint", "constant-force", NULL
+};
+
+const char *epullg_names[epullgNR+1] = { 
+  "distance", "direction", "cylinder", "position", "direction-periodic", NULL
+};
+
+const char *erotg_names[erotgNR+1] = { 
+  "iso", "iso-pf", "pm", "pm-pf", "rm", "rm-pf", "rm2", "rm2-pf", "flex", "flex-t", "flex2", "flex2-t", NULL
+};
+
+const char *erotg_fitnames[erotgFitNR+1] = { 
+  "rmsd", "norm", "potential", NULL
+};
+
+const char *eQMmethod_names[eQMmethodNR+1] = {
+  "AM1", "PM3", "RHF",
+  "UHF", "DFT", "B3LYP", "MP2", "CASSCF","B3LYPLAN",
+  "DIRECT", NULL
+};
+
+const char *eQMbasis_names[eQMbasisNR+1] = {
+  "STO3G", "STO-3G", "3-21G",
+  "3-21G*", "3-21+G*", "6-21G",
+  "6-31G", "6-31G*", "6-31+G*",
+  "6-311G", NULL
+};
+
+const char *eQMMMscheme_names[eQMMMschemeNR+1] = {
+  "normal", "ONIOM", NULL
+};
+
+const char *eMultentOpt_names[eMultentOptNR+1] = {
+  "multiple_entries", "no", "use_last", NULL
+};
+
diff --git a/src/gromacs/gmxlib/network.c b/src/gromacs/gmxlib/network.c
new file mode 100644 (file)
index 0000000..12514a6
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "gmx_fatal.h"
+#include "main.h"
+#include "smalloc.h"
+#include "network.h"
+#include "copyrite.h"
+#include "statutil.h"
+#include "ctype.h"
+#include "macros.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+
+/* The source code in this file should be thread-safe. 
+      Please keep it that way. */
+
+gmx_bool gmx_mpi_initialized(void)
+{
+  int n;
+#ifndef GMX_MPI
+  return 0;
+#else
+  MPI_Initialized(&n);
+  
+  return n;
+#endif
+}
+
+int gmx_setup(int *argc,char **argv,int *nnodes)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_setup");
+  return 0;
+#else
+  char   buf[256];
+  int    resultlen;               /* actual length of node name      */
+  int    i,flag;
+  int  mpi_num_nodes;
+  int  mpi_my_rank;
+  char mpi_hostname[MPI_MAX_PROCESSOR_NAME];
+
+  /* Call the MPI routines */
+#ifdef GMX_LIB_MPI
+#ifdef GMX_FAHCORE
+  (void) fah_MPI_Init(argc,&argv);
+#else
+  (void) MPI_Init(argc,&argv);
+#endif
+#endif
+  (void) MPI_Comm_size( MPI_COMM_WORLD, &mpi_num_nodes );
+  (void) MPI_Comm_rank( MPI_COMM_WORLD, &mpi_my_rank );
+  (void) MPI_Get_processor_name( mpi_hostname, &resultlen );
+#ifdef GMX_LIB_MPI 
+  fprintf(stderr,"NNODES=%d, MYRANK=%d, HOSTNAME=%s\n",
+         mpi_num_nodes,mpi_my_rank,mpi_hostname);
+#endif
+  
+  *nnodes=mpi_num_nodes;
+  
+  return mpi_my_rank;
+#endif
+}
+
+int  gmx_node_num(void)
+{
+#ifndef GMX_MPI
+  return 1;
+#else
+  int i;
+  (void) MPI_Comm_size(MPI_COMM_WORLD, &i);
+  return i;
+#endif
+}
+
+int gmx_node_rank(void)
+{
+#ifndef GMX_MPI
+  return 0;
+#else
+  int i;
+  (void) MPI_Comm_rank(MPI_COMM_WORLD, &i);
+  return i;
+#endif
+}
+
+void gmx_setup_nodecomm(FILE *fplog,t_commrec *cr)
+{
+  gmx_nodecomm_t *nc;
+  int  n,rank,resultlen,hostnum,i,j,ng,ni;
+#ifdef GMX_MPI
+  char mpi_hostname[MPI_MAX_PROCESSOR_NAME],num[MPI_MAX_PROCESSOR_NAME];
+#endif
+
+  /* Many MPI implementations do not optimize MPI_Allreduce
+   * (and probably also other global communication calls)
+   * for multi-core nodes connected by a network.
+   * We can optimize such communication by using one MPI call
+   * within each node and one between the nodes.
+   * For MVAPICH2 and Intel MPI this reduces the time for
+   * the global_stat communication by 25%
+   * for 2x2-core 3 GHz Woodcrest connected by mixed DDR/SDR Infiniband.
+   * B. Hess, November 2007
+   */
+
+  nc = &cr->nc;
+
+  nc->bUse = FALSE;
+#ifndef GMX_THREADS
+  if (getenv("GMX_NO_NODECOMM") == NULL) {
+#ifdef GMX_MPI
+    MPI_Comm_size(cr->mpi_comm_mygroup,&n);
+    MPI_Comm_rank(cr->mpi_comm_mygroup,&rank);
+    MPI_Get_processor_name(mpi_hostname,&resultlen);
+    /* This procedure can only differentiate nodes with host names
+     * that end on unique numbers.
+     */
+    i = 0;
+    j = 0;
+    /* Only parse the host name up to the first dot */
+    while(i < resultlen && mpi_hostname[i] != '.') {
+      if (isdigit(mpi_hostname[i])) {
+       num[j++] = mpi_hostname[i];
+      }
+      i++;
+    }
+    num[j] = '\0';
+    if (j == 0) {
+      hostnum = 0;
+    } else {
+      /* Use only the last 9 decimals, so we don't overflow an int */
+      hostnum = strtol(num + max(0,j-9), NULL, 10); 
+    }
+
+    if (debug) {
+      fprintf(debug,
+             "In gmx_setup_nodecomm: splitting communicator of size %d\n",
+             n);
+      fprintf(debug,"In gmx_setup_nodecomm: hostname '%s', hostnum %d\n",
+             mpi_hostname,hostnum);
+    }
+
+    /* The intra-node communicator, split on node number */
+    MPI_Comm_split(cr->mpi_comm_mygroup,hostnum,rank,&nc->comm_intra);
+    MPI_Comm_rank(nc->comm_intra,&nc->rank_intra);
+    if (debug) {
+      fprintf(debug,"In gmx_setup_nodecomm: node rank %d rank_intra %d\n",
+             rank,nc->rank_intra);
+    }
+    /* The inter-node communicator, split on rank_intra.
+     * We actually only need the one for rank=0,
+     * but it is easier to create them all.
+     */
+    MPI_Comm_split(cr->mpi_comm_mygroup,nc->rank_intra,rank,&nc->comm_inter);
+    /* Check if this really created two step communication */
+    MPI_Comm_size(nc->comm_inter,&ng);
+    MPI_Comm_size(nc->comm_intra,&ni);
+    if (debug) {
+      fprintf(debug,"In gmx_setup_nodecomm: groups %d, my group size %d\n",
+             ng,ni);
+    }
+    if ((ng > 1 && ng < n) || (ni > 1 && ni < n)) {
+      nc->bUse = TRUE;
+      if (fplog)
+       fprintf(fplog,"Using two step summing over %d groups of on average %.1f processes\n\n",ng,(real)n/(real)ng);
+      if (nc->rank_intra > 0)
+       MPI_Comm_free(&nc->comm_inter);
+    } else {
+      /* One group or all processes in a separate group, use normal summing */
+      MPI_Comm_free(&nc->comm_inter);
+      MPI_Comm_free(&nc->comm_intra);
+    }
+#endif
+  }
+#endif
+}
+
+void gmx_barrier(const t_commrec *cr)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_barrier");
+#else
+  MPI_Barrier(cr->mpi_comm_mygroup);
+#endif
+}
+
+void gmx_abort(int noderank,int nnodes,int errorno)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_abort");
+#else
+#ifdef GMX_THREADS
+  fprintf(stderr,"Halting program %s\n",ShortProgram());
+  thanx(stderr);
+  exit(1);
+#else
+  if (nnodes > 1)
+  {
+      fprintf(stderr,"Halting parallel program %s on CPU %d out of %d\n",
+              ShortProgram(),noderank,nnodes);
+  }
+  else
+  {
+      fprintf(stderr,"Halting program %s\n",ShortProgram());
+  }
+
+  thanx(stderr);
+  MPI_Abort(MPI_COMM_WORLD,errorno);
+  exit(1);
+#endif
+#endif
+}
+
+void gmx_bcast(int nbytes,void *b,const t_commrec *cr)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_bast");
+#else
+  MPI_Bcast(b,nbytes,MPI_BYTE,MASTERRANK(cr),cr->mpi_comm_mygroup);
+#endif
+}
+
+void gmx_bcast_sim(int nbytes,void *b,const t_commrec *cr)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_bast");
+#else
+  MPI_Bcast(b,nbytes,MPI_BYTE,MASTERRANK(cr),cr->mpi_comm_mysim);
+#endif
+}
+
+void gmx_sumd(int nr,double r[],const t_commrec *cr)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumd");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    if (cr->nc.bUse) {
+        if (cr->nc.rank_intra == 0)
+        {
+            /* Use two step summing. */
+            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,0,
+                       cr->nc.comm_intra);
+            /* Sum the roots of the internal (intra) buffers. */
+            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,
+                          cr->nc.comm_inter);
+        }
+        else
+        {
+            /* This is here because of the silly MPI specification
+                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
+            MPI_Reduce(r,NULL,nr,MPI_DOUBLE,MPI_SUM,0,cr->nc.comm_intra);
+        }
+        MPI_Bcast(r,nr,MPI_DOUBLE,0,cr->nc.comm_intra);
+    } 
+    else 
+    {
+        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM, 
+                      cr->mpi_comm_mygroup);
+    }
+#else
+    int i;
+
+    if (nr > cr->mpb->dbuf_alloc) {
+        cr->mpb->dbuf_alloc = nr;
+        srenew(cr->mpb->dbuf,cr->mpb->dbuf_alloc);
+    }
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        MPI_Allreduce(r,cr->mpb->dbuf,nr,MPI_DOUBLE,MPI_SUM,cr->nc.comm_intra);
+        if (cr->nc.rank_intra == 0) {
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(cr->mpb->dbuf,r,nr,MPI_DOUBLE,MPI_SUM, 
+                          cr->nc.comm_inter);
+        }
+        MPI_Bcast(r,nr,MPI_DOUBLE,0,cr->nc.comm_intra);
+    } else {
+        MPI_Allreduce(r,cr->mpb->dbuf,nr,MPI_DOUBLE,MPI_SUM,
+                      cr->mpi_comm_mygroup);
+        for(i=0; i<nr; i++)
+            r[i] = cr->mpb->dbuf[i];
+    }
+#endif
+#endif
+}
+
+void gmx_sumf(int nr,float r[],const t_commrec *cr)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumf");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    if (cr->nc.bUse) {
+        /* Use two step summing.  */
+        if (cr->nc.rank_intra == 0)
+        {
+            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,0,
+                       cr->nc.comm_intra);
+            /* Sum the roots of the internal (intra) buffers */
+            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,
+                          cr->nc.comm_inter);
+        }
+        else
+        {
+            /* This is here because of the silly MPI specification
+                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
+            MPI_Reduce(r,NULL,nr,MPI_FLOAT,MPI_SUM,0,cr->nc.comm_intra);
+        }
+        MPI_Bcast(r,nr,MPI_FLOAT,0,cr->nc.comm_intra);
+    } 
+    else 
+    {
+        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,cr->mpi_comm_mygroup);
+    }
+#else
+    int i;
+
+    if (nr > cr->mpb->fbuf_alloc) {
+        cr->mpb->fbuf_alloc = nr;
+        srenew(cr->mpb->fbuf,cr->mpb->fbuf_alloc);
+    }
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        MPI_Allreduce(r,cr->mpb->fbuf,nr,MPI_FLOAT,MPI_SUM,cr->nc.comm_intra);
+        if (cr->nc.rank_intra == 0) {
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(cr->mpb->fbuf,r,nr,MPI_FLOAT,MPI_SUM, 
+                          cr->nc.comm_inter);
+        }
+        MPI_Bcast(r,nr,MPI_FLOAT,0,cr->nc.comm_intra);
+    } else {
+        MPI_Allreduce(r,cr->mpb->fbuf,nr,MPI_FLOAT,MPI_SUM,
+                      cr->mpi_comm_mygroup);
+        for(i=0; i<nr; i++)
+            r[i] = cr->mpb->fbuf[i];
+    }
+#endif
+#endif
+}
+
+void gmx_sumi(int nr,int r[],const t_commrec *cr)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumi");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        if (cr->nc.rank_intra == 0) 
+        {
+            MPI_Reduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,0,cr->nc.comm_intra);
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,cr->nc.comm_inter);
+        }
+        else
+        {
+            /* This is here because of the silly MPI specification
+                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
+            MPI_Reduce(r,NULL,nr,MPI_INT,MPI_SUM,0,cr->nc.comm_intra);
+        }
+        MPI_Bcast(r,nr,MPI_INT,0,cr->nc.comm_intra);
+    } 
+    else 
+    {
+        MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,cr->mpi_comm_mygroup);
+    }
+#else
+    int i;
+
+    if (nr > cr->mpb->ibuf_alloc) {
+        cr->mpb->ibuf_alloc = nr;
+        srenew(cr->mpb->ibuf,cr->mpb->ibuf_alloc);
+    }
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        MPI_Allreduce(r,cr->mpb->ibuf,nr,MPI_INT,MPI_SUM,cr->nc.comm_intra);
+        if (cr->nc.rank_intra == 0) {
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(cr->mpb->ibuf,r,nr,MPI_INT,MPI_SUM,cr->nc.comm_inter);
+        }
+        MPI_Bcast(r,nr,MPI_INT,0,cr->nc.comm_intra);
+    } else {
+        MPI_Allreduce(r,cr->mpb->ibuf,nr,MPI_INT,MPI_SUM,cr->mpi_comm_mygroup);
+        for(i=0; i<nr; i++)
+            r[i] = cr->mpb->ibuf[i];
+    }
+#endif
+#endif
+}
+
+void gmx_sumli(int nr,gmx_large_int_t r[],const t_commrec *cr)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumli");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        if (cr->nc.rank_intra == 0) 
+        {
+            MPI_Reduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,0,
+                       cr->nc.comm_intra);
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                          cr->nc.comm_inter);
+        }
+        else
+        {
+            /* This is here because of the silly MPI specification
+                that MPI_IN_PLACE should be put in sendbuf instead of recvbuf */
+            MPI_Reduce(r,NULL,nr,GMX_MPI_LARGE_INT,MPI_SUM,0,cr->nc.comm_intra);
+        }
+        MPI_Bcast(r,nr,GMX_MPI_LARGE_INT,0,cr->nc.comm_intra);
+    } 
+    else 
+    {
+        MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,cr->mpi_comm_mygroup);
+    }
+#else
+    int i;
+
+    if (nr > cr->mpb->libuf_alloc) {
+        cr->mpb->libuf_alloc = nr;
+        srenew(cr->mpb->libuf,cr->mpb->libuf_alloc);
+    }
+    if (cr->nc.bUse) {
+        /* Use two step summing */
+        MPI_Allreduce(r,cr->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                      cr->nc.comm_intra);
+        if (cr->nc.rank_intra == 0) {
+            /* Sum with the buffers reversed */
+            MPI_Allreduce(cr->mpb->libuf,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                          cr->nc.comm_inter);
+        }
+        MPI_Bcast(r,nr,GMX_MPI_LARGE_INT,0,cr->nc.comm_intra);
+    } else {
+        MPI_Allreduce(r,cr->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                      cr->mpi_comm_mygroup);
+        for(i=0; i<nr; i++)
+            r[i] = cr->mpb->libuf[i];
+    }
+#endif
+#endif
+}
+
+
+
+#ifdef GMX_MPI
+void gmx_sumd_comm(int nr,double r[],MPI_Comm mpi_comm)
+{
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_DOUBLE,MPI_SUM,mpi_comm);
+#else
+    /* this function is only used in code that is not performance critical,
+       (during setup, when comm_rec is not the appropriate communication  
+       structure), so this isn't as bad as it looks. */
+    double *buf;
+    int i;
+
+    snew(buf, nr);
+    MPI_Allreduce(r,buf,nr,MPI_DOUBLE,MPI_SUM,mpi_comm);
+    for(i=0; i<nr; i++)
+        r[i] = buf[i];
+    sfree(buf);
+#endif
+}
+#endif
+
+#ifdef GMX_MPI
+void gmx_sumf_comm(int nr,float r[],MPI_Comm mpi_comm)
+{
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_FLOAT,MPI_SUM,mpi_comm);
+#else
+    /* this function is only used in code that is not performance critical,
+       (during setup, when comm_rec is not the appropriate communication  
+       structure), so this isn't as bad as it looks. */
+    float *buf;
+    int i;
+
+    snew(buf, nr);
+    MPI_Allreduce(r,buf,nr,MPI_FLOAT,MPI_SUM,mpi_comm);
+    for(i=0; i<nr; i++)
+        r[i] = buf[i];
+    sfree(buf);
+#endif
+}
+#endif
+
+void gmx_sumd_sim(int nr,double r[],const gmx_multisim_t *ms)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_sumd_sim");
+#else
+  gmx_sumd_comm(nr,r,ms->mpi_comm_masters);
+#endif
+}
+
+void gmx_sumf_sim(int nr,float r[],const gmx_multisim_t *ms)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_sumf_sim");
+#else
+  gmx_sumf_comm(nr,r,ms->mpi_comm_masters);
+#endif
+}
+
+void gmx_sumi_sim(int nr,int r[], const gmx_multisim_t *ms)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumi_sim");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    MPI_Allreduce(MPI_IN_PLACE,r,nr,MPI_INT,MPI_SUM,ms->mpi_comm_masters);
+#else
+    /* this is thread-unsafe, but it will do for now: */
+    int i;
+
+    if (nr > ms->mpb->ibuf_alloc) {
+        ms->mpb->ibuf_alloc = nr;
+        srenew(ms->mpb->ibuf,ms->mpb->ibuf_alloc);
+    }
+    MPI_Allreduce(r,ms->mpb->ibuf,nr,MPI_INT,MPI_SUM,ms->mpi_comm_masters);
+    for(i=0; i<nr; i++)
+        r[i] = ms->mpb->ibuf[i];
+#endif
+#endif
+}
+
+void gmx_sumli_sim(int nr,gmx_large_int_t r[], const gmx_multisim_t *ms)
+{
+#ifndef GMX_MPI
+    gmx_call("gmx_sumli_sim");
+#else
+#if defined(MPI_IN_PLACE_EXISTS) || defined(GMX_THREADS)
+    MPI_Allreduce(MPI_IN_PLACE,r,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                  ms->mpi_comm_masters);
+#else
+    /* this is thread-unsafe, but it will do for now: */
+    int i;
+
+    if (nr > ms->mpb->libuf_alloc) {
+        ms->mpb->libuf_alloc = nr;
+        srenew(ms->mpb->libuf,ms->mpb->libuf_alloc);
+    }
+    MPI_Allreduce(r,ms->mpb->libuf,nr,GMX_MPI_LARGE_INT,MPI_SUM,
+                  ms->mpi_comm_masters);
+    for(i=0; i<nr; i++)
+        r[i] = ms->mpb->libuf[i];
+#endif
+#endif
+}
+
+
+void gmx_finalize(void)
+{
+#ifndef GMX_MPI
+  gmx_call("gmx_finalize");
+#else
+  int ret;
+
+  /* just as a check; we don't want to finalize twice */
+  int finalized;
+  MPI_Finalized(&finalized);
+  if (finalized)
+      return;
+
+  /* We sync the processes here to try to avoid problems
+   * with buggy MPI implementations that could cause
+   * unfinished processes to terminate.
+   */
+  MPI_Barrier(MPI_COMM_WORLD);
+
+  /*
+  if (DOMAINDECOMP(cr)) {
+    if (cr->npmenodes > 0 || cr->dd->bCartesian) 
+      MPI_Comm_free(&cr->mpi_comm_mygroup);
+    if (cr->dd->bCartesian)
+      MPI_Comm_free(&cr->mpi_comm_mysim);
+  }
+  */
+
+  /* Apparently certain mpich implementations cause problems
+   * with MPI_Finalize. In that case comment out MPI_Finalize.
+   */
+  if (debug)
+    fprintf(debug,"Will call MPI_Finalize now\n");
+
+  ret = MPI_Finalize();
+  if (debug)
+    fprintf(debug,"Return code from MPI_Finalize = %d\n",ret);
+#endif
+}
+
similarity index 100%
rename from src/gmxlib/nrnb.c
rename to src/gromacs/gmxlib/nrnb.c
similarity index 100%
rename from src/gmxlib/oenv.c
rename to src/gromacs/gmxlib/oenv.c
similarity index 100%
rename from src/gmxlib/pbc.c
rename to src/gromacs/gmxlib/pbc.c
diff --git a/src/gromacs/gmxlib/physics.c b/src/gromacs/gmxlib/physics.c
new file mode 100644 (file)
index 0000000..33ffdab
--- /dev/null
@@ -0,0 +1,127 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * $Id: molprop_util.c,v 1.51 2009/06/01 06:13:18 spoel Exp $
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 4.0.99
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+#include <stdio.h>
+#include "string2.h"
+#include "physics.h"
+       
+double convert2gmx(double x,int unit)
+{
+    switch (unit) 
+    {
+    case eg2cAngstrom:
+        return x*A2NM;
+    case eg2cNm:
+        return x;
+    case eg2cBohr:
+        return x*BOHR2NM;
+    case eg2cKcal_Mole:
+        return x/CAL2JOULE;
+    case eg2cHartree:
+        return x*ONE_4PI_EPS0/BOHR2NM;
+    case eg2cHartree_e:
+        return x*ONE_4PI_EPS0/BOHR2NM;
+    case eg2cAngstrom3:
+        return x*A2NM*A2NM*A2NM;
+    case eg2cCoulomb:
+        return x/E_CHARGE;
+    case eg2cDebye:
+        return x*DEBYE2ENM;
+    case eg2cElectron:
+        return x;
+    case eg2cBuckingham:
+        return x*A2NM*DEBYE2ENM;
+    default:
+        fprintf(stderr,"Unknown unit %d, not converting.\n",unit);
+    }  
+    return x;
+}
+
+double gmx2convert(double x,int unit)
+{
+    switch (unit) 
+    {
+    case eg2cAngstrom:
+        return x/A2NM;
+    case eg2cNm:
+        return x;
+    case eg2cBohr:
+        return x/BOHR2NM;
+    case eg2cKcal_Mole:
+        return x*CAL2JOULE;
+    case eg2cHartree:
+        return x/(ONE_4PI_EPS0/BOHR2NM);
+    case eg2cHartree_e:
+        return x/(ONE_4PI_EPS0/BOHR2NM);
+    case eg2cAngstrom3:
+        return x/(A2NM*A2NM*A2NM);
+    case eg2cCoulomb:
+        return x*E_CHARGE;
+    case eg2cDebye:
+        return x/DEBYE2ENM;
+    case eg2cElectron:
+        return x;
+    case eg2cBuckingham:
+        return x/(A2NM*DEBYE2ENM);
+    default:
+        fprintf(stderr,"Unknown unit %d, not converting.\n",unit);
+    }  
+    return x;
+}
+
+/* This has to have the same order as the enums. */
+static const char *eg2c_names[eg2cNR] = {
+    "Angstrom", "Nm", "Bohr", "Kcal_Mole", 
+    "Hartree", "Hartree_e", "Angstrom3", "Coulomb",
+    "Debye", "Electron", "Buckingham" 
+};
+
+int string2unit(char *string)
+{
+    int i;
+    
+    for(i=0; (i<eg2cNR); i++)
+        if (strcasecmp(string,eg2c_names[i]) == 0)
+            return i;
+    return -1;
+}
+
+const char *unit2string(int unit)
+{
+    if ((unit >= 0) && (unit < eg2cNR))
+        return eg2c_names[unit];
+        
+    return NULL;
+}
diff --git a/src/gromacs/gmxlib/physics_test.c b/src/gromacs/gmxlib/physics_test.c
new file mode 100644 (file)
index 0000000..323c54e
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include "physics.h"
+
+int main(int argc,char *argv[])
+{
+  int i;
+  double x,y,z;
+  
+  x = 3.25; 
+  for(i=0; (i<eg2cNR); i++) {
+    y = gmx2convert(x,i);
+    z = convert2gmx(y,i);
+    printf("Converted %g [type %d] to %g and back to %g. Diff %g\n",
+          x,i,y,z,x-z);
+  }
+}
similarity index 100%
rename from src/gmxlib/rbin.c
rename to src/gromacs/gmxlib/rbin.c
diff --git a/src/gromacs/gmxlib/statistics/gmx_statistics.c b/src/gromacs/gmxlib/statistics/gmx_statistics.c
new file mode 100644 (file)
index 0000000..339c2df
--- /dev/null
@@ -0,0 +1,800 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- */
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Green Red Orange Magenta Azure Cyan Skyblue
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "gmx_statistics.h"
+
+static double sqr(double x)
+{
+    return x*x;
+}
+
+static int gmx_nint(double x)
+{
+    return (int) (x+0.5);
+}
+
+typedef struct gmx_stats {
+    double aa,a,b,sigma_aa,sigma_a,sigma_b,aver,sigma_aver,error;
+    double rmsd,Rdata,Rfit,Rfitaa,chi2,chi2aa;
+    double *x,*y,*dx,*dy;
+    int    computed;
+    int    np,np_c,nalloc;
+} gmx_stats;
+
+gmx_stats_t gmx_stats_init()
+{
+    gmx_stats *stats;
+  
+    snew(stats,1);
+  
+    return (gmx_stats_t) stats;
+}
+
+int gmx_stats_get_npoints(gmx_stats_t gstats, int *N)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+  
+    *N = stats->np;
+  
+    return estatsOK;
+}
+
+int gmx_stats_done(gmx_stats_t gstats)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+  
+    sfree(stats->x);
+    stats->x = NULL;
+    sfree(stats->y);
+    stats->y = NULL;
+    sfree(stats->dx);
+    stats->dx = NULL;
+    sfree(stats->dy);
+    stats->dy = NULL;
+  
+    return estatsOK;
+}
+
+int gmx_stats_add_point(gmx_stats_t gstats,double x,double y,
+                        double dx,double dy)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int i;
+  
+    if (stats->np+1 >= stats->nalloc) 
+    {
+        if (stats->nalloc == 0) 
+            stats->nalloc = 1024;
+        else
+            stats->nalloc *= 2;
+        srenew(stats->x,stats->nalloc);
+        srenew(stats->y,stats->nalloc);
+        srenew(stats->dx,stats->nalloc);
+        srenew(stats->dy,stats->nalloc);
+        for(i=stats->np; (i<stats->nalloc); i++) 
+        {
+            stats->x[i]  = 0;
+            stats->y[i]  = 0;
+            stats->dx[i] = 0;
+            stats->dy[i] = 0;
+        }
+    }
+    stats->x[stats->np]  = x;
+    stats->y[stats->np]  = y;
+    stats->dx[stats->np] = dx;
+    stats->dy[stats->np] = dy;
+    stats->np++;
+    stats->computed = 0;
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_point(gmx_stats_t gstats,real *x,real *y,
+                        real *dx,real *dy,real level)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int  ok,outlier;
+    real rmsd,r;
+    
+    if ((ok = gmx_stats_get_rmsd(gstats,&rmsd)) != estatsOK)
+    {
+        return ok;
+    }
+    outlier = 0;
+    while ((outlier == 0) && (stats->np_c < stats->np))
+    {
+        r = fabs(stats->x[stats->np_c] - stats->y[stats->np_c]);
+        outlier = (r > rmsd*level);
+        if (outlier)
+        {
+            if (NULL != x)  *x  = stats->x[stats->np_c];
+            if (NULL != y)  *y  = stats->y[stats->np_c];
+            if (NULL != dx) *dx = stats->dx[stats->np_c];
+            if (NULL != dy) *dy = stats->dy[stats->np_c];
+        }
+        stats->np_c++;
+        
+        if (outlier)    
+            return estatsOK;
+    }
+    
+    stats->np_c = 0;
+  
+    return estatsNO_POINTS;
+}
+
+int gmx_stats_add_points(gmx_stats_t gstats,int n,real *x,real *y,
+                         real *dx,real *dy)
+{
+    int i,ok;
+  
+    for(i=0; (i<n); i++) 
+    {
+        if ((ok = gmx_stats_add_point(gstats,x[i],y[i],
+                                      (NULL != dx) ? dx[i] : 0,
+                                      (NULL != dy) ? dy[i] : 0)) != estatsOK)
+        {
+            return ok;
+        }
+    }
+    return estatsOK;
+}
+
+static int gmx_stats_compute(gmx_stats *stats,int weight)
+{
+    double yy,yx,xx,sx,sy,dy,chi2,chi2aa,d2;
+    double ssxx,ssyy,ssxy;
+    double w,wtot,yx_nw,sy_nw,sx_nw,yy_nw,xx_nw,dx2,dy2;
+    int i,N;
+  
+    N = stats->np;
+    if (stats->computed == 0) 
+    {
+        if (N < 1)
+        {
+            return estatsNO_POINTS;
+        }
+      
+        xx = xx_nw = 0;
+        yy = yy_nw = 0;
+        yx = yx_nw = 0;
+        sx = sx_nw = 0;
+        sy = sy_nw = 0;
+        wtot = 0;
+        d2   = 0;
+        for(i=0; (i<N); i++) 
+        {
+            d2 += sqr(stats->x[i]-stats->y[i]);
+            if ((stats->dy[i]) && (weight == elsqWEIGHT_Y))
+            {
+                w = 1/sqr(stats->dy[i]);
+            }
+            else
+            {
+                w = 1;
+            }
+            
+            wtot  += w;
+            
+            xx    += w*sqr(stats->x[i]);
+            xx_nw += sqr(stats->x[i]);
+            
+            yy    += w*sqr(stats->y[i]);
+            yy_nw += sqr(stats->y[i]);
+            
+            yx    += w*stats->y[i]*stats->x[i];
+            yx_nw += stats->y[i]*stats->x[i];
+            
+            sx    += w*stats->x[i];
+            sx_nw += stats->x[i];
+            
+            sy    += w*stats->y[i];
+            sy_nw += stats->y[i];
+        }
+      
+        /* Compute average, sigma and error */
+        stats->aver       = sy_nw/N;
+        stats->sigma_aver = sqrt(yy_nw/N - sqr(sy_nw/N));
+        stats->error      = stats->sigma_aver/sqrt(N);
+
+        /* Compute RMSD between x and y */
+        stats->rmsd = sqrt(d2/N);
+       
+        /* Correlation coefficient for data */
+        yx_nw /= N;
+        xx_nw /= N;
+        yy_nw /= N;
+        sx_nw /= N;
+        sy_nw /= N;
+        ssxx = N*(xx_nw - sqr(sx_nw));
+        ssyy = N*(yy_nw - sqr(sy_nw));
+        ssxy = N*(yx_nw - (sx_nw*sy_nw));
+        stats->Rdata = sqrt(sqr(ssxy)/(ssxx*ssyy)); 
+        
+        /* Compute straight line through datapoints, either with intercept
+           zero (result in aa) or with intercept variable (results in a
+           and b) */
+        yx = yx/wtot;
+        xx = xx/wtot;
+        sx = sx/wtot;
+        sy = sy/wtot;
+  
+        stats->aa = (yx/xx);  
+        stats->a  = (yx-sx*sy)/(xx-sx*sx);
+        stats->b  = (sy)-(stats->a)*(sx);
+    
+        /* Compute chi2, deviation from a line y = ax+b. Also compute
+           chi2aa which returns the deviation from a line y = ax. */
+        chi2   = 0;
+        chi2aa = 0;
+        for(i=0; (i<N); i++) 
+        {
+            if (stats->dy[i] > 0)
+            {
+                dy = stats->dy[i];
+            }
+            else
+            {
+                dy = 1;
+            }
+            chi2aa += sqr((stats->y[i]-(stats->aa*stats->x[i]))/dy);
+            chi2   += sqr((stats->y[i]-(stats->a*stats->x[i]+stats->b))/dy);
+        }
+        if (N > 2) 
+        {
+            stats->chi2   = sqrt(chi2/(N-2));
+            stats->chi2aa = sqrt(chi2aa/(N-2));
+            
+            /* Look up equations! */
+            dx2 = (xx-sx*sx);
+            dy2 = (yy-sy*sy);
+            stats->sigma_a = sqrt(stats->chi2/((N-2)*dx2));
+            stats->sigma_b = stats->sigma_a*sqrt(xx);
+            stats->Rfit    = fabs(ssxy)/sqrt(ssxx*ssyy);
+                /*stats->a*sqrt(dx2/dy2);*/
+            stats->Rfitaa  = stats->aa*sqrt(dx2/dy2);  
+        }
+        else
+        {
+            stats->chi2    = 0;
+            stats->chi2aa  = 0;
+            stats->sigma_a = 0;
+            stats->sigma_b = 0;
+            stats->Rfit    = 0;
+            stats->Rfitaa  = 0;
+        }    
+
+        stats->computed = 1;
+    }
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_ab(gmx_stats_t gstats,int weight,
+                     real *a,real *b,real *da,real *db,
+                     real *chi2,real *Rfit)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,weight)) != estatsOK)
+        return ok;
+    if (NULL != a)
+    {
+        *a    = stats->a;
+    }
+    if (NULL != b)   
+    {
+        *b    = stats->b;
+    }
+    if (NULL != da)  
+    {
+        *da   = stats->sigma_a;
+    }
+    if (NULL != db)  
+    {
+        *db   = stats->sigma_b;
+    }
+    if (NULL != chi2) 
+    {
+        *chi2 = stats->chi2;
+    }
+    if (NULL != Rfit) 
+    {
+        *Rfit = stats->Rfit;
+    }
+    
+    return estatsOK;
+}
+
+int gmx_stats_get_a(gmx_stats_t gstats,int weight,real *a,real *da,
+                    real *chi2,real *Rfit)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,weight)) != estatsOK)
+        return ok;
+    if (NULL != a)    *a    = stats->aa;
+    if (NULL != da)   *da   = stats->sigma_aa;
+    if (NULL != chi2) *chi2 = stats->chi2aa;
+    if (NULL != Rfit) *Rfit = stats->Rfitaa;
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_average(gmx_stats_t gstats,real *aver)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+    {
+        return ok;
+    }
+    
+    *aver = stats->aver;
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_ase(gmx_stats_t gstats,real *aver,real *sigma,real *error)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+    {
+        return ok;
+    }
+    
+    if (NULL != aver)
+    {
+        *aver  = stats->aver;
+    }
+    if (NULL != sigma) 
+    {
+        *sigma = stats->sigma_aver;
+    }
+    if (NULL != error) 
+    {
+        *error = stats->error;
+    }
+    
+    return estatsOK;
+}
+
+int gmx_stats_get_sigma(gmx_stats_t gstats,real *sigma)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+        return ok;
+
+    *sigma = stats->sigma_aver;
+    
+    return estatsOK;
+}
+
+int gmx_stats_get_error(gmx_stats_t gstats,real *error)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+        return ok;
+
+    *error = stats->error;
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_corr_coeff(gmx_stats_t gstats,real *R)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+        return ok;
+
+    *R = stats->Rdata;
+  
+    return estatsOK;
+}
+
+int gmx_stats_get_rmsd(gmx_stats_t gstats,real *rmsd)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int ok;
+  
+    if ((ok = gmx_stats_compute(stats,elsqWEIGHT_NONE)) != estatsOK)
+    {
+        return ok;
+    }
+    
+    *rmsd = stats->rmsd;
+  
+    return estatsOK;
+}
+
+int gmx_stats_dump_xy(gmx_stats_t gstats,FILE *fp)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int i,ok;
+  
+    for(i=0; (i<stats->np); i++) 
+    {
+        fprintf(fp,"%12g  %12g  %12g  %12g\n",stats->x[i],stats->y[i],
+                stats->dx[i],stats->dy[i]);
+    }
+    
+    return estatsOK;
+}
+
+int gmx_stats_remove_outliers(gmx_stats_t gstats,double level)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int  i,iter=1,done=0,ok;
+    real rmsd,r;
+  
+    while ((stats->np >= 10) && !done) 
+    {
+        if ((ok = gmx_stats_get_rmsd(gstats,&rmsd)) != estatsOK)
+        {
+            return ok;
+        }
+        done = 1;
+        for(i=0; (i<stats->np); ) 
+        {
+            r = fabs(stats->x[i]-stats->y[i]);
+            if (r > level*rmsd) 
+            {
+                fprintf(stderr,"Removing outlier, iter = %d, rmsd = %g, x = %g, y = %g\n",
+                        iter,rmsd,stats->x[i],stats->y[i]);
+                if (i < stats->np-1) 
+                {
+                    stats->x[i]  = stats->x[stats->np-1];
+                    stats->y[i]  = stats->y[stats->np-1];
+                    stats->dx[i] = stats->dx[stats->np-1];
+                    stats->dy[i] = stats->dy[stats->np-1];
+                }
+                stats->np--;
+                done = 0;
+            }
+            else 
+            {
+                i++;
+            }
+        }
+        iter++;
+    }
+    
+    return estatsOK;
+}
+
+int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nb,
+                             int ehisto,int normalized,real **x,real **y)
+{
+    gmx_stats *stats = (gmx_stats *) gstats;
+    int    i,ok,index=0,nbins=*nb,*nindex;
+    double minx,maxx,maxy,miny,delta,dd,minh;
+  
+    if (((binwidth <= 0) && (nbins <= 0)) ||
+        ((binwidth > 0) && (nbins > 0)))
+    {
+        return estatsINVALID_INPUT;
+    }
+    if (stats->np <= 2)
+    {
+        return estatsNO_POINTS;
+    }
+    minx = maxx = stats->x[0];
+    miny = maxy = stats->y[0];
+    for(i=1; (i<stats->np); i++) 
+    {
+        miny = (stats->y[i] < miny) ? stats->y[i] : miny;
+        maxy = (stats->y[i] > maxy) ? stats->y[i] : maxy;
+        minx = (stats->x[i] < minx) ? stats->x[i] : minx;
+        maxx = (stats->x[i] > maxx) ? stats->x[i] : maxx;
+    }
+    if (ehisto == ehistoX)
+    {
+        delta = maxx-minx;
+        minh = minx;
+    }
+    else if (ehisto == ehistoY)
+    {
+        delta = maxy-miny;
+        minh = miny;
+    }
+    else
+        return estatsINVALID_INPUT;
+        
+    if (binwidth == 0)
+    {
+        binwidth = (delta)/nbins;
+    }
+    else
+    {
+        nbins = gmx_nint((delta)/binwidth + 0.5);
+    }
+    snew(*x,nbins);
+    snew(nindex,nbins);
+    for(i=0; (i<nbins); i++) 
+    {
+        (*x)[i] = minh + binwidth*(i+0.5);
+    }
+    if (normalized == 0)
+    {
+        dd = 1;
+    }
+    else
+    {
+        dd = 1.0/(binwidth*stats->np);
+    }
+    
+    snew(*y,nbins);
+    for(i=0; (i<stats->np); i++) 
+    {
+        if (ehisto == ehistoY)
+            index = (stats->y[i]-miny)/binwidth;
+               else if (ehisto == ehistoX)
+            index = (stats->x[i]-minx)/binwidth;
+               if (index<0)
+               {
+                       index = 0;
+               }
+               if (index>nbins-1)
+               {
+                       index = nbins-1;
+               }
+        (*y)[index] += dd;
+        nindex[index]++;
+    }
+    if (*nb == 0)
+        *nb = nbins;
+    for(i=0; (i<nbins); i++)
+        if (nindex[i] > 0)
+            (*y)[i] /= nindex[i];
+            
+    sfree(nindex);
+    
+    return estatsOK;
+}
+
+static const char *stats_error[estatsNR] = 
+{
+    "All well in STATS land",
+    "No points",
+    "Not enough memory",
+    "Invalid histogram input",
+    "Unknown error",
+    "Not implemented yet"
+};
+
+const char *gmx_stats_message(int estats)
+{
+    if ((estats >= 0) && (estats < estatsNR))
+    {
+        return stats_error[estats];
+    }
+    else
+    {
+        return stats_error[estatsERROR];
+    }
+}
+    
+/* Old convenience functions, should be merged with the core
+   statistics above. */
+int lsq_y_ax(int n, real x[], real y[], real *a)
+{
+    gmx_stats_t lsq = gmx_stats_init();
+    int  ok;
+    real da,chi2,Rfit;
+  
+    gmx_stats_add_points(lsq,n,x,y,0,0);
+    if ((ok = gmx_stats_get_a(lsq,elsqWEIGHT_NONE,a,&da,&chi2,&Rfit)) != estatsOK)
+    {
+        return ok;
+    }
+    
+    /*  int    i;
+        double xx,yx;
+  
+        yx=xx=0.0;
+        for (i=0; i<n; i++) {
+        yx+=y[i]*x[i];
+        xx+=x[i]*x[i];
+        }
+        *a=yx/xx;
+        */
+    return estatsOK;
+}
+
+static int low_lsq_y_ax_b(int n, real *xr, double *xd, real yr[],
+                          real *a, real *b,real *r,real *chi2)
+{
+    int    i,ok;
+    gmx_stats_t lsq;
+  
+    lsq = gmx_stats_init();
+    for(i=0; (i<n); i++) 
+    {
+        if ((ok = gmx_stats_add_point(lsq,(NULL != xd) ? xd[i] : xr[i],yr[i],0,0)) 
+            != estatsOK)
+        {
+            return ok;
+        }
+    }
+    if ((ok = gmx_stats_get_ab(lsq,elsqWEIGHT_NONE,a,b,NULL,NULL,chi2,r)) != estatsOK)
+    {
+        return ok;
+    }
+    
+    return estatsOK;
+    /*
+      double x,y,yx,xx,yy,sx,sy,chi2;
+
+      yx=xx=yy=sx=sy=0.0;
+      for (i=0; i<n; i++) {
+      if (xd != NULL) {
+      x = xd[i];
+      } else {
+      x = xr[i];
+      }
+      y =   yr[i];
+
+      yx += y*x;
+      xx += x*x;
+      yy += y*y;
+      sx += x;
+      sy += y;
+      }
+      *a = (n*yx-sy*sx)/(n*xx-sx*sx);
+      *b = (sy-(*a)*sx)/n;
+      *r = sqrt((xx-sx*sx)/(yy-sy*sy));
+  
+      chi2 = 0;
+      if (xd != NULL) {
+      for(i=0; i<n; i++)
+      chi2 += sqr(yr[i] - ((*a)*xd[i] + (*b)));
+      } else {
+      for(i=0; i<n; i++)
+      chi2 += sqr(yr[i] - ((*a)*xr[i] + (*b)));
+      }
+  
+      if (n > 2)
+      return sqrt(chi2/(n-2));
+      else
+      return 0;
+    */
+}
+
+int lsq_y_ax_b(int n, real x[], real y[], real *a, real *b,real *r,real *chi2)
+{
+    return low_lsq_y_ax_b(n,x,NULL,y,a,b,r,chi2);
+}
+
+int lsq_y_ax_b_xdouble(int n, double x[], real y[], real *a, real *b,
+                       real *r,real *chi2)
+{
+    return low_lsq_y_ax_b(n,NULL,x,y,a,b,r,chi2);
+}
+
+int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
+                     real *a, real *b, real *da, real *db,
+                     real *r,real *chi2)
+{
+    gmx_stats_t lsq;
+    int    i,ok;
+  
+    lsq = gmx_stats_init();
+    for(i=0; (i<n); i++)
+    {
+        if ((ok = gmx_stats_add_point(lsq,x[i],y[i],0,dy[i])) != estatsOK)
+        {
+            return ok;
+        }
+    }
+    if ((ok = gmx_stats_get_ab(lsq,elsqWEIGHT_Y,a,b,da,db,chi2,r)) != estatsOK)
+    {
+        return ok;
+    }
+    if ((ok = gmx_stats_done(lsq)) != estatsOK)
+    {
+        return ok;
+    }
+    sfree(lsq);
+
+    return estatsOK;
+    /*
+      double sxy,sxx,syy,sx,sy,w,s_2,dx2,dy2,mins;
+
+      sxy=sxx=syy=sx=sy=w=0.0;
+      mins = dy[0];
+      for(i=1; (i<n); i++)
+      mins = min(mins,dy[i]);
+      if (mins <= 0)
+      gmx_fatal(FARGS,"Zero or negative weigths in linear regression analysis");
+    
+      for (i=0; i<n; i++) {
+      s_2  = sqr(1.0/dy[i]);
+      sxx += s_2*sqr(x[i]);
+      sxy += s_2*y[i]*x[i];
+      syy += s_2*sqr(y[i]);
+      sx  += s_2*x[i];
+      sy  += s_2*y[i];
+      w   += s_2;
+      }
+      sxx = sxx/w;
+      sxy = sxy/w;
+      syy = syy/w;
+      sx  = sx/w;
+      sy  = sy/w;
+      dx2 = (sxx-sx*sx);
+      dy2 = (syy-sy*sy);
+      *a=(sxy-sy*sx)/dx2;
+      *b=(sy-(*a)*sx);
+  
+      *chi2=0;
+      for(i=0; i<n; i++)
+      *chi2+=sqr((y[i]-((*a)*x[i]+(*b)))/dy[i]);
+      *chi2 = *chi2/w;
+  
+      *da = sqrt(*chi2/((n-2)*dx2));
+      *db = *da*sqrt(sxx);
+      *r  = *a*sqrt(dx2/dy2);
+  
+      if (debug)
+      fprintf(debug,"sx = %g, sy = %g, sxy = %g, sxx = %g, w = %g\n"
+      "chi2 = %g, dx2 = %g\n",
+      sx,sy,sxy,sxx,w,*chi2,dx2);
+  
+      if (n > 2)
+      *chi2 = sqrt(*chi2/(n-2));
+      else
+      *chi2 = 0;
+      */
+}
+
+
diff --git a/src/gromacs/gmxlib/string2.c b/src/gromacs/gmxlib/string2.c
new file mode 100644 (file)
index 0000000..9f06494
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+/* This file is completely threadsafe - keep it that way! */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef GMX_CRAY_XT3
+#undef HAVE_PWD_H
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <time.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <time.h>
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "string2.h"
+#include "futil.h"
+
+int continuing(char *s)
+/* strip trailing spaces and if s ends with a CONTINUE remove that too.
+ * returns TRUE if s ends with a CONTINUE, FALSE otherwise.
+ */
+{
+  int sl;
+
+  rtrim(s);
+  sl = strlen(s);
+  if ((sl > 0) && (s[sl-1] == CONTINUE)) {
+    s[sl-1] = 0;
+    return TRUE;
+  }
+  else
+    return FALSE;
+}
+
+
+
+char *fgets2(char *line, int n, FILE *stream)
+/* This routine reads a string from stream of max length n
+ * and zero terminated, without newlines
+ * line should be long enough (>= n)
+ */
+{
+  char *c;
+  if (fgets(line,n,stream) == NULL) {
+    return NULL;
+  }
+  if ((c=strchr(line,'\n')) != NULL) {
+    *c = '\0';
+  } else {
+    /* A line not ending in a newline can only occur at the end of a file,
+     * or because of n being too small.
+     * Since both cases occur very infrequently, we can check for EOF.
+     */
+    if (!gmx_eof(stream)) {
+      gmx_fatal(FARGS,"An input file contains a line longer than %d characters, while the buffer passed to fgets2 has size %d. The line starts with: '%20.20s'",n,n,line);
+    }
+  }
+  if ((c=strchr(line,'\r')) != NULL) {
+    *c = '\0';
+  }
+
+  return line;
+}
+
+void strip_comment (char *line)
+{
+  char *c;
+
+  if (!line)
+    return;
+
+  /* search for a comment mark and replace it by a zero */
+  if ((c = strchr(line,COMMENTSIGN)) != NULL) 
+    (*c) = 0;
+}
+
+void upstring (char *str)
+{
+  int i;
+
+  for (i=0; (i < (int)strlen(str)); i++) 
+    str[i] = toupper(str[i]);
+}
+
+void ltrim (char *str)
+{
+  char *tr;
+  int i,c;
+
+  if (NULL == str)
+    return;
+
+  c = 0;
+  while (('\0' != str[c]) && isspace(str[c]))
+    c++;
+  if (c > 0) 
+    {
+      for(i=c; ('\0' != str[i]); i++)
+       str[i-c] = str[i];
+      str[i-c] = '\0';
+    }
+}
+
+void rtrim (char *str)
+{
+  int nul;
+
+  if (NULL == str)
+    return;
+
+  nul = strlen(str)-1;
+  while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
+    str[nul] = '\0';
+    nul--;
+  }
+}
+
+void trim (char *str)
+{
+  ltrim (str);
+  rtrim (str);
+}
+
+char *
+gmx_ctime_r(const time_t *clock,char *buf, int n)
+{
+    char tmpbuf[STRLEN];
+  
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+    /* Windows */
+    ctime_s( tmpbuf, STRLEN, clock );
+#elif (defined(__sun))
+    /*Solaris*/
+    ctime_r(clock, tmpbuf, n);
+#else
+    ctime_r(clock,tmpbuf);
+#endif
+    strncpy(buf,tmpbuf,n-1);
+    buf[n-1]='\0';
+    
+    return buf;
+}
+          
+void nice_header (FILE *out,const char *fn)
+{
+  const char *unk = "onbekend";
+  time_t clock;
+  char   *user=NULL;
+  int    gh;
+  uid_t  uid;
+  char   buf[256];
+  char   timebuf[STRLEN];
+#ifdef HAVE_PWD_H
+  struct passwd *pw;
+#endif
+
+  /* Print a nice header above the file */
+  time(&clock);
+  fprintf (out,"%c\n",COMMENTSIGN);
+  fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
+  
+#ifdef HAVE_PWD_H
+  uid = getuid();
+  pw  = getpwuid(uid);
+  gh  = gethostname(buf,255);
+  user= pw->pw_name;
+#else
+  uid = 0;
+  gh  = -1;
+#endif
+  
+  gmx_ctime_r(&clock,timebuf,STRLEN);
+  fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
+          user ? user : unk,(int) uid);
+  fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
+
+  fprintf (out,"%c\tAt date: %s",COMMENTSIGN,timebuf);
+  fprintf (out,"%c\n",COMMENTSIGN);
+}
+
+int gmx_strcasecmp_min(const char *str1, const char *str2)
+{
+  char ch1,ch2;
+  
+  do
+    {
+      do
+       ch1=toupper(*(str1++));
+      while ((ch1=='-') || (ch1=='_'));
+      do 
+       ch2=toupper(*(str2++));
+      while ((ch2=='-') || (ch2=='_'));
+      if (ch1!=ch2) return (ch1-ch2);
+    }
+  while (ch1);
+  return 0; 
+}
+
+int gmx_strncasecmp_min(const char *str1, const char *str2, int n)
+{
+  char ch1,ch2;
+  char *stri1, *stri2;
+
+  stri1=(char *)str1;
+  stri2=(char *)str2;  
+  do
+    {
+      do
+       ch1=toupper(*(str1++));
+      while ((ch1=='-') || (ch1=='_'));
+      do 
+       ch2=toupper(*(str2++));
+      while ((ch2=='-') || (ch2=='_'));
+      if (ch1!=ch2) return (ch1-ch2);
+    }
+  while (ch1 && (str1-stri1<n) && (str2-stri2<n));
+  return 0; 
+}
+
+int gmx_strcasecmp(const char *str1, const char *str2)
+{
+  char ch1,ch2;
+  
+  do
+    {
+      ch1=toupper(*(str1++));
+      ch2=toupper(*(str2++));
+      if (ch1!=ch2) return (ch1-ch2);
+    }
+  while (ch1);
+  return 0; 
+}
+
+int gmx_strncasecmp(const char *str1, const char *str2, int n)
+{
+  char ch1,ch2;
+  if(n==0) 
+    return 0;
+
+  do
+    {
+      ch1=toupper(*(str1++));
+      ch2=toupper(*(str2++));
+      if (ch1!=ch2) return (ch1-ch2);
+      n--;
+    }
+  while (ch1 && n);
+  return 0; 
+}
+
+char *gmx_strdup(const char *src)
+{
+  char *dest;
+
+  snew(dest,strlen(src)+1);
+  strcpy(dest,src);
+  
+  return dest;
+}
+
+char *
+gmx_strndup(const char *src, int n)
+{
+    int   len;
+    char *dest;
+
+    len = strlen(src);
+    if (len > n) 
+    {
+        len = n;
+    }
+    snew(dest, len+1);
+    strncpy(dest, src, len);
+    dest[len] = 0;
+    return dest;
+}
+
+/*!
+ * \param[in] pattern  Pattern to match against.
+ * \param[in] str      String to match.
+ * \returns   0 on match, GMX_NO_WCMATCH if there is no match.
+ *
+ * Matches \p str against \p pattern, which may contain * and ? wildcards.
+ * All other characters are matched literally.
+ * Currently, it is not possible to match literal * or ?.
+ */
+int
+gmx_wcmatch(const char *pattern, const char *str)
+{
+    while (*pattern)
+    {
+        if (*pattern == '*')
+        {
+            /* Skip multiple wildcards in a sequence */
+            while (*pattern == '*' || *pattern == '?')
+            {
+                ++pattern;
+                /* For ?, we need to check that there are characters left
+                 * in str. */
+                if (*pattern == '?')
+                {
+                    if (*str == 0)
+                    {
+                        return GMX_NO_WCMATCH;
+                    }
+                    else
+                    {
+                        ++str;
+                    }
+                }
+            }
+            /* If the pattern ends after the star, we have a match */
+            if (*pattern == 0)
+            {
+                return 0;
+            }
+            /* Match the rest against each possible suffix of str */
+            while (*str)
+            {
+                /* Only do the recursive call if the first character
+                 * matches. We don't have to worry about wildcards here,
+                 * since we have processed them above. */
+                if (*pattern == *str)
+                {
+                    int rc;
+                    /* Match the suffix, and return if a match or an error */
+                    rc = gmx_wcmatch(pattern, str);
+                    if (rc != GMX_NO_WCMATCH)
+                    {
+                        return rc;
+                    }
+                }
+                ++str;
+            }
+            /* If no suffix of str matches, we don't have a match */
+            return GMX_NO_WCMATCH;
+        }
+        else if ((*pattern == '?' && *str != 0) || *pattern == *str)
+        {
+            ++str;
+        }
+        else
+        {
+            return GMX_NO_WCMATCH;
+        }
+        ++pattern;
+    }
+    /* When the pattern runs out, we have a match if the string has ended. */
+    return (*str == 0) ? 0 : GMX_NO_WCMATCH;
+}
+
+char *wrap_lines(const char *buf,int line_width, int indent,gmx_bool bIndentFirst)
+{
+  char *b2;
+  int i,i0,i2,j,b2len,lspace=0,l2space=0;
+  gmx_bool bFirst,bFitsOnLine;
+
+  /* characters are copied from buf to b2 with possible spaces changed
+   * into newlines and extra space added for indentation.
+   * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
+   * i0 points to the beginning of the current line (in buf, source)
+   * lspace and l2space point to the last space on the current line
+   * bFirst is set to prevent indentation of first line
+   * bFitsOnLine says if the first space occurred before line_width, if 
+   * that is not the case, we have a word longer than line_width which 
+   * will also not fit on the next line, so we might as well keep it on 
+   * the current line (where it also won't fit, but looks better)
+   */
+  
+  b2=NULL;
+  b2len=strlen(buf)+1+indent;
+  snew(b2,b2len);
+  i0=i2=0;
+  if (bIndentFirst)
+    for(i2=0; (i2<indent); i2++)
+      b2[i2] = ' ';
+  bFirst=TRUE;
+  do {
+    l2space = -1;
+    /* find the last space before end of line */
+    for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
+      b2[i2++] = buf[i];
+      /* remember the position of a space */
+      if (buf[i] == ' ') {
+        lspace = i;
+       l2space = i2-1;
+      }
+      /* if we have a newline before the line is full, reset counters */
+      if (buf[i]=='\n' && buf[i+1]) { 
+       i0=i+1;
+       b2len+=indent;
+       srenew(b2, b2len);
+       /* add indentation after the newline */
+       for(j=0; (j<indent); j++)
+         b2[i2++]=' ';
+      }
+    }
+    /* If we are at the last newline, copy it */
+    if (buf[i]=='\n' && !buf[i+1]) {
+      b2[i2++] = buf[i++];
+    }
+    /* if we're not at the end of the string */
+    if (buf[i]) {
+      /* check if one word does not fit on the line */
+      bFitsOnLine = (i-i0 <= line_width);
+      /* reset line counters to just after the space */
+      i0 = lspace+1;
+      i2 = l2space+1;
+      /* if the words fit on the line, and we're beyond the indentation part */
+      if ( (bFitsOnLine) && (l2space >= indent) ) {
+       /* start a new line */
+       b2[l2space] = '\n';
+       /* and add indentation */
+       if (indent) {
+         if (bFirst) {
+           line_width-=indent;
+           bFirst=FALSE;
+         }
+         b2len+=indent;
+         srenew(b2, b2len);
+         for(j=0; (j<indent); j++)
+           b2[i2++]=' ';
+         /* no extra spaces after indent; */
+         while(buf[i0]==' ')
+           i0++;
+       }
+      }
+    }
+  } while (buf[i]);
+  b2[i2] = '\0';
+  
+  return b2;
+}
+
+char **split(char sep,const char *str)
+{
+  char **ptr = NULL;
+  int  n,nn,nptr = 0;
+  
+  if (str == NULL)
+    return NULL;
+  nn = strlen(str);
+  for(n=0; (n<nn); n++)
+    if (str[n] == sep)
+      nptr++;
+  snew(ptr,nptr+2);
+  nptr = 0;
+  while (*str != '\0') {
+    while ((*str != '\0') && (*str == sep))
+      str++;
+    if (*str != '\0') {
+      snew(ptr[nptr],1+strlen(str));
+      n = 0;
+      while ((*str != '\0') && (*str != sep)) {
+       ptr[nptr][n] = *str;
+       str++;
+       n++;
+      }
+      ptr[nptr][n] = '\0';
+      nptr++;
+    }
+  }
+  ptr[nptr] = NULL;
+  
+  return ptr;
+}
+
+
+gmx_large_int_t
+str_to_large_int_t(const char *str, char **endptr)
+{
+       int         sign = 1;
+       gmx_large_int_t  val  = 0;
+       char        ch;
+       const char  *p;
+       
+       p = str;
+       if(p==NULL)
+       {
+               *endptr=NULL;
+               return 0;
+       }
+       
+       /* Strip off initial white space */
+       while(isspace(*p))
+       {
+               p++;
+       }
+       /* Conform to ISO C99 - return original pointer if string does not contain a number */
+       if(*str=='\0')
+       {
+               *endptr=(char *)str;
+       }
+       
+       if(*p=='-')
+       {
+               p++;
+               sign *= -1;
+       }
+       
+       while( ((ch=*p) != '\0') && isdigit(ch) )
+       {
+               /* Important to add sign here, so we dont overflow in final multiplication */
+               ch = (ch-'0')*sign; 
+               val = val*10 + ch;
+               if(ch != val%10) 
+               {
+                       /* Some sort of overflow has occured, set endptr to original string */
+                       *endptr=(char *)str;
+                       errno = ERANGE;
+                       return(0);
+               }
+               p++;
+       }
+       
+       *endptr=(char *)p;
+       
+       return val;
+}
+
+char *gmx_strsep(char **stringp, const char *delim)
+{
+    char *ret;
+    int len=strlen(delim);
+    int i,j=0;
+    int found=0;
+
+    if (! *stringp)
+        return NULL;
+    ret=*stringp;
+    do
+    {
+        if ( (*stringp)[j] == '\0')
+        {
+            found=1;
+            *stringp=NULL;
+            break;
+        }
+        for (i=0;i<len;i++)
+        {
+            if ( (*stringp)[j]==delim[i])
+            {
+                (*stringp)[j]='\0';
+                *stringp=*stringp+j+1;
+                found=1;
+                break;
+            }
+        }
+        j++;
+    } while (!found);
+
+    return ret;
+}
+
diff --git a/src/gromacs/gmxlib/tpxio.c b/src/gromacs/gmxlib/tpxio.c
new file mode 100644 (file)
index 0000000..e0b8a15
--- /dev/null
@@ -0,0 +1,2482 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* This file is completely threadsafe - keep it that way! */
+#ifdef GMX_THREADS
+#include <thread_mpi.h>
+#endif
+
+
+#include <ctype.h>
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "string2.h"
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "names.h"
+#include "symtab.h"
+#include "futil.h"
+#include "filenm.h"
+#include "gmxfio.h"
+#include "topsort.h"
+#include "tpxio.h"
+#include "txtdump.h"
+#include "confio.h"
+#include "atomprop.h"
+#include "copyrite.h"
+#include "vec.h"
+#include "mtop_util.h"
+
+/* This number should be increased whenever the file format changes! */
+static const int tpx_version = 75;
+
+/* This number should only be increased when you edit the TOPOLOGY section
+ * of the tpx format. This way we can maintain forward compatibility too
+ * for all analysis tools and/or external programs that only need to
+ * know the atom/residue names, charges, and bond connectivity.
+ *  
+ * It first appeared in tpx version 26, when I also moved the inputrecord
+ * to the end of the tpx file, so we can just skip it if we only
+ * want the topology.
+ */
+static const int tpx_generation = 23;
+
+/* This number should be the most recent backwards incompatible version 
+ * I.e., if this number is 9, we cannot read tpx version 9 with this code.
+ */
+static const int tpx_incompatible_version = 9;
+
+
+
+/* Struct used to maintain tpx compatibility when function types are added */
+typedef struct {
+  int fvnr; /* file version number in which the function type first appeared */
+  int ftype; /* function type */
+} t_ftupd;
+
+/* 
+ *The entries should be ordered in:
+ * 1. ascending file version number
+ * 2. ascending function type number
+ */
+/*static const t_ftupd ftupd[] = {
+  { 20, F_CUBICBONDS        },
+  { 20, F_CONNBONDS         },
+  { 20, F_HARMONIC          },
+  { 20, F_EQM,              },
+  { 22, F_DISRESVIOL        },
+  { 22, F_ORIRES            },
+  { 22, F_ORIRESDEV         },
+  { 26, F_FOURDIHS          },
+  { 26, F_PIDIHS            },
+  { 26, F_DIHRES            },
+  { 26, F_DIHRESVIOL        },
+  { 30, F_CROSS_BOND_BONDS  },
+  { 30, F_CROSS_BOND_ANGLES },
+  { 30, F_UREY_BRADLEY      },
+  { 30, F_POLARIZATION      }
+  };*/
+  
+/* 
+ *The entries should be ordered in:
+ * 1. ascending function type number
+ * 2. ascending file version number
+ */
+static const t_ftupd ftupd[] = {
+  { 20, F_CUBICBONDS        },
+  { 20, F_CONNBONDS         },
+  { 20, F_HARMONIC          },
+  { 34, F_FENEBONDS         },
+  { 43, F_TABBONDS          },
+  { 43, F_TABBONDSNC        },
+  { 70, F_RESTRBONDS        },
+  { 30, F_CROSS_BOND_BONDS  },
+  { 30, F_CROSS_BOND_ANGLES },
+  { 30, F_UREY_BRADLEY      },
+  { 34, F_QUARTIC_ANGLES    },
+  { 43, F_TABANGLES         },
+  { 26, F_FOURDIHS          },
+  { 26, F_PIDIHS            },
+  { 43, F_TABDIHS           },
+  { 65, F_CMAP              },
+  { 60, F_GB12              },
+  { 61, F_GB13              },
+  { 61, F_GB14              }, 
+  { 72, F_GBPOL             },
+  { 72, F_NPSOLVATION       },
+  { 41, F_LJC14_Q           },
+  { 41, F_LJC_PAIRS_NB      },
+  { 32, F_BHAM_LR           },
+  { 32, F_RF_EXCL           },
+  { 32, F_COUL_RECIP        },
+  { 46, F_DPD               },
+  { 30, F_POLARIZATION      },
+  { 36, F_THOLE_POL         },
+  { 22, F_DISRESVIOL        },
+  { 22, F_ORIRES            },
+  { 22, F_ORIRESDEV         },
+  { 26, F_DIHRES            },
+  { 26, F_DIHRESVIOL        },
+  { 49, F_VSITE4FDN         },
+  { 50, F_VSITEN            },
+  { 46, F_COM_PULL          },
+  { 20, F_EQM               },
+  { 46, F_ECONSERVED        },
+  { 69, F_VTEMP             },
+  { 66, F_PDISPCORR         },
+  { 54, F_DHDL_CON          },
+};
+#define NFTUPD asize(ftupd)
+
+/* Needed for backward compatibility */
+#define MAXNODES 256
+
+static void _do_section(t_fileio *fio,int key,gmx_bool bRead,const char *src,
+                        int line)
+{
+  char buf[STRLEN];
+  gmx_bool bDbg;
+
+  if (gmx_fio_getftp(fio) == efTPA) {
+    if (!bRead) {
+      gmx_fio_write_string(fio,itemstr[key]);
+      bDbg       = gmx_fio_getdebug(fio);
+      gmx_fio_setdebug(fio,FALSE);
+      gmx_fio_write_string(fio,comment_str[key]);
+      gmx_fio_setdebug(fio,bDbg);
+    }
+    else {
+      if (gmx_fio_getdebug(fio))
+       fprintf(stderr,"Looking for section %s (%s, %d)",
+               itemstr[key],src,line);
+      
+      do {
+       gmx_fio_do_string(fio,buf);
+      } while ((gmx_strcasecmp(buf,itemstr[key]) != 0));
+      
+      if (gmx_strcasecmp(buf,itemstr[key]) != 0) 
+       gmx_fatal(FARGS,"\nCould not find section heading %s",itemstr[key]);
+      else if (gmx_fio_getdebug(fio))
+       fprintf(stderr," and found it\n");
+    }
+  }
+}
+
+#define do_section(fio,key,bRead) _do_section(fio,key,bRead,__FILE__,__LINE__)
+
+/**************************************************************
+ *
+ * Now the higer level routines that do io of the structures and arrays
+ *
+ **************************************************************/
+static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, gmx_bool bRead, 
+                       int file_version)
+{
+  gmx_bool bDum=TRUE;
+  int  i;
+
+  gmx_fio_do_int(fio,pgrp->nat);
+  if (bRead)
+    snew(pgrp->ind,pgrp->nat);
+  bDum=gmx_fio_ndo_int(fio,pgrp->ind,pgrp->nat);
+  gmx_fio_do_int(fio,pgrp->nweight);
+  if (bRead)
+    snew(pgrp->weight,pgrp->nweight);
+  bDum=gmx_fio_ndo_real(fio,pgrp->weight,pgrp->nweight);
+  gmx_fio_do_int(fio,pgrp->pbcatom);
+  gmx_fio_do_rvec(fio,pgrp->vec);
+  gmx_fio_do_rvec(fio,pgrp->init);
+  gmx_fio_do_real(fio,pgrp->rate);
+  gmx_fio_do_real(fio,pgrp->k);
+  if (file_version >= 56) {
+    gmx_fio_do_real(fio,pgrp->kB);
+  } else {
+    pgrp->kB = pgrp->k;
+  }
+}
+
+static void do_pull(t_fileio *fio, t_pull *pull,gmx_bool bRead, int file_version)
+{
+  int g;
+
+  gmx_fio_do_int(fio,pull->ngrp);
+  gmx_fio_do_int(fio,pull->eGeom);
+  gmx_fio_do_ivec(fio,pull->dim);
+  gmx_fio_do_real(fio,pull->cyl_r1);
+  gmx_fio_do_real(fio,pull->cyl_r0);
+  gmx_fio_do_real(fio,pull->constr_tol);
+  gmx_fio_do_int(fio,pull->nstxout);
+  gmx_fio_do_int(fio,pull->nstfout);
+  if (bRead)
+    snew(pull->grp,pull->ngrp+1);
+  for(g=0; g<pull->ngrp+1; g++)
+    do_pullgrp(fio,&pull->grp[g],bRead,file_version);
+}
+
+
+static void do_rotgrp(t_fileio *fio, t_rotgrp *rotg,gmx_bool bRead, int file_version)
+{
+  gmx_bool bDum=TRUE;
+  int  i;
+
+  gmx_fio_do_int(fio,rotg->eType);
+  gmx_fio_do_int(fio,rotg->bMassW);
+  gmx_fio_do_int(fio,rotg->nat);
+  if (bRead)
+    snew(rotg->ind,rotg->nat);
+  gmx_fio_ndo_int(fio,rotg->ind,rotg->nat);
+  if (bRead)
+      snew(rotg->x_ref,rotg->nat);
+  gmx_fio_ndo_rvec(fio,rotg->x_ref,rotg->nat);
+  gmx_fio_do_rvec(fio,rotg->vec);
+  gmx_fio_do_rvec(fio,rotg->pivot);
+  gmx_fio_do_real(fio,rotg->rate);
+  gmx_fio_do_real(fio,rotg->k);
+  gmx_fio_do_real(fio,rotg->slab_dist);
+  gmx_fio_do_real(fio,rotg->min_gaussian);
+  gmx_fio_do_real(fio,rotg->eps);
+  gmx_fio_do_int(fio,rotg->eFittype);
+  if (file_version >= 75)
+  {
+      gmx_fio_do_int(fio,rotg->PotAngle_nstep);
+      gmx_fio_do_real(fio,rotg->PotAngle_step);
+  }
+}
+
+static void do_rot(t_fileio *fio, t_rot *rot,gmx_bool bRead, int file_version)
+{
+  int g;
+
+  gmx_fio_do_int(fio,rot->ngrp);
+  gmx_fio_do_int(fio,rot->nstrout);
+  gmx_fio_do_int(fio,rot->nstsout);
+  if (bRead)
+    snew(rot->grp,rot->ngrp);
+  for(g=0; g<rot->ngrp; g++)
+    do_rotgrp(fio, &rot->grp[g],bRead,file_version);
+}
+
+
+static void do_inputrec(t_fileio *fio, t_inputrec *ir,gmx_bool bRead, 
+                        int file_version, real *fudgeQQ)
+{
+    int  i,j,k,*tmp,idum=0; 
+    gmx_bool bDum=TRUE;
+    real rdum,bd_temp;
+    rvec vdum;
+    gmx_bool bSimAnn;
+    real zerotemptime,finish_t,init_temp,finish_temp;
+    
+    if (file_version != tpx_version)
+    {
+        /* Give a warning about features that are not accessible */
+        fprintf(stderr,"Note: tpx file_version %d, software version %d\n",
+                file_version,tpx_version);
+    }
+
+    if (bRead)
+    {
+        init_inputrec(ir);
+    }
+
+    if (file_version == 0)
+    {
+        return;
+    }
+
+    /* Basic inputrec stuff */  
+    gmx_fio_do_int(fio,ir->eI); 
+    if (file_version >= 62) {
+      gmx_fio_do_gmx_large_int(fio, ir->nsteps);
+    } else {
+      gmx_fio_do_int(fio,idum);
+      ir->nsteps = idum;
+    }
+    if(file_version > 25) {
+      if (file_version >= 62) {
+       gmx_fio_do_gmx_large_int(fio, ir->init_step);
+      } else {
+       gmx_fio_do_int(fio,idum);
+       ir->init_step = idum;
+      }
+    }  else {
+      ir->init_step=0;
+    }
+
+       if(file_version >= 58)
+         gmx_fio_do_int(fio,ir->simulation_part);
+       else
+         ir->simulation_part=1;
+         
+    if (file_version >= 67) {
+      gmx_fio_do_int(fio,ir->nstcalcenergy);
+    } else {
+      ir->nstcalcenergy = 1;
+    }
+    if (file_version < 53) {
+      /* The pbc info has been moved out of do_inputrec,
+       * since we always want it, also without reading the inputrec.
+       */
+      gmx_fio_do_int(fio,ir->ePBC);
+      if ((file_version <= 15) && (ir->ePBC == 2))
+       ir->ePBC = epbcNONE;
+      if (file_version >= 45) {
+       gmx_fio_do_int(fio,ir->bPeriodicMols);
+      } else {
+       if (ir->ePBC == 2) {
+         ir->ePBC = epbcXYZ;
+         ir->bPeriodicMols = TRUE;
+       } else {
+       ir->bPeriodicMols = FALSE;
+       }
+      }
+    }
+    gmx_fio_do_int(fio,ir->ns_type);
+    gmx_fio_do_int(fio,ir->nstlist);
+    gmx_fio_do_int(fio,ir->ndelta);
+    if (file_version < 41) {
+      gmx_fio_do_int(fio,idum);
+      gmx_fio_do_int(fio,idum);
+    }
+    if (file_version >= 45)
+      gmx_fio_do_real(fio,ir->rtpi);
+    else
+      ir->rtpi = 0.05;
+    gmx_fio_do_int(fio,ir->nstcomm); 
+    if (file_version > 34)
+      gmx_fio_do_int(fio,ir->comm_mode);
+    else if (ir->nstcomm < 0) 
+      ir->comm_mode = ecmANGULAR;
+    else
+      ir->comm_mode = ecmLINEAR;
+    ir->nstcomm = abs(ir->nstcomm);
+    
+    if(file_version > 25)
+      gmx_fio_do_int(fio,ir->nstcheckpoint);
+    else
+      ir->nstcheckpoint=0;
+    
+    gmx_fio_do_int(fio,ir->nstcgsteep); 
+
+    if(file_version>=30)
+      gmx_fio_do_int(fio,ir->nbfgscorr); 
+    else if (bRead)
+      ir->nbfgscorr = 10;
+
+    gmx_fio_do_int(fio,ir->nstlog); 
+    gmx_fio_do_int(fio,ir->nstxout); 
+    gmx_fio_do_int(fio,ir->nstvout); 
+    gmx_fio_do_int(fio,ir->nstfout); 
+    gmx_fio_do_int(fio,ir->nstenergy); 
+    gmx_fio_do_int(fio,ir->nstxtcout); 
+    if (file_version >= 59) {
+      gmx_fio_do_double(fio,ir->init_t);
+      gmx_fio_do_double(fio,ir->delta_t);
+    } else {
+      gmx_fio_do_real(fio,rdum);
+      ir->init_t = rdum;
+      gmx_fio_do_real(fio,rdum);
+      ir->delta_t = rdum;
+    }
+    gmx_fio_do_real(fio,ir->xtcprec); 
+    if (file_version < 19) {
+      gmx_fio_do_int(fio,idum); 
+      gmx_fio_do_int(fio,idum);
+    }
+    if(file_version < 18)
+      gmx_fio_do_int(fio,idum); 
+    gmx_fio_do_real(fio,ir->rlist); 
+    if (file_version >= 67) {
+      gmx_fio_do_real(fio,ir->rlistlong);
+    }
+    gmx_fio_do_int(fio,ir->coulombtype); 
+    if (file_version < 32 && ir->coulombtype == eelRF)
+      ir->coulombtype = eelRF_NEC;      
+    gmx_fio_do_real(fio,ir->rcoulomb_switch); 
+    gmx_fio_do_real(fio,ir->rcoulomb); 
+    gmx_fio_do_int(fio,ir->vdwtype);
+    gmx_fio_do_real(fio,ir->rvdw_switch); 
+    gmx_fio_do_real(fio,ir->rvdw); 
+    if (file_version < 67) {
+      ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
+    }
+    gmx_fio_do_int(fio,ir->eDispCorr); 
+    gmx_fio_do_real(fio,ir->epsilon_r);
+    if (file_version >= 37) {
+      gmx_fio_do_real(fio,ir->epsilon_rf);
+    } else {
+      if (EEL_RF(ir->coulombtype)) {
+       ir->epsilon_rf = ir->epsilon_r;
+       ir->epsilon_r  = 1.0;
+      } else {
+       ir->epsilon_rf = 1.0;
+      }
+    }
+    if (file_version >= 29)
+      gmx_fio_do_real(fio,ir->tabext);
+    else
+      ir->tabext=1.0;
+    if(file_version > 25) {
+      gmx_fio_do_int(fio,ir->gb_algorithm);
+      gmx_fio_do_int(fio,ir->nstgbradii);
+      gmx_fio_do_real(fio,ir->rgbradii);
+      gmx_fio_do_real(fio,ir->gb_saltconc);
+      gmx_fio_do_int(fio,ir->implicit_solvent);
+    } else {
+      ir->gb_algorithm=egbSTILL;
+      ir->nstgbradii=1;
+      ir->rgbradii=1.0;
+      ir->gb_saltconc=0;
+      ir->implicit_solvent=eisNO;
+    }
+       if(file_version>=55)
+       {
+               gmx_fio_do_real(fio,ir->gb_epsilon_solvent);
+               gmx_fio_do_real(fio,ir->gb_obc_alpha);
+               gmx_fio_do_real(fio,ir->gb_obc_beta);
+               gmx_fio_do_real(fio,ir->gb_obc_gamma);
+               if(file_version>=60)
+               {
+                       gmx_fio_do_real(fio,ir->gb_dielectric_offset);
+                       gmx_fio_do_int(fio,ir->sa_algorithm);
+               }
+               else
+               {
+                       ir->gb_dielectric_offset = 0.009;
+                       ir->sa_algorithm = esaAPPROX;
+               }
+               gmx_fio_do_real(fio,ir->sa_surface_tension);
+
+    /* Override sa_surface_tension if it is not changed in the mpd-file */
+    if(ir->sa_surface_tension<0)
+    {
+      if(ir->gb_algorithm==egbSTILL)
+      {
+        ir->sa_surface_tension = 0.0049 * 100 * CAL2JOULE;
+      }
+      else if(ir->gb_algorithm==egbHCT || ir->gb_algorithm==egbOBC)
+      {
+        ir->sa_surface_tension = 0.0054 * 100 * CAL2JOULE;
+      }
+    }
+    
+       }
+       else
+       {
+               /* Better use sensible values than insane (0.0) ones... */
+               ir->gb_epsilon_solvent = 80;
+               ir->gb_obc_alpha       = 1.0;
+               ir->gb_obc_beta        = 0.8;
+               ir->gb_obc_gamma       = 4.85;
+               ir->sa_surface_tension = 2.092;
+       }
+
+         
+    gmx_fio_do_int(fio,ir->nkx); 
+    gmx_fio_do_int(fio,ir->nky); 
+    gmx_fio_do_int(fio,ir->nkz);
+    gmx_fio_do_int(fio,ir->pme_order);
+    gmx_fio_do_real(fio,ir->ewald_rtol);
+
+    if (file_version >=24) 
+      gmx_fio_do_int(fio,ir->ewald_geometry);
+    else
+      ir->ewald_geometry=eewg3D;
+
+    if (file_version <=17) {
+      ir->epsilon_surface=0;
+      if (file_version==17)
+       gmx_fio_do_int(fio,idum);
+    } 
+    else
+      gmx_fio_do_real(fio,ir->epsilon_surface);
+    
+    gmx_fio_do_gmx_bool(fio,ir->bOptFFT);
+
+    gmx_fio_do_gmx_bool(fio,ir->bContinuation); 
+    gmx_fio_do_int(fio,ir->etc);
+    /* before version 18, ir->etc was a gmx_bool (ir->btc),
+     * but the values 0 and 1 still mean no and
+     * berendsen temperature coupling, respectively.
+     */
+    if (file_version >= 71)
+    {
+        gmx_fio_do_int(fio,ir->nsttcouple);
+    }
+    else
+    {
+        ir->nsttcouple = ir->nstcalcenergy;
+    }
+    if (file_version <= 15)
+    {
+        gmx_fio_do_int(fio,idum);
+    }
+    if (file_version <=17)
+    {
+        gmx_fio_do_int(fio,ir->epct); 
+        if (file_version <= 15)
+        {
+            if (ir->epct == 5)
+            {
+                ir->epct = epctSURFACETENSION;
+            }
+            gmx_fio_do_int(fio,idum);
+        }
+        ir->epct -= 1;
+        /* we have removed the NO alternative at the beginning */
+        if(ir->epct==-1)
+        {
+            ir->epc=epcNO;
+            ir->epct=epctISOTROPIC;
+        } 
+        else
+        {
+            ir->epc=epcBERENDSEN;
+        }
+    } 
+    else
+    {
+        gmx_fio_do_int(fio,ir->epc);
+        gmx_fio_do_int(fio,ir->epct);
+    }
+    if (file_version >= 71)
+    {
+        gmx_fio_do_int(fio,ir->nstpcouple);
+    }
+    else
+    {
+        ir->nstpcouple = ir->nstcalcenergy;
+    }
+    gmx_fio_do_real(fio,ir->tau_p); 
+    if (file_version <= 15) {
+      gmx_fio_do_rvec(fio,vdum);
+      clear_mat(ir->ref_p);
+      for(i=0; i<DIM; i++)
+       ir->ref_p[i][i] = vdum[i];
+    } else {
+      gmx_fio_do_rvec(fio,ir->ref_p[XX]);
+      gmx_fio_do_rvec(fio,ir->ref_p[YY]);
+      gmx_fio_do_rvec(fio,ir->ref_p[ZZ]);
+    }
+    if (file_version <= 15) {
+      gmx_fio_do_rvec(fio,vdum);
+      clear_mat(ir->compress);
+      for(i=0; i<DIM; i++)
+       ir->compress[i][i] = vdum[i];
+    } 
+    else {
+      gmx_fio_do_rvec(fio,ir->compress[XX]);
+      gmx_fio_do_rvec(fio,ir->compress[YY]);
+      gmx_fio_do_rvec(fio,ir->compress[ZZ]);
+    }
+    if (file_version >= 47) {
+      gmx_fio_do_int(fio,ir->refcoord_scaling);
+      gmx_fio_do_rvec(fio,ir->posres_com);
+      gmx_fio_do_rvec(fio,ir->posres_comB);
+    } else {
+      ir->refcoord_scaling = erscNO;
+      clear_rvec(ir->posres_com);
+      clear_rvec(ir->posres_comB);
+    }
+    if(file_version > 25)
+      gmx_fio_do_int(fio,ir->andersen_seed);
+    else
+      ir->andersen_seed=0;
+    
+    if(file_version < 26) {
+      gmx_fio_do_gmx_bool(fio,bSimAnn); 
+      gmx_fio_do_real(fio,zerotemptime);
+    }
+    
+    if (file_version < 37)
+      gmx_fio_do_real(fio,rdum); 
+
+    gmx_fio_do_real(fio,ir->shake_tol);
+    if (file_version < 54)
+      gmx_fio_do_real(fio,*fudgeQQ);
+    gmx_fio_do_int(fio,ir->efep);
+    if (file_version <= 14 && ir->efep > efepNO)
+      ir->efep = efepYES;
+    if (file_version >= 59) {
+      gmx_fio_do_double(fio, ir->init_lambda); 
+      gmx_fio_do_double(fio, ir->delta_lambda);
+    } else {
+      gmx_fio_do_real(fio,rdum);
+      ir->init_lambda = rdum;
+      gmx_fio_do_real(fio,rdum);
+      ir->delta_lambda = rdum;
+    }
+    if (file_version >= 64) {
+      gmx_fio_do_int(fio,ir->n_flambda);
+      if (bRead) {
+       snew(ir->flambda,ir->n_flambda);
+      }
+      bDum=gmx_fio_ndo_double(fio,ir->flambda,ir->n_flambda);
+    } else {
+      ir->n_flambda = 0;
+      ir->flambda   = NULL;
+    }
+    if (file_version >= 13)
+      gmx_fio_do_real(fio,ir->sc_alpha);
+    else
+      ir->sc_alpha = 0;
+    if (file_version >= 38)
+      gmx_fio_do_int(fio,ir->sc_power);
+    else
+      ir->sc_power = 2;
+    if (file_version >= 15)
+      gmx_fio_do_real(fio,ir->sc_sigma);
+    else
+      ir->sc_sigma = 0.3;
+    if (bRead)
+    {
+        if (file_version >= 71)
+        {
+            ir->sc_sigma_min = ir->sc_sigma;
+        }
+        else
+        {
+            ir->sc_sigma_min = 0;
+        }
+    }
+    if (file_version >= 64) {
+      gmx_fio_do_int(fio,ir->nstdhdl);
+    } else {
+      ir->nstdhdl = 1;
+    }
+
+    if (file_version >= 73)
+    {
+        gmx_fio_do_int(fio, ir->separate_dhdl_file);
+        gmx_fio_do_int(fio, ir->dhdl_derivatives);
+    }
+    else
+    {
+        ir->separate_dhdl_file = sepdhdlfileYES;
+        ir->dhdl_derivatives = dhdlderivativesYES;
+    }
+
+    if (file_version >= 71)
+    {
+        gmx_fio_do_int(fio,ir->dh_hist_size);
+        gmx_fio_do_double(fio,ir->dh_hist_spacing);
+    }
+    else
+    {
+        ir->dh_hist_size    = 0;
+        ir->dh_hist_spacing = 0.1;
+    }
+    if (file_version >= 57) {
+      gmx_fio_do_int(fio,ir->eDisre); 
+    }
+    gmx_fio_do_int(fio,ir->eDisreWeighting); 
+    if (file_version < 22) {
+      if (ir->eDisreWeighting == 0)
+       ir->eDisreWeighting = edrwEqual;
+      else
+       ir->eDisreWeighting = edrwConservative;
+    }
+    gmx_fio_do_gmx_bool(fio,ir->bDisreMixed); 
+    gmx_fio_do_real(fio,ir->dr_fc); 
+    gmx_fio_do_real(fio,ir->dr_tau); 
+    gmx_fio_do_int(fio,ir->nstdisreout);
+    if (file_version >= 22) {
+      gmx_fio_do_real(fio,ir->orires_fc);
+      gmx_fio_do_real(fio,ir->orires_tau);
+      gmx_fio_do_int(fio,ir->nstorireout);
+    } else {
+      ir->orires_fc = 0;
+      ir->orires_tau = 0;
+      ir->nstorireout = 0;
+    }
+    if(file_version >= 26) {
+      gmx_fio_do_real(fio,ir->dihre_fc);
+      if (file_version < 56) {
+       gmx_fio_do_real(fio,rdum);
+       gmx_fio_do_int(fio,idum);
+      }
+    } else {
+      ir->dihre_fc=0;
+    }
+
+    gmx_fio_do_real(fio,ir->em_stepsize); 
+    gmx_fio_do_real(fio,ir->em_tol); 
+    if (file_version >= 22) 
+      gmx_fio_do_gmx_bool(fio,ir->bShakeSOR);
+    else if (bRead)
+      ir->bShakeSOR = TRUE;
+    if (file_version >= 11)
+      gmx_fio_do_int(fio,ir->niter);
+    else if (bRead) {
+      ir->niter = 25;
+      fprintf(stderr,"Note: niter not in run input file, setting it to %d\n",
+             ir->niter);
+    }
+    if (file_version >= 21)
+      gmx_fio_do_real(fio,ir->fc_stepsize);
+    else
+      ir->fc_stepsize = 0;
+    gmx_fio_do_int(fio,ir->eConstrAlg);
+    gmx_fio_do_int(fio,ir->nProjOrder);
+    gmx_fio_do_real(fio,ir->LincsWarnAngle);
+    if (file_version <= 14)
+      gmx_fio_do_int(fio,idum);
+    if (file_version >=26)
+      gmx_fio_do_int(fio,ir->nLincsIter);
+    else if (bRead) {
+      ir->nLincsIter = 1;
+      fprintf(stderr,"Note: nLincsIter not in run input file, setting it to %d\n",
+             ir->nLincsIter);
+    }
+    if (file_version < 33)
+      gmx_fio_do_real(fio,bd_temp);
+    gmx_fio_do_real(fio,ir->bd_fric);
+    gmx_fio_do_int(fio,ir->ld_seed);
+    if (file_version >= 33) {
+      for(i=0; i<DIM; i++)
+       gmx_fio_do_rvec(fio,ir->deform[i]);
+    } else {
+      for(i=0; i<DIM; i++)
+       clear_rvec(ir->deform[i]);
+    }
+    if (file_version >= 14)
+      gmx_fio_do_real(fio,ir->cos_accel);
+    else if (bRead)
+      ir->cos_accel = 0;
+    gmx_fio_do_int(fio,ir->userint1); 
+    gmx_fio_do_int(fio,ir->userint2); 
+    gmx_fio_do_int(fio,ir->userint3); 
+    gmx_fio_do_int(fio,ir->userint4); 
+    gmx_fio_do_real(fio,ir->userreal1); 
+    gmx_fio_do_real(fio,ir->userreal2); 
+    gmx_fio_do_real(fio,ir->userreal3); 
+    gmx_fio_do_real(fio,ir->userreal4); 
+    
+    /* pull stuff */
+    if (file_version >= 48) {
+      gmx_fio_do_int(fio,ir->ePull);
+      if (ir->ePull != epullNO) {
+       if (bRead)
+         snew(ir->pull,1);
+       do_pull(fio, ir->pull,bRead,file_version);
+      }
+    } else {
+      ir->ePull = epullNO;
+    }
+    
+    /* Enforced rotation */
+    if (file_version >= 74) {
+        gmx_fio_do_int(fio,ir->bRot);
+        if (ir->bRot == TRUE) {
+            if (bRead)
+                snew(ir->rot,1);
+            do_rot(fio, ir->rot,bRead,file_version);
+        }
+    } else {
+        ir->bRot = FALSE;
+    }
+    
+    /* grpopts stuff */
+    gmx_fio_do_int(fio,ir->opts.ngtc); 
+    if (file_version >= 69) {
+      gmx_fio_do_int(fio,ir->opts.nhchainlength);
+    } else {
+      ir->opts.nhchainlength = 1;
+    }
+    gmx_fio_do_int(fio,ir->opts.ngacc); 
+    gmx_fio_do_int(fio,ir->opts.ngfrz); 
+    gmx_fio_do_int(fio,ir->opts.ngener);
+    
+    if (bRead) {
+      snew(ir->opts.nrdf,   ir->opts.ngtc); 
+      snew(ir->opts.ref_t,  ir->opts.ngtc); 
+      snew(ir->opts.annealing, ir->opts.ngtc); 
+      snew(ir->opts.anneal_npoints, ir->opts.ngtc); 
+      snew(ir->opts.anneal_time, ir->opts.ngtc); 
+      snew(ir->opts.anneal_temp, ir->opts.ngtc); 
+      snew(ir->opts.tau_t,  ir->opts.ngtc); 
+      snew(ir->opts.nFreeze,ir->opts.ngfrz); 
+      snew(ir->opts.acc,    ir->opts.ngacc); 
+      snew(ir->opts.egp_flags,ir->opts.ngener*ir->opts.ngener);
+    } 
+    if (ir->opts.ngtc > 0) {
+      if (bRead && file_version<13) {
+       snew(tmp,ir->opts.ngtc);
+       bDum=gmx_fio_ndo_int(fio,tmp, ir->opts.ngtc);
+       for(i=0; i<ir->opts.ngtc; i++)
+         ir->opts.nrdf[i] = tmp[i];
+       sfree(tmp);
+      } else {
+       bDum=gmx_fio_ndo_real(fio,ir->opts.nrdf, ir->opts.ngtc);
+      }
+      bDum=gmx_fio_ndo_real(fio,ir->opts.ref_t,ir->opts.ngtc); 
+      bDum=gmx_fio_ndo_real(fio,ir->opts.tau_t,ir->opts.ngtc); 
+      if (file_version<33 && ir->eI==eiBD) {
+       for(i=0; i<ir->opts.ngtc; i++)
+         ir->opts.tau_t[i] = bd_temp;
+      }
+    }
+    if (ir->opts.ngfrz > 0) 
+      bDum=gmx_fio_ndo_ivec(fio,ir->opts.nFreeze,ir->opts.ngfrz);
+    if (ir->opts.ngacc > 0) 
+      gmx_fio_ndo_rvec(fio,ir->opts.acc,ir->opts.ngacc); 
+    if (file_version >= 12)
+      bDum=gmx_fio_ndo_int(fio,ir->opts.egp_flags,
+                           ir->opts.ngener*ir->opts.ngener);
+
+    if(bRead && file_version < 26) {
+      for(i=0;i<ir->opts.ngtc;i++) {
+       if(bSimAnn) {
+         ir->opts.annealing[i] = eannSINGLE;
+         ir->opts.anneal_npoints[i] = 2;
+         snew(ir->opts.anneal_time[i],2);
+         snew(ir->opts.anneal_temp[i],2);
+         /* calculate the starting/ending temperatures from reft, zerotemptime, and nsteps */
+         finish_t = ir->init_t + ir->nsteps * ir->delta_t;
+         init_temp = ir->opts.ref_t[i]*(1-ir->init_t/zerotemptime);
+         finish_temp = ir->opts.ref_t[i]*(1-finish_t/zerotemptime);
+         ir->opts.anneal_time[i][0] = ir->init_t;
+         ir->opts.anneal_time[i][1] = finish_t;
+         ir->opts.anneal_temp[i][0] = init_temp;
+         ir->opts.anneal_temp[i][1] = finish_temp;
+       } else {
+         ir->opts.annealing[i] = eannNO;
+         ir->opts.anneal_npoints[i] = 0;
+       }
+      }
+    } else {
+      /* file version 26 or later */
+      /* First read the lists with annealing and npoints for each group */
+      bDum=gmx_fio_ndo_int(fio,ir->opts.annealing,ir->opts.ngtc);
+      bDum=gmx_fio_ndo_int(fio,ir->opts.anneal_npoints,ir->opts.ngtc);
+      for(j=0;j<(ir->opts.ngtc);j++) {
+       k=ir->opts.anneal_npoints[j];
+       if(bRead) {
+         snew(ir->opts.anneal_time[j],k);
+         snew(ir->opts.anneal_temp[j],k);
+       }
+       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_time[j],k);
+       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_temp[j],k);
+      }
+    }
+    /* Walls */
+    if (file_version >= 45) {
+      gmx_fio_do_int(fio,ir->nwall);
+      gmx_fio_do_int(fio,ir->wall_type);
+      if (file_version >= 50)
+       gmx_fio_do_real(fio,ir->wall_r_linpot);
+      else
+       ir->wall_r_linpot = -1;
+      gmx_fio_do_int(fio,ir->wall_atomtype[0]);
+      gmx_fio_do_int(fio,ir->wall_atomtype[1]);
+      gmx_fio_do_real(fio,ir->wall_density[0]);
+      gmx_fio_do_real(fio,ir->wall_density[1]);
+      gmx_fio_do_real(fio,ir->wall_ewald_zfac);
+    } else {
+      ir->nwall = 0;
+      ir->wall_type = 0;
+      ir->wall_atomtype[0] = -1;
+      ir->wall_atomtype[1] = -1;
+      ir->wall_density[0] = 0;
+      ir->wall_density[1] = 0;
+      ir->wall_ewald_zfac = 3;
+    }
+    /* Cosine stuff for electric fields */
+    for(j=0; (j<DIM); j++) {
+      gmx_fio_do_int(fio,ir->ex[j].n);
+      gmx_fio_do_int(fio,ir->et[j].n);
+      if (bRead) {
+       snew(ir->ex[j].a,  ir->ex[j].n);
+       snew(ir->ex[j].phi,ir->ex[j].n);
+       snew(ir->et[j].a,  ir->et[j].n);
+       snew(ir->et[j].phi,ir->et[j].n);
+      }
+      bDum=gmx_fio_ndo_real(fio,ir->ex[j].a,  ir->ex[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->ex[j].phi,ir->ex[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->et[j].a,  ir->et[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->et[j].phi,ir->et[j].n);
+    }
+    
+    /* QMMM stuff */
+    if(file_version>=39){
+      gmx_fio_do_gmx_bool(fio,ir->bQMMM);
+      gmx_fio_do_int(fio,ir->QMMMscheme);
+      gmx_fio_do_real(fio,ir->scalefactor);
+      gmx_fio_do_int(fio,ir->opts.ngQM);
+      if (bRead) {
+        snew(ir->opts.QMmethod,    ir->opts.ngQM);
+        snew(ir->opts.QMbasis,     ir->opts.ngQM);
+        snew(ir->opts.QMcharge,    ir->opts.ngQM);
+        snew(ir->opts.QMmult,      ir->opts.ngQM);
+        snew(ir->opts.bSH,         ir->opts.ngQM);
+        snew(ir->opts.CASorbitals, ir->opts.ngQM);
+        snew(ir->opts.CASelectrons,ir->opts.ngQM);
+        snew(ir->opts.SAon,        ir->opts.ngQM);
+        snew(ir->opts.SAoff,       ir->opts.ngQM);
+        snew(ir->opts.SAsteps,     ir->opts.ngQM);
+        snew(ir->opts.bOPT,        ir->opts.ngQM);
+        snew(ir->opts.bTS,         ir->opts.ngQM);
+      }
+      if (ir->opts.ngQM > 0) {
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmethod,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMbasis,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMcharge,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmult,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bSH,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.CASorbitals,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.CASelectrons,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_real(fio,ir->opts.SAon,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_real(fio,ir->opts.SAoff,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.SAsteps,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bOPT,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_gmx_bool(fio,ir->opts.bTS,ir->opts.ngQM);
+      }
+      /* end of QMMM stuff */
+    }    
+}
+
+
+static void do_harm(t_fileio *fio, t_iparams *iparams,gmx_bool bRead)
+{
+  gmx_fio_do_real(fio,iparams->harmonic.rA);
+  gmx_fio_do_real(fio,iparams->harmonic.krA);
+  gmx_fio_do_real(fio,iparams->harmonic.rB);
+  gmx_fio_do_real(fio,iparams->harmonic.krB);
+}
+
+void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
+                gmx_bool bRead, int file_version)
+{
+  int i;
+  gmx_bool bDum;
+  real rdum;
+  
+  if (!bRead)
+    gmx_fio_set_comment(fio, interaction_function[ftype].name);
+  switch (ftype) {
+  case F_ANGLES:
+  case F_G96ANGLES:
+  case F_BONDS:
+  case F_G96BONDS:
+  case F_HARMONIC:
+  case F_IDIHS:
+    do_harm(fio, iparams,bRead);
+    if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && bRead) {
+      /* Correct incorrect storage of parameters */
+      iparams->pdihs.phiB = iparams->pdihs.phiA;
+      iparams->pdihs.cpB  = iparams->pdihs.cpA;
+    }
+    break;
+  case F_FENEBONDS:
+    gmx_fio_do_real(fio,iparams->fene.bm);
+    gmx_fio_do_real(fio,iparams->fene.kb);
+    break;
+  case F_RESTRBONDS:
+    gmx_fio_do_real(fio,iparams->restraint.lowA);
+    gmx_fio_do_real(fio,iparams->restraint.up1A);
+    gmx_fio_do_real(fio,iparams->restraint.up2A);
+    gmx_fio_do_real(fio,iparams->restraint.kA);
+    gmx_fio_do_real(fio,iparams->restraint.lowB);
+    gmx_fio_do_real(fio,iparams->restraint.up1B);
+    gmx_fio_do_real(fio,iparams->restraint.up2B);
+    gmx_fio_do_real(fio,iparams->restraint.kB);
+    break;
+  case F_TABBONDS:
+  case F_TABBONDSNC:
+  case F_TABANGLES:
+  case F_TABDIHS:
+    gmx_fio_do_real(fio,iparams->tab.kA);
+    gmx_fio_do_int(fio,iparams->tab.table);
+    gmx_fio_do_real(fio,iparams->tab.kB);
+    break;
+  case F_CROSS_BOND_BONDS:
+    gmx_fio_do_real(fio,iparams->cross_bb.r1e);
+    gmx_fio_do_real(fio,iparams->cross_bb.r2e);
+    gmx_fio_do_real(fio,iparams->cross_bb.krr);
+    break;
+  case F_CROSS_BOND_ANGLES:
+    gmx_fio_do_real(fio,iparams->cross_ba.r1e);
+    gmx_fio_do_real(fio,iparams->cross_ba.r2e);
+    gmx_fio_do_real(fio,iparams->cross_ba.r3e);
+    gmx_fio_do_real(fio,iparams->cross_ba.krt);
+    break;
+  case F_UREY_BRADLEY:
+    gmx_fio_do_real(fio,iparams->u_b.theta);
+    gmx_fio_do_real(fio,iparams->u_b.ktheta);
+    gmx_fio_do_real(fio,iparams->u_b.r13);
+    gmx_fio_do_real(fio,iparams->u_b.kUB);
+    break;
+  case F_QUARTIC_ANGLES:
+    gmx_fio_do_real(fio,iparams->qangle.theta);
+    bDum=gmx_fio_ndo_real(fio,iparams->qangle.c,5);
+    break;
+  case F_BHAM:
+    gmx_fio_do_real(fio,iparams->bham.a);
+    gmx_fio_do_real(fio,iparams->bham.b);
+    gmx_fio_do_real(fio,iparams->bham.c);
+    break;
+  case F_MORSE:
+    gmx_fio_do_real(fio,iparams->morse.b0);
+    gmx_fio_do_real(fio,iparams->morse.cb);
+    gmx_fio_do_real(fio,iparams->morse.beta);
+    break;
+  case F_CUBICBONDS:
+    gmx_fio_do_real(fio,iparams->cubic.b0);
+    gmx_fio_do_real(fio,iparams->cubic.kb);
+    gmx_fio_do_real(fio,iparams->cubic.kcub);
+    break;
+  case F_CONNBONDS:
+    break;
+  case F_POLARIZATION:
+    gmx_fio_do_real(fio,iparams->polarize.alpha);
+    break;
+  case F_WATER_POL:
+    if (file_version < 31) 
+      gmx_fatal(FARGS,"Old tpr files with water_polarization not supported. Make a new.");
+    gmx_fio_do_real(fio,iparams->wpol.al_x);
+    gmx_fio_do_real(fio,iparams->wpol.al_y);
+    gmx_fio_do_real(fio,iparams->wpol.al_z);
+    gmx_fio_do_real(fio,iparams->wpol.rOH);
+    gmx_fio_do_real(fio,iparams->wpol.rHH);
+    gmx_fio_do_real(fio,iparams->wpol.rOD);
+    break;
+  case F_THOLE_POL:
+    gmx_fio_do_real(fio,iparams->thole.a);
+    gmx_fio_do_real(fio,iparams->thole.alpha1);
+    gmx_fio_do_real(fio,iparams->thole.alpha2);
+    gmx_fio_do_real(fio,iparams->thole.rfac);
+    break;
+  case F_LJ:
+    gmx_fio_do_real(fio,iparams->lj.c6);
+    gmx_fio_do_real(fio,iparams->lj.c12);
+    break;
+  case F_LJ14:
+    gmx_fio_do_real(fio,iparams->lj14.c6A);
+    gmx_fio_do_real(fio,iparams->lj14.c12A);
+    gmx_fio_do_real(fio,iparams->lj14.c6B);
+    gmx_fio_do_real(fio,iparams->lj14.c12B);
+    break;
+  case F_LJC14_Q:
+    gmx_fio_do_real(fio,iparams->ljc14.fqq);
+    gmx_fio_do_real(fio,iparams->ljc14.qi);
+    gmx_fio_do_real(fio,iparams->ljc14.qj);
+    gmx_fio_do_real(fio,iparams->ljc14.c6);
+    gmx_fio_do_real(fio,iparams->ljc14.c12);
+    break;
+  case F_LJC_PAIRS_NB:
+    gmx_fio_do_real(fio,iparams->ljcnb.qi);
+    gmx_fio_do_real(fio,iparams->ljcnb.qj);
+    gmx_fio_do_real(fio,iparams->ljcnb.c6);
+    gmx_fio_do_real(fio,iparams->ljcnb.c12);
+    break;
+  case F_PDIHS:
+  case F_PIDIHS:
+  case F_ANGRES:
+  case F_ANGRESZ:
+    gmx_fio_do_real(fio,iparams->pdihs.phiA);
+    gmx_fio_do_real(fio,iparams->pdihs.cpA);
+    if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && file_version < 42) {
+      /* Read the incorrectly stored multiplicity */
+      gmx_fio_do_real(fio,iparams->harmonic.rB);
+      gmx_fio_do_real(fio,iparams->harmonic.krB);
+      iparams->pdihs.phiB = iparams->pdihs.phiA;
+      iparams->pdihs.cpB  = iparams->pdihs.cpA;
+    } else {
+      gmx_fio_do_real(fio,iparams->pdihs.phiB);
+      gmx_fio_do_real(fio,iparams->pdihs.cpB);
+      gmx_fio_do_int(fio,iparams->pdihs.mult);
+    }
+    break;
+  case F_DISRES:
+    gmx_fio_do_int(fio,iparams->disres.label);
+    gmx_fio_do_int(fio,iparams->disres.type);
+    gmx_fio_do_real(fio,iparams->disres.low);
+    gmx_fio_do_real(fio,iparams->disres.up1);
+    gmx_fio_do_real(fio,iparams->disres.up2);
+    gmx_fio_do_real(fio,iparams->disres.kfac);
+    break;
+  case F_ORIRES:
+    gmx_fio_do_int(fio,iparams->orires.ex);
+    gmx_fio_do_int(fio,iparams->orires.label);
+    gmx_fio_do_int(fio,iparams->orires.power);
+    gmx_fio_do_real(fio,iparams->orires.c);
+    gmx_fio_do_real(fio,iparams->orires.obs);
+    gmx_fio_do_real(fio,iparams->orires.kfac);
+    break;
+  case F_DIHRES:
+    gmx_fio_do_int(fio,iparams->dihres.power);
+    gmx_fio_do_int(fio,iparams->dihres.label);
+    gmx_fio_do_real(fio,iparams->dihres.phi);
+    gmx_fio_do_real(fio,iparams->dihres.dphi);
+    gmx_fio_do_real(fio,iparams->dihres.kfac);
+    break;
+  case F_POSRES:
+    gmx_fio_do_rvec(fio,iparams->posres.pos0A);
+    gmx_fio_do_rvec(fio,iparams->posres.fcA);
+    if (bRead && file_version < 27) {
+      copy_rvec(iparams->posres.pos0A,iparams->posres.pos0B);
+      copy_rvec(iparams->posres.fcA,iparams->posres.fcB);
+    } else {
+      gmx_fio_do_rvec(fio,iparams->posres.pos0B);
+      gmx_fio_do_rvec(fio,iparams->posres.fcB);
+    }
+    break;
+  case F_RBDIHS:
+    bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA,NR_RBDIHS);
+    if(file_version>=25) 
+      bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB,NR_RBDIHS);
+    break;
+  case F_FOURDIHS:
+    /* Fourier dihedrals are internally represented
+     * as Ryckaert-Bellemans since those are faster to compute.
+     */
+     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA, NR_RBDIHS);
+     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB, NR_RBDIHS);
+    break;
+  case F_CONSTR:
+  case F_CONSTRNC:
+    gmx_fio_do_real(fio,iparams->constr.dA);
+    gmx_fio_do_real(fio,iparams->constr.dB);
+    break;
+  case F_SETTLE:
+    gmx_fio_do_real(fio,iparams->settle.doh);
+    gmx_fio_do_real(fio,iparams->settle.dhh);
+    break;
+  case F_VSITE2:
+    gmx_fio_do_real(fio,iparams->vsite.a);
+    break;
+  case F_VSITE3:
+  case F_VSITE3FD:
+  case F_VSITE3FAD:
+    gmx_fio_do_real(fio,iparams->vsite.a);
+    gmx_fio_do_real(fio,iparams->vsite.b);
+    break;
+  case F_VSITE3OUT:
+  case F_VSITE4FD: 
+  case F_VSITE4FDN: 
+    gmx_fio_do_real(fio,iparams->vsite.a);
+    gmx_fio_do_real(fio,iparams->vsite.b);
+    gmx_fio_do_real(fio,iparams->vsite.c);
+    break;
+  case F_VSITEN:
+    gmx_fio_do_int(fio,iparams->vsiten.n);
+    gmx_fio_do_real(fio,iparams->vsiten.a);
+    break;
+  case F_GB12:
+  case F_GB13:
+  case F_GB14:
+    /* We got rid of some parameters in version 68 */
+    if(bRead && file_version<68)
+    {
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+    }
+       gmx_fio_do_real(fio,iparams->gb.sar);   
+       gmx_fio_do_real(fio,iparams->gb.st);
+       gmx_fio_do_real(fio,iparams->gb.pi);
+       gmx_fio_do_real(fio,iparams->gb.gbr);
+       gmx_fio_do_real(fio,iparams->gb.bmlt);
+       break;
+  case F_CMAP:
+       gmx_fio_do_int(fio,iparams->cmap.cmapA);
+       gmx_fio_do_int(fio,iparams->cmap.cmapB);
+    break;
+  default:
+    gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
+               
+               ftype,interaction_function[ftype].name,__FILE__,__LINE__);
+  }
+  if (!bRead)
+    gmx_fio_unset_comment(fio);
+}
+
+static void do_ilist(t_fileio *fio, t_ilist *ilist,gmx_bool bRead,int file_version,
+                    int ftype)
+{
+  int  i,k,idum;
+  gmx_bool bDum=TRUE;
+  
+  if (!bRead) {
+    gmx_fio_set_comment(fio, interaction_function[ftype].name);
+  }
+  if (file_version < 44) {
+    for(i=0; i<MAXNODES; i++)
+      gmx_fio_do_int(fio,idum);
+  }
+  gmx_fio_do_int(fio,ilist->nr);
+  if (bRead)
+    snew(ilist->iatoms,ilist->nr);
+  bDum=gmx_fio_ndo_int(fio,ilist->iatoms,ilist->nr);
+  if (!bRead)
+    gmx_fio_unset_comment(fio);
+}
+
+static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
+                       gmx_bool bRead, int file_version)
+{
+  int  idum,i,j;
+  gmx_bool bDum=TRUE;
+  unsigned int k;
+
+  gmx_fio_do_int(fio,ffparams->atnr);
+  if (file_version < 57) {
+    gmx_fio_do_int(fio,idum);
+  }
+  gmx_fio_do_int(fio,ffparams->ntypes);
+  if (bRead && debug)
+    fprintf(debug,"ffparams->atnr = %d, ntypes = %d\n",
+           ffparams->atnr,ffparams->ntypes);
+  if (bRead) {
+    snew(ffparams->functype,ffparams->ntypes);
+    snew(ffparams->iparams,ffparams->ntypes);
+  }
+  /* Read/write all the function types */
+  bDum=gmx_fio_ndo_int(fio,ffparams->functype,ffparams->ntypes);
+  if (bRead && debug)
+    pr_ivec(debug,0,"functype",ffparams->functype,ffparams->ntypes,TRUE);
+
+  if (file_version >= 66) {
+    gmx_fio_do_double(fio,ffparams->reppow);
+  } else {
+    ffparams->reppow = 12.0;
+  }
+
+  if (file_version >= 57) {
+    gmx_fio_do_real(fio,ffparams->fudgeQQ);
+  }
+
+  /* Check whether all these function types are supported by the code.
+   * In practice the code is backwards compatible, which means that the
+   * numbering may have to be altered from old numbering to new numbering
+   */
+  for (i=0; (i<ffparams->ntypes); i++) {
+    if (bRead)
+      /* Loop over file versions */
+      for (k=0; (k<NFTUPD); k++)
+       /* Compare the read file_version to the update table */
+       if ((file_version < ftupd[k].fvnr) && 
+           (ffparams->functype[i] >= ftupd[k].ftype)) {
+         ffparams->functype[i] += 1;
+         if (debug) {
+           fprintf(debug,"Incrementing function type %d to %d (due to %s)\n",
+                   i,ffparams->functype[i],
+                   interaction_function[ftupd[k].ftype].longname);
+           fflush(debug);
+         }
+       }
+    
+    do_iparams(fio, ffparams->functype[i],&ffparams->iparams[i],bRead,
+               file_version);
+    if (bRead && debug)
+      pr_iparams(debug,ffparams->functype[i],&ffparams->iparams[i]);
+  }
+}
+
+static void do_ilists(t_fileio *fio, t_ilist *ilist,gmx_bool bRead, 
+                      int file_version)
+{
+  int i,j,renum[F_NRE];
+  gmx_bool bDum=TRUE,bClear;
+  unsigned int k;
+  
+  for(j=0; (j<F_NRE); j++) {
+    bClear = FALSE;
+    if (bRead)
+      for (k=0; k<NFTUPD; k++)
+       if ((file_version < ftupd[k].fvnr) && (j == ftupd[k].ftype))
+         bClear = TRUE;
+    if (bClear) {
+      ilist[j].nr = 0;
+      ilist[j].iatoms = NULL;
+    } else {
+      do_ilist(fio, &ilist[j],bRead,file_version,j);
+    }
+    /*
+    if (bRead && gmx_debug_at)
+      pr_ilist(debug,0,interaction_function[j].longname,
+              functype,&ilist[j],TRUE);
+    */
+  }
+}
+
+static void do_idef(t_fileio *fio, gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
+                   gmx_bool bRead, int file_version)
+{
+  do_ffparams(fio, ffparams,bRead,file_version);
+    
+  if (file_version >= 54) {
+    gmx_fio_do_real(fio,ffparams->fudgeQQ);
+  }
+
+  do_ilists(fio, molt->ilist,bRead,file_version);
+}
+
+static void do_block(t_fileio *fio, t_block *block,gmx_bool bRead,int file_version)
+{
+  int  i,idum,dum_nra,*dum_a;
+  gmx_bool bDum=TRUE;
+
+  if (file_version < 44)
+    for(i=0; i<MAXNODES; i++)
+      gmx_fio_do_int(fio,idum);
+  gmx_fio_do_int(fio,block->nr);
+  if (file_version < 51)
+    gmx_fio_do_int(fio,dum_nra);
+  if (bRead) {
+    block->nalloc_index = block->nr+1;
+    snew(block->index,block->nalloc_index);
+  }
+  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
+
+  if (file_version < 51 && dum_nra > 0) {
+    snew(dum_a,dum_nra);
+    bDum=gmx_fio_ndo_int(fio,dum_a,dum_nra);
+    sfree(dum_a);
+  }
+}
+
+static void do_blocka(t_fileio *fio, t_blocka *block,gmx_bool bRead,
+                      int file_version)
+{
+  int  i,idum;
+  gmx_bool bDum=TRUE;
+
+  if (file_version < 44)
+    for(i=0; i<MAXNODES; i++)
+      gmx_fio_do_int(fio,idum);
+  gmx_fio_do_int(fio,block->nr);
+  gmx_fio_do_int(fio,block->nra);
+  if (bRead) {
+    block->nalloc_index = block->nr+1;
+    snew(block->index,block->nalloc_index);
+    block->nalloc_a = block->nra;
+    snew(block->a,block->nalloc_a);
+  }
+  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
+  bDum=gmx_fio_ndo_int(fio,block->a,block->nra);
+}
+
+static void do_atom(t_fileio *fio, t_atom *atom,int ngrp,gmx_bool bRead, 
+                    int file_version, gmx_groups_t *groups,int atnr)
+{ 
+  int i,myngrp;
+  
+  gmx_fio_do_real(fio,atom->m);
+  gmx_fio_do_real(fio,atom->q);
+  gmx_fio_do_real(fio,atom->mB);
+  gmx_fio_do_real(fio,atom->qB);
+  gmx_fio_do_ushort(fio, atom->type);
+  gmx_fio_do_ushort(fio, atom->typeB);
+  gmx_fio_do_int(fio,atom->ptype);
+  gmx_fio_do_int(fio,atom->resind);
+  if (file_version >= 52)
+    gmx_fio_do_int(fio,atom->atomnumber);
+  else if (bRead)
+    atom->atomnumber = NOTSET;
+  if (file_version < 23) 
+    myngrp = 8;
+  else if (file_version < 39) 
+    myngrp = 9;
+  else
+    myngrp = ngrp;
+
+  if (file_version < 57) {
+    unsigned char uchar[egcNR];
+    gmx_fio_ndo_uchar(fio,uchar,myngrp);
+    for(i=myngrp; (i<ngrp); i++) {
+      uchar[i] = 0;
+    }
+    /* Copy the old data format to the groups struct */
+    for(i=0; i<ngrp; i++) {
+      groups->grpnr[i][atnr] = uchar[i];
+    }
+  }
+}
+
+static void do_grps(t_fileio *fio, int ngrp,t_grps grps[],gmx_bool bRead, 
+                    int file_version)
+{
+  int i,j,myngrp;
+  gmx_bool bDum=TRUE;
+  
+  if (file_version < 23) 
+    myngrp = 8;
+  else if (file_version < 39) 
+    myngrp = 9;
+  else
+    myngrp = ngrp;
+
+  for(j=0; (j<ngrp); j++) {
+    if (j<myngrp) {
+      gmx_fio_do_int(fio,grps[j].nr);
+      if (bRead)
+       snew(grps[j].nm_ind,grps[j].nr);
+      bDum=gmx_fio_ndo_int(fio,grps[j].nm_ind,grps[j].nr);
+    }
+    else {
+      grps[j].nr = 1;
+      snew(grps[j].nm_ind,grps[j].nr);
+    }
+  }
+}
+
+static void do_symstr(t_fileio *fio, char ***nm,gmx_bool bRead,t_symtab *symtab)
+{
+  int ls;
+  
+  if (bRead) {
+    gmx_fio_do_int(fio,ls);
+    *nm = get_symtab_handle(symtab,ls);
+  }
+  else {
+    ls = lookup_symtab(symtab,*nm);
+    gmx_fio_do_int(fio,ls);
+  }
+}
+
+static void do_strstr(t_fileio *fio, int nstr,char ***nm,gmx_bool bRead,
+                      t_symtab *symtab)
+{
+  int  j;
+  
+  for (j=0; (j<nstr); j++) 
+    do_symstr(fio, &(nm[j]),bRead,symtab);
+}
+
+static void do_resinfo(t_fileio *fio, int n,t_resinfo *ri,gmx_bool bRead,
+                       t_symtab *symtab, int file_version)
+{
+  int  j;
+  
+  for (j=0; (j<n); j++) {
+    do_symstr(fio, &(ri[j].name),bRead,symtab);
+    if (file_version >= 63) {
+      gmx_fio_do_int(fio,ri[j].nr);
+      gmx_fio_do_uchar(fio, ri[j].ic);
+    } else {
+      ri[j].nr = j + 1;
+      ri[j].ic = ' ';
+    }
+  }
+}
+
+static void do_atoms(t_fileio *fio, t_atoms *atoms,gmx_bool bRead,t_symtab *symtab,
+                    int file_version,
+                    gmx_groups_t *groups)
+{
+  int i;
+  
+  gmx_fio_do_int(fio,atoms->nr);
+  gmx_fio_do_int(fio,atoms->nres);
+  if (file_version < 57) {
+    gmx_fio_do_int(fio,groups->ngrpname);
+    for(i=0; i<egcNR; i++) {
+      groups->ngrpnr[i] = atoms->nr;
+      snew(groups->grpnr[i],groups->ngrpnr[i]);
+    }
+  }
+  if (bRead) {
+    snew(atoms->atom,atoms->nr);
+    snew(atoms->atomname,atoms->nr);
+    snew(atoms->atomtype,atoms->nr);
+    snew(atoms->atomtypeB,atoms->nr);
+    snew(atoms->resinfo,atoms->nres);
+    if (file_version < 57) {
+      snew(groups->grpname,groups->ngrpname);
+    }
+    atoms->pdbinfo = NULL;
+  }
+  for(i=0; (i<atoms->nr); i++) {
+    do_atom(fio, &atoms->atom[i],egcNR,bRead, file_version,groups,i);
+  }
+  do_strstr(fio, atoms->nr,atoms->atomname,bRead,symtab);
+  if (bRead && (file_version <= 20)) {
+    for(i=0; i<atoms->nr; i++) {
+      atoms->atomtype[i]  = put_symtab(symtab,"?");
+      atoms->atomtypeB[i] = put_symtab(symtab,"?");
+    }
+  } else {
+    do_strstr(fio, atoms->nr,atoms->atomtype,bRead,symtab);
+    do_strstr(fio, atoms->nr,atoms->atomtypeB,bRead,symtab);
+  }
+  do_resinfo(fio, atoms->nres,atoms->resinfo,bRead,symtab,file_version);
+
+  if (file_version < 57) {
+    do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
+  
+    do_grps(fio, egcNR,groups->grps,bRead,file_version);
+  }
+}
+
+static void do_groups(t_fileio *fio, gmx_groups_t *groups,
+                     gmx_bool bRead,t_symtab *symtab,
+                     int file_version)
+{
+  int  g,n,i;
+  gmx_bool bDum=TRUE;
+
+  do_grps(fio, egcNR,groups->grps,bRead,file_version);
+  gmx_fio_do_int(fio,groups->ngrpname);
+  if (bRead) {
+    snew(groups->grpname,groups->ngrpname);
+  }
+  do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
+  for(g=0; g<egcNR; g++) {
+    gmx_fio_do_int(fio,groups->ngrpnr[g]);
+    if (groups->ngrpnr[g] == 0) {
+      if (bRead) {
+       groups->grpnr[g] = NULL;
+      }
+    } else {
+      if (bRead) {
+       snew(groups->grpnr[g],groups->ngrpnr[g]);
+      }
+      bDum=gmx_fio_ndo_uchar(fio, groups->grpnr[g],groups->ngrpnr[g]);
+    }
+  }
+}
+
+static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes,gmx_bool bRead,
+                        t_symtab *symtab,int file_version)
+{
+  int i,j;
+  gmx_bool bDum = TRUE;
+  
+  if (file_version > 25) {
+    gmx_fio_do_int(fio,atomtypes->nr);
+    j=atomtypes->nr;
+    if (bRead) {
+      snew(atomtypes->radius,j);
+      snew(atomtypes->vol,j);
+      snew(atomtypes->surftens,j);
+      snew(atomtypes->atomnumber,j);
+      snew(atomtypes->gb_radius,j);
+      snew(atomtypes->S_hct,j);
+    }
+    bDum=gmx_fio_ndo_real(fio,atomtypes->radius,j);
+    bDum=gmx_fio_ndo_real(fio,atomtypes->vol,j);
+    bDum=gmx_fio_ndo_real(fio,atomtypes->surftens,j);
+    if(file_version >= 40)
+    {
+        bDum=gmx_fio_ndo_int(fio,atomtypes->atomnumber,j);
+    }
+       if(file_version >= 60)
+       {
+               bDum=gmx_fio_ndo_real(fio,atomtypes->gb_radius,j);
+               bDum=gmx_fio_ndo_real(fio,atomtypes->S_hct,j);
+       }
+  } else {
+    /* File versions prior to 26 cannot do GBSA, 
+     * so they dont use this structure 
+     */
+    atomtypes->nr = 0;
+    atomtypes->radius = NULL;
+    atomtypes->vol = NULL;
+    atomtypes->surftens = NULL;
+    atomtypes->atomnumber = NULL;
+    atomtypes->gb_radius = NULL;
+    atomtypes->S_hct = NULL;
+  }  
+}
+
+static void do_symtab(t_fileio *fio, t_symtab *symtab,gmx_bool bRead)
+{
+  int i,nr;
+  t_symbuf *symbuf;
+  char buf[STRLEN];
+  
+  gmx_fio_do_int(fio,symtab->nr);
+  nr     = symtab->nr;
+  if (bRead) {
+    snew(symtab->symbuf,1);
+    symbuf = symtab->symbuf;
+    symbuf->bufsize = nr;
+    snew(symbuf->buf,nr);
+    for (i=0; (i<nr); i++) {
+      gmx_fio_do_string(fio,buf);
+      symbuf->buf[i]=strdup(buf);
+    }
+  }
+  else {
+    symbuf = symtab->symbuf;
+    while (symbuf!=NULL) {
+      for (i=0; (i<symbuf->bufsize) && (i<nr); i++) 
+       gmx_fio_do_string(fio,symbuf->buf[i]);
+      nr-=i;
+      symbuf=symbuf->next;
+    }
+    if (nr != 0)
+      gmx_fatal(FARGS,"nr of symtab strings left: %d",nr);
+  }
+}
+
+static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, gmx_bool bRead)
+{
+       int i,j,ngrid,gs,nelem;
+       
+       gmx_fio_do_int(fio,cmap_grid->ngrid);
+       gmx_fio_do_int(fio,cmap_grid->grid_spacing);
+       
+       ngrid = cmap_grid->ngrid;
+       gs    = cmap_grid->grid_spacing;
+       nelem = gs * gs;
+       
+       if(bRead)
+       {
+               snew(cmap_grid->cmapdata,ngrid);
+               
+               for(i=0;i<cmap_grid->ngrid;i++)
+               {
+                       snew(cmap_grid->cmapdata[i].cmap,4*nelem);
+               }
+       }
+       
+       for(i=0;i<cmap_grid->ngrid;i++)
+       {
+               for(j=0;j<nelem;j++)
+               {
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+1]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+2]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+3]);
+               }
+       }       
+}
+
+
+void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
+{
+    int m,a,a0,a1,r;
+    char c,chainid;
+    int  chainnum;
+    
+    /* We always assign a new chain number, but save the chain id characters 
+     * for larger molecules.
+     */
+#define CHAIN_MIN_ATOMS 15
+    
+    chainnum=0;
+    chainid='A';
+    for(m=0; m<mols->nr; m++) 
+    {
+        a0=mols->index[m];
+        a1=mols->index[m+1];
+        if ((a1-a0 >= CHAIN_MIN_ATOMS) && (chainid <= 'Z')) 
+        {
+            c=chainid;
+            chainid++;
+        } 
+        else
+        {
+            c=' ';
+        }
+        for(a=a0; a<a1; a++) 
+        {
+            atoms->resinfo[atoms->atom[a].resind].chainnum = chainnum;
+            atoms->resinfo[atoms->atom[a].resind].chainid  = c;
+        }
+        chainnum++;
+    }
+    
+    /* Blank out the chain id if there was only one chain */
+    if (chainid == 'B') 
+    {
+        for(r=0; r<atoms->nres; r++) 
+        {
+            atoms->resinfo[r].chainid = ' ';
+        }
+    }
+}
+  
+static void do_moltype(t_fileio *fio, gmx_moltype_t *molt,gmx_bool bRead,
+                       t_symtab *symtab, int file_version,
+                      gmx_groups_t *groups)
+{
+  int i;
+
+  if (file_version >= 57) {
+    do_symstr(fio, &(molt->name),bRead,symtab);
+  }
+
+  do_atoms(fio, &molt->atoms, bRead, symtab, file_version, groups);
+
+  if (bRead && gmx_debug_at) {
+    pr_atoms(debug,0,"atoms",&molt->atoms,TRUE);
+  }
+  
+  if (file_version >= 57) {
+    do_ilists(fio, molt->ilist,bRead,file_version);
+
+    do_block(fio, &molt->cgs,bRead,file_version);
+    if (bRead && gmx_debug_at) {
+      pr_block(debug,0,"cgs",&molt->cgs,TRUE);
+    }
+  }
+
+  /* This used to be in the atoms struct */
+  do_blocka(fio, &molt->excls, bRead, file_version);
+}
+
+static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,gmx_bool bRead,
+                        int file_version)
+{
+  int i;
+
+  gmx_fio_do_int(fio,molb->type);
+  gmx_fio_do_int(fio,molb->nmol);
+  gmx_fio_do_int(fio,molb->natoms_mol);
+  /* Position restraint coordinates */
+  gmx_fio_do_int(fio,molb->nposres_xA);
+  if (molb->nposres_xA > 0) {
+    if (bRead) {
+      snew(molb->posres_xA,molb->nposres_xA);
+    }
+    gmx_fio_ndo_rvec(fio,molb->posres_xA,molb->nposres_xA);
+  }
+  gmx_fio_do_int(fio,molb->nposres_xB);
+  if (molb->nposres_xB > 0) {
+    if (bRead) {
+      snew(molb->posres_xB,molb->nposres_xB);
+    }
+    gmx_fio_ndo_rvec(fio,molb->posres_xB,molb->nposres_xB);
+  }
+
+}
+
+static t_block mtop_mols(gmx_mtop_t *mtop)
+{
+  int mb,m,a,mol;
+  t_block mols;
+
+  mols.nr = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    mols.nr += mtop->molblock[mb].nmol;
+  }
+  mols.nalloc_index = mols.nr + 1;
+  snew(mols.index,mols.nalloc_index);
+
+  a = 0;
+  m = 0;
+  mols.index[m] = a;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    for(mol=0; mol<mtop->molblock[mb].nmol; mol++) {
+      a += mtop->molblock[mb].natoms_mol;
+      m++;
+      mols.index[m] = a;
+    }
+  }
+  
+  return mols;
+}
+
+static void add_posres_molblock(gmx_mtop_t *mtop)
+{
+  t_ilist *il;
+  int am,i,mol,a;
+  gmx_bool bFE;
+  gmx_molblock_t *molb;
+  t_iparams *ip;
+
+  il = &mtop->moltype[0].ilist[F_POSRES];
+  if (il->nr == 0) {
+    return;
+  }
+  am = 0;
+  bFE = FALSE;
+  for(i=0; i<il->nr; i+=2) {
+    ip = &mtop->ffparams.iparams[il->iatoms[i]];
+    am = max(am,il->iatoms[i+1]);
+    if (ip->posres.pos0B[XX] != ip->posres.pos0A[XX] ||
+       ip->posres.pos0B[YY] != ip->posres.pos0A[YY] ||
+       ip->posres.pos0B[ZZ] != ip->posres.pos0A[ZZ]) {
+      bFE = TRUE;
+    }
+  }
+  /* Make the posres coordinate block end at a molecule end */
+  mol = 0;
+  while(am >= mtop->mols.index[mol+1]) {
+    mol++;
+  }
+  molb = &mtop->molblock[0];
+  molb->nposres_xA = mtop->mols.index[mol+1];
+  snew(molb->posres_xA,molb->nposres_xA);
+  if (bFE) {
+    molb->nposres_xB = molb->nposres_xA;
+    snew(molb->posres_xB,molb->nposres_xB);
+  } else {
+    molb->nposres_xB = 0;
+  }
+  for(i=0; i<il->nr; i+=2) {
+    ip = &mtop->ffparams.iparams[il->iatoms[i]];
+    a  = il->iatoms[i+1];
+    molb->posres_xA[a][XX] = ip->posres.pos0A[XX];
+    molb->posres_xA[a][YY] = ip->posres.pos0A[YY];
+    molb->posres_xA[a][ZZ] = ip->posres.pos0A[ZZ];
+    if (bFE) {
+      molb->posres_xB[a][XX] = ip->posres.pos0B[XX];
+      molb->posres_xB[a][YY] = ip->posres.pos0B[YY];
+      molb->posres_xB[a][ZZ] = ip->posres.pos0B[ZZ];
+    }
+  }
+}
+
+static void set_disres_npair(gmx_mtop_t *mtop)
+{
+  int mt,i,npair;
+  t_iparams *ip;
+  t_ilist *il;
+  t_iatom *a;
+
+  ip = mtop->ffparams.iparams;
+
+  for(mt=0; mt<mtop->nmoltype; mt++) {
+    il = &mtop->moltype[mt].ilist[F_DISRES];
+    if (il->nr > 0) {
+      a = il->iatoms;
+      npair = 0;
+      for(i=0; i<il->nr; i+=3) {
+       npair++;
+       if (i+3 == il->nr || ip[a[i]].disres.label != ip[a[i+3]].disres.label) {
+         ip[a[i]].disres.npair = npair;
+         npair = 0;
+       }
+      }
+    }
+  }
+}
+
+static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop,gmx_bool bRead, 
+                    int file_version)
+{
+  int  mt,mb,i;
+  t_blocka dumb;
+
+  if (bRead)
+    init_mtop(mtop);
+  do_symtab(fio, &(mtop->symtab),bRead);
+  if (bRead && debug) 
+    pr_symtab(debug,0,"symtab",&mtop->symtab);
+  
+  do_symstr(fio, &(mtop->name),bRead,&(mtop->symtab));
+  
+  if (file_version >= 57) {
+    do_ffparams(fio, &mtop->ffparams,bRead,file_version);
+
+    gmx_fio_do_int(fio,mtop->nmoltype);
+  } else {
+    mtop->nmoltype = 1;
+  }
+  if (bRead) {
+    snew(mtop->moltype,mtop->nmoltype);
+    if (file_version < 57) {
+      mtop->moltype[0].name = mtop->name;
+    }
+  }
+  for(mt=0; mt<mtop->nmoltype; mt++) {
+    do_moltype(fio, &mtop->moltype[mt],bRead,&mtop->symtab,file_version,
+              &mtop->groups);
+  }
+
+  if (file_version >= 57) {
+    gmx_fio_do_int(fio,mtop->nmolblock);
+  } else {
+    mtop->nmolblock = 1;
+  }
+  if (bRead) {
+    snew(mtop->molblock,mtop->nmolblock);
+  }
+  if (file_version >= 57) {
+    for(mb=0; mb<mtop->nmolblock; mb++) {
+      do_molblock(fio, &mtop->molblock[mb],bRead,file_version);
+    }
+    gmx_fio_do_int(fio,mtop->natoms);
+  } else {
+    mtop->molblock[0].type = 0;
+    mtop->molblock[0].nmol = 1;
+    mtop->molblock[0].natoms_mol = mtop->moltype[0].atoms.nr;
+    mtop->molblock[0].nposres_xA = 0;
+    mtop->molblock[0].nposres_xB = 0;
+  }
+
+  do_atomtypes (fio, &(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
+  if (bRead && debug) 
+    pr_atomtypes(debug,0,"atomtypes",&mtop->atomtypes,TRUE);
+
+  if (file_version < 57) {
+    /* Debug statements are inside do_idef */    
+    do_idef (fio, &mtop->ffparams,&mtop->moltype[0],bRead,file_version);
+    mtop->natoms = mtop->moltype[0].atoms.nr;
+  }
+       
+  if(file_version >= 65)
+  {
+      do_cmap(fio, &mtop->ffparams.cmap_grid,bRead);
+  }
+  else
+  {
+      mtop->ffparams.cmap_grid.ngrid        = 0;
+      mtop->ffparams.cmap_grid.grid_spacing = 0.1;
+      mtop->ffparams.cmap_grid.cmapdata     = NULL;
+  }
+         
+  if (file_version >= 57) {
+    do_groups(fio, &mtop->groups,bRead,&(mtop->symtab),file_version);
+  }
+
+  if (file_version < 57) {
+    do_block(fio, &mtop->moltype[0].cgs,bRead,file_version);
+    if (bRead && gmx_debug_at) {
+      pr_block(debug,0,"cgs",&mtop->moltype[0].cgs,TRUE);
+    }
+    do_block(fio, &mtop->mols,bRead,file_version);
+    /* Add the posres coordinates to the molblock */
+    add_posres_molblock(mtop);
+  }
+  if (bRead) {
+    if (file_version >= 57) {
+      mtop->mols = mtop_mols(mtop);
+    }
+    if (gmx_debug_at) { 
+      pr_block(debug,0,"mols",&mtop->mols,TRUE);
+    }
+  }
+
+  if (file_version < 51) {
+    /* Here used to be the shake blocks */
+    do_blocka(fio, &dumb,bRead,file_version);
+    if (dumb.nr > 0)
+      sfree(dumb.index);
+    if (dumb.nra > 0)
+      sfree(dumb.a);
+  }
+
+  if (bRead) {
+    close_symtab(&(mtop->symtab));
+  }
+}
+
+/* If TopOnlyOK is TRUE then we can read even future versions
+ * of tpx files, provided the file_generation hasn't changed.
+ * If it is FALSE, we need the inputrecord too, and bail out
+ * if the file is newer than the program.
+ * 
+ * The version and generation if the topology (see top of this file)
+ * are returned in the two last arguments.
+ * 
+ * If possible, we will read the inputrec even when TopOnlyOK is TRUE.
+ */
+static void do_tpxheader(t_fileio *fio,gmx_bool bRead,t_tpxheader *tpx, 
+                         gmx_bool TopOnlyOK, int *file_version, 
+                         int *file_generation)
+{
+  char  buf[STRLEN];
+  gmx_bool  bDouble;
+  int   precision;
+  int   fver,fgen;
+  int   idum=0;
+  real  rdum=0;
+
+  gmx_fio_checktype(fio);
+  gmx_fio_setdebug(fio,bDebugMode());
+  
+  /* NEW! XDR tpb file */
+  precision = sizeof(real);
+  if (bRead) {
+    gmx_fio_do_string(fio,buf);
+    if (strncmp(buf,"VERSION",7))
+      gmx_fatal(FARGS,"Can not read file %s,\n"
+                 "             this file is from a Gromacs version which is older than 2.0\n"
+                 "             Make a new one with grompp or use a gro or pdb file, if possible",
+                 gmx_fio_getname(fio));
+    gmx_fio_do_int(fio,precision);
+    bDouble = (precision == sizeof(double));
+    if ((precision != sizeof(float)) && !bDouble)
+      gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
+                 "instead of %d or %d",
+                 gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+    gmx_fio_setprecision(fio,bDouble);
+    fprintf(stderr,"Reading file %s, %s (%s precision)\n",
+           gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
+  }
+  else {
+    gmx_fio_write_string(fio,GromacsVersion());
+    bDouble = (precision == sizeof(double));
+    gmx_fio_setprecision(fio,bDouble);
+    gmx_fio_do_int(fio,precision);
+    fver = tpx_version;
+    fgen = tpx_generation;
+  }
+  
+  /* Check versions! */
+  gmx_fio_do_int(fio,fver);
+  
+  if(fver>=26)
+    gmx_fio_do_int(fio,fgen);
+  else
+    fgen=0;
+  if(file_version!=NULL)
+    *file_version = fver;
+  if(file_generation!=NULL)
+    *file_generation = fgen;
+   
+  
+  if ((fver <= tpx_incompatible_version) ||
+      ((fver > tpx_version) && !TopOnlyOK) ||
+      (fgen > tpx_generation))
+    gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",
+               gmx_fio_getname(fio),fver,tpx_version);
+  
+  do_section(fio,eitemHEADER,bRead);
+  gmx_fio_do_int(fio,tpx->natoms);
+  if (fver >= 28)
+    gmx_fio_do_int(fio,tpx->ngtc);
+  else
+    tpx->ngtc = 0;
+  if (fver < 62) {
+    gmx_fio_do_int(fio,idum);
+    gmx_fio_do_real(fio,rdum);
+  }
+  gmx_fio_do_real(fio,tpx->lambda);
+  gmx_fio_do_int(fio,tpx->bIr);
+  gmx_fio_do_int(fio,tpx->bTop);
+  gmx_fio_do_int(fio,tpx->bX);
+  gmx_fio_do_int(fio,tpx->bV);
+  gmx_fio_do_int(fio,tpx->bF);
+  gmx_fio_do_int(fio,tpx->bBox);
+
+  if((fgen > tpx_generation)) {
+    /* This can only happen if TopOnlyOK=TRUE */
+    tpx->bIr=FALSE;
+  }
+}
+
+static int do_tpx(t_fileio *fio, gmx_bool bRead,
+                 t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop,
+                 gmx_bool bXVallocated)
+{
+  t_tpxheader tpx;
+  t_inputrec  dum_ir;
+  gmx_mtop_t  dum_top;
+  gmx_bool        TopOnlyOK,bDum=TRUE;
+  int         file_version,file_generation;
+  int         i;
+  rvec        *xptr,*vptr;
+  int         ePBC;
+  gmx_bool        bPeriodicMols;
+
+  if (!bRead) {
+    tpx.natoms = state->natoms;
+    tpx.ngtc   = state->ngtc;
+    tpx.lambda = state->lambda;
+    tpx.bIr  = (ir       != NULL);
+    tpx.bTop = (mtop     != NULL);
+    tpx.bX   = (state->x != NULL);
+    tpx.bV   = (state->v != NULL);
+    tpx.bF   = (f        != NULL);
+    tpx.bBox = TRUE;
+  }
+  
+  TopOnlyOK = (ir==NULL);
+  
+  do_tpxheader(fio,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
+
+  if (bRead) {
+    state->flags  = 0;
+    state->lambda = tpx.lambda;
+    /* The init_state calls initialize the Nose-Hoover xi integrals to zero */
+    if (bXVallocated) {
+      xptr = state->x;
+      vptr = state->v;
+      init_state(state,0,tpx.ngtc,0,0);  /* nose-hoover chains */ /* eventually, need to add nnhpres here? */
+      state->natoms = tpx.natoms; 
+      state->nalloc = tpx.natoms; 
+      state->x = xptr;
+      state->v = vptr;
+    } else {
+      init_state(state,tpx.natoms,tpx.ngtc,0,0);  /* nose-hoover chains */
+    }
+  }
+
+#define do_test(fio,b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fio)) 
+
+  do_test(fio,tpx.bBox,state->box);
+  do_section(fio,eitemBOX,bRead);
+  if (tpx.bBox) {
+    gmx_fio_ndo_rvec(fio,state->box,DIM);
+    if (file_version >= 51) {
+      gmx_fio_ndo_rvec(fio,state->box_rel,DIM);
+    } else {
+      /* We initialize box_rel after reading the inputrec */
+      clear_mat(state->box_rel);
+    }
+    if (file_version >= 28) {
+      gmx_fio_ndo_rvec(fio,state->boxv,DIM);
+      if (file_version < 56) {
+       matrix mdum;
+       gmx_fio_ndo_rvec(fio,mdum,DIM);
+      }
+    }
+  }
+  
+  if (state->ngtc > 0 && file_version >= 28) {
+    real *dumv;
+    /*ndo_double(state->nosehoover_xi,state->ngtc,bDum);*/
+    /*ndo_double(state->nosehoover_vxi,state->ngtc,bDum);*/
+    /*ndo_double(state->therm_integral,state->ngtc,bDum);*/
+    snew(dumv,state->ngtc);
+    if (file_version < 69) {
+      bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
+    }
+    /* These used to be the Berendsen tcoupl_lambda's */
+    bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
+    sfree(dumv);
+  }
+
+  /* Prior to tpx version 26, the inputrec was here.
+   * I moved it to enable partial forward-compatibility
+   * for analysis/viewer programs.
+   */
+  if(file_version<26) {
+    do_test(fio,tpx.bIr,ir);
+    do_section(fio,eitemIR,bRead);
+    if (tpx.bIr) {
+      if (ir) {
+       do_inputrec(fio, ir,bRead,file_version,
+                    mtop ? &mtop->ffparams.fudgeQQ : NULL);
+       if (bRead && debug) 
+         pr_inputrec(debug,0,"inputrec",ir,FALSE);
+      }
+      else {
+       do_inputrec(fio, &dum_ir,bRead,file_version,
+                    mtop ? &mtop->ffparams.fudgeQQ :NULL);
+       if (bRead && debug) 
+         pr_inputrec(debug,0,"inputrec",&dum_ir,FALSE);
+       done_inputrec(&dum_ir);
+      }
+      
+    }
+  }
+  
+  do_test(fio,tpx.bTop,mtop);
+  do_section(fio,eitemTOP,bRead);
+  if (tpx.bTop) {
+    if (mtop) {
+      do_mtop(fio,mtop,bRead, file_version);
+    } else {
+      do_mtop(fio,&dum_top,bRead,file_version);
+      done_mtop(&dum_top,TRUE);
+    }
+  }
+  do_test(fio,tpx.bX,state->x);  
+  do_section(fio,eitemX,bRead);
+  if (tpx.bX) {
+    if (bRead) {
+      state->flags |= (1<<estX);
+    }
+    gmx_fio_ndo_rvec(fio,state->x,state->natoms);
+  }
+  
+  do_test(fio,tpx.bV,state->v);
+  do_section(fio,eitemV,bRead);
+  if (tpx.bV) {
+    if (bRead) {
+      state->flags |= (1<<estV);
+    }
+    gmx_fio_ndo_rvec(fio,state->v,state->natoms);
+  }
+
+  do_test(fio,tpx.bF,f);
+  do_section(fio,eitemF,bRead);
+  if (tpx.bF) gmx_fio_ndo_rvec(fio,f,state->natoms);
+
+  /* Starting with tpx version 26, we have the inputrec
+   * at the end of the file, so we can ignore it 
+   * if the file is never than the software (but still the
+   * same generation - see comments at the top of this file.
+   *
+   * 
+   */
+  ePBC = -1;
+  bPeriodicMols = FALSE;
+  if (file_version >= 26) {
+    do_test(fio,tpx.bIr,ir);
+    do_section(fio,eitemIR,bRead);
+    if (tpx.bIr) {
+      if (file_version >= 53) {
+       /* Removed the pbc info from do_inputrec, since we always want it */
+       if (!bRead) {
+         ePBC          = ir->ePBC;
+         bPeriodicMols = ir->bPeriodicMols;
+       }
+       gmx_fio_do_int(fio,ePBC);
+       gmx_fio_do_gmx_bool(fio,bPeriodicMols);
+      }
+      if (file_generation <= tpx_generation && ir) {
+       do_inputrec(fio, ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
+       if (bRead && debug) 
+         pr_inputrec(debug,0,"inputrec",ir,FALSE);
+       if (file_version < 51)
+         set_box_rel(ir,state);
+       if (file_version < 53) {
+         ePBC          = ir->ePBC;
+         bPeriodicMols = ir->bPeriodicMols;
+       }
+      }
+      if (bRead && ir && file_version >= 53) {
+       /* We need to do this after do_inputrec, since that initializes ir */
+       ir->ePBC          = ePBC;
+       ir->bPeriodicMols = bPeriodicMols;
+      }
+    }
+  }
+
+    if (bRead)
+    {
+        if (tpx.bIr && ir)
+        {
+            if (state->ngtc == 0)
+            {
+                /* Reading old version without tcoupl state data: set it */
+                init_gtc_state(state,ir->opts.ngtc,0,ir->opts.nhchainlength);
+            }
+            if (tpx.bTop && mtop)
+            {
+                if (file_version < 57)
+                {
+                    if (mtop->moltype[0].ilist[F_DISRES].nr > 0)
+                    {
+                        ir->eDisre = edrSimple;
+                    }
+                    else
+                    {
+                        ir->eDisre = edrNone;
+                    }
+                }
+                set_disres_npair(mtop);
+            }
+        }
+
+        if (tpx.bTop && mtop)
+        {
+            gmx_mtop_finalize(mtop);
+        }
+
+        if (file_version >= 57)
+        {
+            char *env;
+            int  ienv;
+            env = getenv("GMX_NOCHARGEGROUPS");
+            if (env != NULL)
+            {
+                sscanf(env,"%d",&ienv);
+                fprintf(stderr,"\nFound env.var. GMX_NOCHARGEGROUPS = %d\n",
+                        ienv);
+                if (ienv > 0)
+                {
+                    fprintf(stderr,
+                            "Will make single atomic charge groups in non-solvent%s\n",
+                            ienv > 1 ? " and solvent" : "");
+                    gmx_mtop_make_atomic_charge_groups(mtop,ienv==1);
+                }
+                fprintf(stderr,"\n");
+            }
+        }
+    }
+
+    return ePBC;
+}
+
+/************************************************************
+ *
+ *  The following routines are the exported ones
+ *
+ ************************************************************/
+
+t_fileio *open_tpx(const char *fn,const char *mode)
+{
+  return gmx_fio_open(fn,mode);
+}    
+void close_tpx(t_fileio *fio)
+{
+  gmx_fio_close(fio);
+}
+
+void read_tpxheader(const char *fn, t_tpxheader *tpx, gmx_bool TopOnlyOK,
+                    int *file_version, int *file_generation)
+{
+  t_fileio *fio;
+
+  fio = open_tpx(fn,"r");
+  do_tpxheader(fio,TRUE,tpx,TopOnlyOK,file_version,file_generation);
+  close_tpx(fio);
+}
+
+void write_tpx_state(const char *fn,
+                    t_inputrec *ir,t_state *state,gmx_mtop_t *mtop)
+{
+  t_fileio *fio;
+
+  fio = open_tpx(fn,"w");
+  do_tpx(fio,FALSE,ir,state,NULL,mtop,FALSE);
+  close_tpx(fio);
+}
+
+void read_tpx_state(const char *fn,
+                   t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop)
+{
+  t_fileio *fio;
+       
+  fio = open_tpx(fn,"r");
+  do_tpx(fio,TRUE,ir,state,f,mtop,FALSE);
+  close_tpx(fio);
+}
+
+int read_tpx(const char *fn,
+            t_inputrec *ir, matrix box,int *natoms,
+            rvec *x,rvec *v,rvec *f,gmx_mtop_t *mtop)
+{
+  t_fileio *fio;
+  t_state state;
+  int ePBC;
+
+  state.x = x;
+  state.v = v;
+  fio = open_tpx(fn,"r");
+  ePBC = do_tpx(fio,TRUE,ir,&state,f,mtop,TRUE);
+  close_tpx(fio);
+  *natoms = state.natoms;
+  if (box) 
+    copy_mat(state.box,box);
+  state.x = NULL;
+  state.v = NULL;
+  done_state(&state);
+
+  return ePBC;
+}
+
+int read_tpx_top(const char *fn,
+                t_inputrec *ir, matrix box,int *natoms,
+                rvec *x,rvec *v,rvec *f,t_topology *top)
+{
+  gmx_mtop_t mtop;
+  t_topology *ltop;
+  int ePBC;
+
+  ePBC = read_tpx(fn,ir,box,natoms,x,v,f,&mtop);
+  
+  *top = gmx_mtop_t_to_t_topology(&mtop);
+
+  return ePBC;
+}
+
+gmx_bool fn2bTPX(const char *file)
+{
+  switch (fn2ftp(file)) {
+  case efTPR:
+  case efTPB:
+  case efTPA:
+    return TRUE;
+  default:
+    return FALSE;
+  }
+}
+
+gmx_bool read_tps_conf(const char *infile,char *title,t_topology *top,int *ePBC,
+                  rvec **x,rvec **v,matrix box,gmx_bool bMass)
+{
+  t_tpxheader  header;
+  int          natoms,i,version,generation;
+  gmx_bool         bTop,bXNULL;
+  gmx_mtop_t   *mtop;
+  t_topology   *topconv;
+  gmx_atomprop_t aps;
+  
+  bTop = fn2bTPX(infile);
+  *ePBC = -1;
+  if (bTop) {
+    read_tpxheader(infile,&header,TRUE,&version,&generation);
+    if (x)
+      snew(*x,header.natoms);
+    if (v)
+      snew(*v,header.natoms);
+    snew(mtop,1);
+    *ePBC = read_tpx(infile,NULL,box,&natoms,
+                    (x==NULL) ? NULL : *x,(v==NULL) ? NULL : *v,NULL,mtop);
+    *top = gmx_mtop_t_to_t_topology(mtop);
+    sfree(mtop);
+    strcpy(title,*top->name);
+    tpx_make_chain_identifiers(&top->atoms,&top->mols);
+  }
+  else {
+    get_stx_coordnum(infile,&natoms);
+    init_t_atoms(&top->atoms,natoms,FALSE);
+    bXNULL = (x == NULL);
+    snew(*x,natoms);
+    if (v)
+      snew(*v,natoms);
+    read_stx_conf(infile,title,&top->atoms,*x,(v==NULL) ? NULL : *v,ePBC,box);
+    if (bXNULL) {
+      sfree(*x);
+      x = NULL;
+    }
+    if (bMass) {
+      aps = gmx_atomprop_init();
+      for(i=0; (i<natoms); i++)
+       if (!gmx_atomprop_query(aps,epropMass,
+                               *top->atoms.resinfo[top->atoms.atom[i].resind].name,
+                               *top->atoms.atomname[i],
+                               &(top->atoms.atom[i].m))) {
+         if (debug) 
+           fprintf(debug,"Can not find mass for atom %s %d %s, setting to 1\n",
+                   *top->atoms.resinfo[top->atoms.atom[i].resind].name,
+                   top->atoms.resinfo[top->atoms.atom[i].resind].nr,
+                   *top->atoms.atomname[i]);
+       }
+      gmx_atomprop_destroy(aps);
+    }
+    top->idef.ntypes=-1;
+  }
+
+  return bTop;
+}
diff --git a/src/gromacs/gmxlib/txtdump.c b/src/gromacs/gmxlib/txtdump.c
new file mode 100644 (file)
index 0000000..33c9837
--- /dev/null
@@ -0,0 +1,1501 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* This file is completely threadsafe - please keep it that way! */
+#ifdef GMX_THREADS
+#include <thread_mpi.h>
+#endif
+
+
+#include <stdio.h>
+#include "smalloc.h"
+#include "typedefs.h"
+#include "names.h"
+#include "txtdump.h"
+#include "string2.h"
+#include "vec.h"
+
+
+int pr_indent(FILE *fp,int n)
+{
+  int i;
+
+  for (i=0; i<n; i++) (void) fprintf(fp," ");
+  return n;
+}
+
+int available(FILE *fp,void *p,int indent,const char *title)
+{
+  if (!p) {
+    if (indent > 0)
+      pr_indent(fp,indent);
+    (void) fprintf(fp,"%s: not available\n",title);
+  }
+  return (p!=NULL);
+}
+
+int pr_title(FILE *fp,int indent,const char *title)
+{
+  (void) pr_indent(fp,indent);
+  (void) fprintf(fp,"%s:\n",title);
+  return (indent+INDENT);
+}
+
+int pr_title_n(FILE *fp,int indent,const char *title,int n)
+{
+  (void) pr_indent(fp,indent);
+  (void) fprintf(fp,"%s (%d):\n",title,n);
+  return (indent+INDENT);
+}
+
+int pr_title_nxn(FILE *fp,int indent,const char *title,int n1,int n2)
+{
+  (void) pr_indent(fp,indent);
+  (void) fprintf(fp,"%s (%dx%d):\n",title,n1,n2);
+  return (indent+INDENT);
+}
+
+void pr_ivec(FILE *fp,int indent,const char *title,int vec[],int n, gmx_bool bShowNumbers)
+{
+  int i;
+
+  if (available(fp,vec,indent,title))
+    {
+      indent=pr_title_n(fp,indent,title,n);
+      for (i=0; i<n; i++)
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"%s[%d]=%d\n",title,bShowNumbers?i:-1,vec[i]);
+        }
+    }
+}
+
+void pr_ivec_block(FILE *fp,int indent,const char *title,int vec[],int n, gmx_bool bShowNumbers)
+{
+    int i,j;
+    
+    if (available(fp,vec,indent,title))
+    {
+        indent=pr_title_n(fp,indent,title,n);
+        i = 0;
+        while (i < n)
+        {
+            j = i+1;
+            while (j < n && vec[j] == vec[j-1]+1)
+            {
+                j++;
+            }
+            /* Print consecutive groups of 3 or more as blocks */
+            if (j - i < 3)
+            {
+                while(i < j)
+                {
+                    (void) pr_indent(fp,indent);
+                    (void) fprintf(fp,"%s[%d]=%d\n",
+                                   title,bShowNumbers?i:-1,vec[i]);
+                    i++;
+                }
+            }
+            else
+            {
+                (void) pr_indent(fp,indent);
+                (void) fprintf(fp,"%s[%d,...,%d] = {%d,...,%d}\n",
+                               title,
+                               bShowNumbers?i:-1,
+                               bShowNumbers?j-1:-1,
+                               vec[i],vec[j-1]); 
+                i = j;
+            }
+        }
+    }
+}
+
+void pr_bvec(FILE *fp,int indent,const char *title,gmx_bool vec[],int n, gmx_bool bShowNumbers)
+{
+  int i;
+
+  if (available(fp,vec,indent,title))
+    {
+      indent=pr_title_n(fp,indent,title,n);
+      for (i=0; i<n; i++)
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"%s[%d]=%s\n",title,bShowNumbers?i:-1,
+                        BOOL(vec[i]));
+        }
+    }
+}
+
+void pr_ivecs(FILE *fp,int indent,const char *title,ivec vec[],int n, gmx_bool bShowNumbers)
+{
+  int i,j;
+
+  if (available(fp,vec,indent,title))
+    {  
+      indent=pr_title_nxn(fp,indent,title,n,DIM);
+      for (i=0; i<n; i++)
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"%s[%d]={",title,bShowNumbers?i:-1);
+          for (j=0; j<DIM; j++)
+            {
+              if (j!=0) (void) fprintf(fp,", ");
+              fprintf(fp,"%d",vec[i][j]);
+            }
+          (void) fprintf(fp,"}\n");
+        }
+    }
+}
+
+void pr_rvec(FILE *fp,int indent,const char *title,real vec[],int n, gmx_bool bShowNumbers)
+{
+  int i;
+
+  if (available(fp,vec,indent,title))
+    {  
+      indent=pr_title_n(fp,indent,title,n);
+      for (i=0; i<n; i++)
+        {
+          pr_indent(fp,indent);
+          fprintf(fp,"%s[%d]=%12.5e\n",title,bShowNumbers?i:-1,vec[i]);
+        }
+    }
+}
+
+void pr_dvec(FILE *fp,int indent,const char *title,double vec[],int n, gmx_bool bShowNumbers)
+{
+       int i;
+       
+       if (available(fp,vec,indent,title))
+    {  
+               indent=pr_title_n(fp,indent,title,n);
+               for (i=0; i<n; i++)
+        {
+                       pr_indent(fp,indent);
+                       fprintf(fp,"%s[%d]=%12.5e\n",title,bShowNumbers?i:-1,vec[i]);
+        }
+    }
+}
+
+
+/*
+void pr_mat(FILE *fp,int indent,char *title,matrix m)
+{
+  int i,j;
+  
+  if (available(fp,m,indent,title)) {  
+    indent=pr_title_n(fp,indent,title,n);
+    for(i=0; i<n; i++) {
+      pr_indent(fp,indent);
+      fprintf(fp,"%s[%d]=%12.5e %12.5e %12.5e\n",
+             title,bShowNumbers?i:-1,m[i][XX],m[i][YY],m[i][ZZ]);
+    }
+  }
+}
+*/
+
+void pr_rvecs_len(FILE *fp,int indent,const char *title,rvec vec[],int n)
+{
+  int i,j;
+
+  if (available(fp,vec,indent,title)) {  
+    indent=pr_title_nxn(fp,indent,title,n,DIM);
+    for (i=0; i<n; i++) {
+      (void) pr_indent(fp,indent);
+      (void) fprintf(fp,"%s[%5d]={",title,i);
+      for (j=0; j<DIM; j++) {
+       if (j != 0) 
+         (void) fprintf(fp,", ");
+       (void) fprintf(fp,"%12.5e",vec[i][j]);
+      }
+      (void) fprintf(fp,"} len=%12.5e\n",norm(vec[i]));
+    }
+  }
+}
+
+void pr_rvecs(FILE *fp,int indent,const char *title,rvec vec[],int n)
+{
+  const char *fshort = "%12.5e";
+  const char *flong  = "%15.8e";
+  const char *format;
+  int i,j;
+
+  if (getenv("LONGFORMAT") != NULL)
+    format = flong;
+  else
+    format = fshort;
+    
+  if (available(fp,vec,indent,title)) {  
+    indent=pr_title_nxn(fp,indent,title,n,DIM);
+    for (i=0; i<n; i++) {
+      (void) pr_indent(fp,indent);
+      (void) fprintf(fp,"%s[%5d]={",title,i);
+      for (j=0; j<DIM; j++) {
+       if (j != 0) 
+         (void) fprintf(fp,", ");
+       (void) fprintf(fp,format,vec[i][j]);
+      }
+      (void) fprintf(fp,"}\n");
+    }
+  }
+}
+
+
+void pr_reals(FILE *fp,int indent,const char *title,real *vec,int n)
+{
+  int i;
+    
+  if (available(fp,vec,indent,title)) {  
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"%s:\t",title);
+    for(i=0; i<n; i++)
+      fprintf(fp,"  %10g",vec[i]);
+    (void) fprintf(fp,"\n");
+  }
+}
+
+void pr_doubles(FILE *fp,int indent,const char *title,double *vec,int n)
+{
+  int i;
+    
+  if (available(fp,vec,indent,title)) {  
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"%s:\t",title);
+    for(i=0; i<n; i++)
+      fprintf(fp,"  %10g",vec[i]);
+    (void) fprintf(fp,"\n");
+  }
+}
+
+static void pr_int(FILE *fp,int indent,const char *title,int i)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"%-20s = %d\n",title,i);
+}
+
+static void pr_gmx_large_int(FILE *fp,int indent,const char *title,gmx_large_int_t i)
+{
+  char buf[STEPSTRSIZE];
+
+  pr_indent(fp,indent);
+  fprintf(fp,"%-20s = %s\n",title,gmx_step_str(i,buf));
+}
+
+static void pr_real(FILE *fp,int indent,const char *title,real r)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"%-20s = %g\n",title,r);
+}
+
+static void pr_double(FILE *fp,int indent,const char *title,double d)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"%-20s = %g\n",title,d);
+}
+
+static void pr_str(FILE *fp,int indent,const char *title,const char *s)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"%-20s = %s\n",title,s);
+}
+
+void pr_qm_opts(FILE *fp,int indent,const char *title,t_grpopts *opts)
+{
+  int i,m,j;
+
+  fprintf(fp,"%s:\n",title);
+  
+  pr_int(fp,indent,"ngQM",opts->ngQM);
+  if (opts->ngQM > 0) {
+    pr_ivec(fp,indent,"QMmethod",opts->QMmethod,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"QMbasis",opts->QMbasis,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"QMcharge",opts->QMcharge,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"QMmult",opts->QMmult,opts->ngQM,FALSE);
+    pr_bvec(fp,indent,"bSH",opts->bSH,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"CASorbitals",opts->CASorbitals,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"CASelectrons",opts->CASelectrons,opts->ngQM,FALSE);
+    pr_rvec(fp,indent,"SAon",opts->SAon,opts->ngQM,FALSE);
+    pr_rvec(fp,indent,"SAon",opts->SAon,opts->ngQM,FALSE);
+    pr_ivec(fp,indent,"SAsteps",opts->SAsteps,opts->ngQM,FALSE);
+    pr_bvec(fp,indent,"bOPT",opts->bOPT,opts->ngQM,FALSE);
+    pr_bvec(fp,indent,"bTS",opts->bTS,opts->ngQM,FALSE);
+  }
+}
+
+static void pr_grp_opts(FILE *out,int indent,const char *title,t_grpopts *opts,
+                       gmx_bool bMDPformat)
+{
+  int i,m,j;
+
+  if (!bMDPformat)
+    fprintf(out,"%s:\n",title);
+  
+  pr_indent(out,indent);
+  fprintf(out,"nrdf%s",bMDPformat ? " = " : ":");
+  for(i=0; (i<opts->ngtc); i++)
+    fprintf(out,"  %10g",opts->nrdf[i]);
+  fprintf(out,"\n");
+  
+  pr_indent(out,indent);
+  fprintf(out,"ref-t%s",bMDPformat ? " = " : ":");
+  for(i=0; (i<opts->ngtc); i++)
+    fprintf(out,"  %10g",opts->ref_t[i]);
+  fprintf(out,"\n");
+
+  pr_indent(out,indent);
+  fprintf(out,"tau-t%s",bMDPformat ? " = " : ":");
+  for(i=0; (i<opts->ngtc); i++)
+    fprintf(out,"  %10g",opts->tau_t[i]);
+  fprintf(out,"\n");  
+  
+  /* Pretty-print the simulated annealing info */
+  fprintf(out,"anneal%s",bMDPformat ? " = " : ":");
+  for(i=0; (i<opts->ngtc); i++)
+    fprintf(out,"  %10s",EANNEAL(opts->annealing[i]));
+  fprintf(out,"\n");  
+  fprintf(out,"ann-npoints%s",bMDPformat ? " = " : ":");
+  for(i=0; (i<opts->ngtc); i++)
+    fprintf(out,"  %10d",opts->anneal_npoints[i]);
+  fprintf(out,"\n");  
+  for(i=0; (i<opts->ngtc); i++) {
+    if(opts->anneal_npoints[i]>0) {
+      fprintf(out,"ann. times [%d]:\t",i);
+      for(j=0; (j<opts->anneal_npoints[i]); j++)
+       fprintf(out,"  %10.1f",opts->anneal_time[i][j]);
+      fprintf(out,"\n");  
+      fprintf(out,"ann. temps [%d]:\t",i);
+      for(j=0; (j<opts->anneal_npoints[i]); j++)
+       fprintf(out,"  %10.1f",opts->anneal_temp[i][j]);
+      fprintf(out,"\n");  
+    }
+  }
+  
+  pr_indent(out,indent);
+  fprintf(out,"acc:\t");
+  for(i=0; (i<opts->ngacc); i++)
+    for(m=0; (m<DIM); m++)
+      fprintf(out,"  %10g",opts->acc[i][m]);
+  fprintf(out,"\n");
+
+  pr_indent(out,indent);
+  fprintf(out,"nfreeze:");
+  for(i=0; (i<opts->ngfrz); i++)
+    for(m=0; (m<DIM); m++)
+      fprintf(out,"  %10s",opts->nFreeze[i][m] ? "Y" : "N");
+  fprintf(out,"\n");
+
+
+  for(i=0; (i<opts->ngener); i++) {
+    pr_indent(out,indent);
+    fprintf(out,"energygrp-flags[%3d]:",i);
+    for(m=0; (m<opts->ngener); m++)
+      fprintf(out," %d",opts->egp_flags[opts->ngener*i+m]);
+    fprintf(out,"\n");
+  }
+
+  fflush(out);
+}
+
+static void pr_matrix(FILE *fp,int indent,const char *title,rvec *m,
+                     gmx_bool bMDPformat)
+{
+  if (bMDPformat)
+    fprintf(fp,"%-10s    = %g %g %g %g %g %g\n",title,
+           m[XX][XX],m[YY][YY],m[ZZ][ZZ],m[XX][YY],m[XX][ZZ],m[YY][ZZ]);
+  else
+    pr_rvecs(fp,indent,title,m,DIM);
+}
+
+static void pr_cosine(FILE *fp,int indent,const char *title,t_cosines *cos,
+                     gmx_bool bMDPformat)
+{
+  int j;
+  
+  if (bMDPformat) {
+    fprintf(fp,"%s = %d\n",title,cos->n);
+  }
+  else {
+    indent=pr_title(fp,indent,title);
+    (void) pr_indent(fp,indent);
+    fprintf(fp,"n = %d\n",cos->n);
+    if (cos->n > 0) {
+      (void) pr_indent(fp,indent+2);
+      fprintf(fp,"a =");
+      for(j=0; (j<cos->n); j++)
+       fprintf(fp," %e",cos->a[j]);
+      fprintf(fp,"\n");
+      (void) pr_indent(fp,indent+2);
+      fprintf(fp,"phi =");
+      for(j=0; (j<cos->n); j++)
+       fprintf(fp," %e",cos->phi[j]);
+      fprintf(fp,"\n");
+    }
+  }
+}
+
+#define PS(t,s) pr_str(fp,indent,t,s)
+#define PI(t,s) pr_int(fp,indent,t,s)
+#define PSTEP(t,s) pr_gmx_large_int(fp,indent,t,s)
+#define PR(t,s) pr_real(fp,indent,t,s)
+#define PD(t,s) pr_double(fp,indent,t,s)
+
+static void pr_pullgrp(FILE *fp,int indent,int g,t_pullgrp *pg)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"pull-group %d:\n",g);
+  indent += 2;
+  pr_ivec_block(fp,indent,"atom",pg->ind,pg->nat,TRUE);
+  pr_rvec(fp,indent,"weight",pg->weight,pg->nweight,TRUE);
+  PI("pbcatom",pg->pbcatom);
+  pr_rvec(fp,indent,"vec",pg->vec,DIM,TRUE);
+  pr_rvec(fp,indent,"init",pg->init,DIM,TRUE);
+  PR("rate",pg->rate);
+  PR("k",pg->k);
+  PR("kB",pg->kB);
+}
+
+static void pr_pull(FILE *fp,int indent,t_pull *pull)
+{
+  int g;
+
+  PS("pull-geometry",EPULLGEOM(pull->eGeom));
+  pr_ivec(fp,indent,"pull-dim",pull->dim,DIM,TRUE);
+  PR("pull-r1",pull->cyl_r1);
+  PR("pull-r0",pull->cyl_r0);
+  PR("pull-constr-tol",pull->constr_tol);
+  PI("pull-nstxout",pull->nstxout);
+  PI("pull-nstfout",pull->nstfout);
+  PI("pull-ngrp",pull->ngrp);
+  for(g=0; g<pull->ngrp+1; g++)
+    pr_pullgrp(fp,indent,g,&pull->grp[g]);
+}
+
+static void pr_rotgrp(FILE *fp,int indent,int g,t_rotgrp *rotg)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"rotation_group %d:\n",g);
+  indent += 2;
+  PS("type",EROTGEOM(rotg->eType));
+  PS("massw",BOOL(rotg->bMassW));
+  pr_ivec_block(fp,indent,"atom",rotg->ind,rotg->nat,TRUE);
+  pr_rvecs(fp,indent,"x_ref",rotg->x_ref,rotg->nat);
+  pr_rvec(fp,indent,"vec",rotg->vec,DIM,TRUE);
+  pr_rvec(fp,indent,"pivot",rotg->pivot,DIM,TRUE);
+  PR("rate",rotg->rate);
+  PR("k",rotg->k);
+  PR("slab_dist",rotg->slab_dist);
+  PR("min_gaussian",rotg->min_gaussian);
+  PR("epsilon",rotg->eps);
+  PS("fit_method",EROTFIT(rotg->eFittype));
+  PI("potfitangle_nstep",rotg->PotAngle_nstep);
+  PR("potfitangle_step",rotg->PotAngle_step);
+}
+
+static void pr_rot(FILE *fp,int indent,t_rot *rot)
+{
+  int g;
+
+  PI("rot_nstrout",rot->nstrout);
+  PI("rot_nstsout",rot->nstsout);
+  PI("rot_ngrp",rot->ngrp);
+  for(g=0; g<rot->ngrp; g++)
+    pr_rotgrp(fp,indent,g,&rot->grp[g]);
+}
+
+void pr_inputrec(FILE *fp,int indent,const char *title,t_inputrec *ir,
+                 gmx_bool bMDPformat)
+{
+  const char *infbuf="inf";
+  int  i;
+  
+  if (available(fp,ir,indent,title)) {
+    if (!bMDPformat)
+      indent=pr_title(fp,indent,title);
+    PS("integrator",EI(ir->eI));
+    PSTEP("nsteps",ir->nsteps);
+    PSTEP("init-step",ir->init_step);
+    PS("ns-type",ENS(ir->ns_type));
+    PI("nstlist",ir->nstlist);
+    PI("ndelta",ir->ndelta);
+    PI("nstcomm",ir->nstcomm);
+    PS("comm-mode",ECOM(ir->comm_mode));
+    PI("nstlog",ir->nstlog);
+    PI("nstxout",ir->nstxout);
+    PI("nstvout",ir->nstvout);
+    PI("nstfout",ir->nstfout);
+    PI("nstcalcenergy",ir->nstcalcenergy);
+    PI("nstenergy",ir->nstenergy);
+    PI("nstxtcout",ir->nstxtcout);
+    PR("init-t",ir->init_t);
+    PR("delta-t",ir->delta_t);
+    
+    PR("xtcprec",ir->xtcprec);
+    PI("nkx",ir->nkx);
+    PI("nky",ir->nky);
+    PI("nkz",ir->nkz);
+    PI("pme-order",ir->pme_order);
+    PR("ewald-rtol",ir->ewald_rtol);
+    PR("ewald-geometry",ir->ewald_geometry);
+    PR("epsilon-surface",ir->epsilon_surface);
+    PS("optimize-fft",BOOL(ir->bOptFFT));
+    PS("ePBC",EPBC(ir->ePBC));
+    PS("bPeriodicMols",BOOL(ir->bPeriodicMols));
+    PS("bContinuation",BOOL(ir->bContinuation));
+    PS("bShakeSOR",BOOL(ir->bShakeSOR));
+    PS("etc",ETCOUPLTYPE(ir->etc));
+    PI("nsttcouple",ir->nsttcouple);
+    PS("epc",EPCOUPLTYPE(ir->epc));
+    PS("epctype",EPCOUPLTYPETYPE(ir->epct));
+    PI("nstpcouple",ir->nstpcouple);
+    PR("tau-p",ir->tau_p);
+    pr_matrix(fp,indent,"ref-p",ir->ref_p,bMDPformat);
+    pr_matrix(fp,indent,"compress",ir->compress,bMDPformat);
+    PS("refcoord-scaling",EREFSCALINGTYPE(ir->refcoord_scaling));
+    if (bMDPformat)
+      fprintf(fp,"posres-com  = %g %g %g\n",ir->posres_com[XX],
+             ir->posres_com[YY],ir->posres_com[ZZ]);
+    else
+      pr_rvec(fp,indent,"posres-com",ir->posres_com,DIM,TRUE);
+    if (bMDPformat)
+      fprintf(fp,"posres-comB = %g %g %g\n",ir->posres_comB[XX],
+             ir->posres_comB[YY],ir->posres_comB[ZZ]);
+    else
+      pr_rvec(fp,indent,"posres-comB",ir->posres_comB,DIM,TRUE);
+    PI("andersen-seed",ir->andersen_seed);
+    PR("rlist",ir->rlist);
+    PR("rlistlong",ir->rlistlong);
+    PR("rtpi",ir->rtpi);
+    PS("coulombtype",EELTYPE(ir->coulombtype));
+    PR("rcoulomb-switch",ir->rcoulomb_switch);
+    PR("rcoulomb",ir->rcoulomb);
+    PS("vdwtype",EVDWTYPE(ir->vdwtype));
+    PR("rvdw-switch",ir->rvdw_switch);
+    PR("rvdw",ir->rvdw);
+    if (ir->epsilon_r != 0)
+      PR("epsilon-r",ir->epsilon_r);
+    else
+      PS("epsilon-r",infbuf);
+    if (ir->epsilon_rf != 0)
+      PR("epsilon-rf",ir->epsilon_rf);
+    else
+      PS("epsilon-rf",infbuf);
+    PR("tabext",ir->tabext);
+    PS("implicit-solvent",EIMPLICITSOL(ir->implicit_solvent));
+    PS("gb-algorithm",EGBALGORITHM(ir->gb_algorithm));
+    PR("gb-epsilon-solvent",ir->gb_epsilon_solvent);
+    PI("nstgbradii",ir->nstgbradii);
+    PR("rgbradii",ir->rgbradii);
+    PR("gb-saltconc",ir->gb_saltconc);
+    PR("gb-obc-alpha",ir->gb_obc_alpha);
+    PR("gb-obc-beta",ir->gb_obc_beta);
+    PR("gb-obc-gamma",ir->gb_obc_gamma);
+    PR("gb-dielectric-offset",ir->gb_dielectric_offset);
+    PS("sa-algorithm",ESAALGORITHM(ir->gb_algorithm));
+    PR("sa-surface-tension",ir->sa_surface_tension);
+         
+    PS("DispCorr",EDISPCORR(ir->eDispCorr));
+    PS("free-energy",EFEPTYPE(ir->efep));
+    PR("init-lambda",ir->init_lambda);
+    PR("delta-lambda",ir->delta_lambda);
+    if (!bMDPformat)
+    {
+        PI("n-foreign-lambda",ir->n_flambda);
+    }
+    if (ir->n_flambda > 0)
+    {
+        pr_indent(fp,indent);
+        fprintf(fp,"foreign-lambda%s",bMDPformat ? " = " : ":");
+        for(i=0; i<ir->n_flambda; i++)
+        {
+            fprintf(fp,"  %10g",ir->flambda[i]);
+        }
+        fprintf(fp,"\n");
+    }
+    PR("sc-alpha",ir->sc_alpha);
+    PI("sc-power",ir->sc_power);
+    PR("sc-sigma",ir->sc_sigma);
+    PR("sc-sigma-min",ir->sc_sigma_min);
+    PI("nstdhdl", ir->nstdhdl);
+    PS("separate-dhdl-file", SEPDHDLFILETYPE(ir->separate_dhdl_file));
+    PS("dhdl-derivatives", DHDLDERIVATIVESTYPE(ir->dhdl_derivatives));
+    PI("dh-hist-size", ir->dh_hist_size);
+    PD("dh-hist-spacing", ir->dh_hist_spacing);
+
+    PI("nwall",ir->nwall);
+    PS("wall-type",EWALLTYPE(ir->wall_type));
+    PI("wall-atomtype[0]",ir->wall_atomtype[0]);
+    PI("wall-atomtype[1]",ir->wall_atomtype[1]);
+    PR("wall-density[0]",ir->wall_density[0]);
+    PR("wall-density[1]",ir->wall_density[1]);
+    PR("wall-ewald-zfac",ir->wall_ewald_zfac);
+
+    PS("pull",EPULLTYPE(ir->ePull));
+    if (ir->ePull != epullNO)
+      pr_pull(fp,indent,ir->pull);
+    
+    PS("rotation",BOOL(ir->bRot));
+    if (ir->bRot)
+      pr_rot(fp,indent,ir->rot);
+
+    PS("disre",EDISRETYPE(ir->eDisre));
+    PS("disre-weighting",EDISREWEIGHTING(ir->eDisreWeighting));
+    PS("disre-mixed",BOOL(ir->bDisreMixed));
+    PR("dr-fc",ir->dr_fc);
+    PR("dr-tau",ir->dr_tau);
+    PR("nstdisreout",ir->nstdisreout);
+    PR("orires-fc",ir->orires_fc);
+    PR("orires-tau",ir->orires_tau);
+    PR("nstorireout",ir->nstorireout);
+
+    PR("dihre-fc",ir->dihre_fc);
+    
+    PR("em-stepsize",ir->em_stepsize);
+    PR("em-tol",ir->em_tol);
+    PI("niter",ir->niter);
+    PR("fc-stepsize",ir->fc_stepsize);
+    PI("nstcgsteep",ir->nstcgsteep);
+    PI("nbfgscorr",ir->nbfgscorr);
+
+    PS("ConstAlg",ECONSTRTYPE(ir->eConstrAlg));
+    PR("shake-tol",ir->shake_tol);
+    PI("lincs-order",ir->nProjOrder);
+    PR("lincs-warnangle",ir->LincsWarnAngle);
+    PI("lincs-iter",ir->nLincsIter);
+    PR("bd-fric",ir->bd_fric);
+    PI("ld-seed",ir->ld_seed);
+    PR("cos-accel",ir->cos_accel);
+    pr_matrix(fp,indent,"deform",ir->deform,bMDPformat);
+    PI("userint1",ir->userint1);
+    PI("userint2",ir->userint2);
+    PI("userint3",ir->userint3);
+    PI("userint4",ir->userint4);
+    PR("userreal1",ir->userreal1);
+    PR("userreal2",ir->userreal2);
+    PR("userreal3",ir->userreal3);
+    PR("userreal4",ir->userreal4);
+    pr_grp_opts(fp,indent,"grpopts",&(ir->opts),bMDPformat);
+    pr_cosine(fp,indent,"efield-x",&(ir->ex[XX]),bMDPformat);
+    pr_cosine(fp,indent,"efield-xt",&(ir->et[XX]),bMDPformat);
+    pr_cosine(fp,indent,"efield-y",&(ir->ex[YY]),bMDPformat);
+    pr_cosine(fp,indent,"efield-yt",&(ir->et[YY]),bMDPformat);
+    pr_cosine(fp,indent,"efield-z",&(ir->ex[ZZ]),bMDPformat);
+    pr_cosine(fp,indent,"efield-zt",&(ir->et[ZZ]),bMDPformat);
+    PS("bQMMM",BOOL(ir->bQMMM));
+    PI("QMconstraints",ir->QMconstraints);
+    PI("QMMMscheme",ir->QMMMscheme);
+    PR("scalefactor",ir->scalefactor);
+    pr_qm_opts(fp,indent,"qm-opts",&(ir->opts));
+  }
+}
+#undef PS
+#undef PR
+#undef PI
+
+static void pr_harm(FILE *fp,t_iparams *iparams,const char *r,const char *kr)
+{
+  fprintf(fp,"%sA=%12.5e, %sA=%12.5e, %sB=%12.5e, %sB=%12.5e\n",
+         r,iparams->harmonic.rA,kr,iparams->harmonic.krA,
+         r,iparams->harmonic.rB,kr,iparams->harmonic.krB);
+}
+
+void pr_iparams(FILE *fp,t_functype ftype,t_iparams *iparams)
+{
+  int i;
+  real VA[4],VB[4],*rbcA,*rbcB;
+
+  switch (ftype) {
+  case F_ANGLES:
+  case F_G96ANGLES:
+    pr_harm(fp,iparams,"th","ct");
+    break;
+  case F_CROSS_BOND_BONDS:
+    fprintf(fp,"r1e=%15.8e, r2e=%15.8e, krr=%15.8e\n",
+           iparams->cross_bb.r1e,iparams->cross_bb.r2e,
+           iparams->cross_bb.krr);
+    break;
+  case F_CROSS_BOND_ANGLES:
+    fprintf(fp,"r1e=%15.8e, r1e=%15.8e, r3e=%15.8e, krt=%15.8e\n",
+           iparams->cross_ba.r1e,iparams->cross_ba.r2e,
+           iparams->cross_ba.r3e,iparams->cross_ba.krt);
+    break;
+  case F_UREY_BRADLEY:
+    fprintf(fp,"theta=%15.8e, ktheta=%15.8e, r13=%15.8e, kUB=%15.8e\n",
+           iparams->u_b.theta,iparams->u_b.ktheta,iparams->u_b.r13,iparams->u_b.kUB);
+    break;
+  case F_QUARTIC_ANGLES:
+    fprintf(fp,"theta=%15.8e",iparams->qangle.theta);
+    for(i=0; i<5; i++)
+      fprintf(fp,", c%c=%15.8e",'0'+i,iparams->qangle.c[i]);
+    fprintf(fp,"\n");
+    break;
+  case F_BHAM:
+    fprintf(fp,"a=%15.8e, b=%15.8e, c=%15.8e\n",
+           iparams->bham.a,iparams->bham.b,iparams->bham.c);
+    break;
+  case F_BONDS:
+  case F_G96BONDS:
+  case F_HARMONIC:
+    pr_harm(fp,iparams,"b0","cb");
+    break;
+  case F_IDIHS:
+    pr_harm(fp,iparams,"xi","cx");
+    break;
+  case F_MORSE:
+    fprintf(fp,"b0=%15.8e, cb=%15.8e, beta=%15.8e\n",
+           iparams->morse.b0,iparams->morse.cb,iparams->morse.beta);
+    break;
+  case F_CUBICBONDS:
+    fprintf(fp,"b0=%15.8e, kb=%15.8e, kcub=%15.8e\n",
+           iparams->cubic.b0,iparams->cubic.kb,iparams->cubic.kcub);
+    break;
+  case F_CONNBONDS:
+    fprintf(fp,"\n");
+    break;
+  case F_FENEBONDS:
+    fprintf(fp,"bm=%15.8e, kb=%15.8e\n",iparams->fene.bm,iparams->fene.kb);
+    break;
+  case F_RESTRBONDS:
+      fprintf(fp,"lowA=%15.8e, up1A=%15.8e, up2A=%15.8e, kA=%15.8e, lowB=%15.8e, up1B=%15.8e, up2B=%15.8e, kB=%15.8e,\n",
+              iparams->restraint.lowA,iparams->restraint.up1A,
+              iparams->restraint.up2A,iparams->restraint.kA,
+              iparams->restraint.lowB,iparams->restraint.up1B,
+              iparams->restraint.up2B,iparams->restraint.kB);
+      break;
+  case F_TABBONDS:
+  case F_TABBONDSNC:
+  case F_TABANGLES:
+  case F_TABDIHS:
+    fprintf(fp,"tab=%d, kA=%15.8e, kB=%15.8e\n",
+           iparams->tab.table,iparams->tab.kA,iparams->tab.kB);
+    break;
+  case F_POLARIZATION:
+    fprintf(fp,"alpha=%15.8e\n",iparams->polarize.alpha);
+    break;
+  case F_THOLE_POL:
+    fprintf(fp,"a=%15.8e, alpha1=%15.8e, alpha2=%15.8e, rfac=%15.8e\n",
+           iparams->thole.a,iparams->thole.alpha1,iparams->thole.alpha2,
+           iparams->thole.rfac);
+    break;
+  case F_WATER_POL:
+    fprintf(fp,"al_x=%15.8e, al_y=%15.8e, al_z=%15.8e, rOH=%9.6f, rHH=%9.6f, rOD=%9.6f\n",
+           iparams->wpol.al_x,iparams->wpol.al_y,iparams->wpol.al_z,
+           iparams->wpol.rOH,iparams->wpol.rHH,iparams->wpol.rOD);
+    break;
+  case F_LJ:
+    fprintf(fp,"c6=%15.8e, c12=%15.8e\n",iparams->lj.c6,iparams->lj.c12);
+    break;
+  case F_LJ14:
+    fprintf(fp,"c6A=%15.8e, c12A=%15.8e, c6B=%15.8e, c12B=%15.8e\n",
+           iparams->lj14.c6A,iparams->lj14.c12A,
+           iparams->lj14.c6B,iparams->lj14.c12B);
+    break;
+  case F_LJC14_Q:
+    fprintf(fp,"fqq=%15.8e, qi=%15.8e, qj=%15.8e, c6=%15.8e, c12=%15.8e\n",
+           iparams->ljc14.fqq,
+           iparams->ljc14.qi,iparams->ljc14.qj,
+           iparams->ljc14.c6,iparams->ljc14.c12);
+    break;
+  case F_LJC_PAIRS_NB:
+    fprintf(fp,"qi=%15.8e, qj=%15.8e, c6=%15.8e, c12=%15.8e\n",
+           iparams->ljcnb.qi,iparams->ljcnb.qj,
+           iparams->ljcnb.c6,iparams->ljcnb.c12);
+    break;
+  case F_PDIHS:
+  case F_PIDIHS:
+  case F_ANGRES:
+  case F_ANGRESZ:
+    fprintf(fp,"phiA=%15.8e, cpA=%15.8e, phiB=%15.8e, cpB=%15.8e, mult=%d\n",
+           iparams->pdihs.phiA,iparams->pdihs.cpA,
+           iparams->pdihs.phiB,iparams->pdihs.cpB,
+           iparams->pdihs.mult);
+    break;
+  case F_DISRES:
+    fprintf(fp,"label=%4d, type=%1d, low=%15.8e, up1=%15.8e, up2=%15.8e, fac=%15.8e)\n",
+           iparams->disres.label,iparams->disres.type,
+           iparams->disres.low,iparams->disres.up1,
+           iparams->disres.up2,iparams->disres.kfac);
+    break;
+  case F_ORIRES:
+    fprintf(fp,"ex=%4d, label=%d, power=%4d, c=%15.8e, obs=%15.8e, kfac=%15.8e)\n",
+           iparams->orires.ex,iparams->orires.label,iparams->orires.power,
+           iparams->orires.c,iparams->orires.obs,iparams->orires.kfac);
+    break;
+  case F_DIHRES:
+    fprintf(fp,"label=%d, power=%4d phi=%15.8e, dphi=%15.8e, kfac=%15.8e)\n",
+           iparams->dihres.label,iparams->dihres.power,
+           iparams->dihres.phi,iparams->dihres.dphi,iparams->dihres.kfac);
+    break;
+  case F_POSRES:
+    fprintf(fp,"pos0A=(%15.8e,%15.8e,%15.8e), fcA=(%15.8e,%15.8e,%15.8e), pos0B=(%15.8e,%15.8e,%15.8e), fcB=(%15.8e,%15.8e,%15.8e)\n",
+           iparams->posres.pos0A[XX],iparams->posres.pos0A[YY],
+           iparams->posres.pos0A[ZZ],iparams->posres.fcA[XX],
+           iparams->posres.fcA[YY],iparams->posres.fcA[ZZ],
+           iparams->posres.pos0B[XX],iparams->posres.pos0B[YY],
+           iparams->posres.pos0B[ZZ],iparams->posres.fcB[XX],
+           iparams->posres.fcB[YY],iparams->posres.fcB[ZZ]);
+    break;
+  case F_RBDIHS:
+    for (i=0; i<NR_RBDIHS; i++) 
+      fprintf(fp,"%srbcA[%d]=%15.8e",i==0?"":", ",i,iparams->rbdihs.rbcA[i]);
+    fprintf(fp,"\n");
+    for (i=0; i<NR_RBDIHS; i++) 
+      fprintf(fp,"%srbcB[%d]=%15.8e",i==0?"":", ",i,iparams->rbdihs.rbcB[i]);
+    fprintf(fp,"\n");
+    break;
+  case F_FOURDIHS:
+    /* Use the OPLS -> Ryckaert-Bellemans formula backwards to get the
+     * OPLS potential constants back.
+     */
+    rbcA = iparams->rbdihs.rbcA;
+    rbcB = iparams->rbdihs.rbcB;
+
+    VA[3] = -0.25*rbcA[4];
+    VA[2] = -0.5*rbcA[3];
+    VA[1] = 4.0*VA[3]-rbcA[2];
+    VA[0] = 3.0*VA[2]-2.0*rbcA[1];
+
+    VB[3] = -0.25*rbcB[4];
+    VB[2] = -0.5*rbcB[3];
+    VB[1] = 4.0*VB[3]-rbcB[2];
+    VB[0] = 3.0*VB[2]-2.0*rbcB[1];
+
+    for (i=0; i<NR_FOURDIHS; i++) 
+      fprintf(fp,"%sFourA[%d]=%15.8e",i==0?"":", ",i,VA[i]);
+    fprintf(fp,"\n");
+    for (i=0; i<NR_FOURDIHS; i++) 
+      fprintf(fp,"%sFourB[%d]=%15.8e",i==0?"":", ",i,VB[i]);
+    fprintf(fp,"\n");
+    break;
+   
+  case F_CONSTR:
+  case F_CONSTRNC:
+    fprintf(fp,"dA=%15.8e, dB=%15.8e\n",iparams->constr.dA,iparams->constr.dB);
+    break;
+  case F_SETTLE:
+    fprintf(fp,"doh=%15.8e, dhh=%15.8e\n",iparams->settle.doh,
+           iparams->settle.dhh);
+    break;
+  case F_VSITE2:
+    fprintf(fp,"a=%15.8e\n",iparams->vsite.a);
+    break;
+  case F_VSITE3:
+  case F_VSITE3FD:
+  case F_VSITE3FAD:
+    fprintf(fp,"a=%15.8e, b=%15.8e\n",iparams->vsite.a,iparams->vsite.b);
+    break;
+  case F_VSITE3OUT:
+  case F_VSITE4FD:
+  case F_VSITE4FDN:
+    fprintf(fp,"a=%15.8e, b=%15.8e, c=%15.8e\n",
+           iparams->vsite.a,iparams->vsite.b,iparams->vsite.c);
+    break;
+  case F_VSITEN:
+    fprintf(fp,"n=%2d, a=%15.8e\n",iparams->vsiten.n,iparams->vsiten.a);
+    break;
+  case F_GB12:
+  case F_GB13:
+  case F_GB14:
+    fprintf(fp, "sar=%15.8e, st=%15.8e, pi=%15.8e, gbr=%15.8e, bmlt=%15.8e\n",iparams->gb.sar,iparams->gb.st,iparams->gb.pi,iparams->gb.gbr,iparams->gb.bmlt);
+    break;               
+  case F_CMAP:
+    fprintf(fp, "cmapA=%1d, cmapB=%1d\n",iparams->cmap.cmapA, iparams->cmap.cmapB);
+    break;               
+  default:
+    gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
+             ftype,interaction_function[ftype].name,__FILE__,__LINE__);
+  }
+}
+
+void pr_ilist(FILE *fp,int indent,const char *title,
+              t_functype *functype,t_ilist *ilist, gmx_bool bShowNumbers)
+{
+    int i,j,k,type,ftype;
+    t_iatom *iatoms;
+    
+    if (available(fp,ilist,indent,title) && ilist->nr > 0)
+    {  
+        indent=pr_title(fp,indent,title);
+        (void) pr_indent(fp,indent);
+        fprintf(fp,"nr: %d\n",ilist->nr);
+        if (ilist->nr > 0) {
+            (void) pr_indent(fp,indent);
+            fprintf(fp,"iatoms:\n");
+            iatoms=ilist->iatoms;
+            for (i=j=0; i<ilist->nr;) {
+#ifndef DEBUG
+                (void) pr_indent(fp,indent+INDENT);
+                type=*(iatoms++);
+                ftype=functype[type];
+                (void) fprintf(fp,"%d type=%d (%s)",
+                               bShowNumbers?j:-1,bShowNumbers?type:-1,
+                               interaction_function[ftype].name);
+                j++;
+                for (k=0; k<interaction_function[ftype].nratoms; k++)
+                    (void) fprintf(fp," %u",*(iatoms++));
+                (void) fprintf(fp,"\n");
+                i+=1+interaction_function[ftype].nratoms;
+#else
+                fprintf(fp,"%5d%5d\n",i,iatoms[i]);
+                i++;
+#endif
+            }
+        }
+    }
+}
+
+static void pr_cmap(FILE *fp, int indent, const char *title,
+                    gmx_cmap_t *cmap_grid, gmx_bool bShowNumbers)
+{
+    int i,j,nelem;
+    real dx,idx;
+       
+    dx    = 360.0 / cmap_grid->grid_spacing;
+    nelem = cmap_grid->grid_spacing*cmap_grid->grid_spacing;
+       
+    if(available(fp,cmap_grid,indent,title))
+    {
+        fprintf(fp,"%s\n",title);
+               
+        for(i=0;i<cmap_grid->ngrid;i++)
+        {
+            idx = -180.0;
+            fprintf(fp,"%8s %8s %8s %8s\n","V","dVdx","dVdy","d2dV");
+                       
+            fprintf(fp,"grid[%3d]={\n",bShowNumbers?i:-1);
+                       
+            for(j=0;j<nelem;j++)
+            {
+                if( (j%cmap_grid->grid_spacing)==0)
+                {
+                    fprintf(fp,"%8.1f\n",idx);
+                    idx+=dx;
+                }
+                               
+                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4]);
+                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4+1]);
+                fprintf(fp,"%8.3f ",cmap_grid->cmapdata[i].cmap[j*4+2]);
+                fprintf(fp,"%8.3f\n",cmap_grid->cmapdata[i].cmap[j*4+3]);
+            }
+            fprintf(fp,"\n");
+        }
+    }
+       
+}
+
+void pr_ffparams(FILE *fp,int indent,const char *title,
+                 gmx_ffparams_t *ffparams,
+                 gmx_bool bShowNumbers)
+{
+  int i,j;
+  
+  indent=pr_title(fp,indent,title);
+  (void) pr_indent(fp,indent);
+  (void) fprintf(fp,"atnr=%d\n",ffparams->atnr);
+  (void) pr_indent(fp,indent);
+  (void) fprintf(fp,"ntypes=%d\n",ffparams->ntypes);
+  for (i=0; i<ffparams->ntypes; i++) {
+      (void) pr_indent(fp,indent+INDENT);
+      (void) fprintf(fp,"functype[%d]=%s, ",
+                     bShowNumbers?i:-1,
+                     interaction_function[ffparams->functype[i]].name);
+      pr_iparams(fp,ffparams->functype[i],&ffparams->iparams[i]);
+  }
+  (void) pr_double(fp,indent,"reppow",ffparams->reppow);
+  (void) pr_real(fp,indent,"fudgeQQ",ffparams->fudgeQQ);
+  pr_cmap(fp,indent,"cmap",&ffparams->cmap_grid,bShowNumbers);
+}
+
+void pr_idef(FILE *fp,int indent,const char *title,t_idef *idef, gmx_bool bShowNumbers)
+{
+  int i,j;
+  
+  if (available(fp,idef,indent,title)) {  
+    indent=pr_title(fp,indent,title);
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"atnr=%d\n",idef->atnr);
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"ntypes=%d\n",idef->ntypes);
+    for (i=0; i<idef->ntypes; i++) {
+      (void) pr_indent(fp,indent+INDENT);
+      (void) fprintf(fp,"functype[%d]=%s, ",
+                    bShowNumbers?i:-1,
+                    interaction_function[idef->functype[i]].name);
+      pr_iparams(fp,idef->functype[i],&idef->iparams[i]);
+    }
+    (void) pr_real(fp,indent,"fudgeQQ",idef->fudgeQQ);
+
+    for(j=0; (j<F_NRE); j++)
+      pr_ilist(fp,indent,interaction_function[j].longname,
+               idef->functype,&idef->il[j],bShowNumbers);
+  }
+}
+
+static int pr_block_title(FILE *fp,int indent,const char *title,t_block *block)
+{
+  int i;
+
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_title(fp,indent,title);
+      (void) pr_indent(fp,indent);
+      (void) fprintf(fp,"nr=%d\n",block->nr);
+    }
+  return indent;
+}
+
+static int pr_blocka_title(FILE *fp,int indent,const char *title,t_blocka *block)
+{
+  int i;
+
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_title(fp,indent,title);
+      (void) pr_indent(fp,indent);
+      (void) fprintf(fp,"nr=%d\n",block->nr);
+      (void) pr_indent(fp,indent);
+      (void) fprintf(fp,"nra=%d\n",block->nra);
+    }
+  return indent;
+}
+
+static void low_pr_block(FILE *fp,int indent,const char *title,t_block *block, gmx_bool bShowNumbers)
+{
+  int i;
+  
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_block_title(fp,indent,title,block);
+      for (i=0; i<=block->nr; i++)
+        {
+          (void) pr_indent(fp,indent+INDENT);
+          (void) fprintf(fp,"%s->index[%d]=%u\n",
+                        title,bShowNumbers?i:-1,block->index[i]);
+        }
+    }
+}
+
+static void low_pr_blocka(FILE *fp,int indent,const char *title,t_blocka *block, gmx_bool bShowNumbers)
+{
+  int i;
+  
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_blocka_title(fp,indent,title,block);
+      for (i=0; i<=block->nr; i++)
+        {
+          (void) pr_indent(fp,indent+INDENT);
+          (void) fprintf(fp,"%s->index[%d]=%u\n",
+                        title,bShowNumbers?i:-1,block->index[i]);
+        }
+      for (i=0; i<block->nra; i++)
+        {
+          (void) pr_indent(fp,indent+INDENT);
+          (void) fprintf(fp,"%s->a[%d]=%u\n",
+                        title,bShowNumbers?i:-1,block->a[i]);
+        }
+    }
+}
+
+void pr_block(FILE *fp,int indent,const char *title,t_block *block,gmx_bool bShowNumbers)
+{
+  int i,j,ok,size,start,end;
+  
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_block_title(fp,indent,title,block);
+      start=0;
+      end=start;
+      if ((ok=(block->index[start]==0))==0)
+        (void) fprintf(fp,"block->index[%d] should be 0\n",start);
+      else
+        for (i=0; i<block->nr; i++)
+          {
+            end=block->index[i+1];
+            size=pr_indent(fp,indent);
+            if (end<=start)
+              size+=fprintf(fp,"%s[%d]={}\n",title,i);
+            else
+              size+=fprintf(fp,"%s[%d]={%d..%d}\n",
+                           title,bShowNumbers?i:-1,
+                           bShowNumbers?start:-1,bShowNumbers?end-1:-1);
+            start=end;
+          }
+    }
+}
+
+void pr_blocka(FILE *fp,int indent,const char *title,t_blocka *block,gmx_bool bShowNumbers)
+{
+  int i,j,ok,size,start,end;
+  
+  if (available(fp,block,indent,title))
+    {
+      indent=pr_blocka_title(fp,indent,title,block);
+      start=0;
+      end=start;
+      if ((ok=(block->index[start]==0))==0)
+        (void) fprintf(fp,"block->index[%d] should be 0\n",start);
+      else
+        for (i=0; i<block->nr; i++)
+          {
+            end=block->index[i+1];
+            size=pr_indent(fp,indent);
+            if (end<=start)
+              size+=fprintf(fp,"%s[%d]={",title,i);
+            else
+              size+=fprintf(fp,"%s[%d][%d..%d]={",
+                           title,bShowNumbers?i:-1,
+                           bShowNumbers?start:-1,bShowNumbers?end-1:-1);
+            for (j=start; j<end; j++)
+              {
+                if (j>start) size+=fprintf(fp,", ");
+                if ((size)>(USE_WIDTH))
+                  {
+                    (void) fprintf(fp,"\n");
+                    size=pr_indent(fp,indent+INDENT);
+                  }
+                size+=fprintf(fp,"%u",block->a[j]);
+              }
+            (void) fprintf(fp,"}\n");
+            start=end;
+          }
+      if ((end!=block->nra)||(!ok)) 
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"tables inconsistent, dumping complete tables:\n");
+          low_pr_blocka(fp,indent,title,block,bShowNumbers);
+        }
+    }
+}
+
+static void pr_strings(FILE *fp,int indent,const char *title,char ***nm,int n, gmx_bool bShowNumbers)
+{
+  int i;
+
+  if (available(fp,nm,indent,title))
+    {  
+      indent=pr_title_n(fp,indent,title,n);
+      for (i=0; i<n; i++)
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"%s[%d]={name=\"%s\"}\n",
+                        title,bShowNumbers?i:-1,*(nm[i]));
+        }
+    }
+}
+
+static void pr_strings2(FILE *fp,int indent,const char *title,
+                       char ***nm,char ***nmB,int n, gmx_bool bShowNumbers)
+{
+  int i;
+
+  if (available(fp,nm,indent,title))
+    {  
+      indent=pr_title_n(fp,indent,title,n);
+      for (i=0; i<n; i++)
+        {
+          (void) pr_indent(fp,indent);
+          (void) fprintf(fp,"%s[%d]={name=\"%s\",nameB=\"%s\"}\n",
+                        title,bShowNumbers?i:-1,*(nm[i]),*(nmB[i]));
+        }
+    }
+}
+
+static void pr_resinfo(FILE *fp,int indent,const char *title,t_resinfo *resinfo,int n, gmx_bool bShowNumbers)
+{
+    int i;
+    
+    if (available(fp,resinfo,indent,title))
+    {  
+        indent=pr_title_n(fp,indent,title,n);
+        for (i=0; i<n; i++)
+        {
+            (void) pr_indent(fp,indent);
+            (void) fprintf(fp,"%s[%d]={name=\"%s\", nr=%d, ic='%c'}\n",
+                           title,bShowNumbers?i:-1,
+                           *(resinfo[i].name),resinfo[i].nr,
+                           (resinfo[i].ic == '\0') ? ' ' : resinfo[i].ic);
+        }
+    }
+}
+
+static void pr_atom(FILE *fp,int indent,const char *title,t_atom *atom,int n)
+{
+  int i,j;
+  
+  if (available(fp,atom,indent,title)) {  
+    indent=pr_title_n(fp,indent,title,n);
+    for (i=0; i<n; i++) {
+      (void) pr_indent(fp,indent);
+      fprintf(fp,"%s[%6d]={type=%3d, typeB=%3d, ptype=%8s, m=%12.5e, "
+              "q=%12.5e, mB=%12.5e, qB=%12.5e, resind=%5d, atomnumber=%3d}\n",
+              title,i,atom[i].type,atom[i].typeB,ptype_str[atom[i].ptype],
+              atom[i].m,atom[i].q,atom[i].mB,atom[i].qB,
+              atom[i].resind,atom[i].atomnumber);
+    }
+  }
+}
+
+static void pr_grps(FILE *fp,int indent,const char *title,t_grps grps[],
+                   char **grpname[], gmx_bool bShowNumbers)
+{
+    int i,j;
+
+    for(i=0; (i<egcNR); i++)
+    {
+        fprintf(fp,"%s[%-12s] nr=%d, name=[",title,gtypes[i],grps[i].nr);
+        for(j=0; (j<grps[i].nr); j++)
+        {
+            fprintf(fp," %s",*(grpname[grps[i].nm_ind[j]]));
+        }
+        fprintf(fp,"]\n");
+    }
+}
+
+static void pr_groups(FILE *fp,int indent,const char *title,
+                      gmx_groups_t *groups,
+                      gmx_bool bShowNumbers)
+{
+    int grpnr[egcNR];
+    int nat_max,i,g;
+
+    pr_grps(fp,indent,"grp",groups->grps,groups->grpname,bShowNumbers);
+    pr_strings(fp,indent,"grpname",groups->grpname,groups->ngrpname,bShowNumbers);
+
+    (void) pr_indent(fp,indent);
+    fprintf(fp,"groups          ");
+    for(g=0; g<egcNR; g++)
+    {
+       printf(" %5.5s",gtypes[g]);
+    }
+    printf("\n");
+
+    (void) pr_indent(fp,indent);
+    fprintf(fp,"allocated       ");
+    nat_max = 0;
+    for(g=0; g<egcNR; g++)
+    {
+        printf(" %5d",groups->ngrpnr[g]);
+        nat_max = max(nat_max,groups->ngrpnr[g]);
+    }
+    printf("\n");
+
+    if (nat_max == 0)
+    {
+        (void) pr_indent(fp,indent);
+        fprintf(fp,"groupnr[%5s] =","*");
+        for(g=0; g<egcNR; g++)
+        {
+            fprintf(fp,"  %3d ",0);
+        }
+        fprintf(fp,"\n");
+    }
+    else
+    {
+        for(i=0; i<nat_max; i++)
+        {
+            (void) pr_indent(fp,indent);
+            fprintf(fp,"groupnr[%5d] =",i);
+            for(g=0; g<egcNR; g++)
+            {
+                fprintf(fp,"  %3d ",
+                        groups->grpnr[g] ? groups->grpnr[g][i] : 0);
+            }
+            fprintf(fp,"\n");
+        }
+    }
+}
+
+void pr_atoms(FILE *fp,int indent,const char *title,t_atoms *atoms, 
+             gmx_bool bShownumbers)
+{
+  if (available(fp,atoms,indent,title))
+    {
+      indent=pr_title(fp,indent,title);
+      pr_atom(fp,indent,"atom",atoms->atom,atoms->nr);
+      pr_strings(fp,indent,"atom",atoms->atomname,atoms->nr,bShownumbers);
+      pr_strings2(fp,indent,"type",atoms->atomtype,atoms->atomtypeB,atoms->nr,bShownumbers);
+      pr_resinfo(fp,indent,"residue",atoms->resinfo,atoms->nres,bShownumbers);
+    }
+}
+
+
+void pr_atomtypes(FILE *fp,int indent,const char *title,t_atomtypes *atomtypes, 
+                 gmx_bool bShowNumbers)
+{
+  int i;
+  if (available(fp,atomtypes,indent,title)) 
+  {
+    indent=pr_title(fp,indent,title);
+    for(i=0;i<atomtypes->nr;i++) {
+      pr_indent(fp,indent);
+               fprintf(fp,
+                               "atomtype[%3d]={radius=%12.5e, volume=%12.5e, gb_radius=%12.5e, surftens=%12.5e, atomnumber=%4d, S_hct=%12.5e)}\n",
+                               bShowNumbers?i:-1,atomtypes->radius[i],atomtypes->vol[i],
+                               atomtypes->gb_radius[i],
+                               atomtypes->surftens[i],atomtypes->atomnumber[i],atomtypes->S_hct[i]);
+    }
+  }
+}
+
+static void pr_moltype(FILE *fp,int indent,const char *title,
+                       gmx_moltype_t *molt,int n,
+                       gmx_ffparams_t *ffparams,
+                       gmx_bool bShowNumbers)
+{
+    int j;
+
+    indent = pr_title_n(fp,indent,title,n);
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"name=\"%s\"\n",*(molt->name));
+    pr_atoms(fp,indent,"atoms",&(molt->atoms),bShowNumbers);
+    pr_block(fp,indent,"cgs",&molt->cgs, bShowNumbers);
+    pr_blocka(fp,indent,"excls",&molt->excls, bShowNumbers);
+    for(j=0; (j<F_NRE); j++) {
+        pr_ilist(fp,indent,interaction_function[j].longname,
+                 ffparams->functype,&molt->ilist[j],bShowNumbers);
+    }
+}
+
+static void pr_molblock(FILE *fp,int indent,const char *title,
+                        gmx_molblock_t *molb,int n,
+                        gmx_moltype_t *molt,
+                        gmx_bool bShowNumbers)
+{
+    indent = pr_title_n(fp,indent,title,n);
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"%-20s = %d \"%s\"\n",
+                   "moltype",molb->type,*(molt[molb->type].name));
+    pr_int(fp,indent,"#molecules",molb->nmol);
+    pr_int(fp,indent,"#atoms_mol",molb->natoms_mol);
+    pr_int(fp,indent,"#posres_xA",molb->nposres_xA);
+    if (molb->nposres_xA > 0) {
+        pr_rvecs(fp,indent,"posres_xA",molb->posres_xA,molb->nposres_xA);
+    }
+    pr_int(fp,indent,"#posres_xB",molb->nposres_xB);
+    if (molb->nposres_xB > 0) {
+        pr_rvecs(fp,indent,"posres_xB",molb->posres_xB,molb->nposres_xB);
+    }
+}
+
+void pr_mtop(FILE *fp,int indent,const char *title,gmx_mtop_t *mtop,
+             gmx_bool bShowNumbers)
+{
+    int mt,mb;
+
+    if (available(fp,mtop,indent,title)) {
+        indent=pr_title(fp,indent,title);
+        (void) pr_indent(fp,indent);
+        (void) fprintf(fp,"name=\"%s\"\n",*(mtop->name));
+        pr_int(fp,indent,"#atoms",mtop->natoms);
+        for(mb=0; mb<mtop->nmolblock; mb++) {
+            pr_molblock(fp,indent,"molblock",&mtop->molblock[mb],mb,
+                        mtop->moltype,bShowNumbers);
+        }
+        pr_ffparams(fp,indent,"ffparams",&(mtop->ffparams),bShowNumbers);
+        pr_atomtypes(fp,indent,"atomtypes",&(mtop->atomtypes),bShowNumbers);
+        for(mt=0; mt<mtop->nmoltype; mt++) {
+            pr_moltype(fp,indent,"moltype",&mtop->moltype[mt],mt,
+                       &mtop->ffparams,bShowNumbers);
+        }
+        pr_groups(fp,indent,"groups",&mtop->groups,bShowNumbers);
+    }
+}
+
+void pr_top(FILE *fp,int indent,const char *title,t_topology *top, gmx_bool bShowNumbers)
+{
+  if (available(fp,top,indent,title)) {
+    indent=pr_title(fp,indent,title);
+    (void) pr_indent(fp,indent);
+    (void) fprintf(fp,"name=\"%s\"\n",*(top->name));
+    pr_atoms(fp,indent,"atoms",&(top->atoms),bShowNumbers);
+    pr_atomtypes(fp,indent,"atomtypes",&(top->atomtypes),bShowNumbers);
+    pr_block(fp,indent,"cgs",&top->cgs, bShowNumbers);
+    pr_block(fp,indent,"mols",&top->mols, bShowNumbers);
+    pr_blocka(fp,indent,"excls",&top->excls, bShowNumbers);
+    pr_idef(fp,indent,"idef",&top->idef,bShowNumbers);
+  }
+}
+
+void pr_header(FILE *fp,int indent,const char *title,t_tpxheader *sh)
+{
+  char buf[22];
+    
+  if (available(fp,sh,indent,title))
+    {
+      indent=pr_title(fp,indent,title);
+      pr_indent(fp,indent);
+      fprintf(fp,"bIr    = %spresent\n",sh->bIr?"":"not ");
+      pr_indent(fp,indent);
+      fprintf(fp,"bBox   = %spresent\n",sh->bBox?"":"not ");
+      pr_indent(fp,indent);
+      fprintf(fp,"bTop   = %spresent\n",sh->bTop?"":"not ");
+      pr_indent(fp,indent);
+      fprintf(fp,"bX     = %spresent\n",sh->bX?"":"not ");
+      pr_indent(fp,indent);
+      fprintf(fp,"bV     = %spresent\n",sh->bV?"":"not ");
+      pr_indent(fp,indent);
+      fprintf(fp,"bF     = %spresent\n",sh->bF?"":"not ");
+      
+      pr_indent(fp,indent);
+      fprintf(fp,"natoms = %d\n",sh->natoms);
+      pr_indent(fp,indent);
+      fprintf(fp,"lambda = %e\n",sh->lambda);
+    }
+}
+
+void pr_commrec(FILE *fp,int indent,t_commrec *cr)
+{
+  pr_indent(fp,indent);
+  fprintf(fp,"commrec:\n");
+  indent+=2;
+  pr_indent(fp,indent);
+  fprintf(fp,"nodeid    = %d\n",cr->nodeid);
+  pr_indent(fp,indent);
+  fprintf(fp,"nnodes    = %d\n",cr->nnodes);
+  pr_indent(fp,indent);
+  fprintf(fp,"npmenodes = %d\n",cr->npmenodes);
+  /*
+  pr_indent(fp,indent);
+  fprintf(fp,"threadid  = %d\n",cr->threadid);
+  pr_indent(fp,indent);
+  fprintf(fp,"nthreads  = %d\n",cr->nthreads);
+  */
+}
similarity index 100%
rename from src/gmxlib/wgms.c
rename to src/gromacs/gmxlib/wgms.c
similarity index 100%
rename from src/gmxlib/wman.c
rename to src/gromacs/gmxlib/wman.c
similarity index 100%
rename from src/gmxlib/xdrd.c
rename to src/gromacs/gmxlib/xdrd.c
similarity index 100%
rename from src/gmxlib/xvgr.c
rename to src/gromacs/gmxlib/xvgr.c
diff --git a/src/gromacs/gmxpreprocess/CMakeLists.txt b/src/gromacs/gmxpreprocess/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c50ad9e
--- /dev/null
@@ -0,0 +1,3 @@
+file(GLOB GMXPREPROCESS_SOURCES *.c)
+
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${GMXPREPROCESS_SOURCES} PARENT_SCOPE)
diff --git a/src/gromacs/gmxpreprocess/readir.c b/src/gromacs/gmxpreprocess/readir.c
new file mode 100644 (file)
index 0000000..97f2078
--- /dev/null
@@ -0,0 +1,2605 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "typedefs.h"
+#include "physics.h"
+#include "names.h"
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "index.h"
+#include "symtab.h"
+#include "string2.h"
+#include "readinp.h"
+#include "warninp.h"
+#include "readir.h" 
+#include "toputil.h"
+#include "index.h"
+#include "network.h"
+#include "vec.h"
+#include "pbc.h"
+#include "mtop_util.h"
+#include "chargegroup.h"
+#include "inputrec.h"
+
+#define MAXPTR 254
+#define NOGID  255
+
+/* Resource parameters 
+ * Do not change any of these until you read the instruction
+ * in readinp.h. Some cpp's do not take spaces after the backslash
+ * (like the c-shell), which will give you a very weird compiler
+ * message.
+ */
+
+static char tcgrps[STRLEN],tau_t[STRLEN],ref_t[STRLEN],
+  acc[STRLEN],accgrps[STRLEN],freeze[STRLEN],frdim[STRLEN],
+  energy[STRLEN],user1[STRLEN],user2[STRLEN],vcm[STRLEN],xtc_grps[STRLEN],
+  couple_moltype[STRLEN],orirefitgrp[STRLEN],egptable[STRLEN],egpexcl[STRLEN],
+  wall_atomtype[STRLEN],wall_density[STRLEN],deform[STRLEN],QMMM[STRLEN];
+static char foreign_lambda[STRLEN];
+static char **pull_grp;
+static char **rot_grp;
+static char anneal[STRLEN],anneal_npoints[STRLEN],
+  anneal_time[STRLEN],anneal_temp[STRLEN];
+static char QMmethod[STRLEN],QMbasis[STRLEN],QMcharge[STRLEN],QMmult[STRLEN],
+  bSH[STRLEN],CASorbitals[STRLEN], CASelectrons[STRLEN],SAon[STRLEN],
+  SAoff[STRLEN],SAsteps[STRLEN],bTS[STRLEN],bOPT[STRLEN]; 
+static char efield_x[STRLEN],efield_xt[STRLEN],efield_y[STRLEN],
+  efield_yt[STRLEN],efield_z[STRLEN],efield_zt[STRLEN];
+
+enum {
+    egrptpALL,         /* All particles have to be a member of a group.     */
+    egrptpALL_GENREST, /* A rest group with name is generated for particles *
+                        * that are not part of any group.                   */
+    egrptpPART,        /* As egrptpALL_GENREST, but no name is generated    *
+                        * for the rest group.                               */
+    egrptpONE          /* Merge all selected groups into one group,         *
+                        * make a rest group for the remaining particles.    */
+};
+
+
+void init_ir(t_inputrec *ir, t_gromppopts *opts)
+{
+  snew(opts->include,STRLEN); 
+  snew(opts->define,STRLEN);
+}
+
+static void _low_check(gmx_bool b,char *s,warninp_t wi)
+{
+    if (b)
+    {
+        warning_error(wi,s);
+    }
+}
+
+static void check_nst(const char *desc_nst,int nst,
+                      const char *desc_p,int *p,
+                      warninp_t wi)
+{
+    char buf[STRLEN];
+
+    if (*p > 0 && *p % nst != 0)
+    {
+        /* Round up to the next multiple of nst */
+        *p = ((*p)/nst + 1)*nst;
+        sprintf(buf,"%s should be a multiple of %s, changing %s to %d\n",
+               desc_p,desc_nst,desc_p,*p);
+        warning(wi,buf);
+    }
+}
+
+static gmx_bool ir_NVE(const t_inputrec *ir)
+{
+    return ((ir->eI == eiMD || EI_VV(ir->eI)) && ir->etc == etcNO);
+}
+
+static int lcd(int n1,int n2)
+{
+    int d,i;
+    
+    d = 1;
+    for(i=2; (i<=n1 && i<=n2); i++)
+    {
+        if (n1 % i == 0 && n2 % i == 0)
+        {
+            d = i;
+        }
+    }
+    
+  return d;
+}
+
+void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
+              warninp_t wi)
+/* Check internal consistency */
+{
+    /* Strange macro: first one fills the err_buf, and then one can check 
+     * the condition, which will print the message and increase the error
+     * counter.
+     */
+#define CHECK(b) _low_check(b,err_buf,wi)
+    char err_buf[256],warn_buf[STRLEN];
+    int  ns_type=0;
+    real dt_pcoupl;
+
+  set_warning_line(wi,mdparin,-1);
+
+  /* BASIC CUT-OFF STUFF */
+  if (ir->rlist == 0 ||
+      !((EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > ir->rlist) ||
+        (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype)    && ir->rvdw     > ir->rlist))) {
+    /* No switched potential and/or no twin-range:
+     * we can set the long-range cut-off to the maximum of the other cut-offs.
+     */
+    ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
+  } else if (ir->rlistlong < 0) {
+    ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
+    sprintf(warn_buf,"rlistlong was not set, setting it to %g (no buffer)",
+           ir->rlistlong);
+    warning(wi,warn_buf);
+  }
+  if (ir->rlistlong == 0 && ir->ePBC != epbcNONE) {
+      warning_error(wi,"Can not have an infinite cut-off with PBC");
+  }
+  if (ir->rlistlong > 0 && (ir->rlist == 0 || ir->rlistlong < ir->rlist)) {
+      warning_error(wi,"rlistlong can not be shorter than rlist");
+  }
+  if (IR_TWINRANGE(*ir) && ir->nstlist <= 0) {
+      warning_error(wi,"Can not have nstlist<=0 with twin-range interactions");
+  }
+
+    /* GENERAL INTEGRATOR STUFF */
+    if (!(ir->eI == eiMD || EI_VV(ir->eI)))
+    {
+        ir->etc = etcNO;
+    }
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        ir->epc = epcNO;
+    }
+    if (EI_DYNAMICS(ir->eI))
+    {
+        if (ir->nstcalcenergy < 0)
+        {
+            ir->nstcalcenergy = ir_optimal_nstcalcenergy(ir);
+            if (ir->nstenergy != 0 && ir->nstenergy < ir->nstcalcenergy)
+            {
+                /* nstcalcenergy larger than nstener does not make sense.
+                 * We ideally want nstcalcenergy=nstener.
+                 */
+                if (ir->nstlist > 0)
+                {
+                    ir->nstcalcenergy = lcd(ir->nstenergy,ir->nstlist);
+                }
+                else
+                {
+                    ir->nstcalcenergy = ir->nstenergy;
+                }
+            }
+        }
+        if (ir->epc != epcNO)
+        {
+            if (ir->nstpcouple < 0)
+            {
+                ir->nstpcouple = ir_optimal_nstpcouple(ir);
+            }
+        }
+        if (IR_TWINRANGE(*ir))
+        {
+            check_nst("nstlist",ir->nstlist,
+                      "nstcalcenergy",&ir->nstcalcenergy,wi);
+            if (ir->epc != epcNO)
+            {
+                check_nst("nstlist",ir->nstlist,
+                          "nstpcouple",&ir->nstpcouple,wi); 
+            }
+        }
+
+        if (ir->nstcalcenergy > 1)
+        {
+            /* for storing exact averages nstenergy should be
+             * a multiple of nstcalcenergy
+             */
+            check_nst("nstcalcenergy",ir->nstcalcenergy,
+                      "nstenergy",&ir->nstenergy,wi);
+            if (ir->efep != efepNO)
+            {
+                /* nstdhdl should be a multiple of nstcalcenergy */
+                check_nst("nstcalcenergy",ir->nstcalcenergy,
+                          "nstdhdl",&ir->nstdhdl,wi);
+            }
+        }
+    }
+
+  /* LD STUFF */
+  if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
+      ir->bContinuation && ir->ld_seed != -1) {
+      warning_note(wi,"You are doing a continuation with SD or BD, make sure that ld_seed is different from the previous run (using ld_seed=-1 will ensure this)");
+  }
+
+  /* TPI STUFF */
+  if (EI_TPI(ir->eI)) {
+    sprintf(err_buf,"TPI only works with pbc = %s",epbc_names[epbcXYZ]);
+    CHECK(ir->ePBC != epbcXYZ);
+    sprintf(err_buf,"TPI only works with ns = %s",ens_names[ensGRID]);
+    CHECK(ir->ns_type != ensGRID);
+    sprintf(err_buf,"with TPI nstlist should be larger than zero");
+    CHECK(ir->nstlist <= 0);
+    sprintf(err_buf,"TPI does not work with full electrostatics other than PME");
+    CHECK(EEL_FULL(ir->coulombtype) && !EEL_PME(ir->coulombtype));
+  }
+
+  /* SHAKE / LINCS */
+  if ( (opts->nshake > 0) && (opts->bMorse) ) {
+    sprintf(warn_buf,
+           "Using morse bond-potentials while constraining bonds is useless");
+    warning(wi,warn_buf);
+  }
+  
+  sprintf(err_buf,"shake_tol must be > 0 instead of %g while using shake",
+         ir->shake_tol);
+  CHECK(((ir->shake_tol <= 0.0) && (opts->nshake>0) && 
+        (ir->eConstrAlg == econtSHAKE)));
+     
+  /* PBC/WALLS */
+  sprintf(err_buf,"walls only work with pbc=%s",epbc_names[epbcXY]);
+  CHECK(ir->nwall && ir->ePBC!=epbcXY);
+
+  /* VACUUM STUFF */
+  if (ir->ePBC != epbcXYZ && ir->nwall != 2) {
+    if (ir->ePBC == epbcNONE) {
+      if (ir->epc != epcNO) {
+          warning(wi,"Turning off pressure coupling for vacuum system");
+          ir->epc = epcNO;
+      }
+    } else {
+      sprintf(err_buf,"Can not have pressure coupling with pbc=%s",
+             epbc_names[ir->ePBC]);
+      CHECK(ir->epc != epcNO);
+    }
+    sprintf(err_buf,"Can not have Ewald with pbc=%s",epbc_names[ir->ePBC]);
+    CHECK(EEL_FULL(ir->coulombtype));
+    
+    sprintf(err_buf,"Can not have dispersion correction with pbc=%s",
+           epbc_names[ir->ePBC]);
+    CHECK(ir->eDispCorr != edispcNO);
+  }
+
+  if (ir->rlist == 0.0) {
+    sprintf(err_buf,"can only have neighborlist cut-off zero (=infinite)\n"
+           "with coulombtype = %s or coulombtype = %s\n"
+           "without periodic boundary conditions (pbc = %s) and\n"
+           "rcoulomb and rvdw set to zero",
+           eel_names[eelCUT],eel_names[eelUSER],epbc_names[epbcNONE]);
+    CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER)) ||
+         (ir->ePBC     != epbcNONE) || 
+         (ir->rcoulomb != 0.0)      || (ir->rvdw != 0.0));
+
+    if (ir->nstlist < 0) {
+        warning_error(wi,"Can not have heuristic neighborlist updates without cut-off");
+    }
+    if (ir->nstlist > 0) {
+        warning_note(wi,"Simulating without cut-offs is usually (slightly) faster with nstlist=0, nstype=simple and particle decomposition");
+    }
+  }
+
+  /* COMM STUFF */
+  if (ir->nstcomm == 0) {
+    ir->comm_mode = ecmNO;
+  }
+  if (ir->comm_mode != ecmNO) {
+    if (ir->nstcomm < 0) {
+        warning(wi,"If you want to remove the rotation around the center of mass, you should set comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to its absolute value");
+      ir->nstcomm = abs(ir->nstcomm);
+    }
+    
+    if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy) {
+        warning_note(wi,"nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting nstcomm to nstcalcenergy");
+      ir->nstcomm = ir->nstcalcenergy;
+    }
+
+    if (ir->comm_mode == ecmANGULAR) {
+      sprintf(err_buf,"Can not remove the rotation around the center of mass with periodic molecules");
+      CHECK(ir->bPeriodicMols);
+      if (ir->ePBC != epbcNONE)
+          warning(wi,"Removing the rotation around the center of mass in a periodic system (this is not a problem when you have only one molecule).");
+    }
+  }
+    
+  if (EI_STATE_VELOCITY(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR) {
+      warning_note(wi,"Tumbling and or flying ice-cubes: We are not removing rotation around center of mass in a non-periodic system. You should probably set comm_mode = ANGULAR.");
+  }
+  
+  sprintf(err_buf,"Free-energy not implemented for Ewald and PPPM");
+  CHECK((ir->coulombtype==eelEWALD || ir->coulombtype==eelPPPM)
+       && (ir->efep!=efepNO));
+  
+  sprintf(err_buf,"Twin-range neighbour searching (NS) with simple NS"
+         " algorithm not implemented");
+  CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist)) 
+       && (ir->ns_type == ensSIMPLE));
+  
+    /* TEMPERATURE COUPLING */
+    if (ir->etc == etcYES)
+    {
+        ir->etc = etcBERENDSEN;
+        warning_note(wi,"Old option for temperature coupling given: "
+                     "changing \"yes\" to \"Berendsen\"\n");
+    }
+  
+    if (ir->etc == etcNOSEHOOVER)
+    {
+        if (ir->opts.nhchainlength < 1) 
+        {
+            sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
+            ir->opts.nhchainlength =1;
+            warning(wi,warn_buf);
+        }
+        
+        if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
+        {
+            warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
+            ir->opts.nhchainlength = 1;
+        }
+    }
+    else
+    {
+        ir->opts.nhchainlength = 0;
+    }
+
+    if (ir->etc == etcBERENDSEN)
+    {
+        sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
+                ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
+        warning_note(wi,warn_buf);
+    }
+
+    if ((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL) 
+        && ir->epc==epcBERENDSEN)
+    {
+        sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
+                "true ensemble for the thermostat");
+        warning(wi,warn_buf);
+    }
+
+    /* PRESSURE COUPLING */
+    if (ir->epc == epcISOTROPIC)
+    {
+        ir->epc = epcBERENDSEN;
+        warning_note(wi,"Old option for pressure coupling given: "
+                     "changing \"Isotropic\" to \"Berendsen\"\n"); 
+    }
+
+    if (ir->epc != epcNO)
+    {
+        dt_pcoupl = ir->nstpcouple*ir->delta_t;
+
+        sprintf(err_buf,"tau-p must be > 0 instead of %g\n",ir->tau_p);
+        CHECK(ir->tau_p <= 0);
+        
+        if (ir->tau_p/dt_pcoupl < pcouple_min_integration_steps(ir->epc))
+        {
+            sprintf(warn_buf,"For proper integration of the %s barostat, tau-p (%g) should be at least %d times larger than nstpcouple*dt (%g)",
+                    EPCOUPLTYPE(ir->epc),ir->tau_p,pcouple_min_integration_steps(ir->epc),dt_pcoupl);
+            warning(wi,warn_buf);
+        }      
+        
+        sprintf(err_buf,"compressibility must be > 0 when using pressure" 
+                " coupling %s\n",EPCOUPLTYPE(ir->epc));
+        CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || 
+              ir->compress[ZZ][ZZ] < 0 || 
+              (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
+               ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
+        
+        sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
+        CHECK(ir->coulombtype == eelPPPM);
+        
+    }
+    else if (ir->coulombtype == eelPPPM)
+    {
+        sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
+        warning(wi,warn_buf);
+    }
+    
+    if (EI_VV(ir->eI))
+    {
+        if (ir->epc > epcNO)
+        {
+            if (ir->epc!=epcMTTK)
+            {
+                warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");          
+            }
+        }
+    }
+
+  /* ELECTROSTATICS */
+  /* More checks are in triple check (grompp.c) */
+    if (ir->coulombtype == eelPPPM)
+    {
+        warning_error(wi,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code");
+    }
+
+  if (ir->coulombtype == eelSWITCH) {
+    sprintf(warn_buf,"coulombtype = %s is only for testing purposes and can lead to serious artifacts, advice: use coulombtype = %s",
+           eel_names[ir->coulombtype],
+           eel_names[eelRF_ZERO]);
+    warning(wi,warn_buf);
+  }
+
+  if (ir->epsilon_r!=1 && ir->implicit_solvent==eisGBSA) {
+    sprintf(warn_buf,"epsilon-r = %g with GB implicit solvent, will use this value for inner dielectric",ir->epsilon_r);
+    warning_note(wi,warn_buf);
+  }
+
+  if (EEL_RF(ir->coulombtype) && ir->epsilon_rf==1 && ir->epsilon_r!=1) {
+    sprintf(warn_buf,"epsilon-r = %g and epsilon-rf = 1 with reaction field, assuming old format and exchanging epsilon-r and epsilon-rf",ir->epsilon_r);
+    warning(wi,warn_buf);
+    ir->epsilon_rf = ir->epsilon_r;
+    ir->epsilon_r  = 1.0;
+  }
+
+  if (getenv("GALACTIC_DYNAMICS") == NULL) {  
+    sprintf(err_buf,"epsilon-r must be >= 0 instead of %g\n",ir->epsilon_r);
+    CHECK(ir->epsilon_r < 0);
+  }
+  
+  if (EEL_RF(ir->coulombtype)) {
+    /* reaction field (at the cut-off) */
+    
+    if (ir->coulombtype == eelRF_ZERO) {
+       sprintf(err_buf,"With coulombtype = %s, epsilon-rf must be 0",
+              eel_names[ir->coulombtype]);
+      CHECK(ir->epsilon_rf != 0);
+    }
+
+    sprintf(err_buf,"epsilon-rf must be >= epsilon-r");
+    CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) ||
+         (ir->epsilon_r == 0));
+    if (ir->epsilon_rf == ir->epsilon_r) {
+      sprintf(warn_buf,"Using epsilon-rf = epsilon-r with %s does not make sense",
+             eel_names[ir->coulombtype]);
+      warning(wi,warn_buf);
+    }
+  }
+  /* Allow rlist>rcoulomb for tabulated long range stuff. This just
+   * means the interaction is zero outside rcoulomb, but it helps to
+   * provide accurate energy conservation.
+   */
+  if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype)) {
+    if (EEL_SWITCHED(ir->coulombtype)) {
+      sprintf(err_buf,
+             "With coulombtype = %s rcoulomb_switch must be < rcoulomb",
+             eel_names[ir->coulombtype]);
+      CHECK(ir->rcoulomb_switch >= ir->rcoulomb);
+    }
+  } else if (ir->coulombtype == eelCUT || EEL_RF(ir->coulombtype)) {
+    sprintf(err_buf,"With coulombtype = %s, rcoulomb must be >= rlist",
+           eel_names[ir->coulombtype]);
+    CHECK(ir->rlist > ir->rcoulomb);
+  }
+
+  if (EEL_FULL(ir->coulombtype)) {
+    if (ir->coulombtype==eelPMESWITCH || ir->coulombtype==eelPMEUSER ||
+        ir->coulombtype==eelPMEUSERSWITCH) {
+      sprintf(err_buf,"With coulombtype = %s, rcoulomb must be <= rlist",
+             eel_names[ir->coulombtype]);
+      CHECK(ir->rcoulomb > ir->rlist);
+    } else {
+      if (ir->coulombtype == eelPME) {
+       sprintf(err_buf,
+               "With coulombtype = %s, rcoulomb must be equal to rlist\n"
+               "If you want optimal energy conservation or exact integration use %s",
+               eel_names[ir->coulombtype],eel_names[eelPMESWITCH]);
+      } else { 
+       sprintf(err_buf,
+               "With coulombtype = %s, rcoulomb must be equal to rlist",
+               eel_names[ir->coulombtype]);
+      }
+      CHECK(ir->rcoulomb != ir->rlist);
+    }
+  }
+
+  if (EEL_PME(ir->coulombtype)) {
+    if (ir->pme_order < 3) {
+        warning_error(wi,"pme-order can not be smaller than 3");
+    }
+  }
+
+  if (ir->nwall==2 && EEL_FULL(ir->coulombtype)) {
+    if (ir->ewald_geometry == eewg3D) {
+      sprintf(warn_buf,"With pbc=%s you should use ewald-geometry=%s",
+             epbc_names[ir->ePBC],eewg_names[eewg3DC]);
+      warning(wi,warn_buf);
+    }
+    /* This check avoids extra pbc coding for exclusion corrections */
+    sprintf(err_buf,"wall-ewald-zfac should be >= 2");
+    CHECK(ir->wall_ewald_zfac < 2);
+  }
+
+  if (EVDW_SWITCHED(ir->vdwtype)) {
+    sprintf(err_buf,"With vdwtype = %s rvdw-switch must be < rvdw",
+           evdw_names[ir->vdwtype]);
+    CHECK(ir->rvdw_switch >= ir->rvdw);
+  } else if (ir->vdwtype == evdwCUT) {
+    sprintf(err_buf,"With vdwtype = %s, rvdw must be >= rlist",evdw_names[ir->vdwtype]);
+    CHECK(ir->rlist > ir->rvdw);
+  }
+  if (EEL_IS_ZERO_AT_CUTOFF(ir->coulombtype)
+      && (ir->rlistlong <= ir->rcoulomb)) {
+    sprintf(warn_buf,"For energy conservation with switch/shift potentials, %s should be 0.1 to 0.3 nm larger than rcoulomb.",
+           IR_TWINRANGE(*ir) ? "rlistlong" : "rlist");
+    warning_note(wi,warn_buf);
+  }
+  if (EVDW_SWITCHED(ir->vdwtype) && (ir->rlistlong <= ir->rvdw)) {
+    sprintf(warn_buf,"For energy conservation with switch/shift potentials, %s should be 0.1 to 0.3 nm larger than rvdw.",
+           IR_TWINRANGE(*ir) ? "rlistlong" : "rlist");
+    warning_note(wi,warn_buf);
+  }
+
+  if (ir->vdwtype == evdwUSER && ir->eDispCorr != edispcNO) {
+      warning_note(wi,"You have selected user tables with dispersion correction, the dispersion will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction between rvdw_switch and rvdw will not be double counted). Make sure that you really want dispersion correction to -C6/r^6.");
+  }
+
+  if (ir->nstlist == -1) {
+    sprintf(err_buf,
+           "nstlist=-1 only works with switched or shifted potentials,\n"
+           "suggestion: use vdw-type=%s and coulomb-type=%s",
+           evdw_names[evdwSHIFT],eel_names[eelPMESWITCH]);
+    CHECK(!(EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) &&
+            EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype)));
+
+    sprintf(err_buf,"With nstlist=-1 rvdw and rcoulomb should be smaller than rlist to account for diffusion and possibly charge-group radii");
+    CHECK(ir->rvdw >= ir->rlist || ir->rcoulomb >= ir->rlist);
+  }
+  sprintf(err_buf,"nstlist can not be smaller than -1");
+  CHECK(ir->nstlist < -1);
+
+  if (ir->eI == eiLBFGS && (ir->coulombtype==eelCUT || ir->vdwtype==evdwCUT)
+     && ir->rvdw != 0) {
+    warning(wi,"For efficient BFGS minimization, use switch/shift/pme instead of cut-off.");
+  }
+
+  if (ir->eI == eiLBFGS && ir->nbfgscorr <= 0) {
+    warning(wi,"Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
+  }
+
+  /* FREE ENERGY */
+  if (ir->efep != efepNO) {
+    sprintf(err_buf,"The soft-core power is %d and can only be 1 or 2",
+           ir->sc_power);
+    CHECK(ir->sc_alpha!=0 && ir->sc_power!=1 && ir->sc_power!=2);
+  }
+
+    /* ENERGY CONSERVATION */
+    if (ir_NVE(ir))
+    {
+        if (!EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype) && ir->rvdw > 0)
+        {
+            sprintf(warn_buf,"You are using a cut-off for VdW interactions with NVE, for good energy conservation use vdwtype = %s (possibly with DispCorr)",
+                    evdw_names[evdwSHIFT]);
+            warning_note(wi,warn_buf);
+        }
+        if (!EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > 0)
+        {
+            sprintf(warn_buf,"You are using a cut-off for electrostatics with NVE, for good energy conservation use coulombtype = %s or %s",
+                    eel_names[eelPMESWITCH],eel_names[eelRF_ZERO]);
+            warning_note(wi,warn_buf);
+        }
+    }
+  
+  /* IMPLICIT SOLVENT */
+  if(ir->coulombtype==eelGB_NOTUSED)
+  {
+    ir->coulombtype=eelCUT;
+    ir->implicit_solvent=eisGBSA;
+    fprintf(stderr,"Note: Old option for generalized born electrostatics given:\n"
+           "Changing coulombtype from \"generalized-born\" to \"cut-off\" and instead\n"
+            "setting implicit-solvent value to \"GBSA\" in input section.\n");
+  }
+
+  if(ir->sa_algorithm==esaSTILL)
+  {
+    sprintf(err_buf,"Still SA algorithm not available yet, use %s or %s instead\n",esa_names[esaAPPROX],esa_names[esaNO]);
+    CHECK(ir->sa_algorithm == esaSTILL);
+  }
+  
+  if(ir->implicit_solvent==eisGBSA)
+  {
+    sprintf(err_buf,"With GBSA implicit solvent, rgbradii must be equal to rlist.");
+    CHECK(ir->rgbradii != ir->rlist);
+         
+    if(ir->coulombtype!=eelCUT)
+         {
+                 sprintf(err_buf,"With GBSA, coulombtype must be equal to %s\n",eel_names[eelCUT]);
+                 CHECK(ir->coulombtype!=eelCUT);
+         }
+         if(ir->vdwtype!=evdwCUT)
+         {
+                 sprintf(err_buf,"With GBSA, vdw-type must be equal to %s\n",evdw_names[evdwCUT]);
+                 CHECK(ir->vdwtype!=evdwCUT);
+         }
+    if(ir->nstgbradii<1)
+    {
+      sprintf(warn_buf,"Using GBSA with nstgbradii<1, setting nstgbradii=1");
+      warning_note(wi,warn_buf);
+      ir->nstgbradii=1;
+    }
+    if(ir->sa_algorithm==esaNO)
+    {
+      sprintf(warn_buf,"No SA (non-polar) calculation requested together with GB. Are you sure this is what you want?\n");
+      warning_note(wi,warn_buf);
+    }
+    if(ir->sa_surface_tension<0 && ir->sa_algorithm!=esaNO)
+    {
+      sprintf(warn_buf,"Value of sa_surface_tension is < 0. Changing it to 2.05016 or 2.25936 kJ/nm^2/mol for Still and HCT/OBC respectively\n");
+      warning_note(wi,warn_buf);
+      
+      if(ir->gb_algorithm==egbSTILL)
+      {
+        ir->sa_surface_tension = 0.0049 * CAL2JOULE * 100;
+      }
+      else
+      {
+        ir->sa_surface_tension = 0.0054 * CAL2JOULE * 100;
+      }
+    }
+    if(ir->sa_surface_tension==0 && ir->sa_algorithm!=esaNO)
+    {
+      sprintf(err_buf, "Surface tension set to 0 while SA-calculation requested\n");
+      CHECK(ir->sa_surface_tension==0 && ir->sa_algorithm!=esaNO);
+    }
+    
+  }
+}
+
+static int str_nelem(const char *str,int maxptr,char *ptr[])
+{
+  int  np=0;
+  char *copy0,*copy;
+  
+  copy0=strdup(str); 
+  copy=copy0;
+  ltrim(copy);
+  while (*copy != '\0') {
+    if (np >= maxptr)
+      gmx_fatal(FARGS,"Too many groups on line: '%s' (max is %d)",
+                 str,maxptr);
+    if (ptr) 
+      ptr[np]=copy;
+    np++;
+    while ((*copy != '\0') && !isspace(*copy))
+      copy++;
+    if (*copy != '\0') {
+      *copy='\0';
+      copy++;
+    }
+    ltrim(copy);
+  }
+  if (ptr == NULL)
+    sfree(copy0);
+
+  return np;
+}
+
+static void parse_n_double(char *str,int *n,double **r)
+{
+  char *ptr[MAXPTR];
+  int  i;
+
+  *n = str_nelem(str,MAXPTR,ptr);
+
+  snew(*r,*n);
+  for(i=0; i<*n; i++) {
+    (*r)[i] = strtod(ptr[i],NULL);
+  }
+}
+
+static void do_wall_params(t_inputrec *ir,
+                           char *wall_atomtype, char *wall_density,
+                           t_gromppopts *opts)
+{
+    int  nstr,i;
+    char *names[MAXPTR];
+    double dbl;
+
+    opts->wall_atomtype[0] = NULL;
+    opts->wall_atomtype[1] = NULL;
+
+    ir->wall_atomtype[0] = -1;
+    ir->wall_atomtype[1] = -1;
+    ir->wall_density[0] = 0;
+    ir->wall_density[1] = 0;
+  
+    if (ir->nwall > 0)
+    {
+        nstr = str_nelem(wall_atomtype,MAXPTR,names);
+        if (nstr != ir->nwall)
+        {
+            gmx_fatal(FARGS,"Expected %d elements for wall_atomtype, found %d",
+                      ir->nwall,nstr);
+        }
+        for(i=0; i<ir->nwall; i++)
+        {
+            opts->wall_atomtype[i] = strdup(names[i]);
+        }
+    
+        if (ir->wall_type == ewt93 || ir->wall_type == ewt104) {
+            nstr = str_nelem(wall_density,MAXPTR,names);
+            if (nstr != ir->nwall)
+            {
+                gmx_fatal(FARGS,"Expected %d elements for wall-density, found %d",ir->nwall,nstr);
+            }
+            for(i=0; i<ir->nwall; i++)
+            {
+                sscanf(names[i],"%lf",&dbl);
+                if (dbl <= 0)
+                {
+                    gmx_fatal(FARGS,"wall-density[%d] = %f\n",i,dbl);
+                }
+                ir->wall_density[i] = dbl;
+            }
+        }
+    }
+}
+
+static void add_wall_energrps(gmx_groups_t *groups,int nwall,t_symtab *symtab)
+{
+  int  i;
+  t_grps *grps;
+  char str[STRLEN];
+  
+  if (nwall > 0) {
+    srenew(groups->grpname,groups->ngrpname+nwall);
+    grps = &(groups->grps[egcENER]);
+    srenew(grps->nm_ind,grps->nr+nwall);
+    for(i=0; i<nwall; i++) {
+      sprintf(str,"wall%d",i);
+      groups->grpname[groups->ngrpname] = put_symtab(symtab,str);
+      grps->nm_ind[grps->nr++] = groups->ngrpname++;
+    }
+  }
+}
+
+void get_ir(const char *mdparin,const char *mdparout,
+            t_inputrec *ir,t_gromppopts *opts,
+            warninp_t wi)
+{
+  char      *dumstr[2];
+  double    dumdub[2][6];
+  t_inpfile *inp;
+  const char *tmp;
+  int       i,j,m,ninp;
+  char      warn_buf[STRLEN];
+  
+  inp = read_inpfile(mdparin, &ninp, NULL, wi);
+
+  snew(dumstr[0],STRLEN);
+  snew(dumstr[1],STRLEN);
+
+  REM_TYPE("title");
+  REM_TYPE("cpp");
+  REM_TYPE("domain-decomposition");
+  REPL_TYPE("unconstrained-start","continuation");
+  REM_TYPE("dihre-tau");
+  REM_TYPE("nstdihreout");
+  REM_TYPE("nstcheckpoint");
+
+  CCTYPE ("VARIOUS PREPROCESSING OPTIONS");
+  CTYPE ("Preprocessor information: use cpp syntax.");
+  CTYPE ("e.g.: -I/home/joe/doe -I/home/mary/roe");
+  STYPE ("include",    opts->include,  NULL);
+  CTYPE ("e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
+  STYPE ("define",     opts->define,   NULL);
+    
+  CCTYPE ("RUN CONTROL PARAMETERS");
+  EETYPE("integrator",  ir->eI,         ei_names);
+  CTYPE ("Start time and timestep in ps");
+  RTYPE ("tinit",      ir->init_t,     0.0);
+  RTYPE ("dt",         ir->delta_t,    0.001);
+  STEPTYPE ("nsteps",   ir->nsteps,     0);
+  CTYPE ("For exact run continuation or redoing part of a run");
+  STEPTYPE ("init-step",ir->init_step,  0);
+  CTYPE ("Part index is updated automatically on checkpointing (keeps files separate)");
+  ITYPE ("simulation-part", ir->simulation_part, 1);
+  CTYPE ("mode for center of mass motion removal");
+  EETYPE("comm-mode",   ir->comm_mode,  ecm_names);
+  CTYPE ("number of steps for center of mass motion removal");
+  ITYPE ("nstcomm",    ir->nstcomm,    10);
+  CTYPE ("group(s) for center of mass motion removal");
+  STYPE ("comm-grps",   vcm,            NULL);
+  
+  CCTYPE ("LANGEVIN DYNAMICS OPTIONS");
+  CTYPE ("Friction coefficient (amu/ps) and random seed");
+  RTYPE ("bd-fric",     ir->bd_fric,    0.0);
+  ITYPE ("ld-seed",     ir->ld_seed,    1993);
+  
+  /* Em stuff */
+  CCTYPE ("ENERGY MINIMIZATION OPTIONS");
+  CTYPE ("Force tolerance and initial step-size");
+  RTYPE ("emtol",       ir->em_tol,     10.0);
+  RTYPE ("emstep",      ir->em_stepsize,0.01);
+  CTYPE ("Max number of iterations in relax-shells");
+  ITYPE ("niter",       ir->niter,      20);
+  CTYPE ("Step size (ps^2) for minimization of flexible constraints");
+  RTYPE ("fcstep",      ir->fc_stepsize, 0);
+  CTYPE ("Frequency of steepest descents steps when doing CG");
+  ITYPE ("nstcgsteep", ir->nstcgsteep, 1000);
+  ITYPE ("nbfgscorr",   ir->nbfgscorr,  10); 
+
+  CCTYPE ("TEST PARTICLE INSERTION OPTIONS");
+  RTYPE ("rtpi",       ir->rtpi,       0.05);
+
+  /* Output options */
+  CCTYPE ("OUTPUT CONTROL OPTIONS");
+  CTYPE ("Output frequency for coords (x), velocities (v) and forces (f)");
+  ITYPE ("nstxout",    ir->nstxout,    100);
+  ITYPE ("nstvout",    ir->nstvout,    100);
+  ITYPE ("nstfout",    ir->nstfout,    0);
+  ir->nstcheckpoint = 1000;
+  CTYPE ("Output frequency for energies to log file and energy file");
+  ITYPE ("nstlog",     ir->nstlog,     100);
+  ITYPE ("nstcalcenergy",ir->nstcalcenergy,    -1);
+  ITYPE ("nstenergy",   ir->nstenergy,  100);
+  CTYPE ("Output frequency and precision for .xtc file");
+  ITYPE ("nstxtcout",   ir->nstxtcout,  0);
+  RTYPE ("xtc-precision",ir->xtcprec,   1000.0);
+  CTYPE ("This selects the subset of atoms for the .xtc file. You can");
+  CTYPE ("select multiple groups. By default all atoms will be written.");
+  STYPE ("xtc-grps",    xtc_grps,       NULL);
+  CTYPE ("Selection of energy groups");
+  STYPE ("energygrps",  energy,         NULL);
+
+  /* Neighbor searching */  
+  CCTYPE ("NEIGHBORSEARCHING PARAMETERS");
+  CTYPE ("nblist update frequency");
+  ITYPE ("nstlist",    ir->nstlist,    10);
+  CTYPE ("ns algorithm (simple or grid)");
+  EETYPE("ns-type",     ir->ns_type,    ens_names);
+  /* set ndelta to the optimal value of 2 */
+  ir->ndelta = 2;
+  CTYPE ("Periodic boundary conditions: xyz, no, xy");
+  EETYPE("pbc",         ir->ePBC,       epbc_names);
+  EETYPE("periodic-molecules", ir->bPeriodicMols, yesno_names);
+  CTYPE ("nblist cut-off");
+  RTYPE ("rlist",      ir->rlist,      1.0);
+  CTYPE ("long-range cut-off for switched potentials");
+  RTYPE ("rlistlong",  ir->rlistlong,  -1);
+
+  /* Electrostatics */
+  CCTYPE ("OPTIONS FOR ELECTROSTATICS AND VDW");
+  CTYPE ("Method for doing electrostatics");
+  EETYPE("coulombtype",        ir->coulombtype,    eel_names);
+  CTYPE ("cut-off lengths");
+  RTYPE ("rcoulomb-switch",    ir->rcoulomb_switch,    0.0);
+  RTYPE ("rcoulomb",   ir->rcoulomb,   1.0);
+  CTYPE ("Relative dielectric constant for the medium and the reaction field");
+  RTYPE ("epsilon-r",   ir->epsilon_r,  1.0);
+  RTYPE ("epsilon-rf",  ir->epsilon_rf, 1.0);
+  CTYPE ("Method for doing Van der Waals");
+  EETYPE("vdw-type",   ir->vdwtype,    evdw_names);
+  CTYPE ("cut-off lengths");
+  RTYPE ("rvdw-switch",        ir->rvdw_switch,        0.0);
+  RTYPE ("rvdw",       ir->rvdw,       1.0);
+  CTYPE ("Apply long range dispersion corrections for Energy and Pressure");
+  EETYPE("DispCorr",    ir->eDispCorr,  edispc_names);
+  CTYPE ("Extension of the potential lookup tables beyond the cut-off");
+  RTYPE ("table-extension", ir->tabext, 1.0);
+  CTYPE ("Seperate tables between energy group pairs");
+  STYPE ("energygrp-table", egptable,   NULL);
+  CTYPE ("Spacing for the PME/PPPM FFT grid");
+  RTYPE ("fourierspacing", opts->fourierspacing,0.12);
+  CTYPE ("FFT grid size, when a value is 0 fourierspacing will be used");
+  ITYPE ("fourier-nx",  ir->nkx,         0);
+  ITYPE ("fourier-ny",  ir->nky,         0);
+  ITYPE ("fourier-nz",  ir->nkz,         0);
+  CTYPE ("EWALD/PME/PPPM parameters");
+  ITYPE ("pme-order",   ir->pme_order,   4);
+  RTYPE ("ewald-rtol",  ir->ewald_rtol, 0.00001);
+  EETYPE("ewald-geometry", ir->ewald_geometry, eewg_names);
+  RTYPE ("epsilon-surface", ir->epsilon_surface, 0.0);
+  EETYPE("optimize-fft",ir->bOptFFT,  yesno_names);
+
+  CCTYPE("IMPLICIT SOLVENT ALGORITHM");
+  EETYPE("implicit-solvent", ir->implicit_solvent, eis_names);
+       
+  CCTYPE ("GENERALIZED BORN ELECTROSTATICS"); 
+  CTYPE ("Algorithm for calculating Born radii");
+  EETYPE("gb-algorithm", ir->gb_algorithm, egb_names);
+  CTYPE ("Frequency of calculating the Born radii inside rlist");
+  ITYPE ("nstgbradii", ir->nstgbradii, 1);
+  CTYPE ("Cutoff for Born radii calculation; the contribution from atoms");
+  CTYPE ("between rlist and rgbradii is updated every nstlist steps");
+  RTYPE ("rgbradii",  ir->rgbradii, 1.0);
+  CTYPE ("Dielectric coefficient of the implicit solvent");
+  RTYPE ("gb-epsilon-solvent",ir->gb_epsilon_solvent, 80.0);
+  CTYPE ("Salt concentration in M for Generalized Born models");
+  RTYPE ("gb-saltconc",  ir->gb_saltconc, 0.0);
+  CTYPE ("Scaling factors used in the OBC GB model. Default values are OBC(II)");
+  RTYPE ("gb-obc-alpha", ir->gb_obc_alpha, 1.0);
+  RTYPE ("gb-obc-beta", ir->gb_obc_beta, 0.8);
+  RTYPE ("gb-obc-gamma", ir->gb_obc_gamma, 4.85);
+  RTYPE ("gb-dielectric-offset", ir->gb_dielectric_offset, 0.009);
+  EETYPE("sa-algorithm", ir->sa_algorithm, esa_names);
+  CTYPE ("Surface tension (kJ/mol/nm^2) for the SA (nonpolar surface) part of GBSA");
+  CTYPE ("The value -1 will set default value for Still/HCT/OBC GB-models.");
+  RTYPE ("sa-surface-tension", ir->sa_surface_tension, -1);
+                
+  /* Coupling stuff */
+  CCTYPE ("OPTIONS FOR WEAK COUPLING ALGORITHMS");
+  CTYPE ("Temperature coupling");
+  EETYPE("tcoupl",     ir->etc,        etcoupl_names);
+  ITYPE ("nsttcouple", ir->nsttcouple,  -1);
+  ITYPE("nh-chain-length",     ir->opts.nhchainlength, NHCHAINLENGTH);
+  CTYPE ("Groups to couple separately");
+  STYPE ("tc-grps",     tcgrps,         NULL);
+  CTYPE ("Time constant (ps) and reference temperature (K)");
+  STYPE ("tau-t",      tau_t,          NULL);
+  STYPE ("ref-t",      ref_t,          NULL);
+  CTYPE ("pressure coupling");
+  EETYPE("pcoupl",     ir->epc,        epcoupl_names);
+  EETYPE("pcoupltype", ir->epct,       epcoupltype_names);
+  ITYPE ("nstpcouple", ir->nstpcouple,  -1);
+  CTYPE ("Time constant (ps), compressibility (1/bar) and reference P (bar)");
+  RTYPE ("tau-p",      ir->tau_p,      1.0);
+  STYPE ("compressibility",    dumstr[0],      NULL);
+  STYPE ("ref-p",       dumstr[1],      NULL);
+  CTYPE ("Scaling of reference coordinates, No, All or COM");
+  EETYPE ("refcoord-scaling",ir->refcoord_scaling,erefscaling_names);
+
+  CTYPE ("Random seed for Andersen thermostat");
+  ITYPE ("andersen-seed", ir->andersen_seed, 815131);
+
+  /* QMMM */
+  CCTYPE ("OPTIONS FOR QMMM calculations");
+  EETYPE("QMMM", ir->bQMMM, yesno_names);
+  CTYPE ("Groups treated Quantum Mechanically");
+  STYPE ("QMMM-grps",  QMMM,          NULL);
+  CTYPE ("QM method");
+  STYPE("QMmethod",     QMmethod, NULL);
+  CTYPE ("QMMM scheme");
+  EETYPE("QMMMscheme",  ir->QMMMscheme,    eQMMMscheme_names);
+  CTYPE ("QM basisset");
+  STYPE("QMbasis",      QMbasis, NULL);
+  CTYPE ("QM charge");
+  STYPE ("QMcharge",    QMcharge,NULL);
+  CTYPE ("QM multiplicity");
+  STYPE ("QMmult",      QMmult,NULL);
+  CTYPE ("Surface Hopping");
+  STYPE ("SH",          bSH, NULL);
+  CTYPE ("CAS space options");
+  STYPE ("CASorbitals",      CASorbitals,   NULL);
+  STYPE ("CASelectrons",     CASelectrons,  NULL);
+  STYPE ("SAon", SAon, NULL);
+  STYPE ("SAoff",SAoff,NULL);
+  STYPE ("SAsteps",  SAsteps, NULL);
+  CTYPE ("Scale factor for MM charges");
+  RTYPE ("MMChargeScaleFactor", ir->scalefactor, 1.0);
+  CTYPE ("Optimization of QM subsystem");
+  STYPE ("bOPT",          bOPT, NULL);
+  STYPE ("bTS",          bTS, NULL);
+
+  /* Simulated annealing */
+  CCTYPE("SIMULATED ANNEALING");
+  CTYPE ("Type of annealing for each temperature group (no/single/periodic)");
+  STYPE ("annealing",   anneal,      NULL);
+  CTYPE ("Number of time points to use for specifying annealing in each group");
+  STYPE ("annealing-npoints", anneal_npoints, NULL);
+  CTYPE ("List of times at the annealing points for each group");
+  STYPE ("annealing-time",       anneal_time,       NULL);
+  CTYPE ("Temp. at each annealing point, for each group.");
+  STYPE ("annealing-temp",  anneal_temp,  NULL);
+  
+  /* Startup run */
+  CCTYPE ("GENERATE VELOCITIES FOR STARTUP RUN");
+  EETYPE("gen-vel",     opts->bGenVel,  yesno_names);
+  RTYPE ("gen-temp",    opts->tempi,    300.0);
+  ITYPE ("gen-seed",    opts->seed,     173529);
+  
+  /* Shake stuff */
+  CCTYPE ("OPTIONS FOR BONDS");
+  EETYPE("constraints",        opts->nshake,   constraints);
+  CTYPE ("Type of constraint algorithm");
+  EETYPE("constraint-algorithm",  ir->eConstrAlg, econstr_names);
+  CTYPE ("Do not constrain the start configuration");
+  EETYPE("continuation", ir->bContinuation, yesno_names);
+  CTYPE ("Use successive overrelaxation to reduce the number of shake iterations");
+  EETYPE("Shake-SOR", ir->bShakeSOR, yesno_names);
+  CTYPE ("Relative tolerance of shake");
+  RTYPE ("shake-tol", ir->shake_tol, 0.0001);
+  CTYPE ("Highest order in the expansion of the constraint coupling matrix");
+  ITYPE ("lincs-order", ir->nProjOrder, 4);
+  CTYPE ("Number of iterations in the final step of LINCS. 1 is fine for");
+  CTYPE ("normal simulations, but use 2 to conserve energy in NVE runs.");
+  CTYPE ("For energy minimization with constraints it should be 4 to 8.");
+  ITYPE ("lincs-iter", ir->nLincsIter, 1);
+  CTYPE ("Lincs will write a warning to the stderr if in one step a bond"); 
+  CTYPE ("rotates over more degrees than");
+  RTYPE ("lincs-warnangle", ir->LincsWarnAngle, 30.0);
+  CTYPE ("Convert harmonic bonds to morse potentials");
+  EETYPE("morse",       opts->bMorse,yesno_names);
+
+  /* Energy group exclusions */
+  CCTYPE ("ENERGY GROUP EXCLUSIONS");
+  CTYPE ("Pairs of energy groups for which all non-bonded interactions are excluded");
+  STYPE ("energygrp-excl", egpexcl,     NULL);
+  
+  /* Walls */
+  CCTYPE ("WALLS");
+  CTYPE ("Number of walls, type, atom types, densities and box-z scale factor for Ewald");
+  ITYPE ("nwall", ir->nwall, 0);
+  EETYPE("wall-type",     ir->wall_type,   ewt_names);
+  RTYPE ("wall-r-linpot", ir->wall_r_linpot, -1);
+  STYPE ("wall-atomtype", wall_atomtype, NULL);
+  STYPE ("wall-density",  wall_density,  NULL);
+  RTYPE ("wall-ewald-zfac", ir->wall_ewald_zfac, 3);
+  
+  /* COM pulling */
+  CCTYPE("COM PULLING");
+  CTYPE("Pull type: no, umbrella, constraint or constant-force");
+  EETYPE("pull",          ir->ePull, epull_names);
+  if (ir->ePull != epullNO) {
+    snew(ir->pull,1);
+    pull_grp = read_pullparams(&ninp,&inp,ir->pull,&opts->pull_start,wi);
+  }
+  
+  /* Enforced rotation */
+  CCTYPE("ENFORCED ROTATION");
+  CTYPE("Enforced rotation: No or Yes");
+  EETYPE("rotation",       ir->bRot, yesno_names);
+  if (ir->bRot) {
+    snew(ir->rot,1);
+    rot_grp = read_rotparams(&ninp,&inp,ir->rot,wi);
+  }
+
+  /* Refinement */
+  CCTYPE("NMR refinement stuff");
+  CTYPE ("Distance restraints type: No, Simple or Ensemble");
+  EETYPE("disre",       ir->eDisre,     edisre_names);
+  CTYPE ("Force weighting of pairs in one distance restraint: Conservative or Equal");
+  EETYPE("disre-weighting", ir->eDisreWeighting, edisreweighting_names);
+  CTYPE ("Use sqrt of the time averaged times the instantaneous violation");
+  EETYPE("disre-mixed", ir->bDisreMixed, yesno_names);
+  RTYPE ("disre-fc",   ir->dr_fc,      1000.0);
+  RTYPE ("disre-tau",  ir->dr_tau,     0.0);
+  CTYPE ("Output frequency for pair distances to energy file");
+  ITYPE ("nstdisreout", ir->nstdisreout, 100);
+  CTYPE ("Orientation restraints: No or Yes");
+  EETYPE("orire",       opts->bOrire,   yesno_names);
+  CTYPE ("Orientation restraints force constant and tau for time averaging");
+  RTYPE ("orire-fc",   ir->orires_fc,  0.0);
+  RTYPE ("orire-tau",  ir->orires_tau, 0.0);
+  STYPE ("orire-fitgrp",orirefitgrp,    NULL);
+  CTYPE ("Output frequency for trace(SD) and S to energy file");
+  ITYPE ("nstorireout", ir->nstorireout, 100);
+  CTYPE ("Dihedral angle restraints: No or Yes");
+  EETYPE("dihre",       opts->bDihre,   yesno_names);
+  RTYPE ("dihre-fc",   ir->dihre_fc,   1000.0);
+
+  /* Free energy stuff */
+  CCTYPE ("Free energy control stuff");
+  EETYPE("free-energy",        ir->efep, efep_names);
+  RTYPE ("init-lambda",        ir->init_lambda,0.0);
+  RTYPE ("delta-lambda",ir->delta_lambda,0.0);
+  STYPE ("foreign-lambda", foreign_lambda, NULL);
+  RTYPE ("sc-alpha",ir->sc_alpha,0.0);
+  ITYPE ("sc-power",ir->sc_power,0);
+  RTYPE ("sc-sigma",ir->sc_sigma,0.3);
+  ITYPE ("nstdhdl",     ir->nstdhdl, 10);
+  EETYPE("separate-dhdl-file", ir->separate_dhdl_file, 
+                               separate_dhdl_file_names);
+  EETYPE("dhdl-derivatives", ir->dhdl_derivatives, dhdl_derivatives_names);
+  ITYPE ("dh-hist-size", ir->dh_hist_size, 0);
+  RTYPE ("dh-hist-spacing", ir->dh_hist_spacing, 0.1);
+  STYPE ("couple-moltype",  couple_moltype,  NULL);
+  EETYPE("couple-lambda0", opts->couple_lam0, couple_lam);
+  EETYPE("couple-lambda1", opts->couple_lam1, couple_lam);
+  EETYPE("couple-intramol", opts->bCoupleIntra, yesno_names);
+
+  /* Non-equilibrium MD stuff */  
+  CCTYPE("Non-equilibrium MD stuff");
+  STYPE ("acc-grps",    accgrps,        NULL);
+  STYPE ("accelerate",  acc,            NULL);
+  STYPE ("freezegrps",  freeze,         NULL);
+  STYPE ("freezedim",   frdim,          NULL);
+  RTYPE ("cos-acceleration", ir->cos_accel, 0);
+  STYPE ("deform",      deform,         NULL);
+
+  /* Electric fields */
+  CCTYPE("Electric fields");
+  CTYPE ("Format is number of terms (int) and for all terms an amplitude (real)");
+  CTYPE ("and a phase angle (real)");
+  STYPE ("E-x",        efield_x,       NULL);
+  STYPE ("E-xt",       efield_xt,      NULL);
+  STYPE ("E-y",        efield_y,       NULL);
+  STYPE ("E-yt",       efield_yt,      NULL);
+  STYPE ("E-z",        efield_z,       NULL);
+  STYPE ("E-zt",       efield_zt,      NULL);
+  
+  /* User defined thingies */
+  CCTYPE ("User defined thingies");
+  STYPE ("user1-grps",  user1,          NULL);
+  STYPE ("user2-grps",  user2,          NULL);
+  ITYPE ("userint1",    ir->userint1,   0);
+  ITYPE ("userint2",    ir->userint2,   0);
+  ITYPE ("userint3",    ir->userint3,   0);
+  ITYPE ("userint4",    ir->userint4,   0);
+  RTYPE ("userreal1",   ir->userreal1,  0);
+  RTYPE ("userreal2",   ir->userreal2,  0);
+  RTYPE ("userreal3",   ir->userreal3,  0);
+  RTYPE ("userreal4",   ir->userreal4,  0);
+#undef CTYPE
+
+  write_inpfile(mdparout,ninp,inp,FALSE,wi);
+  for (i=0; (i<ninp); i++) {
+    sfree(inp[i].name);
+    sfree(inp[i].value);
+  }
+  sfree(inp);
+
+  /* Process options if necessary */
+  for(m=0; m<2; m++) {
+    for(i=0; i<2*DIM; i++)
+      dumdub[m][i]=0.0;
+    if(ir->epc) {
+      switch (ir->epct) {
+      case epctISOTROPIC:
+       if (sscanf(dumstr[m],"%lf",&(dumdub[m][XX]))!=1) {
+        warning_error(wi,"Pressure coupling not enough values (I need 1)");
+       }
+       dumdub[m][YY]=dumdub[m][ZZ]=dumdub[m][XX];
+       break;
+      case epctSEMIISOTROPIC:
+      case epctSURFACETENSION:
+       if (sscanf(dumstr[m],"%lf%lf",
+                  &(dumdub[m][XX]),&(dumdub[m][ZZ]))!=2) {
+        warning_error(wi,"Pressure coupling not enough values (I need 2)");
+       }
+       dumdub[m][YY]=dumdub[m][XX];
+       break;
+      case epctANISOTROPIC:
+       if (sscanf(dumstr[m],"%lf%lf%lf%lf%lf%lf",
+                  &(dumdub[m][XX]),&(dumdub[m][YY]),&(dumdub[m][ZZ]),
+                  &(dumdub[m][3]),&(dumdub[m][4]),&(dumdub[m][5]))!=6) {
+        warning_error(wi,"Pressure coupling not enough values (I need 6)");
+       }
+       break;
+      default:
+       gmx_fatal(FARGS,"Pressure coupling type %s not implemented yet",
+                   epcoupltype_names[ir->epct]);
+      }
+    }
+  }
+  clear_mat(ir->ref_p);
+  clear_mat(ir->compress);
+  for(i=0; i<DIM; i++) {
+    ir->ref_p[i][i]    = dumdub[1][i];
+    ir->compress[i][i] = dumdub[0][i];
+  }
+  if (ir->epct == epctANISOTROPIC) {
+    ir->ref_p[XX][YY] = dumdub[1][3];
+    ir->ref_p[XX][ZZ] = dumdub[1][4];
+    ir->ref_p[YY][ZZ] = dumdub[1][5];
+    if (ir->ref_p[XX][YY]!=0 && ir->ref_p[XX][ZZ]!=0 && ir->ref_p[YY][ZZ]!=0) {
+      warning(wi,"All off-diagonal reference pressures are non-zero. Are you sure you want to apply a threefold shear stress?\n");
+    }
+    ir->compress[XX][YY] = dumdub[0][3];
+    ir->compress[XX][ZZ] = dumdub[0][4];
+    ir->compress[YY][ZZ] = dumdub[0][5];
+    for(i=0; i<DIM; i++) {
+      for(m=0; m<i; m++) {
+       ir->ref_p[i][m] = ir->ref_p[m][i];
+       ir->compress[i][m] = ir->compress[m][i];
+      }
+    }
+  } 
+  
+  if (ir->comm_mode == ecmNO)
+    ir->nstcomm = 0;
+
+  opts->couple_moltype = NULL;
+  if (strlen(couple_moltype) > 0) {
+    if (ir->efep != efepNO) {
+      opts->couple_moltype = strdup(couple_moltype);
+      if (opts->couple_lam0 == opts->couple_lam1)
+       warning(wi,"The lambda=0 and lambda=1 states for coupling are identical");
+      if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE ||
+                            opts->couple_lam1 == ecouplamNONE)) {
+       warning(wi,"For proper sampling of the (nearly) decoupled state, stochastic dynamics should be used");
+      }
+    } else {
+      warning(wi,"Can not couple a molecule with free-energy = no");
+    }
+  }
+
+  do_wall_params(ir,wall_atomtype,wall_density,opts);
+  
+  if (opts->bOrire && str_nelem(orirefitgrp,MAXPTR,NULL)!=1) {
+      warning_error(wi,"ERROR: Need one orientation restraint fit group\n");
+  }
+
+  clear_mat(ir->deform);
+  for(i=0; i<6; i++)
+    dumdub[0][i] = 0;
+  m = sscanf(deform,"%lf %lf %lf %lf %lf %lf",
+            &(dumdub[0][0]),&(dumdub[0][1]),&(dumdub[0][2]),
+            &(dumdub[0][3]),&(dumdub[0][4]),&(dumdub[0][5]));
+  for(i=0; i<3; i++)
+    ir->deform[i][i] = dumdub[0][i];
+  ir->deform[YY][XX] = dumdub[0][3];
+  ir->deform[ZZ][XX] = dumdub[0][4];
+  ir->deform[ZZ][YY] = dumdub[0][5];
+  if (ir->epc != epcNO) {
+    for(i=0; i<3; i++)
+      for(j=0; j<=i; j++)
+       if (ir->deform[i][j]!=0 && ir->compress[i][j]!=0) {
+        warning_error(wi,"A box element has deform set and compressibility > 0");
+       }
+    for(i=0; i<3; i++)
+      for(j=0; j<i; j++)
+       if (ir->deform[i][j]!=0) {
+         for(m=j; m<DIM; m++)
+           if (ir->compress[m][j]!=0) {
+             sprintf(warn_buf,"An off-diagonal box element has deform set while compressibility > 0 for the same component of another box vector, this might lead to spurious periodicity effects.");
+             warning(wi,warn_buf);
+           }
+       }
+  }
+
+  if (ir->efep != efepNO) {
+    parse_n_double(foreign_lambda,&ir->n_flambda,&ir->flambda);
+    if (ir->n_flambda > 0 && ir->rlist < max(ir->rvdw,ir->rcoulomb)) {
+      warning_note(wi,"For foreign lambda free energy differences it is assumed that the soft-core interactions have no effect beyond the neighborlist cut-off");
+    }
+  } else {
+    ir->n_flambda = 0;
+  }
+
+  sfree(dumstr[0]);
+  sfree(dumstr[1]);
+}
+
+static int search_QMstring(char *s,int ng,const char *gn[])
+{
+  /* same as normal search_string, but this one searches QM strings */
+  int i;
+
+  for(i=0; (i<ng); i++)
+    if (gmx_strcasecmp(s,gn[i]) == 0)
+      return i;
+
+  gmx_fatal(FARGS,"this QM method or basisset (%s) is not implemented\n!",s);
+
+  return -1;
+
+} /* search_QMstring */
+
+
+int search_string(char *s,int ng,char *gn[])
+{
+  int i;
+  
+  for(i=0; (i<ng); i++)
+  {
+    if (gmx_strcasecmp(s,gn[i]) == 0)
+    {
+      return i;
+    }
+  }
+    
+  gmx_fatal(FARGS,"Group %s not found in index file.\nGroup names must match either [moleculetype] names\nor custom index group names,in which case you\nmust supply an index file to the '-n' option of grompp.",s);
+  
+  return -1;
+}
+
+static gmx_bool do_numbering(int natoms,gmx_groups_t *groups,int ng,char *ptrs[],
+                         t_blocka *block,char *gnames[],
+                         int gtype,int restnm,
+                         int grptp,gmx_bool bVerbose,
+                         warninp_t wi)
+{
+    unsigned short *cbuf;
+    t_grps *grps=&(groups->grps[gtype]);
+    int    i,j,gid,aj,ognr,ntot=0;
+    const char *title;
+    gmx_bool   bRest;
+    char   warn_buf[STRLEN];
+
+    if (debug)
+    {
+        fprintf(debug,"Starting numbering %d groups of type %d\n",ng,gtype);
+    }
+  
+    title = gtypes[gtype];
+    
+    snew(cbuf,natoms);
+    /* Mark all id's as not set */
+    for(i=0; (i<natoms); i++)
+    {
+        cbuf[i] = NOGID;
+    }
+  
+    snew(grps->nm_ind,ng+1); /* +1 for possible rest group */
+    for(i=0; (i<ng); i++)
+    {
+        /* Lookup the group name in the block structure */
+        gid = search_string(ptrs[i],block->nr,gnames);
+        if ((grptp != egrptpONE) || (i == 0))
+        {
+            grps->nm_ind[grps->nr++]=gid;
+        }
+        if (debug) 
+        {
+            fprintf(debug,"Found gid %d for group %s\n",gid,ptrs[i]);
+        }
+    
+        /* Now go over the atoms in the group */
+        for(j=block->index[gid]; (j<block->index[gid+1]); j++)
+        {
+
+            aj=block->a[j];
+      
+            /* Range checking */
+            if ((aj < 0) || (aj >= natoms)) 
+            {
+                gmx_fatal(FARGS,"Invalid atom number %d in indexfile",aj);
+            }
+            /* Lookup up the old group number */
+            ognr = cbuf[aj];
+            if (ognr != NOGID)
+            {
+                gmx_fatal(FARGS,"Atom %d in multiple %s groups (%d and %d)",
+                          aj+1,title,ognr+1,i+1);
+            }
+            else
+            {
+                /* Store the group number in buffer */
+                if (grptp == egrptpONE)
+                {
+                    cbuf[aj] = 0;
+                }
+                else
+                {
+                    cbuf[aj] = i;
+                }
+                ntot++;
+            }
+        }
+    }
+    
+    /* Now check whether we have done all atoms */
+    bRest = FALSE;
+    if (ntot != natoms)
+    {
+        if (grptp == egrptpALL)
+        {
+            gmx_fatal(FARGS,"%d atoms are not part of any of the %s groups",
+                      natoms-ntot,title);
+        }
+        else if (grptp == egrptpPART)
+        {
+            sprintf(warn_buf,"%d atoms are not part of any of the %s groups",
+                    natoms-ntot,title);
+            warning_note(wi,warn_buf);
+        }
+        /* Assign all atoms currently unassigned to a rest group */
+        for(j=0; (j<natoms); j++)
+        {
+            if (cbuf[j] == NOGID)
+            {
+                cbuf[j] = grps->nr;
+                bRest = TRUE;
+            }
+        }
+        if (grptp != egrptpPART)
+        {
+            if (bVerbose)
+            {
+                fprintf(stderr,
+                        "Making dummy/rest group for %s containing %d elements\n",
+                        title,natoms-ntot);
+            }
+            /* Add group name "rest" */ 
+            grps->nm_ind[grps->nr] = restnm;
+            
+            /* Assign the rest name to all atoms not currently assigned to a group */
+            for(j=0; (j<natoms); j++)
+            {
+                if (cbuf[j] == NOGID)
+                {
+                    cbuf[j] = grps->nr;
+                }
+            }
+            grps->nr++;
+        }
+    }
+    
+    if (grps->nr == 1)
+    {
+        groups->ngrpnr[gtype] = 0;
+        groups->grpnr[gtype]  = NULL;
+    }
+    else
+    {
+        groups->ngrpnr[gtype] = natoms;
+        snew(groups->grpnr[gtype],natoms);
+        for(j=0; (j<natoms); j++)
+        {
+            groups->grpnr[gtype][j] = cbuf[j];
+        }
+    }
+    
+    sfree(cbuf);
+
+    return (bRest && grptp == egrptpPART);
+}
+
+static void calc_nrdf(gmx_mtop_t *mtop,t_inputrec *ir,char **gnames)
+{
+  t_grpopts *opts;
+  gmx_groups_t *groups;
+  t_pull  *pull;
+  int     natoms,ai,aj,i,j,d,g,imin,jmin,nc;
+  t_iatom *ia;
+  int     *nrdf2,*na_vcm,na_tot;
+  double  *nrdf_tc,*nrdf_vcm,nrdf_uc,n_sub=0;
+  gmx_mtop_atomloop_all_t aloop;
+  t_atom  *atom;
+  int     mb,mol,ftype,as;
+  gmx_molblock_t *molb;
+  gmx_moltype_t *molt;
+
+  /* Calculate nrdf. 
+   * First calc 3xnr-atoms for each group
+   * then subtract half a degree of freedom for each constraint
+   *
+   * Only atoms and nuclei contribute to the degrees of freedom...
+   */
+
+  opts = &ir->opts;
+  
+  groups = &mtop->groups;
+  natoms = mtop->natoms;
+
+  /* Allocate one more for a possible rest group */
+  /* We need to sum degrees of freedom into doubles,
+   * since floats give too low nrdf's above 3 million atoms.
+   */
+  snew(nrdf_tc,groups->grps[egcTC].nr+1);
+  snew(nrdf_vcm,groups->grps[egcVCM].nr+1);
+  snew(na_vcm,groups->grps[egcVCM].nr+1);
+  
+  for(i=0; i<groups->grps[egcTC].nr; i++)
+    nrdf_tc[i] = 0;
+  for(i=0; i<groups->grps[egcVCM].nr+1; i++)
+    nrdf_vcm[i] = 0;
+
+  snew(nrdf2,natoms);
+  aloop = gmx_mtop_atomloop_all_init(mtop);
+  while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
+    nrdf2[i] = 0;
+    if (atom->ptype == eptAtom || atom->ptype == eptNucleus) {
+      g = ggrpnr(groups,egcFREEZE,i);
+      /* Double count nrdf for particle i */
+      for(d=0; d<DIM; d++) {
+       if (opts->nFreeze[g][d] == 0) {
+         nrdf2[i] += 2;
+       }
+      }
+      nrdf_tc [ggrpnr(groups,egcTC ,i)] += 0.5*nrdf2[i];
+      nrdf_vcm[ggrpnr(groups,egcVCM,i)] += 0.5*nrdf2[i];
+    }
+  }
+
+  as = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    molb = &mtop->molblock[mb];
+    molt = &mtop->moltype[molb->type];
+    atom = molt->atoms.atom;
+    for(mol=0; mol<molb->nmol; mol++) {
+      for (ftype=F_CONSTR; ftype<=F_CONSTRNC; ftype++) {
+       ia = molt->ilist[ftype].iatoms;
+       for(i=0; i<molt->ilist[ftype].nr; ) {
+         /* Subtract degrees of freedom for the constraints,
+          * if the particles still have degrees of freedom left.
+          * If one of the particles is a vsite or a shell, then all
+          * constraint motion will go there, but since they do not
+          * contribute to the constraints the degrees of freedom do not
+          * change.
+          */
+         ai = as + ia[1];
+         aj = as + ia[2];
+         if (((atom[ia[1]].ptype == eptNucleus) ||
+              (atom[ia[1]].ptype == eptAtom)) &&
+             ((atom[ia[2]].ptype == eptNucleus) ||
+              (atom[ia[2]].ptype == eptAtom))) {
+           if (nrdf2[ai] > 0) 
+             jmin = 1;
+           else
+             jmin = 2;
+           if (nrdf2[aj] > 0)
+             imin = 1;
+           else
+             imin = 2;
+           imin = min(imin,nrdf2[ai]);
+           jmin = min(jmin,nrdf2[aj]);
+           nrdf2[ai] -= imin;
+           nrdf2[aj] -= jmin;
+           nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
+           nrdf_tc [ggrpnr(groups,egcTC ,aj)] -= 0.5*jmin;
+           nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
+           nrdf_vcm[ggrpnr(groups,egcVCM,aj)] -= 0.5*jmin;
+         }
+         ia += interaction_function[ftype].nratoms+1;
+         i  += interaction_function[ftype].nratoms+1;
+       }
+      }
+      ia = molt->ilist[F_SETTLE].iatoms;
+      for(i=0; i<molt->ilist[F_SETTLE].nr; ) {
+       /* Subtract 1 dof from every atom in the SETTLE */
+       for(ai=as+ia[1]; ai<as+ia[1]+3; ai++) {
+         imin = min(2,nrdf2[ai]);
+         nrdf2[ai] -= imin;
+         nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
+         nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
+       }
+       ia += 2;
+       i  += 2;
+      }
+      as += molt->atoms.nr;
+    }
+  }
+
+  if (ir->ePull == epullCONSTRAINT) {
+    /* Correct nrdf for the COM constraints.
+     * We correct using the TC and VCM group of the first atom
+     * in the reference and pull group. If atoms in one pull group
+     * belong to different TC or VCM groups it is anyhow difficult
+     * to determine the optimal nrdf assignment.
+     */
+    pull = ir->pull;
+    if (pull->eGeom == epullgPOS) {
+      nc = 0;
+      for(i=0; i<DIM; i++) {
+       if (pull->dim[i])
+         nc++;
+      }
+    } else {
+      nc = 1;
+    }
+    for(i=0; i<pull->ngrp; i++) {
+      imin = 2*nc;
+      if (pull->grp[0].nat > 0) {
+       /* Subtract 1/2 dof from the reference group */
+       ai = pull->grp[0].ind[0];
+       if (nrdf_tc[ggrpnr(groups,egcTC,ai)] > 1) {
+         nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5;
+         nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5;
+         imin--;
+       }
+      }
+      /* Subtract 1/2 dof from the pulled group */
+      ai = pull->grp[1+i].ind[0];
+      nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
+      nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
+      if (nrdf_tc[ggrpnr(groups,egcTC,ai)] < 0)
+       gmx_fatal(FARGS,"Center of mass pulling constraints caused the number of degrees of freedom for temperature coupling group %s to be negative",gnames[groups->grps[egcTC].nm_ind[ggrpnr(groups,egcTC,ai)]]);
+    }
+  }
+  
+  if (ir->nstcomm != 0) {
+    /* Subtract 3 from the number of degrees of freedom in each vcm group
+     * when com translation is removed and 6 when rotation is removed
+     * as well.
+     */
+    switch (ir->comm_mode) {
+    case ecmLINEAR:
+      n_sub = ndof_com(ir);
+      break;
+    case ecmANGULAR:
+      n_sub = 6;
+      break;
+    default:
+      n_sub = 0;
+      gmx_incons("Checking comm_mode");
+    }
+    
+    for(i=0; i<groups->grps[egcTC].nr; i++) {
+      /* Count the number of atoms of TC group i for every VCM group */
+      for(j=0; j<groups->grps[egcVCM].nr+1; j++)
+       na_vcm[j] = 0;
+      na_tot = 0;
+      for(ai=0; ai<natoms; ai++)
+       if (ggrpnr(groups,egcTC,ai) == i) {
+         na_vcm[ggrpnr(groups,egcVCM,ai)]++;
+         na_tot++;
+       }
+      /* Correct for VCM removal according to the fraction of each VCM
+       * group present in this TC group.
+       */
+      nrdf_uc = nrdf_tc[i];
+      if (debug) {
+       fprintf(debug,"T-group[%d] nrdf_uc = %g, n_sub = %g\n",
+               i,nrdf_uc,n_sub);
+      }
+      nrdf_tc[i] = 0;
+      for(j=0; j<groups->grps[egcVCM].nr+1; j++) {
+       if (nrdf_vcm[j] > n_sub) {
+         nrdf_tc[i] += nrdf_uc*((double)na_vcm[j]/(double)na_tot)*
+           (nrdf_vcm[j] - n_sub)/nrdf_vcm[j];
+       }
+       if (debug) {
+         fprintf(debug,"  nrdf_vcm[%d] = %g, nrdf = %g\n",
+                 j,nrdf_vcm[j],nrdf_tc[i]);
+       }
+      }
+    }
+  }
+  for(i=0; (i<groups->grps[egcTC].nr); i++) {
+    opts->nrdf[i] = nrdf_tc[i];
+    if (opts->nrdf[i] < 0)
+      opts->nrdf[i] = 0;
+    fprintf(stderr,
+           "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
+           gnames[groups->grps[egcTC].nm_ind[i]],opts->nrdf[i]);
+  }
+  
+  sfree(nrdf2);
+  sfree(nrdf_tc);
+  sfree(nrdf_vcm);
+  sfree(na_vcm);
+}
+
+static void decode_cos(char *s,t_cosines *cosine,gmx_bool bTime)
+{
+  char   *t;
+  char   format[STRLEN],f1[STRLEN];
+  double a,phi;
+  int    i;
+  
+  t=strdup(s);
+  trim(t);
+  
+  cosine->n=0;
+  cosine->a=NULL;
+  cosine->phi=NULL;
+  if (strlen(t)) {
+    sscanf(t,"%d",&(cosine->n));
+    if (cosine->n <= 0) {
+      cosine->n=0;
+    } else {
+      snew(cosine->a,cosine->n);
+      snew(cosine->phi,cosine->n);
+      
+      sprintf(format,"%%*d");
+      for(i=0; (i<cosine->n); i++) {
+       strcpy(f1,format);
+       strcat(f1,"%lf%lf");
+       if (sscanf(t,f1,&a,&phi) < 2)
+         gmx_fatal(FARGS,"Invalid input for electric field shift: '%s'",t);
+       cosine->a[i]=a;
+       cosine->phi[i]=phi;
+       strcat(format,"%*lf%*lf");
+      }
+    }
+  }
+  sfree(t);
+}
+
+static gmx_bool do_egp_flag(t_inputrec *ir,gmx_groups_t *groups,
+                       const char *option,const char *val,int flag)
+{
+  /* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
+   * But since this is much larger than STRLEN, such a line can not be parsed.
+   * The real maximum is the number of names that fit in a string: STRLEN/2.
+   */
+#define EGP_MAX (STRLEN/2)
+  int  nelem,i,j,k,nr;
+  char *names[EGP_MAX];
+  char ***gnames;
+  gmx_bool bSet;
+
+  gnames = groups->grpname;
+
+  nelem = str_nelem(val,EGP_MAX,names);
+  if (nelem % 2 != 0)
+    gmx_fatal(FARGS,"The number of groups for %s is odd",option);
+  nr = groups->grps[egcENER].nr;
+  bSet = FALSE;
+  for(i=0; i<nelem/2; i++) {
+    j = 0;
+    while ((j < nr) &&
+          gmx_strcasecmp(names[2*i],*(gnames[groups->grps[egcENER].nm_ind[j]])))
+      j++;
+    if (j == nr)
+      gmx_fatal(FARGS,"%s in %s is not an energy group\n",
+                 names[2*i],option);
+    k = 0;
+    while ((k < nr) &&
+          gmx_strcasecmp(names[2*i+1],*(gnames[groups->grps[egcENER].nm_ind[k]])))
+      k++;
+    if (k==nr)
+      gmx_fatal(FARGS,"%s in %s is not an energy group\n",
+             names[2*i+1],option);
+    if ((j < nr) && (k < nr)) {
+      ir->opts.egp_flags[nr*j+k] |= flag;
+      ir->opts.egp_flags[nr*k+j] |= flag;
+      bSet = TRUE;
+    }
+  }
+
+  return bSet;
+}
+
+void do_index(const char* mdparin, const char *ndx,
+              gmx_mtop_t *mtop,
+              gmx_bool bVerbose,
+              t_inputrec *ir,rvec *v,
+              warninp_t wi)
+{
+  t_blocka *grps;
+  gmx_groups_t *groups;
+  int     natoms;
+  t_symtab *symtab;
+  t_atoms atoms_all;
+  char    warnbuf[STRLEN],**gnames;
+  int     nr,ntcg,ntau_t,nref_t,nacc,nofg,nSA,nSA_points,nSA_time,nSA_temp;
+  real    tau_min;
+  int     nstcmin;
+  int     nacg,nfreeze,nfrdim,nenergy,nvcm,nuser;
+  char    *ptr1[MAXPTR],*ptr2[MAXPTR],*ptr3[MAXPTR];
+  int     i,j,k,restnm;
+  real    SAtime;
+  gmx_bool    bExcl,bTable,bSetTCpar,bAnneal,bRest;
+  int     nQMmethod,nQMbasis,nQMcharge,nQMmult,nbSH,nCASorb,nCASelec,
+    nSAon,nSAoff,nSAsteps,nQMg,nbOPT,nbTS;
+  char    warn_buf[STRLEN];
+
+  if (bVerbose)
+    fprintf(stderr,"processing index file...\n");
+  debug_gmx();
+  if (ndx == NULL) {
+    snew(grps,1);
+    snew(grps->index,1);
+    snew(gnames,1);
+    atoms_all = gmx_mtop_global_atoms(mtop);
+    analyse(&atoms_all,grps,&gnames,FALSE,TRUE);
+    free_t_atoms(&atoms_all,FALSE);
+  } else {
+    grps = init_index(ndx,&gnames);
+  }
+
+  groups = &mtop->groups;
+  natoms = mtop->natoms;
+  symtab = &mtop->symtab;
+
+  snew(groups->grpname,grps->nr+1);
+  
+  for(i=0; (i<grps->nr); i++) {
+    groups->grpname[i] = put_symtab(symtab,gnames[i]);
+  }
+  groups->grpname[i] = put_symtab(symtab,"rest");
+  restnm=i;
+  srenew(gnames,grps->nr+1);
+  gnames[restnm] = *(groups->grpname[i]);
+  groups->ngrpname = grps->nr+1;
+
+  set_warning_line(wi,mdparin,-1);
+
+  ntau_t = str_nelem(tau_t,MAXPTR,ptr1);
+  nref_t = str_nelem(ref_t,MAXPTR,ptr2);
+  ntcg   = str_nelem(tcgrps,MAXPTR,ptr3);
+  if ((ntau_t != ntcg) || (nref_t != ntcg)) {
+    gmx_fatal(FARGS,"Invalid T coupling input: %d groups, %d ref-t values and "
+                "%d tau-t values",ntcg,nref_t,ntau_t);
+  }
+
+  bSetTCpar = (ir->etc || EI_SD(ir->eI) || ir->eI==eiBD || EI_TPI(ir->eI));
+  do_numbering(natoms,groups,ntcg,ptr3,grps,gnames,egcTC,
+               restnm,bSetTCpar ? egrptpALL : egrptpALL_GENREST,bVerbose,wi);
+  nr = groups->grps[egcTC].nr;
+  ir->opts.ngtc = nr;
+  snew(ir->opts.nrdf,nr);
+  snew(ir->opts.tau_t,nr);
+  snew(ir->opts.ref_t,nr);
+  if (ir->eI==eiBD && ir->bd_fric==0) {
+    fprintf(stderr,"bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
+  }
+
+  if (bSetTCpar)
+  {
+      if (nr != nref_t)
+      {
+          gmx_fatal(FARGS,"Not enough ref-t and tau-t values!");
+      }
+      
+      tau_min = 1e20;
+      for(i=0; (i<nr); i++)
+      {
+          ir->opts.tau_t[i] = strtod(ptr1[i],NULL);
+          if ((ir->eI == eiBD || ir->eI == eiSD2) && ir->opts.tau_t[i] <= 0)
+          {
+              sprintf(warn_buf,"With integrator %s tau-t should be larger than 0",ei_names[ir->eI]);
+              warning_error(wi,warn_buf);
+          }
+          if ((ir->etc == etcVRESCALE && ir->opts.tau_t[i] >= 0) || 
+              (ir->etc != etcVRESCALE && ir->opts.tau_t[i] >  0))
+          {
+              tau_min = min(tau_min,ir->opts.tau_t[i]);
+          }
+      }
+      if (ir->etc != etcNO && ir->nsttcouple == -1)
+      {
+            ir->nsttcouple = ir_optimal_nsttcouple(ir);
+      }
+      if (EI_VV(ir->eI)) 
+      {
+          if ((ir->epc==epcMTTK) && (ir->etc>etcNO))
+          {
+              int mincouple;
+              mincouple = ir->nsttcouple;
+              if (ir->nstpcouple < mincouple)
+              {
+                  mincouple = ir->nstpcouple;
+              }
+              ir->nstpcouple = mincouple;
+              ir->nsttcouple = mincouple;
+              warning_note(wi,"for current Trotter decomposition methods with vv, nsttcouple and nstpcouple must be equal.  Both have been reset to min(nsttcouple,nstpcouple)");
+          }
+      }
+      nstcmin = tcouple_min_integration_steps(ir->etc);
+      if (nstcmin > 1)
+      {
+          if (tau_min/(ir->delta_t*ir->nsttcouple) < nstcmin)
+          {
+              sprintf(warn_buf,"For proper integration of the %s thermostat, tau-t (%g) should be at least %d times larger than nsttcouple*dt (%g)",
+                      ETCOUPLTYPE(ir->etc),
+                      tau_min,nstcmin,
+                      ir->nsttcouple*ir->delta_t);
+              warning(wi,warn_buf);
+          }
+      }
+      for(i=0; (i<nr); i++)
+      {
+          ir->opts.ref_t[i] = strtod(ptr2[i],NULL);
+          if (ir->opts.ref_t[i] < 0)
+          {
+              gmx_fatal(FARGS,"ref-t for group %d negative",i);
+          }
+      }
+  }
+    
+  /* Simulated annealing for each group. There are nr groups */
+  nSA = str_nelem(anneal,MAXPTR,ptr1);
+  if (nSA == 1 && (ptr1[0][0]=='n' || ptr1[0][0]=='N'))
+     nSA = 0;
+  if(nSA>0 && nSA != nr) 
+    gmx_fatal(FARGS,"Not enough annealing values: %d (for %d groups)\n",nSA,nr);
+  else {
+    snew(ir->opts.annealing,nr);
+    snew(ir->opts.anneal_npoints,nr);
+    snew(ir->opts.anneal_time,nr);
+    snew(ir->opts.anneal_temp,nr);
+    for(i=0;i<nr;i++) {
+      ir->opts.annealing[i]=eannNO;
+      ir->opts.anneal_npoints[i]=0;
+      ir->opts.anneal_time[i]=NULL;
+      ir->opts.anneal_temp[i]=NULL;
+    }
+    if (nSA > 0) {
+      bAnneal=FALSE;
+      for(i=0;i<nr;i++) { 
+       if(ptr1[i][0]=='n' || ptr1[i][0]=='N') {
+         ir->opts.annealing[i]=eannNO;
+       } else if(ptr1[i][0]=='s'|| ptr1[i][0]=='S') {
+         ir->opts.annealing[i]=eannSINGLE;
+         bAnneal=TRUE;
+       } else if(ptr1[i][0]=='p'|| ptr1[i][0]=='P') {
+         ir->opts.annealing[i]=eannPERIODIC;
+         bAnneal=TRUE;
+       } 
+      } 
+      if(bAnneal) {
+       /* Read the other fields too */
+       nSA_points = str_nelem(anneal_npoints,MAXPTR,ptr1);
+       if(nSA_points!=nSA) 
+          gmx_fatal(FARGS,"Found %d annealing-npoints values for %d groups\n",nSA_points,nSA);
+       for(k=0,i=0;i<nr;i++) {
+         ir->opts.anneal_npoints[i]=strtol(ptr1[i],NULL,10);
+         if(ir->opts.anneal_npoints[i]==1)
+           gmx_fatal(FARGS,"Please specify at least a start and an end point for annealing\n");
+         snew(ir->opts.anneal_time[i],ir->opts.anneal_npoints[i]);
+         snew(ir->opts.anneal_temp[i],ir->opts.anneal_npoints[i]);
+         k += ir->opts.anneal_npoints[i];
+       }
+
+       nSA_time = str_nelem(anneal_time,MAXPTR,ptr1);
+       if(nSA_time!=k) 
+          gmx_fatal(FARGS,"Found %d annealing-time values, wanter %d\n",nSA_time,k);
+       nSA_temp = str_nelem(anneal_temp,MAXPTR,ptr2);
+       if(nSA_temp!=k) 
+          gmx_fatal(FARGS,"Found %d annealing-temp values, wanted %d\n",nSA_temp,k);
+
+       for(i=0,k=0;i<nr;i++) {
+         
+         for(j=0;j<ir->opts.anneal_npoints[i];j++) {
+           ir->opts.anneal_time[i][j]=strtod(ptr1[k],NULL);
+           ir->opts.anneal_temp[i][j]=strtod(ptr2[k],NULL);
+           if(j==0) {
+             if(ir->opts.anneal_time[i][0] > (ir->init_t+GMX_REAL_EPS))
+               gmx_fatal(FARGS,"First time point for annealing > init_t.\n");      
+           } else { 
+             /* j>0 */
+             if(ir->opts.anneal_time[i][j]<ir->opts.anneal_time[i][j-1])
+               gmx_fatal(FARGS,"Annealing timepoints out of order: t=%f comes after t=%f\n",
+                           ir->opts.anneal_time[i][j],ir->opts.anneal_time[i][j-1]);
+           }
+           if(ir->opts.anneal_temp[i][j]<0) 
+             gmx_fatal(FARGS,"Found negative temperature in annealing: %f\n",ir->opts.anneal_temp[i][j]);    
+           k++;
+         }
+       }
+       /* Print out some summary information, to make sure we got it right */
+       for(i=0,k=0;i<nr;i++) {
+         if(ir->opts.annealing[i]!=eannNO) {
+           j = groups->grps[egcTC].nm_ind[i];
+           fprintf(stderr,"Simulated annealing for group %s: %s, %d timepoints\n",
+                   *(groups->grpname[j]),eann_names[ir->opts.annealing[i]],
+                   ir->opts.anneal_npoints[i]);
+           fprintf(stderr,"Time (ps)   Temperature (K)\n");
+           /* All terms except the last one */
+           for(j=0;j<(ir->opts.anneal_npoints[i]-1);j++) 
+               fprintf(stderr,"%9.1f      %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
+           
+           /* Finally the last one */
+           j = ir->opts.anneal_npoints[i]-1;
+           if(ir->opts.annealing[i]==eannSINGLE)
+             fprintf(stderr,"%9.1f-     %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
+           else {
+             fprintf(stderr,"%9.1f      %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
+             if(fabs(ir->opts.anneal_temp[i][j]-ir->opts.anneal_temp[i][0])>GMX_REAL_EPS)
+               warning_note(wi,"There is a temperature jump when your annealing loops back.\n");
+           }
+         }
+       } 
+      }
+    }
+  }    
+
+  if (ir->ePull != epullNO) {
+    make_pull_groups(ir->pull,pull_grp,grps,gnames);
+  }
+  
+  if (ir->bRot) {
+    make_rotation_groups(ir->rot,rot_grp,grps,gnames);
+  }
+
+  nacc = str_nelem(acc,MAXPTR,ptr1);
+  nacg = str_nelem(accgrps,MAXPTR,ptr2);
+  if (nacg*DIM != nacc)
+    gmx_fatal(FARGS,"Invalid Acceleration input: %d groups and %d acc. values",
+               nacg,nacc);
+  do_numbering(natoms,groups,nacg,ptr2,grps,gnames,egcACC,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  nr = groups->grps[egcACC].nr;
+  snew(ir->opts.acc,nr);
+  ir->opts.ngacc=nr;
+  
+  for(i=k=0; (i<nacg); i++)
+    for(j=0; (j<DIM); j++,k++)
+      ir->opts.acc[i][j]=strtod(ptr1[k],NULL);
+  for( ;(i<nr); i++)
+    for(j=0; (j<DIM); j++)
+      ir->opts.acc[i][j]=0;
+  
+  nfrdim  = str_nelem(frdim,MAXPTR,ptr1);
+  nfreeze = str_nelem(freeze,MAXPTR,ptr2);
+  if (nfrdim != DIM*nfreeze)
+    gmx_fatal(FARGS,"Invalid Freezing input: %d groups and %d freeze values",
+               nfreeze,nfrdim);
+  do_numbering(natoms,groups,nfreeze,ptr2,grps,gnames,egcFREEZE,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  nr = groups->grps[egcFREEZE].nr;
+  ir->opts.ngfrz=nr;
+  snew(ir->opts.nFreeze,nr);
+  for(i=k=0; (i<nfreeze); i++)
+    for(j=0; (j<DIM); j++,k++) {
+      ir->opts.nFreeze[i][j]=(gmx_strncasecmp(ptr1[k],"Y",1)==0);
+      if (!ir->opts.nFreeze[i][j]) {
+       if (gmx_strncasecmp(ptr1[k],"N",1) != 0) {
+         sprintf(warnbuf,"Please use Y(ES) or N(O) for freezedim only "
+                 "(not %s)", ptr1[k]);
+         warning(wi,warn_buf);
+       }
+      }
+    }
+  for( ; (i<nr); i++)
+    for(j=0; (j<DIM); j++)
+      ir->opts.nFreeze[i][j]=0;
+  
+  nenergy=str_nelem(energy,MAXPTR,ptr1);
+  do_numbering(natoms,groups,nenergy,ptr1,grps,gnames,egcENER,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  add_wall_energrps(groups,ir->nwall,symtab);
+  ir->opts.ngener = groups->grps[egcENER].nr;
+  nvcm=str_nelem(vcm,MAXPTR,ptr1);
+  bRest =
+    do_numbering(natoms,groups,nvcm,ptr1,grps,gnames,egcVCM,
+                 restnm,nvcm==0 ? egrptpALL_GENREST : egrptpPART,bVerbose,wi);
+  if (bRest) {
+    warning(wi,"Some atoms are not part of any center of mass motion removal group.\n"
+           "This may lead to artifacts.\n"
+           "In most cases one should use one group for the whole system.");
+  }
+
+  /* Now we have filled the freeze struct, so we can calculate NRDF */ 
+  calc_nrdf(mtop,ir,gnames);
+
+  if (v && NULL) {
+    real fac,ntot=0;
+    
+    /* Must check per group! */
+    for(i=0; (i<ir->opts.ngtc); i++) 
+      ntot += ir->opts.nrdf[i];
+    if (ntot != (DIM*natoms)) {
+      fac = sqrt(ntot/(DIM*natoms));
+      if (bVerbose)
+       fprintf(stderr,"Scaling velocities by a factor of %.3f to account for constraints\n"
+               "and removal of center of mass motion\n",fac);
+      for(i=0; (i<natoms); i++)
+       svmul(fac,v[i],v[i]);
+    }
+  }
+  
+  nuser=str_nelem(user1,MAXPTR,ptr1);
+  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcUser1,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  nuser=str_nelem(user2,MAXPTR,ptr1);
+  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcUser2,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  nuser=str_nelem(xtc_grps,MAXPTR,ptr1);
+  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcXTC,
+               restnm,egrptpONE,bVerbose,wi);
+  nofg = str_nelem(orirefitgrp,MAXPTR,ptr1);
+  do_numbering(natoms,groups,nofg,ptr1,grps,gnames,egcORFIT,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+
+  /* QMMM input processing */
+  nQMg          = str_nelem(QMMM,MAXPTR,ptr1);
+  nQMmethod     = str_nelem(QMmethod,MAXPTR,ptr2);
+  nQMbasis      = str_nelem(QMbasis,MAXPTR,ptr3);
+  if((nQMmethod != nQMg)||(nQMbasis != nQMg)){
+    gmx_fatal(FARGS,"Invalid QMMM input: %d groups %d basissets"
+             " and %d methods\n",nQMg,nQMbasis,nQMmethod);
+  }
+  /* group rest, if any, is always MM! */
+  do_numbering(natoms,groups,nQMg,ptr1,grps,gnames,egcQMMM,
+               restnm,egrptpALL_GENREST,bVerbose,wi);
+  nr = nQMg; /*atoms->grps[egcQMMM].nr;*/
+  ir->opts.ngQM = nQMg;
+  snew(ir->opts.QMmethod,nr);
+  snew(ir->opts.QMbasis,nr);
+  for(i=0;i<nr;i++){
+    /* input consists of strings: RHF CASSCF PM3 .. These need to be
+     * converted to the corresponding enum in names.c
+     */
+    ir->opts.QMmethod[i] = search_QMstring(ptr2[i],eQMmethodNR,
+                                           eQMmethod_names);
+    ir->opts.QMbasis[i]  = search_QMstring(ptr3[i],eQMbasisNR,
+                                           eQMbasis_names);
+
+  }
+  nQMmult   = str_nelem(QMmult,MAXPTR,ptr1);
+  nQMcharge = str_nelem(QMcharge,MAXPTR,ptr2);
+  nbSH      = str_nelem(bSH,MAXPTR,ptr3);
+  snew(ir->opts.QMmult,nr);
+  snew(ir->opts.QMcharge,nr);
+  snew(ir->opts.bSH,nr);
+
+  for(i=0;i<nr;i++){
+    ir->opts.QMmult[i]   = strtol(ptr1[i],NULL,10);
+    ir->opts.QMcharge[i] = strtol(ptr2[i],NULL,10);
+    ir->opts.bSH[i]      = (gmx_strncasecmp(ptr3[i],"Y",1)==0);
+  }
+
+  nCASelec  = str_nelem(CASelectrons,MAXPTR,ptr1);
+  nCASorb   = str_nelem(CASorbitals,MAXPTR,ptr2);
+  snew(ir->opts.CASelectrons,nr);
+  snew(ir->opts.CASorbitals,nr);
+  for(i=0;i<nr;i++){
+    ir->opts.CASelectrons[i]= strtol(ptr1[i],NULL,10);
+    ir->opts.CASorbitals[i] = strtol(ptr2[i],NULL,10);
+  }
+  /* special optimization options */
+
+  nbOPT = str_nelem(bOPT,MAXPTR,ptr1);
+  nbTS = str_nelem(bTS,MAXPTR,ptr2);
+  snew(ir->opts.bOPT,nr);
+  snew(ir->opts.bTS,nr);
+  for(i=0;i<nr;i++){
+    ir->opts.bOPT[i] = (gmx_strncasecmp(ptr1[i],"Y",1)==0);
+    ir->opts.bTS[i]  = (gmx_strncasecmp(ptr2[i],"Y",1)==0);
+  }
+  nSAon     = str_nelem(SAon,MAXPTR,ptr1);
+  nSAoff    = str_nelem(SAoff,MAXPTR,ptr2);
+  nSAsteps  = str_nelem(SAsteps,MAXPTR,ptr3);
+  snew(ir->opts.SAon,nr);
+  snew(ir->opts.SAoff,nr);
+  snew(ir->opts.SAsteps,nr);
+
+  for(i=0;i<nr;i++){
+    ir->opts.SAon[i]    = strtod(ptr1[i],NULL);
+    ir->opts.SAoff[i]   = strtod(ptr2[i],NULL);
+    ir->opts.SAsteps[i] = strtol(ptr3[i],NULL,10);
+  }
+  /* end of QMMM input */
+
+  if (bVerbose)
+    for(i=0; (i<egcNR); i++) {
+      fprintf(stderr,"%-16s has %d element(s):",gtypes[i],groups->grps[i].nr); 
+      for(j=0; (j<groups->grps[i].nr); j++)
+       fprintf(stderr," %s",*(groups->grpname[groups->grps[i].nm_ind[j]]));
+      fprintf(stderr,"\n");
+    }
+
+  nr = groups->grps[egcENER].nr;
+  snew(ir->opts.egp_flags,nr*nr);
+
+  bExcl = do_egp_flag(ir,groups,"energygrp-excl",egpexcl,EGP_EXCL);
+  if (bExcl && EEL_FULL(ir->coulombtype))
+    warning(wi,"Can not exclude the lattice Coulomb energy between energy groups");
+
+  bTable = do_egp_flag(ir,groups,"energygrp-table",egptable,EGP_TABLE);
+  if (bTable && !(ir->vdwtype == evdwUSER) && 
+      !(ir->coulombtype == eelUSER) && !(ir->coulombtype == eelPMEUSER) &&
+      !(ir->coulombtype == eelPMEUSERSWITCH))
+    gmx_fatal(FARGS,"Can only have energy group pair tables in combination with user tables for VdW and/or Coulomb");
+
+  decode_cos(efield_x,&(ir->ex[XX]),FALSE);
+  decode_cos(efield_xt,&(ir->et[XX]),TRUE);
+  decode_cos(efield_y,&(ir->ex[YY]),FALSE);
+  decode_cos(efield_yt,&(ir->et[YY]),TRUE);
+  decode_cos(efield_z,&(ir->ex[ZZ]),FALSE);
+  decode_cos(efield_zt,&(ir->et[ZZ]),TRUE);
+  
+  for(i=0; (i<grps->nr); i++)
+    sfree(gnames[i]);
+  sfree(gnames);
+  done_blocka(grps);
+  sfree(grps);
+
+}
+
+
+
+static void check_disre(gmx_mtop_t *mtop)
+{
+  gmx_ffparams_t *ffparams;
+  t_functype *functype;
+  t_iparams  *ip;
+  int i,ndouble,ftype;
+  int label,old_label;
+  
+  if (gmx_mtop_ftype_count(mtop,F_DISRES) > 0) {
+    ffparams  = &mtop->ffparams;
+    functype  = ffparams->functype;
+    ip        = ffparams->iparams;
+    ndouble   = 0;
+    old_label = -1;
+    for(i=0; i<ffparams->ntypes; i++) {
+      ftype = functype[i];
+      if (ftype == F_DISRES) {
+       label = ip[i].disres.label;
+       if (label == old_label) {
+         fprintf(stderr,"Distance restraint index %d occurs twice\n",label);
+         ndouble++;
+       }
+       old_label = label;
+      }
+    }
+    if (ndouble>0)
+      gmx_fatal(FARGS,"Found %d double distance restraint indices,\n"
+               "probably the parameters for multiple pairs in one restraint "
+               "are not identical\n",ndouble);
+  }
+}
+
+static gmx_bool absolute_reference(t_inputrec *ir,gmx_mtop_t *sys,
+                                   gmx_bool posres_only,
+                                   ivec AbsRef)
+{
+    int d,g,i;
+    gmx_mtop_ilistloop_t iloop;
+    t_ilist *ilist;
+    int nmol;
+    t_iparams *pr;
+
+    clear_ivec(AbsRef);
+
+    if (!posres_only)
+    {
+        /* Check the COM */
+        for(d=0; d<DIM; d++)
+        {
+            AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
+        }
+        /* Check for freeze groups */
+        for(g=0; g<ir->opts.ngfrz; g++)
+        {
+            for(d=0; d<DIM; d++)
+            {
+                if (ir->opts.nFreeze[g][d] != 0)
+                {
+                    AbsRef[d] = 1;
+                }
+            }
+        }
+    }
+
+    /* Check for position restraints */
+    iloop = gmx_mtop_ilistloop_init(sys);
+    while (gmx_mtop_ilistloop_next(iloop,&ilist,&nmol))
+    {
+        if (nmol > 0 &&
+            (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
+        {
+            for(i=0; i<ilist[F_POSRES].nr; i+=2)
+            {
+                pr = &sys->ffparams.iparams[ilist[F_POSRES].iatoms[i]];
+                for(d=0; d<DIM; d++)
+                {
+                    if (pr->posres.fcA[d] != 0)
+                    {
+                        AbsRef[d] = 1;
+                    }
+                }
+            }
+        }
+    }
+
+    return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
+}
+
+void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
+                  warninp_t wi)
+{
+  char err_buf[256];
+  int  i,m,g,nmol,npct;
+  gmx_bool bCharge,bAcc;
+  real gdt_max,*mgrp,mt;
+  rvec acc;
+  gmx_mtop_atomloop_block_t aloopb;
+  gmx_mtop_atomloop_all_t aloop;
+  t_atom *atom;
+  ivec AbsRef;
+  char warn_buf[STRLEN];
+
+  set_warning_line(wi,mdparin,-1);
+
+  if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD &&
+      ir->comm_mode == ecmNO &&
+      !(absolute_reference(ir,sys,FALSE,AbsRef) || ir->nsteps <= 10)) {
+    warning(wi,"You are not using center of mass motion removal (mdp option comm-mode), numerical rounding errors can lead to build up of kinetic energy of the center of mass");
+  }
+
+    /* Check for pressure coupling with absolute position restraints */
+    if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
+    {
+        absolute_reference(ir,sys,TRUE,AbsRef);
+        {
+            for(m=0; m<DIM; m++)
+            {
+                if (AbsRef[m] && norm2(ir->compress[m]) > 0)
+                {
+                    warning(wi,"You are using pressure coupling with absolute position restraints, this will give artifacts. Use the refcoord_scaling option.");
+                    break;
+                }
+            }
+        }
+    }
+
+  bCharge = FALSE;
+  aloopb = gmx_mtop_atomloop_block_init(sys);
+  while (gmx_mtop_atomloop_block_next(aloopb,&atom,&nmol)) {
+    if (atom->q != 0 || atom->qB != 0) {
+      bCharge = TRUE;
+    }
+  }
+  
+  if (!bCharge) {
+    if (EEL_FULL(ir->coulombtype)) {
+      sprintf(err_buf,
+             "You are using full electrostatics treatment %s for a system without charges.\n"
+             "This costs a lot of performance for just processing zeros, consider using %s instead.\n",
+             EELTYPE(ir->coulombtype),EELTYPE(eelCUT));
+      warning(wi,err_buf);
+    }
+  } else {
+    if (ir->coulombtype == eelCUT && ir->rcoulomb > 0 && !ir->implicit_solvent) {
+      sprintf(err_buf,
+             "You are using a plain Coulomb cut-off, which might produce artifacts.\n"
+             "You might want to consider using %s electrostatics.\n",
+             EELTYPE(eelPME));
+      warning_note(wi,err_buf);
+    }
+  }
+
+  /* Generalized reaction field */  
+  if (ir->opts.ngtc == 0) {
+    sprintf(err_buf,"No temperature coupling while using coulombtype %s",
+           eel_names[eelGRF]);
+    CHECK(ir->coulombtype == eelGRF);
+  }
+  else {
+    sprintf(err_buf,"When using coulombtype = %s"
+           " ref_t for temperature coupling should be > 0",
+           eel_names[eelGRF]);
+    CHECK((ir->coulombtype == eelGRF) && (ir->opts.ref_t[0] <= 0));
+  }
+    
+  if (ir->eI == eiSD1) {
+    gdt_max = 0;
+    for(i=0; (i<ir->opts.ngtc); i++)
+      gdt_max = max(gdt_max,ir->delta_t/ir->opts.tau_t[i]);
+    if (0.5*gdt_max > 0.0015) {
+      sprintf(warn_buf,"The relative error with integrator %s is 0.5*delta-t/tau-t = %g, you might want to switch to integrator %s\n",
+             ei_names[ir->eI],0.5*gdt_max,ei_names[eiSD2]);
+      warning_note(wi,warn_buf);
+    }
+  }
+
+  bAcc = FALSE;
+  for(i=0; (i<sys->groups.grps[egcACC].nr); i++) {
+    for(m=0; (m<DIM); m++) {
+      if (fabs(ir->opts.acc[i][m]) > 1e-6) {
+       bAcc = TRUE;
+      }
+    }
+  }
+  if (bAcc) {
+    clear_rvec(acc);
+    snew(mgrp,sys->groups.grps[egcACC].nr);
+    aloop = gmx_mtop_atomloop_all_init(sys);
+    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
+      mgrp[ggrpnr(&sys->groups,egcACC,i)] += atom->m;
+    }
+    mt = 0.0;
+    for(i=0; (i<sys->groups.grps[egcACC].nr); i++) {
+      for(m=0; (m<DIM); m++)
+       acc[m] += ir->opts.acc[i][m]*mgrp[i];
+      mt += mgrp[i];
+    }
+    for(m=0; (m<DIM); m++) {
+      if (fabs(acc[m]) > 1e-6) {
+       const char *dim[DIM] = { "X", "Y", "Z" };
+       fprintf(stderr,
+               "Net Acceleration in %s direction, will %s be corrected\n",
+               dim[m],ir->nstcomm != 0 ? "" : "not");
+       if (ir->nstcomm != 0 && m < ndof_com(ir)) {
+         acc[m] /= mt;
+         for (i=0; (i<sys->groups.grps[egcACC].nr); i++)
+           ir->opts.acc[i][m] -= acc[m];
+       }
+      }
+    }
+    sfree(mgrp);
+  }
+
+  if (ir->efep != efepNO && ir->sc_alpha != 0 &&
+      !gmx_within_tol(sys->ffparams.reppow,12.0,10*GMX_DOUBLE_EPS)) {
+    gmx_fatal(FARGS,"Soft-core interactions are only supported with VdW repulsion power 12");
+  }
+
+  if (ir->ePull != epullNO) {
+    if (ir->pull->grp[0].nat == 0) {
+        absolute_reference(ir,sys,FALSE,AbsRef);
+      for(m=0; m<DIM; m++) {
+       if (ir->pull->dim[m] && !AbsRef[m]) {
+         warning(wi,"You are using an absolute reference for pulling, but the rest of the system does not have an absolute reference. This will lead to artifacts.");
+         break;
+       }
+      }
+    }
+
+    if (ir->pull->eGeom == epullgDIRPBC) {
+      for(i=0; i<3; i++) {
+       for(m=0; m<=i; m++) {
+         if ((ir->epc != epcNO && ir->compress[i][m] != 0) ||
+             ir->deform[i][m] != 0) {
+           for(g=1; g<ir->pull->ngrp; g++) {
+             if (ir->pull->grp[g].vec[m] != 0) {
+               gmx_fatal(FARGS,"Can not have dynamic box while using pull geometry '%s' (dim %c)",EPULLGEOM(ir->pull->eGeom),'x'+m);
+             }
+           }
+         }
+       }
+      }
+    }
+  }
+
+  check_disre(sys);
+}
+
+void double_check(t_inputrec *ir,matrix box,gmx_bool bConstr,warninp_t wi)
+{
+  real min_size;
+  gmx_bool bTWIN;
+  char warn_buf[STRLEN];
+  const char *ptr;
+  
+  ptr = check_box(ir->ePBC,box);
+  if (ptr) {
+      warning_error(wi,ptr);
+  }  
+
+  if (bConstr && ir->eConstrAlg == econtSHAKE) {
+    if (ir->shake_tol <= 0.0) {
+      sprintf(warn_buf,"ERROR: shake-tol must be > 0 instead of %g\n",
+              ir->shake_tol);
+      warning_error(wi,warn_buf);
+    }
+
+    if (IR_TWINRANGE(*ir) && ir->nstlist > 1) {
+      sprintf(warn_buf,"With twin-range cut-off's and SHAKE the virial and the pressure are incorrect.");
+      if (ir->epc == epcNO) {
+       warning(wi,warn_buf);
+      } else {
+          warning_error(wi,warn_buf);
+      }
+    }
+  }
+
+  if( (ir->eConstrAlg == econtLINCS) && bConstr) {
+    /* If we have Lincs constraints: */
+    if(ir->eI==eiMD && ir->etc==etcNO &&
+       ir->eConstrAlg==econtLINCS && ir->nLincsIter==1) {
+      sprintf(warn_buf,"For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
+      warning_note(wi,warn_buf);
+    }
+    
+    if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder<8)) {
+      sprintf(warn_buf,"For accurate %s with LINCS constraints, lincs-order should be 8 or more.",ei_names[ir->eI]);
+      warning_note(wi,warn_buf);
+    }
+    if (ir->epc==epcMTTK) {
+        warning_error(wi,"MTTK not compatible with lincs -- use shake instead.");
+    }
+  }
+
+  if (ir->LincsWarnAngle > 90.0) {
+    sprintf(warn_buf,"lincs-warnangle can not be larger than 90 degrees, setting it to 90.\n");
+    warning(wi,warn_buf);
+    ir->LincsWarnAngle = 90.0;
+  }
+
+  if (ir->ePBC != epbcNONE) {
+    if (ir->nstlist == 0) {
+      warning(wi,"With nstlist=0 atoms are only put into the box at step 0, therefore drifting atoms might cause the simulation to crash.");
+    }
+    bTWIN = (ir->rlistlong > ir->rlist);
+    if (ir->ns_type == ensGRID) {
+      if (sqr(ir->rlistlong) >= max_cutoff2(ir->ePBC,box)) {
+          sprintf(warn_buf,"ERROR: The cut-off length is longer than half the shortest box vector or longer than the smallest box diagonal element. Increase the box size or decrease %s.\n",
+               bTWIN ? (ir->rcoulomb==ir->rlistlong ? "rcoulomb" : "rvdw"):"rlist");
+          warning_error(wi,warn_buf);
+      }
+    } else {
+      min_size = min(box[XX][XX],min(box[YY][YY],box[ZZ][ZZ]));
+      if (2*ir->rlistlong >= min_size) {
+          sprintf(warn_buf,"ERROR: One of the box lengths is smaller than twice the cut-off length. Increase the box size or decrease rlist.");
+          warning_error(wi,warn_buf);
+       if (TRICLINIC(box))
+         fprintf(stderr,"Grid search might allow larger cut-off's than simple search with triclinic boxes.");
+      }
+    }
+  }
+}
+
+void check_chargegroup_radii(const gmx_mtop_t *mtop,const t_inputrec *ir,
+                             rvec *x,
+                             warninp_t wi)
+{
+    real rvdw1,rvdw2,rcoul1,rcoul2;
+    char warn_buf[STRLEN];
+
+    calc_chargegroup_radii(mtop,x,&rvdw1,&rvdw2,&rcoul1,&rcoul2);
+
+    if (rvdw1 > 0)
+    {
+        printf("Largest charge group radii for Van der Waals: %5.3f, %5.3f nm\n",
+               rvdw1,rvdw2);
+    }
+    if (rcoul1 > 0)
+    {
+        printf("Largest charge group radii for Coulomb:       %5.3f, %5.3f nm\n",
+               rcoul1,rcoul2);
+    }
+
+    if (ir->rlist > 0)
+    {
+        if (rvdw1  + rvdw2  > ir->rlist ||
+            rcoul1 + rcoul2 > ir->rlist)
+        {
+            sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than rlist (%f)\n",max(rvdw1+rvdw2,rcoul1+rcoul2),ir->rlist);
+            warning(wi,warn_buf);
+        }
+        else
+        {
+            /* Here we do not use the zero at cut-off macro,
+             * since user defined interactions might purposely
+             * not be zero at the cut-off.
+             */
+            if (EVDW_IS_ZERO_AT_CUTOFF(ir->vdwtype) &&
+                rvdw1 + rvdw2 > ir->rlist - ir->rvdw)
+            {
+                sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than rlist (%f) - rvdw (%f)\n",
+                        rvdw1+rvdw2,
+                        ir->rlist,ir->rvdw);
+                if (ir_NVE(ir))
+                {
+                    warning(wi,warn_buf);
+                }
+                else
+                {
+                    warning_note(wi,warn_buf);
+                }
+            }
+            if (EEL_IS_ZERO_AT_CUTOFF(ir->coulombtype) &&
+                rcoul1 + rcoul2 > ir->rlistlong - ir->rcoulomb)
+            {
+                sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than %s (%f) - rcoulomb (%f)\n",
+                        rcoul1+rcoul2,
+                        ir->rlistlong > ir->rlist ? "rlistlong" : "rlist",
+                        ir->rlistlong,ir->rcoulomb);
+                if (ir_NVE(ir))
+                {
+                    warning(wi,warn_buf);
+                }
+                else
+                {
+                    warning_note(wi,warn_buf);
+                }
+            }
+        }
+    }
+}
diff --git a/src/gromacs/gmxpreprocess/readir.h b/src/gromacs/gmxpreprocess/readir.h
new file mode 100644 (file)
index 0000000..3f99910
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+#ifndef _readir_h
+#define _readir_h
+
+#include "typedefs.h"
+#include "string2.h"
+#include "readinp.h"
+#include "grompp.h"
+
+enum { eshNONE, eshHBONDS, eshALLBONDS, eshHANGLES, eshALLANGLES, eshNR };
+
+static const char *constraints[eshNR+1]    = { 
+  "none", "h-bonds", "all-bonds", "h-angles", "all-angles", NULL 
+};
+
+enum { ecouplamVDWQ, ecouplamVDW, ecouplamQ, ecouplamNONE, ecouplamNR };
+
+static const char *couple_lam[ecouplamNR+1]    = { 
+  "vdw-q", "vdw", "q", "none", NULL 
+};
+
+typedef struct {
+  int warnings;
+  int nshake;
+  real fourierspacing;
+  char *include;
+  char *define;
+  gmx_bool bGenVel;
+  gmx_bool bGenPairs;
+  real tempi;
+  int  seed;
+  gmx_bool bOrire;
+  gmx_bool bDihre;
+  gmx_bool bMorse;
+  char *wall_atomtype[2];
+  gmx_bool pull_start;
+  char *couple_moltype;
+  int  couple_lam0;
+  int  couple_lam1;
+  gmx_bool bCoupleIntra;
+} t_gromppopts;
+
+
+extern void init_ir(t_inputrec *ir, t_gromppopts *opts);
+/* Initiate stuff */
+
+extern void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
+                    warninp_t wi);
+/* Validate inputrec data.
+ * Fatal errors will be added to nerror.
+ */
+extern int search_string(char *s,int ng,char *gn[]);
+/* Returns the index of string s in the index groups */
+
+extern void double_check(t_inputrec *ir,matrix box,gmx_bool bConstr,
+                        warninp_t wi);
+/* Do more checks */
+
+extern void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
+                        warninp_t wi);
+/* Do even more checks */
+
+extern void check_chargegroup_radii(const gmx_mtop_t *mtop,const t_inputrec *ir,
+                                   rvec *x,
+                                   warninp_t wi);
+/* Even more checks, charge group radii vs. cut-off's only. */
+
+extern void get_ir(const char *mdparin,const char *mdparout,
+                  t_inputrec *ir,t_gromppopts *opts,
+                  warninp_t wi);
+/* Read the input file, and retrieve data for inputrec.
+ * More data are read, but the are only evaluated when the next
+ * function is called. Also prints the input file back to mdparout.
+ */
+extern void do_index(const char* mdparin, 
+                    const char *ndx,
+                    gmx_mtop_t *mtop,
+                    gmx_bool bVerbose,
+                    t_inputrec *ir,
+                    rvec *v,
+                    warninp_t wi);
+/* Read the index file and assign grp numbers to atoms.
+ * If v is not NULL, the velocities will be scaled to the correct number
+ * of degrees of freedom.
+ */
+
+/* Routines In readpull.c */
+
+extern char **read_pullparams(int *ninp_p,t_inpfile **inp,
+                             t_pull *pull,gmx_bool *bStart,
+                             warninp_t wi);
+/* Reads the pull parameters, returns a list of the pull group names */
+
+extern void make_pull_groups(t_pull *pull,char **pgnames,
+                            t_blocka *grps,char **gnames);
+/* Process the pull parameters after reading the index groups */
+
+extern void set_pull_init(t_inputrec *ir,gmx_mtop_t *mtop,rvec *x,matrix box,
+                         const output_env_t oenv, gmx_bool bStart);
+/* Prints the initial pull group distances in x.
+ * If bStart adds the distance to the initial reference location.
+ */
+
+extern char **read_rotparams(int *ninp_p,t_inpfile **inp,t_rot *rot,warninp_t wi);
+/* Reads enforced rotation parameters, returns a list of the rot group names */
+
+extern void make_rotation_groups(t_rot *rot,char **rotgnames,
+                 t_blocka *grps,char **gnames);
+/* Process the rotation parameters after reading the index groups */
+
+extern void set_reference_positions(t_rot *rot, gmx_mtop_t *mtop, rvec *x, matrix box,
+        const char *fn, gmx_bool bSet, warninp_t wi);
+
+#endif /* _readir_h */
diff --git a/src/gromacs/gmxpreprocess/readrot.c b/src/gromacs/gmxpreprocess/readrot.c
new file mode 100644 (file)
index 0000000..6cce84b
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "vec.h"
+#include "smalloc.h"
+#include "readir.h"
+#include "names.h"
+#include "futil.h"
+#include "trnio.h"
+#include "txtdump.h"
+
+static char *RotStr = {"Enforced rotation:"};
+
+
+static char s_vec[STRLEN];
+
+
+static void string2dvec(char buf[], dvec nums)
+{
+    if (sscanf(buf,"%lf%lf%lf",&nums[0],&nums[1],&nums[2]) != 3)
+        gmx_fatal(FARGS,"Expected three numbers at input line %s",buf);
+}
+
+
+extern char **read_rotparams(int *ninp_p,t_inpfile **inp_p,t_rot *rot,
+        warninp_t wi)
+{
+    int  ninp,g,m;
+    t_inpfile *inp;
+    const char *tmp;
+    char **grpbuf;
+    char buf[STRLEN];
+    char warn_buf[STRLEN];
+    dvec vec;
+    t_rotgrp *rotg;
+
+    ninp   = *ninp_p;
+    inp    = *inp_p;
+    
+    /* read rotation parameters */
+    CTYPE("Output frequency for angle, torque and rotation potential energy for the whole group");
+    ITYPE("rot_nstrout",     rot->nstrout, 100);
+    CTYPE("Output frequency for per-slab data (angles, torques and slab centers)");
+    ITYPE("rot_nstsout",     rot->nstsout, 1000);
+    CTYPE("Number of rotation groups");
+    ITYPE("rot_ngroups",     rot->ngrp,1);
+    
+    if (rot->ngrp < 1)
+    {
+        gmx_fatal(FARGS,"rot_ngroups should be >= 1");
+    }
+    
+    snew(rot->grp,rot->ngrp);
+    
+    /* Read the rotation groups */
+    snew(grpbuf,rot->ngrp);
+    for(g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        snew(grpbuf[g],STRLEN);
+        CTYPE("Rotation group name");
+        sprintf(buf,"rot_group%d",g);
+        STYPE(buf, grpbuf[g], "");
+        
+        CTYPE("Rotation potential. Can be iso, iso-pf, pm, pm-pf, rm, rm-pf, rm2, rm2-pf, flex, flex-t, flex2, flex2-t");
+        sprintf(buf,"rot_type%d",g);
+        ETYPE(buf, rotg->eType, erotg_names);
+
+        CTYPE("Use mass-weighting of the rotation group positions");
+        sprintf(buf,"rot_massw%d",g);
+        ETYPE(buf, rotg->bMassW, yesno_names);
+
+        CTYPE("Rotation vector, will get normalized");
+        sprintf(buf,"rot_vec%d",g);
+        STYPE(buf, s_vec, "1.0 0.0 0.0");
+        string2dvec(s_vec,vec);
+        /* Normalize the rotation vector */
+        if (dnorm(vec) != 0)
+        {
+            dsvmul(1.0/dnorm(vec),vec,vec);
+        }
+        else
+        {
+            sprintf(warn_buf, "rot_vec%d = 0", g);
+            warning_error(wi, warn_buf);
+        }
+        fprintf(stderr, "%s Group %d (%s) normalized rot. vector: %f %f %f\n",
+                RotStr, g, erotg_names[rotg->eType], vec[0], vec[1], vec[2]);
+        for(m=0; m<DIM; m++)
+            rotg->vec[m] = vec[m];
+        
+        CTYPE("Pivot point for the potentials iso, pm, rm, and rm2 [nm]");
+        sprintf(buf,"rot_pivot%d",g);
+        STYPE(buf, s_vec, "0.0 0.0 0.0");
+        clear_dvec(vec);
+        if ( (rotg->eType==erotgISO) || (rotg->eType==erotgPM) || (rotg->eType==erotgRM) || (rotg->eType==erotgRM2) )
+            string2dvec(s_vec,vec);
+        for(m=0; m<DIM; m++)
+            rotg->pivot[m] = vec[m];
+
+        CTYPE("Rotation rate [degree/ps] and force constant [kJ/(mol*nm^2)]");
+        sprintf(buf,"rot_rate%d",g);
+        RTYPE(buf, rotg->rate, 0.0);
+
+        sprintf(buf,"rot_k%d",g);
+        RTYPE(buf, rotg->k, 0.0);
+        if (rotg->k <= 0.0)
+        {
+            sprintf(warn_buf, "rot_k%d <= 0", g);
+            warning_note(wi, warn_buf);
+        }
+
+        CTYPE("Slab distance for flexible axis rotation [nm]");
+        sprintf(buf,"rot_slab_dist%d",g);
+        RTYPE(buf, rotg->slab_dist, 1.5);
+        if (rotg->slab_dist <= 0.0)
+        {
+            sprintf(warn_buf, "rot_slab_dist%d <= 0", g);
+            warning_error(wi, warn_buf);
+        }
+
+        CTYPE("Minimum value of Gaussian function for the force to be evaluated (for flex* potentials)");
+        sprintf(buf,"rot_min_gauss%d",g);
+        RTYPE(buf, rotg->min_gaussian, 1e-3);
+        if (rotg->min_gaussian <= 0.0)
+        {
+            sprintf(warn_buf, "rot_min_gauss%d <= 0", g);
+            warning_error(wi, warn_buf);
+        }
+
+        CTYPE("Value of additive constant epsilon' [nm^2] for rm2* and flex2* potentials");
+        sprintf(buf, "rot_eps%d",g);
+        RTYPE(buf, rotg->eps, 1e-4);
+        if ( (rotg->eps <= 0.0) && (rotg->eType==erotgRM2 || rotg->eType==erotgFLEX2) )
+        {
+            sprintf(warn_buf, "rot_eps%d <= 0", g);
+            warning_error(wi, warn_buf);
+        }
+
+        CTYPE("Fitting method to determine angle of rotation group (rmsd, norm, or potential)");
+        sprintf(buf,"rot_fit_method%d",g);
+        ETYPE(buf, rotg->eFittype, erotg_fitnames);
+        CTYPE("For fit type 'potential', nr. of angles around the reference for which the pot. is evaluated");
+        sprintf(buf,"rot_potfit_nsteps%d",g);
+        ITYPE(buf, rotg->PotAngle_nstep, 21);
+        if ( (rotg->eFittype==erotgFitPOT) && (rotg->PotAngle_nstep < 1) )
+        {
+            sprintf(warn_buf, "rot_potfit_nsteps%d < 1", g);
+            warning_error(wi, warn_buf);
+        }
+        CTYPE("For fit type 'potential', distance in degrees between two consecutive angles");
+        sprintf(buf,"rot_potfit_step%d",g);
+        RTYPE(buf, rotg->PotAngle_step, 0.25);
+    }
+    
+    *ninp_p   = ninp;
+    *inp_p    = inp;
+    
+    return grpbuf;
+}
+
+
+/* Check whether the box is unchanged */
+static void check_box(matrix f_box, matrix box, char fn[], warninp_t wi)
+{
+    int i,ii;
+    gmx_bool bSame=TRUE;
+    char warn_buf[STRLEN];
+    
+    
+    for (i=0; i<DIM; i++)
+        for (ii=0; ii<DIM; ii++)
+            if (f_box[i][ii] != box[i][ii]) 
+                bSame = FALSE;
+    if (!bSame)
+    {
+        sprintf(warn_buf, "%s Box size in reference file %s differs from actual box size!",
+                RotStr, fn);
+        warning(wi, warn_buf);
+        pr_rvecs(stderr,0,"Your box is:",box  ,3);
+        pr_rvecs(stderr,0,"Box in file:",f_box,3);
+    }
+}
+
+
+/* Extract the reference positions for the rotation group(s) */
+extern void set_reference_positions(
+        t_rot *rot, gmx_mtop_t *mtop, rvec *x, matrix box,
+        const char *fn, gmx_bool bSet, warninp_t wi)
+{
+    int g,i,ii;
+    t_rotgrp *rotg;
+    t_trnheader header;    /* Header information of reference file */
+    char base[STRLEN],extension[STRLEN],reffile[STRLEN];
+    char *extpos;
+    rvec f_box[3];         /* Box from reference file */
+
+    
+    /* Base name and extension of the reference file: */
+    strncpy(base, fn, STRLEN - 1);
+    extpos = strrchr(base, '.');
+    strcpy(extension,extpos+1);
+    *extpos = '\0';
+
+
+    for (g=0; g<rot->ngrp; g++)
+     {
+         rotg = &rot->grp[g];
+         fprintf(stderr, "%s group %d has %d reference positions.\n",RotStr,g,rotg->nat);
+         snew(rotg->x_ref, rotg->nat);
+         
+         /* Construct the name for the file containing the reference positions for this group: */
+         sprintf(reffile, "%s.%d.%s", base,g,extension);
+
+         /* If the base filename for the reference position files was explicitly set by
+          * the user, we issue a fatal error if the group file can not be found */
+         if (bSet && !gmx_fexist(reffile))
+         {
+             gmx_fatal(FARGS, "%s The file containing the reference positions was not found.\n"
+                              "Expected the file '%s' for group %d.\n",
+                              RotStr, reffile, g);
+         }
+
+         if (gmx_fexist(reffile))
+         {
+             fprintf(stderr, "  Reading them from %s.\n", reffile);
+             read_trnheader(reffile, &header);
+             if (rotg->nat != header.natoms)
+                 gmx_fatal(FARGS,"Number of atoms in file %s (%d) does not match the number of atoms in rotation group (%d)!\n",
+                         reffile, header.natoms, rotg->nat);
+             read_trn(reffile, &header.step, &header.t, &header.lambda, f_box, &header.natoms, rotg->x_ref, NULL, NULL);
+
+             /* Check whether the box is unchanged and output a warning if not: */
+             check_box(f_box,box,reffile,wi);
+         }
+         else
+         {
+             fprintf(stderr, " Saving them to %s.\n", reffile);         
+             for(i=0; i<rotg->nat; i++)
+             {
+                 ii = rotg->ind[i];
+                 copy_rvec(x[ii], rotg->x_ref[i]);
+             }
+             write_trn(reffile,g,0.0,0.0,box,rotg->nat,rotg->x_ref,NULL,NULL);
+         }
+     }
+}
+
+
+extern void make_rotation_groups(t_rot *rot,char **rotgnames,t_blocka *grps,char **gnames)
+{
+    int      g,ig=-1,i;
+    t_rotgrp *rotg;
+    
+    
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        ig = search_string(rotgnames[g],grps->nr,gnames);
+        rotg->nat = grps->index[ig+1] - grps->index[ig];
+        
+        if (rotg->nat > 0)
+        {
+            fprintf(stderr,"Rotation group %d '%s' has %d atoms\n",g,rotgnames[g],rotg->nat);
+            snew(rotg->ind,rotg->nat);
+            for(i=0; i<rotg->nat; i++)
+                rotg->ind[i] = grps->a[grps->index[ig]+i];            
+        }
+        else
+            gmx_fatal(FARGS,"Rotation group %d '%s' is empty",g,rotgnames[g]);
+    }
+}
diff --git a/src/gromacs/gromacs.h b/src/gromacs/gromacs.h
new file mode 100644 (file)
index 0000000..29b90ea
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Dummy header for Doxygen documentation.
+ *
+ * This file just holds the main page for doxygen.  When, at some point in the
+ * future, there is an obvious location for this documentation, we should
+ * move it there.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \mainpage Gromacs
+ * GROMACS is a versatile package to perform molecular dynamics, i.e. simulate
+ * the Newtonian equations of motion for systems with hundreds, to millions
+ * of particles.
+ */
+/*! \defgroup group_publicapi Public API
+ * \brief
+ * Classes and other symbols that are publicly accessible from user code.
+ */
+/*! \defgroup group_libraryapi Library API
+ * \brief
+ * Classes and other symbols that are publicly accessible within the Gromacs
+ * library.
+ *
+ * \see group_publicapi
+ */
+/*! \defgroup group_utilitymodules Utility Modules
+ * \brief
+ * Modules with generic utility functions.
+ */
+/*! \defgroup group_analysismodules Analysis Modules
+ * \brief
+ * Modules used in analysis tools.
+ */
+/*! \namespace gmx
+ * \brief
+ * Generic Gromacs namespace.
+ *
+ * \inpublicapi
+ */
diff --git a/src/gromacs/legacyheaders/CMakeLists.txt b/src/gromacs/legacyheaders/CMakeLists.txt
new file mode 100644 (file)
index 0000000..593fc53
--- /dev/null
@@ -0,0 +1,7 @@
+# includes: Nothing to build, just installation
+install(DIRECTORY . DESTINATION ${INCL_INSTALL_DIR}/gromacs/legacyheaders
+  COMPONENT development
+  PATTERN "Makefile*" EXCLUDE
+  PATTERN "CMake*" EXCLUDE
+  PATTERN "cmake*" EXCLUDE
+)
diff --git a/src/gromacs/legacyheaders/gmx_statistics.h b/src/gromacs/legacyheaders/gmx_statistics.h
new file mode 100644 (file)
index 0000000..afc1248
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+#ifndef _GMX_STATS_H
+#define _GMX_STATS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "typedefs.h"
+
+typedef struct gmx_stats *gmx_stats_t;
+       
+/* Error codes returned by the routines */
+enum { estatsOK, estatsNO_POINTS, estatsNO_MEMORY, estatsERROR, 
+       estatsINVALID_INPUT, estatsNOT_IMPLEMENTED, estatsNR };
+       
+enum { elsqWEIGHT_NONE, elsqWEIGHT_X, elsqWEIGHT_Y, 
+       elsqWEIGHT_XY, elsqWEIGHT_NR  };
+
+enum { ehistoX, ehistoY, ehistoNR };
+  
+gmx_stats_t gmx_stats_init();
+
+int gmx_stats_done(gmx_stats_t stats);
+
+/* Remove outliers from a straight line, where level in units of
+   sigma. Level needs to be larger than one obviously. */
+int gmx_stats_remove_outliers(gmx_stats_t stats,double level);
+
+
+
+int gmx_stats_add_point(gmx_stats_t stats,double x,double y,
+                              double dx,double dy);
+
+/* The arrays dx and dy may be NULL if no uncertainties are available,
+   in that case zero uncertainties will be assumed. */
+int gmx_stats_add_points(gmx_stats_t stats,int n,real *x,real *y,
+                               real *dx,real *dy);
+
+/* Return the data points one by one. Return estatsOK while there are
+   more points, and returns estatsNOPOINTS when the last point has
+   been returned. Should be used in a while loop. Variables for either
+   pointer may be NULL, in which case the routine can be used as an
+   expensive point counter. 
+   If level > 0 then the outliers outside level*sigma are reported
+   only. */
+int gmx_stats_get_point(gmx_stats_t stats,real *x,real *y,
+                       real *dx,real *dy,real level);
+
+/* Fit the data to y = ax + b, possibly weighted, if uncertainties
+   have been input. Returns slope in *a and intercept in b, *return
+   sigmas in *da and *db respectively. Returns normalized *quality of
+   fit in *chi2 and correlation of fit with data in Rfit. chi2, Rfit,
+   da and db may be NULL. */
+int gmx_stats_get_ab(gmx_stats_t stats,int weight,
+                           real *a,real *b,
+                           real *da,real *db,real *chi2,real *Rfit);
+
+/* Fit the data to y = ax, possibly weighted, if uncertainties have
+   been input. Returns slope in *a, sigma in a in *da, and normalized
+   quality of fit in *chi2 and correlation of fit with data in
+   Rfit. chi2, Rfit and da may be NULL. */
+int gmx_stats_get_a(gmx_stats_t stats,int weight,
+                          real *a,real *da,real *chi2,real *Rfit);
+
+/* Return the correlation coefficient between the data (x and y) as
+   input to the structure. */
+int gmx_stats_get_corr_coeff(gmx_stats_t stats,real *R);
+
+/* Returns the root mean square deviation between x and y values. */
+int gmx_stats_get_rmsd(gmx_stats_t gstats,real *rmsd);
+
+int gmx_stats_get_npoints(gmx_stats_t stats,int *N);
+
+int gmx_stats_get_average(gmx_stats_t stats,real *aver);
+
+int gmx_stats_get_sigma(gmx_stats_t stats,real *sigma);
+
+int gmx_stats_get_error(gmx_stats_t stats,real *error);
+
+/* Get all three of the above. Pointers may be null, in which case no
+   assignment will be done. */
+int gmx_stats_get_ase(gmx_stats_t gstats,real *aver,real *sigma,real *error);
+
+/* Dump the x, y, dx, dy data to a text file */
+int gmx_stats_dump_xy(gmx_stats_t gstats,FILE *fp);
+
+/* Make a histogram of the data present. Uses either bindwith to
+   determine the number of bins, or nbins to determine the binwidth,
+   therefore one of these should be zero, but not the other. If *nbins = 0
+   the number of bins will be returned in this variable. ehisto should be one of 
+   ehistoX or ehistoY. If
+   normalized not equal to zero, the integral of the histogram will be
+   normalized to one. The output is in two arrays, *x and *y, to which
+   you should pass a pointer. Memory for the arrays will be allocated
+   as needed. Function returns one of the estats codes. */
+int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nbins,
+                                   int ehisto,
+                                   int normalized,real **x,real **y);
+
+/* Return message belonging to error code */
+const char *gmx_stats_message(int estats);
+
+/****************************************************
+ * Some statistics utilities for convenience: useful when a complete data
+ * set is available already from another source, e.g. an xvg file.
+ ****************************************************/
+int lsq_y_ax(int n, real x[], real y[], real *a);
+/* Fit a straight line y=ax thru the n data points x, y, return the
+   slope in *a. Return value can be estatsOK, or something else. */
+
+int lsq_y_ax_b(int n, real x[], real y[], real *a, real *b,real *r,
+                     real *chi2);
+/* Fit a straight line y=ax+b thru the n data points x,y.
+ * Returns the "fit quality" sigma = sqrt(chi^2/(n-2)).
+ * The correlation coefficient is returned in r.
+ */
+
+int lsq_y_ax_b_xdouble(int n, double x[], real y[],
+                              real *a, real *b,real *r,real *chi2);
+/* As lsq_y_ax_b, but with x in double precision.
+ */
+
+int lsq_y_ax_b_error(int n, real x[], real y[], real dy[],
+                            real *a, real *b, real *da, real *db,
+                            real *r,real *chi2);
+/* Fit a straight line y=ax+b thru the n data points x,y, with sigma dy
+ * Returns the "fit quality" sigma = sqrt(chi^2/(n-2)).
+ * The correlation coefficient is returned in r.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/legacyheaders/gmx_wallcycle.h b/src/gromacs/legacyheaders/gmx_wallcycle.h
new file mode 100644 (file)
index 0000000..b00cd65
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+
+#ifndef _gmx_wallcycle_h
+#define _gmx_wallcycle_h
+
+#include <stdio.h>
+#include "typedefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  enum { ewcRUN, ewcSTEP, ewcPPDURINGPME, ewcDOMDEC, ewcDDCOMMLOAD, ewcDDCOMMBOUND, ewcVSITECONSTR, ewcPP_PMESENDX, ewcMOVEX, ewcNS, ewcGB, ewcFORCE, ewcMOVEF, ewcPMEMESH, ewcPME_REDISTXF, ewcPME_SPREADGATHER, ewcPME_FFT, ewcPME_SOLVE, ewcPMEWAITCOMM, ewcPP_PMEWAITRECVF, ewcVSITESPREAD, ewcTRAJ, ewcUPDATE, ewcCONSTR, ewcMoveE, ewcROT, ewcTEST, ewcNR };
+
+gmx_bool wallcycle_have_counter(void);
+/* Returns if cycle counting is supported */
+
+gmx_wallcycle_t wallcycle_init(FILE *fplog,int resetstep,t_commrec *cr);
+/* Returns the wall cycle structure.
+ * Returns NULL when cycle counting is not supported.
+ */
+
+void wallcycle_start(gmx_wallcycle_t wc, int ewc);
+/* Set the start cycle count for ewc */
+
+double wallcycle_stop(gmx_wallcycle_t wc, int ewc);
+/* Stop the cycle count for ewc, returns the last cycle count */
+
+void wallcycle_reset_all(gmx_wallcycle_t wc);
+/* Resets all cycle counters to zero */
+
+void wallcycle_sum(t_commrec *cr, gmx_wallcycle_t wc,double cycles[]);
+/* Sum the cycles over the nodes in cr->mpi_comm_mysim */
+
+void wallcycle_print(FILE *fplog, int nnodes, int npme, double realtime,
+                           gmx_wallcycle_t wc, double cycles[]);
+/* Print the cycle and time accounting */
+
+gmx_large_int_t wcycle_get_reset_counters(gmx_wallcycle_t wc);
+/* Return reset_counters from wc struct */
+
+void wcycle_set_reset_counters(gmx_wallcycle_t wc, gmx_large_int_t reset_counters);
+/* Set reset_counters */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _gmx_wallcycle_h */
diff --git a/src/gromacs/legacyheaders/gmxfio.h b/src/gromacs/legacyheaders/gmxfio.h
new file mode 100644 (file)
index 0000000..e0db1ad
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _gmxfio_h
+#define _gmxfio_h
+
+#include <stdio.h>
+#include "sysstuff.h"
+#include "typedefs.h"
+#include "xdrf.h"
+#include "futil.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* types */
+
+
+/* Enumerated for different items in files */
+enum { eitemHEADER, eitemIR, eitemBOX, 
+       eitemTOP, eitemX, eitemV, eitemF, eitemNR };
+       
+/* Enumerated for data types in files */
+enum { eioREAL, eioFLOAT, eioDOUBLE, eioINT, eioGMX_LARGE_INT,
+       eioUCHAR, eioNUCHAR, eioUSHORT,
+       eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR };
+
+typedef struct t_fileio t_fileio;
+
+extern const char *itemstr[eitemNR];
+extern const char *comment_str[eitemNR];
+
+/* NOTE ABOUT THREAD SAFETY:
+
+   The functions are all thread-safe, provided that two threads don't 
+   do something silly like closing the same file, or one thread 
+   accesses a file that has been closed by another.
+   */
+
+/********************************************************
+ * Open and Close 
+ ********************************************************/
+
+t_fileio *gmx_fio_open(const char *fn,const char *mode);
+/* Open a new file for reading or writing.
+ * The file type will be deduced from the file name.
+ * If fn is NULL, stdin / stdout will be used for Ascii I/O (TPA type)
+ * mode may be "r", "w", or "a". You should append a "b" to the mode
+ * if you are writing a binary file, but the routine will also 
+ * doublecheck it and try to do it if you forgot. This has no effect on
+ * unix, but is important on windows.
+ */
+int gmx_fio_close(t_fileio *fp);
+/* Close the file corresponding to fp (if not stdio)
+ * The routine will exit when an invalid fio is handled.
+ * Returns 0 on success.
+ */
+
+int gmx_fio_fp_close(t_fileio *fp);
+/* Close the file corresponding to fp without closing the FIO entry
+ * Needed e.g. for trxio because the FIO entries are used to store 
+ * additional data.
+ * NOTE that the fp still needs to be properly closed with gmx_fio_close().
+ * The routine will exit when an invalid fio is handled.
+ * Returns 0 on success.
+ */
+
+
+/* Open a file, return a stream, record the entry in internal FIO object */
+FILE* gmx_fio_fopen(const char *fn,const char *mode);
+
+/* Close a file previously opened with gmx_fio_fopen. 
+ * Do not mix these calls with standard fopen/fclose ones!
+ * Returns 0 on success.  */
+int gmx_fio_fclose(FILE *fp);
+
+
+
+/********************************************************
+ * Change properties of the open file
+ ********************************************************/
+
+void gmx_fio_setprecision(t_fileio *fio,gmx_bool bDouble);
+/* Select the floating point precision for reading and writing files */
+
+char *gmx_fio_getname(t_fileio *fio);
+/* Return the filename corresponding to the fio index */
+
+int gmx_fio_getftp(t_fileio *fio);
+/* Return the filetype corresponding to the fio index. 
+    There is as of now no corresponding setftp function because the file
+    was opened as a specific file type and changing that midway is most 
+    likely an evil hack. */
+
+void gmx_fio_setdebug(t_fileio *fio,gmx_bool bDebug);
+/* Set the debug mode */
+
+gmx_bool gmx_fio_getdebug(t_fileio *fio);
+/* Return  whether debug mode is on in fio  */
+
+gmx_bool gmx_fio_getread(t_fileio *fio);
+/* Return  whether read mode is on in fio  */
+
+
+void gmx_fio_checktype(t_fileio *fio);
+/* Check whether the fio is of a sane type */
+
+/***************************************************
+ * FILE Operations
+ ***************************************************/
+
+void gmx_fio_rewind(t_fileio *fio);
+/* Rewind the tpa file in fio */
+
+int gmx_fio_flush(t_fileio *fio);
+/* Flush the fio, returns 0 on success */
+
+int gmx_fio_fsync(t_fileio *fio);
+/* fsync the fio, returns 0 on success. 
+   NOTE: don't use fsync function unless you're absolutely sure you need it
+   because it deliberately interferes with the OS's caching mechanisms and
+   can cause dramatically slowed down IO performance. Some OSes (Linux, 
+   for example), may implement fsync as a full sync() point. */
+
+gmx_off_t gmx_fio_ftell(t_fileio *fio);
+/* Return file position if possible */
+
+int gmx_fio_seek(t_fileio *fio,gmx_off_t fpos);
+/* Set file position if possible, quit otherwise */
+
+FILE *gmx_fio_getfp(t_fileio *fio);
+/* Return the file pointer itself */
+
+XDR *gmx_fio_getxdr(t_fileio *fio);
+/* Return the file pointer itself */
+
+
+
+
+
+/* Element with information about position in a currently open file.
+ * gmx_off_t should be defined by autoconf if your system does not have it.
+ * If you do not have it on some other platform you do not have largefile 
+ * support at all, and you can define it to int (or better, find out how to 
+ * enable large files).  */
+typedef struct
+{
+       char      filename[STRLEN];
+       gmx_off_t offset; 
+       unsigned char chksum[16];
+       int       chksum_size;
+} 
+gmx_file_position_t;
+
+
+int gmx_fio_check_file_position(t_fileio *fio);
+/* Check if the file position is out of the range of off_t.
+ * The result is stored along with the other file data of fio.
+ */
+
+int gmx_fio_get_output_file_positions(gmx_file_position_t ** outputfiles,
+                                      int *nfiles );
+/* Return the name and file pointer positions for all currently open
+ * output files. This is used for saving in the checkpoint files, so we
+ * can truncate output files upon restart-with-appending.
+ *
+ * For the first argument you should use a pointer, which will be set to
+ * point to a list of open files.
+ */
+
+t_fileio *gmx_fio_all_output_fsync(void);
+/* fsync all open output files. This is used for checkpointing, where
+   we need to ensure that all output is actually written out to 
+   disk. 
+   This is most important in the case of some networked file systems, 
+   where data is not synced with the file server until close() or 
+   fsync(), so data could remain in cache for days.
+   Note the caveats reported with gmx_fio_fsync(). 
+   
+    returns: NULL if no error occurred, or a pointer to the first file that
+             failed if an error occurred 
+*/
+
+
+int gmx_fio_get_file_md5(t_fileio *fio, gmx_off_t offset,  
+                         unsigned char digest[]);
+
+
+int xtc_seek_frame(t_fileio *fio, int frame, int natoms);
+
+int xtc_seek_time(t_fileio *fio, real time, int natoms);
+
+       
+/* Add this to the comment string for debugging */
+void gmx_fio_set_comment(t_fileio *fio, const char *comment);
+
+/* Remove previously set comment */
+void gmx_fio_unset_comment(t_fileio *fio);
+
+
+
+
+/********************************************************
+ * Read and write
+ ********************************************************/
+
+
+/* basic reading & writing */
+gmx_bool gmx_fio_reade_real(t_fileio *fio, real *item, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_float(t_fileio *fio, float *item, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_double(t_fileio *fio, double *item, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_int(t_fileio *fio, int *item, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
+                                 const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_reade_string(t_fileio *fio, char *item, 
+                          const char *desc, const char *srcfile, int line);
+
+gmx_bool gmx_fio_writee_real(t_fileio *fio, real item, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_float(t_fileio *fio, float item, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_double(t_fileio *fio, double item, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_int(t_fileio *fio, int item, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item, 
+                                  const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_writee_string(t_fileio *fio, const char *item, 
+                           const char *desc, const char *srcfile, int line);
+
+/* reading or writing, depending on the file's opening mode string */
+gmx_bool gmx_fio_doe_real(t_fileio *fio, real *item, 
+                      const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_float(t_fileio *fio, float *item, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_double(t_fileio *fio, double *item, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_gmx_bool(t_fileio *fio, gmx_bool *item, 
+                     const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_int(t_fileio *fio, int *item, 
+                     const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
+                               const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item, 
+                      const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item, 
+                      const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_doe_string(t_fileio *fio, char *item, 
+                        const char *desc, const char *srcfile, int line);
+
+
+
+
+/* array reading & writing */
+gmx_bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_float(t_fileio *fio, float *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
+                                  const char *desc, const char *srcfile, 
+                                  int line);
+gmx_bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n, 
+                           const char *desc, const char *srcfile, int line);
+
+gmx_bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_float(t_fileio *fio, const float *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n, 
+                            const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio, 
+                                   const gmx_large_int_t *item, int n,
+                                   const char *desc, const char *srcfile, 
+                                   int line);
+gmx_bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n, 
+                            const char *desc, const char *srcfile, int line);
+
+gmx_bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_float(t_fileio *fio, float *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_gmx_bool(t_fileio *fio, gmx_bool *item, int n, 
+                      const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n, 
+                      const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
+                                const char *desc, const char *srcfile, 
+                                int line);
+gmx_bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n, 
+                         const char *desc, const char *srcfile, int line);
+
+
+
+/* convenience macros */
+#define gmx_fio_read_real(fio, item)           gmx_fio_reade_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_float(fio, item)          gmx_fio_reade_float(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_double(fio, item)         gmx_fio_reade_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_int(fio, item)            gmx_fio_reade_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_gmx_large_int(fio, item)  gmx_fio_reade_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_uchar(fio, item)          gmx_fio_reade_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ushort(fio, item)         gmx_fio_reade_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_rvec(fio, item)           gmx_fio_reade_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ivec(fio, item)           gmx_fio_reade_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_string(fio, item)         gmx_fio_reade_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_write_real(fio, item)           gmx_fio_writee_real(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_float(fio, item)          gmx_fio_writee_float(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_double(fio, item)         gmx_fio_writee_double(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_int(fio, item)            gmx_fio_writee_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_gmx_large_int(fio, item)  gmx_fio_writee_gmx_large_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_uchar(fio, item)          gmx_fio_writee_uchar(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ushort(fio, item)         gmx_fio_writee_ushort(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_rvec(fio, item)           gmx_fio_writee_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ivec(fio, item)           gmx_fio_writee_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_string(fio, item)         gmx_fio_writee_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_do_real(fio, item)              gmx_fio_doe_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_float(fio, item)             gmx_fio_doe_float(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_double(fio, item)            gmx_fio_doe_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_gmx_bool(fio, item)              gmx_fio_doe_gmx_bool(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_int(fio, item)               gmx_fio_doe_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_gmx_large_int(fio, item)     gmx_fio_doe_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_uchar(fio, item)             gmx_fio_doe_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ushort(fio, item)            gmx_fio_doe_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_rvec(fio, item)              gmx_fio_doe_rvec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ivec(fio, item)              gmx_fio_doe_ivec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_string(fio, item)            gmx_fio_doe_string(fio, item, (#item), __FILE__, __LINE__)
+
+
+
+
+#define gmx_fio_nread_real(fio, item, n)            gmx_fio_nreade_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_float(fio, item, n)           gmx_fio_nreade_float(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_double(fio, item, n)          gmx_fio_nreade_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_int(fio, item, n)             gmx_fio_nreade_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_gmx_large_int(fio, item, n)   gmx_fio_nreade_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_uchar(fio, item, n)           gmx_fio_nreade_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ushort(fio, item, n)          gmx_fio_nreade_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_rvec(fio, item, n)            gmx_fio_nreade_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ivec(fio, item, n)            gmx_fio_nreade_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_string(fio, item, n)          gmx_fio_nreade_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_nwrite_real(fio, item, n)           gmx_fio_nwritee_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_float(fio, item, n)          gmx_fio_nwritee_float(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_double(fio, item, n)         gmx_fio_nwritee_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_int(fio, item, n)            gmx_fio_nwritee_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_gmx_large_int(fio, item, n)  gmx_fio_nwritee_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_uchar(fio, item, n)          gmx_fio_nwritee_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ushort(fio, item, n)         gmx_fio_nwritee_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_rvec(fio, item, n)           gmx_fio_nwritee_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ivec(fio, item, n)           gmx_fio_nwritee_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_string(fio, item, n)         gmx_fio_nwritee_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_ndo_real(fio, item, n)              gmx_fio_ndoe_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_float(fio, item, n)             gmx_fio_ndoe_float(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_double(fio, item, n)            gmx_fio_ndoe_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_gmx_bool(fio, item, n)              gmx_fio_ndoe_gmx_bool(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_int(fio, item, n)               gmx_fio_ndoe_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_gmx_large_int(fio, item, n)     gmx_fio_ndoe_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_uchar(fio, item, n)             gmx_fio_ndoe_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ushort(fio, item, n)            gmx_fio_ndoe_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_rvec(fio, item, n)              gmx_fio_ndoe_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ivec(fio, item, n)              gmx_fio_ndoe_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_string(fio, item, n)            gmx_fio_ndoe_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/legacyheaders/mdrun.h b/src/gromacs/legacyheaders/mdrun.h
new file mode 100644 (file)
index 0000000..e5bd8e7
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _mdrun_h
+#define _mdrun_h
+
+#include <stdio.h>
+#include <time.h>
+#include "typedefs.h"
+#include "network.h"
+#include "tgroup.h"
+#include "filenm.h"
+#include "mshift.h"
+#include "force.h"
+#include "edsam.h"
+#include "mdebin.h"
+#include "vcm.h"
+#include "vsite.h"
+#include "pull.h"
+#include "update.h"
+#include "membed.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MD_POLARISE       (1<<2)
+#define MD_IONIZE         (1<<3)
+#define MD_RERUN          (1<<4)
+#define MD_RERUN_VSITE    (1<<5)
+#define MD_FFSCAN         (1<<6)
+#define MD_SEPPOT         (1<<7)
+#define MD_PARTDEC        (1<<9)
+#define MD_DDBONDCHECK    (1<<10)
+#define MD_DDBONDCOMM     (1<<11)
+#define MD_CONFOUT        (1<<12)
+#define MD_REPRODUCIBLE   (1<<13)
+#define MD_READ_RNG       (1<<14)
+#define MD_APPENDFILES    (1<<15)
+#define MD_KEEPANDNUMCPT  (1<<16)
+#define MD_READ_EKIN      (1<<17)
+#define MD_STARTFROMCPT   (1<<18)
+#define MD_RESETCOUNTERSHALFWAY (1<<19)
+
+/* Define a number of flags to better control the information
+ * passed to compute_globals in md.c and global_stat.
+ */
+
+/* We are rerunning the simulation */
+#define CGLO_RERUNMD        (1<<1)
+/* we are computing the kinetic energy from average velocities */
+#define CGLO_EKINAVEVEL     (1<<2)
+/* we are removing the center of mass momenta */
+#define CGLO_STOPCM         (1<<3)
+/* bGStat is defined in do_md */
+#define CGLO_GSTAT          (1<<4)
+/* Sum the energy terms in global computation */
+#define CGLO_ENERGY         (1<<6)
+/* Sum the kinetic energy terms in global computation */
+#define CGLO_TEMPERATURE    (1<<7)
+/* Sum the kinetic energy terms in global computation */
+#define CGLO_PRESSURE       (1<<8)
+/* Sum the constraint term in global computation */
+#define CGLO_CONSTRAINT     (1<<9)
+/* we are using an integrator that requires iteration over some steps - currently not used*/
+#define CGLO_ITERATE        (1<<10)
+/* it is the first time we are iterating (or, only once through is required */
+#define CGLO_FIRSTITERATE   (1<<11)
+/* Reading ekin from the trajectory */
+#define CGLO_READEKIN       (1<<12)
+/* we need to reset the ekin rescaling factor here */
+#define CGLO_SCALEEKIN      (1<<13)
+  
+enum {
+  ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
+};
+
+typedef struct {
+  double real;
+#ifdef GMX_CRAY_XT3
+  double proc;
+#else
+  clock_t proc;
+#endif
+  double realtime;
+  double proctime;
+  double time_per_step;
+  double last;
+  gmx_large_int_t nsteps_done;
+} gmx_runtime_t;
+
+typedef struct {
+  t_fileio *fp_trn;
+  t_fileio *fp_xtc;
+  int  xtc_prec;
+  ener_file_t fp_ene;
+  const char *fn_cpt;
+  gmx_bool bKeepAndNumCPT;
+  int  eIntegrator;
+  int  simulation_part;
+  FILE *fp_dhdl;
+  FILE *fp_field;
+} gmx_mdoutf_t;
+
+/* Variables for temporary use with the deform option,
+ * used in runner.c and md.c.
+ * (These variables should be stored in the tpx file.)
+ */
+extern gmx_large_int_t     deform_init_init_step_tpx;
+extern matrix              deform_init_box_tpx;
+#ifdef GMX_THREADS
+extern tMPI_Thread_mutex_t deform_init_box_mutex;
+
+/* The minimum number of atoms per thread. With fewer atoms than this,
+ * the number of threads will get lowered.
+ */
+#define MIN_ATOMS_PER_THREAD    90
+#endif
+
+
+typedef double gmx_integrator_t(FILE *log,t_commrec *cr,
+                               int nfile,const t_filenm fnm[],
+                               const output_env_t oenv, gmx_bool bVerbose,
+                                gmx_bool bCompact, int nstglobalcomm,
+                               gmx_vsite_t *vsite,gmx_constr_t constr,
+                               int stepout,
+                               t_inputrec *inputrec,
+                               gmx_mtop_t *mtop,t_fcdata *fcd,
+                               t_state *state,
+                               t_mdatoms *mdatoms,
+                               t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                               gmx_edsam_t ed, 
+                               t_forcerec *fr,
+                               int repl_ex_nst,int repl_ex_seed,
+                                gmx_membed_t *membed,
+                               real cpt_period,real max_hours,
+                               const char *deviceOptions,
+                               unsigned long Flags,
+                               gmx_runtime_t *runtime);
+
+typedef struct gmx_global_stat *gmx_global_stat_t;
+
+/* ROUTINES from md.c */
+
+gmx_integrator_t do_md;
+
+gmx_integrator_t do_md_openmm;
+
+
+
+/* ROUTINES from minimize.c */
+
+gmx_integrator_t do_steep;
+/* Do steepest descents EM */
+
+gmx_integrator_t do_cg;
+/* Do conjugate gradient EM */
+
+gmx_integrator_t do_lbfgs;
+/* Do conjugate gradient L-BFGS */
+
+gmx_integrator_t do_nm;
+/* Do normal mode analysis */
+
+/* ROUTINES from tpi.c */
+
+gmx_integrator_t do_tpi;
+/* Do test particle insertion */
+
+
+/* ROUTINES from md_support.c */
+
+/* return the number of steps between global communcations */
+int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
+                        int nstglobalcomm,t_inputrec *ir);
+
+/* check whether an 'nst'-style parameter p is a multiple of nst, and
+   set it to be one if not, with a warning. */
+void check_nst_param(FILE *fplog,t_commrec *cr,
+                     const char *desc_nst,int nst,
+                     const char *desc_p,int *p);
+
+/* check which of the multisim simulations has the shortest number of
+   steps and return that number of nsteps */
+gmx_large_int_t get_multisim_nsteps(const t_commrec *cr,
+                                    gmx_large_int_t nsteps);
+
+void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
+                         gmx_bool *bNotLastFrame);
+
+/* get the conserved energy associated with the ensemble type*/
+real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state,           
+                                      t_extmass *MassQ);
+
+/* reset all cycle and time counters. */
+void reset_all_counters(FILE *fplog,t_commrec *cr,
+                        gmx_large_int_t step,
+                        gmx_large_int_t *step_rel,t_inputrec *ir,
+                        gmx_wallcycle_t wcycle,t_nrnb *nrnb,
+                        gmx_runtime_t *runtime);
+
+
+
+/* ROUTINES from sim_util.c */
+void do_pbc_first(FILE *log,matrix box,t_forcerec *fr,
+                        t_graph *graph,rvec x[]);
+
+void do_pbc_first_mtop(FILE *fplog,int ePBC,matrix box,
+                             gmx_mtop_t *mtop,rvec x[]);
+
+void do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
+                       gmx_mtop_t *mtop,rvec x[]);
+
+
+                    
+/* ROUTINES from stat.c */
+gmx_global_stat_t global_stat_init(t_inputrec *ir);
+
+void global_stat_destroy(gmx_global_stat_t gs);
+
+void global_stat(FILE *log,gmx_global_stat_t gs,
+                       t_commrec *cr,gmx_enerdata_t *enerd,
+                       tensor fvir,tensor svir,rvec mu_tot,
+                       t_inputrec *inputrec,
+                       gmx_ekindata_t *ekind,
+                       gmx_constr_t constr,t_vcm *vcm,
+                       int nsig,real *sig,
+                       gmx_mtop_t *top_global, t_state *state_local, 
+                       gmx_bool bSumEkinhOld, int flags);
+/* Communicate statistics over cr->mpi_comm_mysim */
+
+gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],
+                                int mdrun_flags,
+                                const t_commrec *cr,const t_inputrec *ir,
+                                const output_env_t oenv);
+/* Returns a pointer to a data structure with all output file pointers
+ * and names required by mdrun.
+ */
+
+void done_mdoutf(gmx_mdoutf_t *of);
+/* Close all open output files and free the of pointer */
+
+#define MDOF_X   (1<<0)
+#define MDOF_V   (1<<1)
+#define MDOF_F   (1<<2)
+#define MDOF_XTC (1<<3)
+#define MDOF_CPT (1<<4)
+
+void write_traj(FILE *fplog,t_commrec *cr,
+                      gmx_mdoutf_t *of,
+                      int mdof_flags,
+                      gmx_mtop_t *top_global,
+                      gmx_large_int_t step,double t,
+                      t_state *state_local,t_state *state_global,
+                      rvec *f_local,rvec *f_global,
+                      int *n_xtc,rvec **x_xtc);
+/* Routine that writes frames to trn, xtc and/or checkpoint.
+ * What is written is determined by the mdof_flags defined above.
+ * Data is collected to the master node only when necessary.
+ */
+
+int do_per_step(gmx_large_int_t step,gmx_large_int_t nstep);
+/* Return TRUE if io should be done */
+
+int do_any_io(int step, t_inputrec *ir);
+
+/* ROUTINES from sim_util.c */
+
+double gmx_gettime();
+
+void print_time(FILE *out, gmx_runtime_t *runtime,
+                       gmx_large_int_t step,t_inputrec *ir, t_commrec *cr);
+
+void runtime_start(gmx_runtime_t *runtime);
+
+void runtime_end(gmx_runtime_t *runtime);
+
+void runtime_upd_proc(gmx_runtime_t *runtime);
+/* The processor time should be updated every once in a while,
+ * since on 32-bit manchines it loops after 72 minutes.
+ */
+  
+void print_date_and_time(FILE *log,int pid,const char *title,
+                               const gmx_runtime_t *runtime);
+  
+void nstop_cm(FILE *log,t_commrec *cr,
+                    int start,int nr_atoms,real mass[],rvec x[],rvec v[]);
+
+void finish_run(FILE *log,t_commrec *cr,const char *confout,
+                      t_inputrec *inputrec,
+                      t_nrnb nrnb[],gmx_wallcycle_t wcycle,
+                      gmx_runtime_t *runtime,
+                      gmx_bool bWriteStat);
+
+void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr);
+
+void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
+                         gmx_large_int_t step, int natoms, 
+                         matrix box,real lambda,tensor pres,tensor virial,
+                         real *prescorr, real *enercorr, real *dvdlcorr);
+
+typedef enum
+{
+  LIST_SCALARS =0001,
+  LIST_INPUTREC        =0002,
+  LIST_TOP     =0004,
+  LIST_X       =0010,
+  LIST_V       =0020,
+  LIST_F       =0040,
+  LIST_LOAD    =0100
+} t_listitem;
+
+void check_nnodes_top(char *fn,t_topology *top);
+/* Reset the tpr file to work with one node if necessary */
+
+
+/* check the version */
+void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
+                               t_inputrec *ir,gmx_mtop_t *mtop);
+
+/* Allocate and initialize node-local state entries. */
+void set_state_entries(t_state *state,const t_inputrec *ir,int nnodes);
+
+/* Broadcast the data for a simulation, and allocate node-specific settings
+   such as rng generators. */
+void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
+                          gmx_mtop_t *mtop);
+
+
+void do_constrain_first(FILE *log,gmx_constr_t constr,
+                              t_inputrec *inputrec,t_mdatoms *md,
+                              t_state *state,rvec *f,
+                              t_graph *graph,t_commrec *cr,t_nrnb *nrnb,
+                              t_forcerec *fr, gmx_localtop_t *top, tensor shake_vir); 
+                         
+void dynamic_load_balancing(gmx_bool bVerbose,t_commrec *cr,real capacity[],
+                                  int dimension,t_mdatoms *md,t_topology *top,
+                                  rvec x[],rvec v[],matrix box);
+/* Perform load balancing, i.e. split the particles over processors
+ * based on their coordinates in the "dimension" direction.
+ */
+
+int multisim_min(const gmx_multisim_t *ms,int nmin,int n);
+/* Set an appropriate value for n across the whole multi-simulation */
+
+int multisim_nstsimsync(const t_commrec *cr,
+                       const t_inputrec *ir,int repl_ex_nst);
+/* Determine the interval for inter-simulation communication */
+                                  
+void init_global_signals(globsig_t *gs,const t_commrec *cr,
+                        const t_inputrec *ir,int repl_ex_nst);
+/* Constructor for globsig_t */
+
+void copy_coupling_state(t_state *statea,t_state *stateb,
+                        gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts);
+/* Copy stuff from state A to state B */
+
+void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir,
+                    t_forcerec *fr, gmx_ekindata_t *ekind,
+                    t_state *state, t_state *state_global, t_mdatoms *mdatoms,
+                    t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
+                    gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir,
+                    tensor pres, rvec mu_tot, gmx_constr_t constr,
+                    globsig_t *gs,gmx_bool bInterSimGS,
+                    matrix box, gmx_mtop_t *top_global, real *pcurr,
+                    int natoms, gmx_bool *bSumEkinhOld, int flags);
+/* Compute global variables during integration */
+
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+             const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
+             gmx_bool bCompact, int nstglobalcomm, ivec ddxyz,int dd_node_order,
+             real rdd, real rconstr, const char *dddlb_opt,real dlb_scale,
+            const char *ddcsx,const char *ddcsy,const char *ddcsz,
+            int nstepout, int resetstep, int nmultisim, int repl_ex_nst,
+             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
+            const char *deviceOptions, unsigned long Flags);
+/* Driver routine, that calls the different methods */
+
+void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf);
+/* Print a warning message to stderr on the master node
+ * and to fplog if fplog!=NULL.
+ */
+
+void init_md(FILE *fplog,
+                   t_commrec *cr,t_inputrec *ir, const output_env_t oenv, 
+                   double *t,double *t0,
+                   real *lambda,double *lam0,
+                   t_nrnb *nrnb,gmx_mtop_t *mtop,
+                   gmx_update_t *upd,
+                   int nfile,const t_filenm fnm[],
+                   gmx_mdoutf_t **outf,t_mdebin **mdebin,
+                   tensor force_vir,tensor shake_vir,
+                   rvec mu_tot,
+                   gmx_bool *bSimAnn,t_vcm **vcm, 
+                   t_state *state, unsigned long Flags);
+  /* Routine in sim_util.c */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _mdrun_h */
diff --git a/src/gromacs/legacyheaders/membed.h b/src/gromacs/legacyheaders/membed.h
new file mode 100644 (file)
index 0000000..e22362a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _gmx_membed_h
+#define _gmx_membed_h
+
+#include "typedefs.h"
+
+/* information about scaling center */
+typedef struct {
+       rvec    xmin;
+       rvec    xmax;
+       rvec    *geom_cent;
+       int    pieces;
+       int    *nidx;
+       atom_id **subindex;
+} pos_ins_t;
+
+/* variables needed in do_md */
+typedef struct {
+  int   it_xy;
+  int   it_z;
+  real  xy_step;
+  real  z_step;
+  rvec  fac;           /* scaling factor */
+  rvec  *r_ins;                /* target coordinates */
+  pos_ins_t *pos_ins;
+} gmx_membed_t;
+
+/* initialisation of membed code */
+extern void init_membed(FILE *fplog, gmx_membed_t *membed, int nfile, const t_filenm fnm[], 
+                       gmx_mtop_t *mtop, t_inputrec *inputrec, t_state *state, t_commrec *cr,
+                       real *cpt);
+
+/* rescaling the coordinates voor de membed code */
+extern void rescale_membed(int step_rel, gmx_membed_t *membed, rvec *x);
+#endif
diff --git a/src/gromacs/legacyheaders/names.h b/src/gromacs/legacyheaders/names.h
new file mode 100644 (file)
index 0000000..bd00ec5
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _names_h
+#define _names_h
+
+
+#include "typedefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All string arrays are NULL terminated, and therefore have an
+ * extra argument (the +1)
+ * these should correspond to names.c and include/types/enums.h
+ */
+extern const char *epbc_names[epbcNR+1];
+extern const char *etcoupl_names[etcNR+1];
+extern const char *epcoupl_names[epcNR+1];
+extern const char *epcoupltype_names[epctNR+1];
+extern const char *erefscaling_names[erscNR+1];
+extern const char *ens_names[ensNR+1];
+extern const char *ei_names[eiNR+1];
+extern const char *yesno_names[BOOL_NR+1];
+extern const char *bool_names[BOOL_NR+1];
+extern const char *eel_names[eelNR+1];
+extern const char *eewg_names[eewgNR+1];
+extern const char *evdw_names[evdwNR+1];
+extern const char *econstr_names[econtNR+1];
+extern const char *ptype_str[eptNR+1];
+extern const char *egrp_nm[egNR+1];
+extern const char *edisre_names[edrNR+1];
+extern const char *edisreweighting_names[edrwNR+1];
+extern const char *enbf_names[eNBF_NR+1];
+extern const char *ecomb_names[eCOMB_NR+1];
+extern const char *gtypes[egcNR+1];
+extern const char *efep_names[efepNR+1];
+extern const char *separate_dhdl_file_names[efepNR+1];
+extern const char *dhdl_derivatives_names[efepNR+1];
+extern const char *efep_names[efepNR+1];
+extern const char *esol_names[esolNR+1];
+extern const char *enlist_names[enlistNR+1];
+extern const char *edispc_names[edispcNR+1];
+extern const char *ecm_names[ecmNR+1];
+extern const char *eann_names[eannNR+1];
+extern const char *egb_names[egbNR+1];
+extern const char *eis_names[eisNR+1];
+extern const char *esa_names[esaNR+1];
+extern const char *ewt_names[ewtNR+1];
+extern const char *epull_names[epullNR+1];
+extern const char *epullg_names[epullgNR+1];
+extern const char *erotg_names[erotgNR+1];
+extern const char *erotg_originnames[erotgNR+1];
+extern const char *erotg_fitnames[erotgFitNR+1];
+extern const char *eQMmethod_names[eQMmethodNR+1];
+extern const char *eQMbasis_names[eQMbasisNR+1];
+extern const char *eQMMMscheme_names[eQMMMschemeNR+1];
+extern const char *eMultentOpt_names[eMultentOptNR+1];
+
+#define        UNDEFINED               "UNDEFINED"
+#define ENUM_NAME(e,max,names) ((((e)<0)||((e)>=(max)))?UNDEFINED:(names)[e])
+
+#define BOOL(e)        ENUM_NAME(e,BOOL_NR,bool_names)
+#define ENS(e)         ENUM_NAME(e,ensNR,ens_names)
+#define EI(e)          ENUM_NAME(e,eiNR,ei_names)
+#define EPBC(e)        ENUM_NAME(e,epbcNR,epbc_names)
+#define ETCOUPLTYPE(e) ENUM_NAME(e,etcNR,etcoupl_names)
+#define EPCOUPLTYPE(e) ENUM_NAME(e,epcNR,epcoupl_names)
+#define EPCOUPLTYPETYPE(e) ENUM_NAME(e,epctNR,epcoupltype_names)
+#define EREFSCALINGTYPE(e) ENUM_NAME(e,erscNR,erefscaling_names)
+#define EBLOCKS(e)     ENUM_NAME(e,ebNR,eblock_names)
+#define EPARAM(e)      ENUM_NAME(e,epNR,eparam_names)
+#define EELTYPE(e)     ENUM_NAME(e,eelNR,eel_names)
+#define EVDWTYPE(e)    ENUM_NAME(e,evdwNR,evdw_names)
+#define ECONSTRTYPE(e) ENUM_NAME(e,econtNR,econstr_names)
+#define EDISRETYPE(e)  ENUM_NAME(e,edrNR,edisre_names)
+#define EDISREWEIGHTING(e)  ENUM_NAME(e,edrwNR,edisreweighting_names)
+#define ENBFNAME(e)    ENUM_NAME(e,eNBF_NR,enbf_names)
+#define ECOMBNAME(e)   ENUM_NAME(e,eCOMB_NR,ecomb_names)
+#define EFEPTYPE(e)    ENUM_NAME(e,efepNR,efep_names)
+#define SEPDHDLFILETYPE(e) ENUM_NAME(e,sepdhdlfileNR,separate_dhdl_file_names)
+#define DHDLDERIVATIVESTYPE(e) ENUM_NAME(e,dhdlderivativesNR,dhdl_derivatives_names)
+#define ESOLTYPE(e)    ENUM_NAME(e,esolNR,esol_names)
+#define ENLISTTYPE(e)  ENUM_NAME(e,enlistNR,enlist_names)
+#define EDISPCORR(e)   ENUM_NAME(e,edispcNR,edispc_names)
+#define ECOM(e)        ENUM_NAME(e,ecmNR,ecm_names)
+#define EANNEAL(e)      ENUM_NAME(e,eannNR,eann_names)
+#define EGBALGORITHM(e) ENUM_NAME(e,egbNR,egb_names)
+#define ESAALGORITHM(e) ENUM_NAME(e,esaNR,esa_names)
+#define EIMPLICITSOL(e) ENUM_NAME(e,eisNR,eis_names)
+#define EWALLTYPE(e)   ENUM_NAME(e,ewtNR,ewt_names)
+#define EPULLTYPE(e)   ENUM_NAME(e,epullNR,epull_names)
+#define EPULLGEOM(e)   ENUM_NAME(e,epullgNR,epullg_names)
+#define EROTGEOM(e)    ENUM_NAME(e,erotgNR,erotg_names)
+#define EROTORIGIN(e)  ENUM_NAME(e,erotgOriginNR,erotg_originnames)
+#define EROTFIT(e)     ENUM_NAME(e,erotgFitNR,erotg_fitnames)
+#define EQMMETHOD(e)   ENUM_NAME(e,eQMmethodNR,eQMmethod_names)
+#define EQMBASIS(e)    ENUM_NAME(e,eQMbasisNR,eQMbasis_names)
+#define EQMMMSCHEME(e) ENUM_NAME(e,eQMMMschemeNR,eQMMMscheme_names)
+#define EMULTENTOPT(e) ENUM_NAME(e,eMultentOptNR,eMultentOpt_names)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _names_h */
similarity index 100%
rename from include/ns.h
rename to src/gromacs/legacyheaders/ns.h
diff --git a/src/gromacs/legacyheaders/physics.h b/src/gromacs/legacyheaders/physics.h
new file mode 100644 (file)
index 0000000..941fc7e
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _physics_h
+#define _physics_h
+
+/*
+ * Physical constants to be used in Gromacs.
+ * No constants (apart from 0, 1 or 2) should
+ * be anywhere else in the code.
+ */
+
+#include <math.h>
+
+/* we do it anyway. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef M_PI
+#ifdef _PI
+#define M_PI _PI
+#else
+#define M_PI        3.14159265358979323846
+#endif
+#endif
+
+#define ANGSTROM        (1e-10)                /* Old...       */
+#define KILO            (1e3)                  /* Thousand     */
+#define NANO            (1e-9)                 /* A Number     */
+#define PICO            (1e-12)                /* A Number     */
+#define A2NM            (ANGSTROM/NANO)        /* NANO         */
+#define NM2A            (NANO/ANGSTROM)        /* 10.0         */
+#define RAD2DEG                 (180.0/M_PI)           /* Conversion   */
+#define DEG2RAD                 (M_PI/180.0)           /* id           */
+#define CAL2JOULE       (4.184)                /* id           */
+#define E_CHARGE         (1.60217733e-19)      /* Coulomb      */
+
+#define AMU              (1.6605402e-27)        /* kg           */
+#define BOLTZMANN       (1.380658e-23)         /* (J/K)        */
+#define AVOGADRO        (6.0221367e23)         /* ()           */
+#define RGAS             (BOLTZMANN*AVOGADRO)   /* (J/(mol K))  */
+#define BOLTZ            (RGAS/KILO)            /* (kJ/(mol K)) */
+#define FARADAY          (E_CHARGE*AVOGADRO)    /* (C/mol)      */
+#define ELECTRONVOLT     (E_CHARGE*AVOGADRO/KILO) /* (kJ/mol)   */     
+#define PLANCK1          (6.6262e-34)           /* J s */
+#define PLANCK           (6.6262e-34*AVOGADRO/(PICO*KILO)) /* (kJ/mol) ps */
+
+#define EPSILON0        (5.72765E-4)           /* (e^2 / Na (kJ nm))     
+                                                  == (e^2 mol/(kJ nm)) */
+                                                
+#define SPEED_OF_LIGHT   (2.9979245800E05)      /* nm/ps                */
+#define ATOMICMASS_keV   (940000.0)             /* Atomic mass in keV   */
+#define ELECTRONMASS_keV (512.0)                /* Electron mas in keV  */
+
+/* Improved accuracy (PL & EL, 20090421) */
+#define FACEL           (332.0636930*CAL2JOULE)/* (10 * (ONE_4PI_EPS0)) */
+#define ONE_4PI_EPS0    (FACEL*0.1)            /* 1/(4*pi*e0)*/
+#define PRESFAC           (16.6054)             /* bar / pressure unity */
+#define ENM2DEBYE         48.0321               /* Convert electron nm  *
+                                                * to debye             */
+#define DEBYE2ENM         0.02081941
+/* to convert from a acceleration in (e V)/(amu nm) */
+/* FIELDFAC is also Faraday's constant and E_CHARGE/(1e6 AMU) */
+#define FIELDFAC          (FARADAY/KILO)
+
+/* to convert AU to MD units: */
+#define HARTREE2KJ        4.3597482e-21
+#define BOHR2NM           0.0529177249
+#define HARTREE_BOHR2MD   (HARTREE2KJ*AVOGADRO/BOHR2NM)
+
+
+/* The four basic units */
+#define unit_length   "nm"
+#define unit_time     "ps"
+#define unit_mass     "u"
+#define unit_energy   "kJ/mol"
+
+/* Temperature unit, T in this unit times BOLTZ give energy in unit_energy */
+#define unit_temp_K   "K"
+
+/* Charge unit, electron charge, involves ONE_4PI_EPS0 */
+#define unit_charge_e "e"
+
+/* Pressure unit, pressure in basic units times PRESFAC gives this unit */
+#define unit_pres_bar "bar"
+
+/* Dipole unit, debye, conversion from the unit_charge_e involves ENM2DEBYE */
+#define unit_dipole_D "D"
+
+/* Derived units from basic units only */
+#define unit_vel      unit_length "/" unit_time
+#define unit_volume   unit_length "^3"
+#define unit_invtime  "1/" unit_time
+
+/* Other derived units */
+#define unit_surft_bar unit_pres_bar " " unit_length
+
+/* SI units, conversion from basic units involves NANO, PICO and AMU */
+#define unit_length_SI  "m"
+#define unit_time_SI    "s"
+#define unit_mass_SI    "kg"
+
+#define unit_density_SI unit_mass_SI "/" unit_length_SI "^3"
+#define unit_invvisc_SI unit_length_SI " " unit_time_SI "/" unit_mass_SI
+
+  /* The routines below can be used for converting units from or to GROMACS
+     internal units. */
+  enum { eg2cAngstrom, eg2cNm, eg2cBohr, eg2cKcal_Mole, 
+        eg2cHartree, eg2cHartree_e, eg2cAngstrom3, eg2cCoulomb,
+        eg2cDebye, eg2cElectron, eg2cBuckingham, eg2cNR };
+  
+  /* Convert value x to GROMACS units. Energy -> Energy, Length -> Length etc. 
+     The type of x is deduced from unit, 
+     which should be taken from the enum above. */
+  extern double convert2gmx(double x,int unit);
+  
+  /* Convert value x from GROMACS units to the desired one. 
+     The type of return value is deduced from unit, see above */
+  extern double gmx2convert(double x,int unit);
+
+  /* Convert the string to one of the units supported. Returns -1 if not found. */
+  extern int string2unit(char *string);
+  
+  /* Convert the unit to a strong. Return NULL when unit is out of range. */
+  extern const char *unit2string(int unit);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _physics_h */
+
+
diff --git a/src/gromacs/legacyheaders/pull_rotation.h b/src/gromacs/legacyheaders/pull_rotation.h
new file mode 100644 (file)
index 0000000..8de318e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+/*! \file pull_rotation.h
+ *
+ *  @brief Enforced rotation of protein parts or other groups of particles.
+ *
+ *  This file contains routines that are used to enforce rotational motion
+ *  upon a subgroup of particles.  
+ *  
+ */
+
+#ifndef _pull_rotation_h
+#define _pull_rotation_h
+
+#ifdef HAVE_CONFIG_H
+  #include <config.h>
+#endif
+
+#include "vec.h"
+#include "typedefs.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*! \brief Initialize the enforced rotation groups.
+ * 
+ * This routine does the memory allocation for various helper arrays, opens
+ * the output files etc.  
+ *
+ * \param fplog             General output file, normally md.log.
+ * \param ir                Struct containing MD input parameters, among those
+ *                          also the enforced rotation parameters.
+ * \param nfile             Number of entries in the fnm structure.       
+ * \param fnm               The filenames struct containing also the names
+ *                          of the rotation output files.
+ * \param cr                Pointer to MPI communication data.
+ * \param x                 The positions of all MD particles.
+ * \param mtop              Molecular topology.
+ * \param oenv              Needed to open the rotation output xvgr file.
+ * \param Flags             Flags passed over from main, used to determine
+ *                          whether or not we are doing a rerun.
+ */
+extern void init_rot(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
+        t_commrec *cr, rvec *x, matrix box, gmx_mtop_t *mtop, const output_env_t oenv,
+        gmx_bool bVerbose, unsigned long Flags);
+
+
+/*! \brief Make a selection of the home atoms for all enforced rotation groups.
+ *
+ * This routine is similar to dd_make_local_pull_groups, but works only with
+ * domain decomposition. It should be called at every domain decomposition.
+ *
+ * \param dd                Structure containing domain decomposition data.
+ * \param rot               Pointer to all the enforced rotation data.
+ */
+extern void dd_make_local_rotation_groups(gmx_domdec_t *dd,t_rot *rot);
+
+
+/*! \brief Calculation of the enforced rotation potential.
+ * 
+ * This is the main enforced rotation module which is called during every time
+ * step. Here the rotation potential as well as the resulting forces are 
+ * calculated.
+ * 
+ * \param cr                Pointer to MPI communication data.
+ * \param ir                Struct containing MD input parameters, among those
+ * \param box               Simulation box, needed to make group whole.
+ * \param x                 The positions of all the local particles.
+ * \param t                 Time.
+ * \param step              The time step.
+ * \param wcycle            During the potential calculation the wallcycles are
+ *                          counted. Later they enter the dynamic load balancing.
+ * \param bNS               After domain decomposition / neighborsearching several
+ *                          local arrays have to be updated (masses, shifts)
+ */
+extern void do_rotation(t_commrec *cr,t_inputrec *ir,matrix box,rvec x[],real t,
+        gmx_large_int_t step,gmx_wallcycle_t wcycle,gmx_bool bNS);
+
+
+/*! \brief Add the enforced rotation forces to the official force array.
+ * 
+ * Adds the forces from enforced rotation potential to the local forces and
+ * sums up the contributions to the rotation potential from all the nodes. Since
+ * this needs communication, this routine should be called after the SR forces 
+ * have been evaluated (in order not to spoil cycle counts). 
+ * This routine also outputs data to the various rotation output files (e.g.
+ * the potential, the angle of the group, torques and more).
+ * 
+ * \param rot               Pointer to all the enforced rotation data.
+ * \param f                 The local forces to which the rotational forces have
+ *                          to be added.
+ * \param cr                Pointer to MPI communication data.
+ * \param step              The time step, used for output.
+ * \param t                 Time, used for output.
+ */
+extern real add_rot_forces(t_rot *rot, rvec f[], t_commrec *cr, gmx_large_int_t step, real t);
+
+
+/*! \brief Close the enforced rotation output files.
+ *
+ * \param fplog             General output file, normally md.log.
+ * \param rot               Pointer to all the enforced rotation data.
+ */
+extern void finish_rot(FILE *fplog,t_rot *rot);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gromacs/legacyheaders/string2.h b/src/gromacs/legacyheaders/string2.h
new file mode 100644 (file)
index 0000000..3d46655
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+/*! \file
+ * \brief Generic string handling functions.
+ */
+#ifndef _string2_h
+#define _string2_h
+
+/*
+ *
+ * string2.h
+ * David van der Spoel
+ *
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+
+/*#include "typedefs.h"*/
+#include "types/simple.h"
+
+/* Suppress Cygwin compiler warnings from using newlib version of
+ * ctype.h */
+#ifdef GMX_CYGWIN
+#undef isdigit
+#undef isstring
+#undef isspace
+#undef isalnum
+#undef isalpha
+#undef ispunct
+#undef isxdigit
+#undef isupper
+#undef islower
+#undef toupper
+#undef tolower
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CONTINUE    '\\'
+#define COMMENTSIGN ';'
+
+int continuing(char *s);
+
+char *fgets2(char *s, int n, FILE *stream);
+
+void strip_comment (char *line);
+
+int break_line (char *line,
+                      char *variable,
+                      char *value);
+
+void upstring (char *str);
+
+void ltrim (char *str);
+
+void rtrim (char *str);
+
+void trim (char *str);
+
+void nice_header (FILE *out,const char *fn);
+
+int gmx_strcasecmp_min(const char *str1, const char *str2);
+int gmx_strncasecmp_min(const char *str1, const char *str2, int n);
+/* This funny version of strcasecmp, is not only case-insensitive,
+ * but also ignores '-' and '_'.
+ */
+
+int gmx_strcasecmp(const char *str1, const char *str2);
+int gmx_strncasecmp(const char *str1, const char *str2, int n);
+
+char *gmx_strdup(const char *src);
+char *gmx_strndup(const char *src, int n);
+    
+/** Pattern matcing with wildcards. */
+int gmx_wcmatch(const char *pattern, const char *src);
+
+/** Return value for gmx_wcmatch() when there is no match. */
+#define GMX_NO_WCMATCH 1
+
+
+/* this is our implementation of strsep, the thread-safe replacement for
+   strtok */
+char *gmx_strsep(char **stringp, const char *delim);
+
+
+char *wrap_lines(const char *buf,int line_width, int indent,
+                       gmx_bool bIndentFirst);
+/* wraps lines at 'linewidth', indenting all following
+ * lines by 'indent' spaces. A temp buffer is allocated and returned,
+ * which can be disposed of if no longer needed.
+ * If !bIndentFirst, then the first line will not be indented, only 
+ * the lines that are created due to wapping.
+ */
+
+
+char **split(char sep,const char *str);
+/* Implementation of the well-known Perl function split */
+
+gmx_large_int_t str_to_large_int_t(const char *str, char **endptr);
+
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+#define snprintf _snprintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _string2_h */
diff --git a/src/gromacs/legacyheaders/thread_mpi/atomic/gcc_x86.h b/src/gromacs/legacyheaders/thread_mpi/atomic/gcc_x86.h
new file mode 100644 (file)
index 0000000..f912424
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+This source code file is part of thread_mpi.  
+Written by Sander Pronk, Erik Lindahl, and possibly others. 
+
+Copyright (c) 2009, Sander Pronk, Erik Lindahl.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1) Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2) Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3) Neither the name of the copyright holders nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you want to redistribute modifications, please consider that
+scientific software is very special. Version control is crucial -
+bugs must be traceable. We will be happy to consider code for
+inclusion in the official distribution, but derived work should not
+be called official thread_mpi. Details are found in the README & COPYING
+files.
+*/
+
+
+
+#include <limits.h>
+#include <stdint.h>
+/* This code is executed for x86 and x86-64, with these compilers:
+ * GNU
+ * Intel 
+ * Pathscale
+ * All these support GCC-style inline assembly. 
+ * We also use this section for the documentation.
+ */
+
+
+#if 0
+/* Only gcc and Intel support this check, otherwise set it to true (skip doc) */
+#if (!defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined DOXYGEN)
+#define __builtin_constant_p(i) (1)
+#endif
+#endif
+
+/* we put all of these on their own cache line by specifying an alignment: */
+typedef struct tMPI_Atomic
+{
+    int value __attribute__ ((aligned(64))); 
+} tMPI_Atomic_t;
+
+typedef struct tMPI_Atomic_ptr
+{
+    void* value __attribute__ ((aligned(64)));   
+} tMPI_Atomic_ptr_t;
+
+typedef struct tMPI_Spinlock
+{
+    unsigned int lock __attribute__ ((aligned(64)));
+} tMPI_Spinlock_t;
+
+
+#define TMPI_SPINLOCK_INITIALIZER   { 0 }
+
+
+
+/* these are guaranteed to be  atomic on x86 and x86_64 */
+#define tMPI_Atomic_get(a)  ((a)->value) 
+#define tMPI_Atomic_set(a,i)  (((a)->value) = (i))
+
+#define tMPI_Atomic_ptr_get(a)  ((a)->value) 
+#define tMPI_Atomic_ptr_set(a,i)  (((a)->value) = (void*)(i))
+
+
+/* do the intrinsics. 
+   
+   We disable this for 32-bit builds because the target may be 80386, 
+   which didn't have cmpxchg, etc (they were introduced as only as 'recently' 
+   as the 486, and gcc on some Linux versions still target 80386 by default). 
+  
+   We also specifically check for icc, because intrinsics are not always
+   supported there. */
+#if ( (TMPI_GCC_VERSION >= 40100) && defined(__x86_64__) &&  \
+     !defined(__INTEL_COMPILER) ) 
+#include "gcc_intrinsics.h"
+
+#else
+/* older versions of gcc don't support atomic intrinsics */
+
+
+#define tMPI_Atomic_memory_barrier() __asm__ __volatile__("sfence;": : :"memory")
+static inline int tMPI_Atomic_add_return(tMPI_Atomic_t *a, int i)
+{
+    int __i;
+    
+    __i = i;
+    __asm__ __volatile__("lock ; xaddl %0, %1;"
+                         :"=r"(i) :"m"(a->value), "0"(i) : "memory");
+    return i + __i;
+}  
+
+static inline int tMPI_Atomic_fetch_add(tMPI_Atomic_t *a, int i)
+{
+    __asm__ __volatile__("lock ; xaddl %0, %1;"
+                         :"=r"(i) :"m"(a->value), "0"(i) : "memory");
+    return i;
+}
+
+static inline int tMPI_Atomic_cas(tMPI_Atomic_t *a, int oldval, int newval)
+{
+    int prev;
+    
+    __asm__ __volatile__("lock ; cmpxchgl %1,%2"
+                         : "=a"(prev)
+                         : "q"(newval), "m"(a->value), "0"(oldval)
+                         : "memory");
+    
+    return prev==oldval;
+}
+
+static inline int tMPI_Atomic_ptr_cas(tMPI_Atomic_ptr_t *a, 
+                                      void *oldval,
+                                      void *newval)
+{
+    void* prev;
+#ifndef __x86_64__ 
+    __asm__ __volatile__("lock ; cmpxchgl %1,%2"
+                         : "=a"(prev)
+                         : "q"(newval), "m"(a->value), "0"(oldval)
+                         : "memory");
+#else 
+    __asm__ __volatile__("lock ; cmpxchgq %1,%2"
+                         : "=a"(prev)
+                         : "q"(newval), "m"(a->value), "0"(oldval)
+                         : "memory");
+#endif
+    return prev==oldval;
+}
+
+#endif /* end of check for gcc intrinsics */
+
+#define TMPI_HAVE_SWAP
+/* do the swap fns; we told the intrinsics that we have them. */
+static inline int tMPI_Atomic_swap(tMPI_Atomic_t *a, int b)
+{
+    volatile int ret=b;
+    __asm__ __volatile__("\txchgl %0, %1;" 
+                         :"=r"(ret)
+                         :"m"(a->value), "0"(ret)
+                         :"memory");
+    return (int)ret;
+}
+
+static inline void *tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
+{
+    void *volatile *ret=(void* volatile*)b;
+#ifndef __x86_64__ 
+/*    __asm__ __volatile__("\txchgl %0, %1;" 
+                         :"=m"(a->value),"=q"(b) 
+                         :"q"(b)
+                         :"memory");
+*/
+    __asm__ __volatile__("\txchgl %0, %1;" 
+                         :"=r"(ret)
+                         :"m"(a->value), "0"(ret)
+                         :"memory");
+
+#else
+    __asm__ __volatile__("\txchgq %0, %1;" 
+                         :"=r"(ret)
+                         :"m"(a->value), "0"(ret)
+                         :"memory");
+#endif
+    return (void*)ret;
+}
+
+
+
+/* spinlocks : */
+
+static inline void tMPI_Spinlock_init(tMPI_Spinlock_t *x)
+{
+    x->lock = 0;
+}
+
+
+
+static inline void tMPI_Spinlock_lock(tMPI_Spinlock_t *x)
+{
+    /* this is a spinlock with a double loop, as recommended by Intel
+       it pauses in the outer loop (the one that just checks for the 
+       availability of the lock), and thereby reduces bus contention and
+       prevents the pipeline from flushing. */
+    __asm__ __volatile__("1:\tcmpl $0, %0\n"      /* check the lock */
+                         "\tje 2f\n"              /* try to lock if it is
+                                                     free by jumping forward */
+                         "\tpause\n"              /* otherwise: small pause
+                                                     as recommended by Intel */
+                         "\tjmp 1b\n"             /* and jump back */  
+
+                         "2:\tmovl $1, %%eax\n"   /* set eax to 1, the locked
+                                                     value of the lock */
+                         "\txchgl %%eax, %0\n"    /* atomically exchange 
+                                                     eax with the lock value */
+                         "\tcmpl $0, %%eax\n"     /* compare the exchanged
+                                                     value with 0 */
+                         "\tjne 1b"               /* jump backward if we didn't
+                                                     just lock */
+                         : "=m" (x->lock)         /* input & output var */
+                         : 
+                         : "%eax", "memory"/* we changed memory */
+                        );
+}
+
+
+
+static inline void tMPI_Spinlock_unlock(tMPI_Spinlock_t *  x)
+{
+    /* this is apparently all that is needed for unlocking a lock */
+    __asm__ __volatile__(
+                     "\n\tmovl $0, %0\n"
+                     : "=m"(x->lock) : : "memory" );
+}
+
+
+
+static inline int tMPI_Spinlock_trylock(tMPI_Spinlock_t *x)
+{
+    int old_value;
+        
+    __asm__ __volatile__("\tmovl $1, %0\n"     /* set eax to 1, the locked
+                                                  value of the lock */
+                         "\txchgl %0, %1\n"    /* atomically exchange 
+                                                  eax with the address in
+                                                  rdx. */
+                         :"=r" (old_value), "=m" (x->lock)
+                         : : "memory");
+    return (old_value);
+}
+
+
+static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
+{
+    return ( (*((volatile int*)(&(x->lock)))) != 0);
+}
+
+
+static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
+{
+    /* this is the spinlock without the xchg.  */
+    __asm__ __volatile__("1:\tcmpl $0, %0\n"      /* check the lock */
+                         "\tje 2f\n"              /* try to lock if it is
+                                                     free by jumping forward */
+                         "\tpause\n"              /* otherwise: small pause
+                                                     as recommended by Intel */
+                         "\tjmp 1b\n"             /* and jump back */  
+                         "2:\tnop\n"              /* jump target for end 
+                                                     of wait */
+                         : "=m"(x->lock)         /* input & output var */
+                         : 
+                         : "memory"/* we changed memory */
+                        );
+#if 0
+    do 
+    {
+        tMPI_Atomic_memory_barrier(); 
+    } 
+    while(tMPI_Spinlock_islocked(x));
+#endif
+}
+
diff --git a/src/gromacs/legacyheaders/types/enums.h b/src/gromacs/legacyheaders/types/enums.h
new file mode 100644 (file)
index 0000000..a7b9227
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GRoups of Organic Molecules in ACtion for Science
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* note: these enums should correspond to the names in gmxlib/names.c */
+
+enum {
+  epbcXYZ, epbcNONE, epbcXY, epbcSCREW, epbcNR
+};
+
+enum {
+  etcNO, etcBERENDSEN, etcNOSEHOOVER, etcYES, etcANDERSEN, etcANDERSENINTERVAL, etcVRESCALE, etcNR
+}; /* yes is an alias for berendsen */
+
+enum {
+  epcNO, epcBERENDSEN, epcPARRINELLORAHMAN, epcISOTROPIC, epcMTTK, epcNR
+}; /* isotropic is an alias for berendsen */
+
+/* trotter decomposition extended variable parts */
+enum {
+  etrtNONE, etrtNHC, etrtBAROV, etrtBARONHC, etrtNHC2, etrtBAROV2, etrtBARONHC2, 
+  etrtVELOCITY1, etrtVELOCITY2, etrtPOSITION, etrtSKIPALL, etrtNR
+};
+
+/* sequenced parts of the trotter decomposition */
+enum {
+  ettTSEQ0,  ettTSEQ1,  ettTSEQ2,  ettTSEQ3,  ettTSEQ4, ettTSEQMAX
+};
+
+enum {
+  epctISOTROPIC, epctSEMIISOTROPIC, epctANISOTROPIC,
+  epctSURFACETENSION, epctNR
+};
+
+enum {
+  erscNO, erscALL, erscCOM, erscNR
+};
+
+/*
+ * eelNOTUSED1 used to be GB, but to enable generalized born with different
+ * forms of electrostatics (RF, switch, etc.) in the future it is now selected
+ * separately (through the implicit_solvent option).
+ */
+enum {
+  eelCUT,     eelRF,     eelGRF,   eelPME,  eelEWALD,  eelPPPM, 
+  eelPOISSON, eelSWITCH, eelSHIFT, eelUSER, eelGB_NOTUSED, eelRF_NEC, eelENCADSHIFT, 
+  eelPMEUSER, eelPMESWITCH, eelPMEUSERSWITCH, eelRF_ZERO, eelNR
+};
+
+/* Ewald geometry */
+enum { 
+  eewg3D, eewg3DC, eewgNR
+};
+
+#define EEL_RF(e) ((e) == eelRF || (e) == eelGRF || (e) == eelRF_NEC || (e) == eelRF_ZERO )
+
+#define EEL_PME(e)  ((e) == eelPME || (e) == eelPMESWITCH || (e) == eelPMEUSER || (e) == eelPMEUSERSWITCH)
+#define EEL_FULL(e) (EEL_PME(e) || (e) == eelPPPM || (e) == eelPOISSON || (e) == eelEWALD)
+
+#define EEL_SWITCHED(e) ((e) == eelSWITCH || (e) == eelSHIFT || (e) == eelENCADSHIFT || (e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
+
+#define EEL_IS_ZERO_AT_CUTOFF(e) (EEL_SWITCHED(e) || (e) == eelRF_ZERO)
+
+#define EEL_MIGHT_BE_ZERO_AT_CUTOFF(e) (EEL_IS_ZERO_AT_CUTOFF(e) || (e) == eelUSER || (e) == eelPMEUSER)
+
+enum {
+  evdwCUT, evdwSWITCH, evdwSHIFT, evdwUSER, evdwENCADSHIFT, evdwNR
+};
+
+#define EVDW_SWITCHED(e) ((e) == evdwSWITCH || (e) == evdwSHIFT || (e) == evdwENCADSHIFT)
+
+#define EVDW_IS_ZERO_AT_CUTOFF(e) EVDW_SWITCHED(e)
+
+#define EVDW_MIGHT_BE_ZERO_AT_CUTOFF(e) (EVDW_IS_ZERO_AT_CUTOFF(e) || (e) == evdwUSER)
+
+enum { 
+  ensGRID, ensSIMPLE, ensNR
+};
+
+/* eiVV is normal velocity verlet -- eiVVAK uses 1/2*(KE(t-dt/2)+KE(t+dt/2)) as the kinetic energy, and the half step kinetic
+   energy for temperature control */
+
+enum {
+  eiMD, eiSteep, eiCG, eiBD, eiSD2, eiNM, eiLBFGS, eiTPI, eiTPIC, eiSD1, eiVV, eiVVAK, eiNR
+};
+#define EI_VV(e) ((e) == eiVV || (e) == eiVVAK)
+#define EI_SD(e) ((e) == eiSD1 || (e) == eiSD2)
+#define EI_RANDOM(e) (EI_SD(e) || (e) == eiBD)
+/*above integrators may not conserve momenta*/
+#define EI_DYNAMICS(e) ((e) == eiMD || EI_SD(e) || (e) == eiBD || EI_VV(e))
+#define EI_ENERGY_MINIMIZATION(e) ((e) == eiSteep || (e) == eiCG || (e) == eiLBFGS)
+#define EI_TPI(e) ((e) == eiTPI || (e) == eiTPIC)
+
+#define EI_STATE_VELOCITY(e) ((e) == eiMD || EI_VV(e) || EI_SD(e))
+
+enum {
+  econtLINCS, econtSHAKE, econtNR
+};
+
+enum {
+  edrNone, edrSimple, edrEnsemble, edrNR
+};
+
+enum {
+  edrwConservative, edrwEqual, edrwNR
+};
+
+/* Combination rule things */
+enum { 
+  eCOMB_NONE, eCOMB_GEOMETRIC, eCOMB_ARITHMETIC, eCOMB_GEOM_SIG_EPS, eCOMB_NR 
+};
+
+/* NBF selection */
+enum { 
+  eNBF_NONE, eNBF_LJ, eNBF_BHAM, eNBF_NR 
+};
+
+/* FEP selection */
+enum {
+  efepNO, efepYES, efepNR
+};
+
+/* separate_dhdl_file selection */
+enum
+{
+    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
+    sepdhdlfileYES, sepdhdlfileNO, sepdhdlfileNR
+};
+
+/* dhdl_derivatives selection */
+enum
+{
+    /* NOTE: YES is the first one. Do NOT interpret this one as a gmx_bool */
+    dhdlderivativesYES, dhdlderivativesNO, dhdlderivativesNR
+};
+
+/* Solvent model */
+enum {
+  esolNO, esolSPC, esolTIP4P, esolNR
+};
+
+/* Dispersion correction */
+enum {
+  edispcNO, edispcEnerPres, edispcEner, edispcAllEnerPres, edispcAllEner, edispcNR
+}; 
+
+/* Shell types, for completion stuff */
+enum {
+  eshellCSH, eshellBASH, eshellZSH, eshellNR
+}; 
+
+/* Center of mass motion selection */
+enum { 
+  ecmLINEAR, ecmANGULAR, ecmNO, ecmNR 
+};
+
+/* New version of simulated annealing */
+enum { 
+  eannNO, eannSINGLE, eannPERIODIC, eannNR 
+};
+
+/* Implicit solvent algorithms */
+enum { 
+       eisNO, eisGBSA, eisNR 
+};
+
+/* Algorithms for calculating GB radii */
+enum { 
+  egbSTILL, egbHCT, egbOBC, egbNR 
+};
+
+enum {
+  esaAPPROX, esaNO, esaSTILL, esaNR
+};
+
+/* Wall types */
+enum {
+  ewt93, ewt104, ewtTABLE, ewt126, ewtNR
+};
+
+/* Pull stuff */
+enum {
+  epullNO, epullUMBRELLA, epullCONSTRAINT, epullCONST_F, epullNR
+};
+
+enum {
+  epullgDIST, epullgDIR, epullgCYL, epullgPOS, epullgDIRPBC, epullgNR
+};
+
+#define PULL_CYL(pull) ((pull)->eGeom == epullgCYL)
+
+/* Enforced rotation groups */
+enum {
+  erotgISO  , erotgISOPF ,
+  erotgPM   , erotgPMPF  ,
+  erotgRM   , erotgRMPF  ,
+  erotgRM2  , erotgRM2PF ,
+  erotgFLEX , erotgFLEXT ,
+  erotgFLEX2, erotgFLEX2T,
+  erotgNR
+};
+
+enum {
+    erotgFitRMSD, erotgFitNORM, erotgFitPOT, erotgFitNR
+};
+
+/* QMMM */
+enum {
+  eQMmethodAM1, eQMmethodPM3, eQMmethodRHF, 
+  eQMmethodUHF, eQMmethodDFT, eQMmethodB3LYP, eQMmethodMP2, eQMmethodCASSCF, eQMmethodB3LYPLAN,
+  eQMmethodDIRECT, eQMmethodNR
+};
+
+enum {
+  eQMbasisSTO3G, eQMbasisSTO3G2, eQMbasis321G, 
+  eQMbasis321Gp, eQMbasis321dGp, eQMbasis621G,
+  eQMbasis631G, eQMbasis631Gp, eQMbasis631dGp, 
+  eQMbasis6311G, eQMbasisNR
+};
+
+enum {
+  eQMMMschemenormal,eQMMMschemeoniom,eQMMMschemeNR
+};
+
+enum {
+  eMultentOptName, eMultentOptNo, eMultentOptLast, eMultentOptNR
+};
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/gromacs/legacyheaders/types/inputrec.h b/src/gromacs/legacyheaders/types/inputrec.h
new file mode 100644 (file)
index 0000000..bf8566d
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GRoups of Organic Molecules in ACtion for Science
+ */
+#ifndef _inputrec_h_
+#define _inputrec_h_
+
+
+#include "simple.h"
+#include "../sysstuff.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct {
+  int  n;              /* Number of terms                              */
+  real *a;             /* Coeffients (V / nm )                         */
+  real *phi;           /* Phase angles                                 */
+} t_cosines;
+
+typedef struct {
+  real E0;              /* Field strength (V/nm)                        */
+  real omega;           /* Frequency (1/ps)                             */
+  real t0;              /* Centre of the Gaussian pulse (ps)            */
+  real sigma;           /* Width of the Gaussian pulse (FWHM) (ps)      */
+} t_efield;
+
+#define EGP_EXCL  (1<<0)
+#define EGP_TABLE (1<<1)
+
+typedef struct {
+  int     ngtc;                  /* # T-Coupl groups                        */
+  int     nhchainlength;         /* # of nose-hoover chains per group       */
+  int     ngacc;                 /* # Accelerate groups                     */
+  int     ngfrz;                 /* # Freeze groups                         */
+  int     ngener;               /* # Ener groups                           */
+  real    *nrdf;                /* Nr of degrees of freedom in a group     */
+  real    *ref_t;               /* Coupling temperature        per group   */
+  int     *annealing;            /* No/simple/periodic SA for each group    */
+  int     *anneal_npoints;       /* Number of annealing time points per grp */    
+  real    **anneal_time;         /* For ea. group: Time points              */
+  real    **anneal_temp;         /* For ea. grp: Temperature at these times */
+                                 /* Final temp after all intervals is ref_t */ 
+  real    *tau_t;               /* Tau coupling time                       */
+  rvec    *acc;                         /* Acceleration per group                  */
+  ivec    *nFreeze;             /* Freeze the group in each direction ?    */
+  int     *egp_flags;            /* Exclusions/tables of energy group pairs */
+
+  /* QMMM stuff */
+  int     ngQM;         /* nr of QM groups                              */
+  int     *QMmethod;    /* Level of theory in the QM calculation        */
+  int     *QMbasis;     /* Basisset in the QM calculation               */
+  int     *QMcharge;    /* Total charge in the QM region                */
+  int     *QMmult;      /* Spin multiplicicty in the QM region          */
+  gmx_bool    *bSH;         /* surface hopping (diabatic hop only)          */
+  int     *CASorbitals; /* number of orbiatls in the active space       */
+  int     *CASelectrons;/* number of electrons in the active space      */
+  real    *SAon;        /* at which gap (A.U.) the SA is switched on    */
+  real    *SAoff;
+  int     *SAsteps;     /* in how many steps SA goes from 1-1 to 0.5-0.5*/
+  gmx_bool    *bOPT;
+  gmx_bool    *bTS;
+} t_grpopts;
+
+enum { epgrppbcNONE, epgrppbcREFAT, epgrppbcCOS };
+
+typedef struct {
+  int        nat;      /* Number of atoms in the pull group */
+  atom_id    *ind;     /* The global atoms numbers */
+  int        nat_loc;  /* Number of local pull atoms */
+  int        nalloc_loc; /* Allocation size for ind_loc and weight_loc */ 
+  atom_id    *ind_loc; /* Local pull indices */
+  int        nweight;  /* The number of weights (0 or nat) */
+  real       *weight;  /* Weights (use all 1 when weight==NULL) */
+  real       *weight_loc; /* Weights for the local indices */
+  int        epgrppbc; /* The type of pbc for this pull group, see enum above */
+  atom_id    pbcatom;  /* The reference atom for pbc (global number) */
+  rvec       vec;      /* The pull vector, direction or position */
+  rvec       init;     /* Initial reference displacement */
+  real       rate;     /* Rate of motion (nm/ps) */
+  real       k;        /* force constant */
+  real       kB;       /* force constant for state B */
+  real       wscale;   /* scaling factor for the weights: sum w m/sum w w m */
+  real       invtm;    /* inverse total mass of the group: 1/wscale sum w m */
+  dvec       x;        /* center of mass before update */
+  dvec       xp;       /* center of mass after update before constraining */
+  dvec       dr;       /* The distance from the reference group */
+  double     f_scal;   /* Scalar force for directional pulling */
+  dvec       f;        /* force due to the pulling/constraining */
+} t_pullgrp; 
+
+typedef struct {
+  int        ngrp;        /* number of groups */
+  int        eGeom;       /* pull geometry */
+  ivec       dim;         /* used to select components for constraint */
+  real       cyl_r1;      /* radius of cylinder for dynamic COM */
+  real       cyl_r0;      /* radius of cylinder including switch length */
+  real       constr_tol;  /* absolute tolerance for constraints in (nm) */
+  int        nstxout;     /* Output frequency for pull x */
+  int        nstfout;     /* Output frequency for pull f */
+  int        ePBC;        /* the boundary conditions */
+  int        npbcdim;     /* do pbc in dims 0 <= dim < npbcdim */
+  gmx_bool       bRefAt;      /* do we need reference atoms for a group COM ? */
+  int        cosdim;      /* dimension for cosine weighting, -1 if none */
+  gmx_bool       bVirial;     /* do we need to add the pull virial? */
+  t_pullgrp  *grp;        /* groups to pull/restrain/etc/ */
+  t_pullgrp  *dyna;       /* dynamic groups for use with local constraints */
+  rvec       *rbuf;       /* COM calculation buffer */
+  dvec       *dbuf;       /* COM calculation buffer */
+  double     *dbuf_cyl;   /* cylinder ref. groups COM calculation buffer */
+
+  FILE       *out_x;      /* output file for pull data */
+  FILE       *out_f;      /* output file for pull data */
+} t_pull;
+
+
+/* Abstract types for enforced rotation only defined in pull_rotation.c       */
+typedef struct gmx_enfrot *gmx_enfrot_t;
+typedef struct gmx_enfrotgrp *gmx_enfrotgrp_t;
+
+typedef struct {
+  int        eType;          /* Rotation type for this group                  */
+  int        bMassW;         /* Use mass-weighed positions?                   */
+  int        nat;            /* Number of atoms in the group                  */
+  atom_id    *ind;           /* The global atoms numbers                      */
+  rvec       *x_ref;         /* The reference positions                       */
+  rvec       vec;            /* The normalized rotation vector                */
+  real       rate;           /* Rate of rotation (degree/ps)                  */
+  real       k;              /* Force constant (kJ/(mol nm^2)                 */
+  rvec       pivot;          /* Pivot point of rotation axis (nm)             */
+  int        eFittype;       /* Type of fit to determine actual group angle   */
+  int        PotAngle_nstep; /* Number of angles around the reference angle
+                                for which the rotation potential is also
+                                evaluated (for fit type 'potential' only)     */
+  real       PotAngle_step;  /* Distance between two angles in degrees (for
+                                fit type 'potential' only)                    */
+  real       slab_dist;      /* Slab distance (nm)                            */
+  real       min_gaussian;   /* Minimum value the gaussian must have so that 
+                                the force is actually evaluated               */
+  real       eps;            /* Additive constant for radial motion2 and
+                                flexible2 potentials (nm^2)                   */
+  gmx_enfrotgrp_t enfrotgrp; /* Stores non-inputrec rotation data per group   */
+} t_rotgrp;
+
+typedef struct {
+  int        ngrp;           /* Number of rotation groups                     */
+  int        nstrout;        /* Output frequency for main rotation outfile    */
+  int        nstsout;        /* Output frequency for per-slab data            */
+  t_rotgrp   *grp;           /* Groups to rotate                              */
+  gmx_enfrot_t enfrot;       /* Stores non-inputrec enforced rotation data    */
+} t_rot;
+
+
+typedef struct {
+  int  eI;              /* Integration method                          */
+  gmx_large_int_t nsteps;      /* number of steps to be taken                  */
+  int  simulation_part; /* Used in checkpointing to separate chunks */
+  gmx_large_int_t init_step;   /* start at a stepcount >0 (used w. tpbconv)    */
+  int  nstcalcenergy;  /* fequency of energy calc. and T/P coupl. upd. */
+  int  ns_type;                /* which ns method should we use?               */
+  int  nstlist;                /* number of steps before pairlist is generated */
+  int  ndelta;         /* number of cells per rlong                    */
+  int  nstcomm;                /* number of steps after which center of mass   */
+                        /* motion is removed                           */
+  int  comm_mode;       /* Center of mass motion removal algorithm      */
+  int nstcheckpoint;    /* checkpointing frequency                      */
+  int nstlog;          /* number of steps after which print to logfile */
+  int nstxout;         /* number of steps after which X is output      */
+  int nstvout;         /* id. for V                                    */
+  int nstfout;         /* id. for F                                    */
+  int nstenergy;       /* number of steps after which energies printed */
+  int nstxtcout;       /* id. for compressed trj (.xtc)                */
+  double init_t;       /* initial time (ps)                            */
+  double delta_t;      /* time step (ps)                               */
+  real xtcprec;         /* precision of xtc file                        */
+  int  nkx,nky,nkz;     /* number of k vectors in each spatial dimension*/
+                        /* for fourier methods for long range electrost.*/
+  int  pme_order;       /* interpolation order for PME                  */
+  real ewald_rtol;      /* Real space tolerance for Ewald, determines   */
+                        /* the real/reciprocal space relative weight    */
+  int  ewald_geometry;  /* normal/3d ewald, or pseudo-2d LR corrections */
+  real epsilon_surface; /* Epsilon for PME dipole correction            */
+  gmx_bool bOptFFT;         /* optimize the fft plan at start               */
+  int  ePBC;           /* Type of periodic boundary conditions         */
+  int  bPeriodicMols;   /* Periodic molecules                           */
+  gmx_bool bContinuation;   /* Continuation run: starting state is correct     */
+  int  etc;            /* temperature coupling                         */
+  int  nsttcouple;      /* interval in steps for temperature coupling   */
+  int  epc;            /* pressure coupling                            */
+  int  epct;           /* pressure coupling type                       */
+  int  nstpcouple;      /* interval in steps for pressure coupling      */
+  real tau_p;          /* pressure coupling time (ps)                  */
+  tensor ref_p;                /* reference pressure (kJ/(mol nm^3))           */
+  tensor compress;     /* compressability ((mol nm^3)/kJ)              */
+  int  refcoord_scaling;/* How to scale absolute reference coordinates  */
+  rvec posres_com;      /* The COM of the posres atoms                  */
+  rvec posres_comB;     /* The B-state COM of the posres atoms          */
+  int  andersen_seed;   /* Random seed for Andersen thermostat.         */
+  real rlist;          /* short range pairlist cut-off (nm)            */
+  real rlistlong;      /* long range pairlist cut-off (nm)             */
+  real rtpi;            /* Radius for test particle insertion           */
+  int  coulombtype;    /* Type of electrostatics treatment             */
+  real rcoulomb_switch; /* Coulomb switch range start (nm)             */
+  real rcoulomb;        /* Coulomb cutoff (nm)                         */
+  real epsilon_r;       /* relative dielectric constant                 */ 
+  real epsilon_rf;      /* relative dielectric constant of the RF       */ 
+  int  implicit_solvent;/* No (=explicit water), or GBSA solvent models */
+  int  gb_algorithm;    /* Algorithm to use for calculation Born radii  */
+  int  nstgbradii;      /* Frequency of updating Generalized Born radii */
+  real rgbradii;        /* Cutoff for GB radii calculation              */
+  real gb_saltconc;     /* Salt concentration (M) for GBSA models       */
+  real gb_epsilon_solvent; /* dielectric coeff. of implicit solvent     */
+  real gb_obc_alpha;    /* 1st scaling factor for Bashford-Case GB      */
+  real gb_obc_beta;     /* 2nd scaling factor for Bashford-Case GB      */
+  real gb_obc_gamma;    /* 3rd scaling factor for Bashford-Case GB      */
+  real gb_dielectric_offset; /* Dielectric offset for Still/HCT/OBC     */
+  int  sa_algorithm;    /* Algorithm for SA part of GBSA                */
+  real sa_surface_tension; /* Energy factor for SA part of GBSA */
+  int  vdwtype;         /* Type of Van der Waals treatment              */
+  real rvdw_switch;     /* Van der Waals switch range start (nm)        */
+  real rvdw;               /* Van der Waals cutoff (nm)                */
+  int  eDispCorr;       /* Perform Long range dispersion corrections    */
+  real tabext;          /* Extension of the table beyond the cut-off,   *
+                        * as well as the table length for 1-4 interac. */
+  real shake_tol;      /* tolerance for shake                          */
+  int  efep;                   /* free energy interpolation no/yes             */
+  double init_lambda;  /* initial value for perturbation variable      */
+  double delta_lambda; /* change of lambda per time step (1/dt)        */
+  int  n_flambda;       /* The number of foreign lambda points          */
+  double *flambda;      /* The foreign lambda values                    */
+  real sc_alpha;        /* free energy soft-core parameter              */
+  int  sc_power;        /* lambda power for soft-core interactions      */
+  real sc_sigma;        /* free energy soft-core sigma when c6 or c12=0 */
+  real sc_sigma_min;    /* minimum FE sc sigma (default: =sg_sigma)     */
+  int  nstdhdl;         /* The frequency for writing to dhdl.xvg        */
+  int  separate_dhdl_file; /* whether to write a separate dhdl.xvg file 
+                              note: NOT a gmx_bool, but an enum */
+  int  dhdl_derivatives;/* whether to calculate+write dhdl derivatives 
+                              note: NOT a gmx_bool, but an enum */
+  int  dh_hist_size;    /* The maximum size for the dH histogram        */
+  double dh_hist_spacing; /* The spacing for the dH histogram           */
+  int  eDisre;          /* Type of distance restraining                 */
+  real dr_fc;              /* force constant for ta_disre                      */
+  int  eDisreWeighting; /* type of weighting of pairs in one restraints        */
+  gmx_bool bDisreMixed;     /* Use comb of time averaged and instan. viol's    */
+  int  nstdisreout;     /* frequency of writing pair distances to enx   */ 
+  real dr_tau;             /* time constant for memory function in disres      */
+  real orires_fc;          /* force constant for orientational restraints  */
+  real orires_tau;         /* time constant for memory function in orires      */
+  int  nstorireout;     /* frequency of writing tr(SD) to enx           */ 
+  real dihre_fc;        /* force constant for dihedral restraints      */
+  real em_stepsize;        /* The stepsize for updating                        */
+  real em_tol;             /* The tolerance                            */
+  int  niter;           /* Number of iterations for convergence of      */
+                        /* steepest descent in relax_shells             */
+  real fc_stepsize;     /* Stepsize for directional minimization        */
+                        /* in relax_shells                              */
+  int  nstcgsteep;      /* number of steps after which a steepest       */
+                        /* descents step is done while doing cg         */
+  int  nbfgscorr;       /* Number of corrections to the hessian to keep */
+  int  eConstrAlg;      /* Type of constraint algorithm                 */
+  int  nProjOrder;      /* Order of the LINCS Projection Algorithm      */
+  real LincsWarnAngle;  /* If bond rotates more than %g degrees, warn   */
+  int  nLincsIter;      /* Number of iterations in the final Lincs step */
+  gmx_bool bShakeSOR;       /* Use successive overrelaxation for shake      */
+  real bd_fric;         /* Friction coefficient for BD (amu/ps)         */
+  int  ld_seed;         /* Random seed for SD and BD                    */
+  int  nwall;           /* The number of walls                          */
+  int  wall_type;       /* The type of walls                            */
+  real wall_r_linpot;   /* The potentail is linear for r<=wall_r_linpot */
+  int  wall_atomtype[2];/* The atom type for walls                      */
+  real wall_density[2]; /* Number density for walls                     */
+  real wall_ewald_zfac; /* Scaling factor for the box for Ewald         */
+  int  ePull;           /* Type of pulling: no, umbrella or constraint  */
+  t_pull *pull;         /* The data for center of mass pulling          */
+  gmx_bool bRot;        /* Calculate enforced rotation potential(s)?    */
+  t_rot *rot;           /* The data for enforced rotation potentials    */
+  real cos_accel;       /* Acceleration for viscosity calculation       */
+  tensor deform;        /* Triclinic deformation velocities (nm/ps)     */
+  int  userint1;        /* User determined parameters                   */
+  int  userint2;
+  int  userint3;
+  int  userint4;
+  real userreal1;
+  real userreal2;
+  real userreal3;
+  real userreal4;
+  t_grpopts opts;      /* Group options                                */
+  t_cosines ex[DIM];   /* Electric field stuff (spatial part)          */
+  t_cosines et[DIM];   /* Electric field stuff (time part)             */
+  gmx_bool bQMMM;           /* QM/MM calculation                            */ 
+  int  QMconstraints;   /* constraints on QM bonds                      */
+  int  QMMMscheme;      /* Scheme: ONIOM or normal                      */
+  real scalefactor;     /* factor for scaling the MM charges in QM calc.*/
+} t_inputrec;
+
+#define DEFORM(ir) ((ir).deform[XX][XX]!=0 || (ir).deform[YY][YY]!=0 || (ir).deform[ZZ][ZZ]!=0 || (ir).deform[YY][XX]!=0 || (ir).deform[ZZ][XX]!=0 || (ir).deform[ZZ][YY]!=0)
+
+#define DYNAMIC_BOX(ir) ((ir).epc!=epcNO || (ir).eI==eiTPI || DEFORM(ir))
+
+#define PRESERVE_SHAPE(ir) ((ir).epc != epcNO && (ir).deform[XX][XX] == 0 && ((ir).epct == epctISOTROPIC || (ir).epct == epctSEMIISOTROPIC))
+
+#define NEED_MUTOT(ir) (((ir).coulombtype==eelEWALD || EEL_PME((ir).coulombtype)) && ((ir).ewald_geometry==eewg3DC || (ir).epsilon_surface!=0))
+
+#define IR_TWINRANGE(ir) ((ir).rlist > 0 && ((ir).rlistlong == 0 || (ir).rlistlong > (ir).rlist))
+
+#define IR_ELEC_FIELD(ir) ((ir).ex[XX].n > 0 || (ir).ex[YY].n > 0 || (ir).ex[ZZ].n > 0)
+
+#define IR_EXCL_FORCES(ir) (EEL_FULL((ir).coulombtype) || (EEL_RF((ir).coulombtype) && (ir).coulombtype != eelRF_NEC) || (ir).implicit_solvent != eisNO)
+/* use pointer definitions of ir here, since that's what's usually used in the code */
+#define IR_NVT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->etc == etcNOSEHOOVER))
+
+#define IR_NPT_TROTTER(ir) ((((ir)->eI == eiVV) || ((ir)->eI == eiVVAK)) && ((ir)->epc == epcMTTK))
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gromacs/legacyheaders/vec.h b/src/gromacs/legacyheaders/vec.h
new file mode 100644 (file)
index 0000000..474a45f
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+#ifndef _vec_h
+#define _vec_h
+
+/*
+  collection of in-line ready operations:
+  
+  lookup-table optimized scalar operations:
+  real gmx_invsqrt(real x)
+  void vecinvsqrt(real in[],real out[],int n)
+  void vecrecip(real in[],real out[],int n)
+  real sqr(real x)
+  double dsqr(double x)
+  
+  vector operations:
+  void rvec_add(const rvec a,const rvec b,rvec c)  c = a + b
+  void dvec_add(const dvec a,const dvec b,dvec c)  c = a + b
+  void ivec_add(const ivec a,const ivec b,ivec c)  c = a + b
+  void rvec_inc(rvec a,const rvec b)               a += b
+  void dvec_inc(dvec a,const dvec b)               a += b
+  void ivec_inc(ivec a,const ivec b)               a += b
+  void rvec_sub(const rvec a,const rvec b,rvec c)  c = a - b
+  void dvec_sub(const dvec a,const dvec b,dvec c)  c = a - b
+  void rvec_dec(rvec a,rvec b)                     a -= b
+  void copy_rvec(const rvec a,rvec b)              b = a (reals)
+  void copy_dvec(const dvec a,dvec b)              b = a (reals)
+  void copy_ivec(const ivec a,ivec b)              b = a (integers)
+  void ivec_sub(const ivec a,const ivec b,ivec c)  c = a - b
+  void svmul(real a,rvec v1,rvec v2)               v2 = a * v1
+  void dsvmul(double a,dvec v1,dvec v2)            v2 = a * v1
+  void clear_rvec(rvec a)                          a = 0
+  void clear_dvec(dvec a)                          a = 0
+  void clear_ivec(rvec a)                          a = 0
+  void clear_rvecs(int n,rvec v[])
+  real iprod(rvec a,rvec b)                        = a . b (inner product)
+  double diprod(dvec a,dvec b)                     = a . b (inner product)
+  real iiprod(ivec a,ivec b)                       = a . b (integers)
+  real norm2(rvec a)                               = | a |^2 ( = x*y*z )
+  double dnorm2(dvec a)                            = | a |^2 ( = x*y*z )
+  real norm(rvec a)                                = | a |
+  double dnorm(dvec a)                             = | a |
+  void cprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
+  void dprod(rvec a,rvec b,rvec c)                 c = a x b (cross product)
+  void dprod(rvec a,rvec b,rvec c)                 c = a * b (direct product)
+  real cos_angle(rvec a,rvec b)
+  real cos_angle_no_table(rvec a,rvec b)
+  real distance2(rvec v1, rvec v2)                 = | v2 - v1 |^2
+  void unitv(rvec src,rvec dest)                   dest = src / |src|
+  void unitv_no_table(rvec src,rvec dest)          dest = src / |src|
+  
+  matrix (3x3) operations:
+    ! indicates that dest should not be the same as a, b or src
+    the _ur0 varieties work on matrices that have only zeros
+    in the upper right part, such as box matrices, these varieties
+    could produce less rounding errors, not due to the operations themselves,
+    but because the compiler can easier recombine the operations
+  void copy_mat(matrix a,matrix b)                 b = a
+  void clear_mat(matrix a)                        a = 0
+  void mmul(matrix a,matrix b,matrix dest)     !  dest = a . b
+  void mmul_ur0(matrix a,matrix b,matrix dest)     dest = a . b
+  void transpose(matrix src,matrix dest)       !  dest = src*
+  void tmmul(matrix a,matrix b,matrix dest)    !  dest = a* . b
+  void mtmul(matrix a,matrix b,matrix dest)    !  dest = a . b*
+  real det(matrix a)                              = det(a)
+  void m_add(matrix a,matrix b,matrix dest)       dest = a + b
+  void m_sub(matrix a,matrix b,matrix dest)       dest = a - b
+  void msmul(matrix m1,real r1,matrix dest)       dest = r1 * m1
+  void m_inv_ur0(matrix src,matrix dest)           dest = src^-1
+  void m_inv(matrix src,matrix dest)           !  dest = src^-1
+  void mvmul(matrix a,rvec src,rvec dest)      !  dest = a . src
+  void mvmul_ur0(matrix a,rvec src,rvec dest)      dest = a . src
+  void tmvmul_ur0(matrix a,rvec src,rvec dest)     dest = a* . src
+  real trace(matrix m)                             = trace(m)
+*/
+
+#include "types/simple.h"
+#include "maths.h"
+#include "typedefs.h"
+#include "sysstuff.h"
+#include "macros.h"
+#include "gmx_fatal.h"
+#include "physics.h"
+
+#ifdef __cplusplus
+extern "C" {
+#elif 0
+} /* avoid screwing up indentation */
+#endif
+
+
+#define EXP_LSB         0x00800000
+#define EXP_MASK        0x7f800000
+#define EXP_SHIFT       23
+#define FRACT_MASK      0x007fffff
+#define FRACT_SIZE      11              /* significant part of fraction */
+#define FRACT_SHIFT     (EXP_SHIFT-FRACT_SIZE)
+#define EXP_ADDR(val)   (((val)&EXP_MASK)>>EXP_SHIFT)
+#define FRACT_ADDR(val) (((val)&(FRACT_MASK|EXP_LSB))>>FRACT_SHIFT)
+
+#define PR_VEC(a)       a[XX],a[YY],a[ZZ]
+
+#ifdef GMX_SOFTWARE_INVSQRT
+extern const unsigned int *  gmx_invsqrt_exptab;
+extern const unsigned int *  gmx_invsqrt_fracttab;
+#endif
+
+
+typedef union 
+{
+  unsigned int bval;
+  float fval;
+} t_convert;
+
+
+#ifdef GMX_SOFTWARE_INVSQRT
+static real gmx_invsqrt(real x)
+{
+  const real  half=0.5;
+  const real  three=3.0;
+  t_convert   result,bit_pattern;
+  unsigned int exp,fract;
+  real        lu;
+  real        y;
+#ifdef GMX_DOUBLE
+  real        y2;
+#endif
+  bit_pattern.fval=x;
+  exp   = EXP_ADDR(bit_pattern.bval);
+  fract = FRACT_ADDR(bit_pattern.bval);
+  result.bval=gmx_invsqrt_exptab[exp] | gmx_invsqrt_fracttab[fract];
+  lu    = result.fval;
+  
+  y=(half*lu*(three-((x*lu)*lu)));
+#ifdef GMX_DOUBLE
+  y2=(half*y*(three-((x*y)*y)));
+  
+  return y2;                    /* 10 Flops */
+#else
+  return y;                     /* 5  Flops */
+#endif
+}
+#define INVSQRT_DONE 
+#endif /* gmx_invsqrt */
+
+#ifdef GMX_POWERPC_SQRT
+static real gmx_invsqrt(real x)
+{
+  const real  half=0.5;
+  const real  three=3.0;
+  t_convert   result,bit_pattern;
+  unsigned int exp,fract;
+  real        lu;
+  real        y;
+#ifdef GMX_DOUBLE
+  real        y2;
+#endif
+
+  lu = __frsqrte((double)x);
+
+  y=(half*lu*(three-((x*lu)*lu)));
+
+#if (GMX_POWERPC_SQRT==2)
+  /* Extra iteration required */
+  y=(half*y*(three-((x*y)*y)));
+#endif
+
+#ifdef GMX_DOUBLE
+  y2=(half*y*(three-((x*y)*y)));
+
+  return y2;                    /* 10 Flops */
+#else
+  return y;                     /* 5  Flops */
+#endif
+}
+#define INVSQRT_DONE
+#endif /* powerpc_invsqrt */
+
+
+#ifndef INVSQRT_DONE
+#define gmx_invsqrt(x) (1.0f/sqrt(x))
+#endif
+
+
+
+
+
+static real sqr(real x)
+{
+  return (x*x);
+}
+
+static gmx_inline double dsqr(double x)
+{
+  return (x*x);
+}
+
+/* Maclaurin series for sinh(x)/x, useful for NH chains and MTTK pressure control 
+   Here, we compute it to 10th order, which might be overkill, 8th is probably enough, 
+   but it's not very much more expensive. */
+
+static gmx_inline real series_sinhx(real x) 
+{
+  real x2 = x*x;
+  return (1 + (x2/6.0)*(1 + (x2/20.0)*(1 + (x2/42.0)*(1 + (x2/72.0)*(1 + (x2/110.0))))));
+}
+
+void vecinvsqrt(real in[],real out[],int n);
+/* Perform out[i]=1.0/sqrt(in[i]) for n elements */
+
+
+void vecrecip(real in[],real out[],int n);
+/* Perform out[i]=1.0/(in[i]) for n elements */
+
+/* Note: If you need a fast version of vecinvsqrt 
+ * and/or vecrecip, call detectcpu() and run the SSE/3DNow/SSE2/Altivec
+ * versions if your hardware supports it.
+ *
+ * To use those routines, your memory HAS TO BE CACHE-ALIGNED.
+ * Use snew_aligned(ptr,size,32) to allocate and sfree_aligned to free.
+ */
+
+
+static gmx_inline void rvec_add(const rvec a,const rvec b,rvec c)
+{
+  real x,y,z;
+  
+  x=a[XX]+b[XX];
+  y=a[YY]+b[YY];
+  z=a[ZZ]+b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void dvec_add(const dvec a,const dvec b,dvec c)
+{
+  double x,y,z;
+  
+  x=a[XX]+b[XX];
+  y=a[YY]+b[YY];
+  z=a[ZZ]+b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void ivec_add(const ivec a,const ivec b,ivec c)
+{
+  int x,y,z;
+  
+  x=a[XX]+b[XX];
+  y=a[YY]+b[YY];
+  z=a[ZZ]+b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void rvec_inc(rvec a,const rvec b)
+{
+  real x,y,z;
+  
+  x=a[XX]+b[XX];
+  y=a[YY]+b[YY];
+  z=a[ZZ]+b[ZZ];
+  
+  a[XX]=x;
+  a[YY]=y;
+  a[ZZ]=z;
+}
+
+static gmx_inline void dvec_inc(dvec a,const dvec b)
+{
+  double x,y,z;
+
+  x=a[XX]+b[XX];
+  y=a[YY]+b[YY];
+  z=a[ZZ]+b[ZZ];
+
+  a[XX]=x;
+  a[YY]=y;
+  a[ZZ]=z;
+}
+
+static gmx_inline void rvec_sub(const rvec a,const rvec b,rvec c)
+{
+  real x,y,z;
+  
+  x=a[XX]-b[XX];
+  y=a[YY]-b[YY];
+  z=a[ZZ]-b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void dvec_sub(const dvec a,const dvec b,dvec c)
+{
+  double x,y,z;
+  
+  x=a[XX]-b[XX];
+  y=a[YY]-b[YY];
+  z=a[ZZ]-b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void rvec_dec(rvec a,const rvec b)
+{
+  real x,y,z;
+  
+  x=a[XX]-b[XX];
+  y=a[YY]-b[YY];
+  z=a[ZZ]-b[ZZ];
+  
+  a[XX]=x;
+  a[YY]=y;
+  a[ZZ]=z;
+}
+
+static gmx_inline void copy_rvec(const rvec a,rvec b)
+{
+  b[XX]=a[XX];
+  b[YY]=a[YY];
+  b[ZZ]=a[ZZ];
+}
+
+static gmx_inline void copy_rvecn(rvec *a,rvec *b,int startn, int endn)
+{
+  int i;
+  for (i=startn;i<endn;i++) {
+    b[i][XX]=a[i][XX];
+    b[i][YY]=a[i][YY];
+    b[i][ZZ]=a[i][ZZ];
+  }
+}
+
+static gmx_inline void copy_dvec(const dvec a,dvec b)
+{
+  b[XX]=a[XX];
+  b[YY]=a[YY];
+  b[ZZ]=a[ZZ];
+}
+
+static gmx_inline void copy_ivec(const ivec a,ivec b)
+{
+  b[XX]=a[XX];
+  b[YY]=a[YY];
+  b[ZZ]=a[ZZ];
+}
+
+static gmx_inline void ivec_sub(const ivec a,const ivec b,ivec c)
+{
+  int x,y,z;
+  
+  x=a[XX]-b[XX];
+  y=a[YY]-b[YY];
+  z=a[ZZ]-b[ZZ];
+  
+  c[XX]=x;
+  c[YY]=y;
+  c[ZZ]=z;
+}
+
+static gmx_inline void copy_mat(matrix a,matrix b)
+{
+  copy_rvec(a[XX],b[XX]);
+  copy_rvec(a[YY],b[YY]);
+  copy_rvec(a[ZZ],b[ZZ]);
+}
+
+static gmx_inline void svmul(real a,const rvec v1,rvec v2)
+{
+  v2[XX]=a*v1[XX];
+  v2[YY]=a*v1[YY];
+  v2[ZZ]=a*v1[ZZ];
+}
+
+static gmx_inline void dsvmul(double a,const dvec v1,dvec v2)
+{
+  v2[XX]=a*v1[XX];
+  v2[YY]=a*v1[YY];
+  v2[ZZ]=a*v1[ZZ];
+}
+
+static gmx_inline real distance2(const rvec v1,const rvec v2)
+{
+  return sqr(v2[XX]-v1[XX]) + sqr(v2[YY]-v1[YY]) + sqr(v2[ZZ]-v1[ZZ]);
+}
+
+static gmx_inline void clear_rvec(rvec a)
+{
+  /* The ibm compiler has problems with inlining this 
+   * when we use a const real variable
+   */
+  a[XX]=0.0;
+  a[YY]=0.0;
+  a[ZZ]=0.0;
+}
+
+static gmx_inline void clear_dvec(dvec a)
+{
+  /* The ibm compiler has problems with inlining this 
+   * when we use a const real variable
+   */
+  a[XX]=0.0;
+  a[YY]=0.0;
+  a[ZZ]=0.0;
+}
+
+static gmx_inline void clear_ivec(ivec a)
+{
+  a[XX]=0;
+  a[YY]=0;
+  a[ZZ]=0;
+}
+
+static gmx_inline void clear_rvecs(int n,rvec v[])
+{
+/*  memset(v[0],0,DIM*n*sizeof(v[0][0])); */
+  int i;
+    
+  for(i=0; (i<n); i++) 
+    clear_rvec(v[i]);
+}
+
+static gmx_inline void clear_mat(matrix a)
+{
+/*  memset(a[0],0,DIM*DIM*sizeof(a[0][0])); */
+  
+  const real nul=0.0;
+  
+  a[XX][XX]=a[XX][YY]=a[XX][ZZ]=nul;
+  a[YY][XX]=a[YY][YY]=a[YY][ZZ]=nul;
+  a[ZZ][XX]=a[ZZ][YY]=a[ZZ][ZZ]=nul;
+}
+
+static gmx_inline real iprod(const rvec a,const rvec b)
+{
+  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
+}
+
+static gmx_inline double diprod(const dvec a,const dvec b)
+{
+  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
+}
+
+static gmx_inline int iiprod(const ivec a,const ivec b)
+{
+  return (a[XX]*b[XX]+a[YY]*b[YY]+a[ZZ]*b[ZZ]);
+}
+
+static gmx_inline real norm2(const rvec a)
+{
+  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
+}
+
+static gmx_inline double dnorm2(const dvec a)
+{
+  return a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ];
+}
+
+static gmx_inline real norm(const rvec a)
+{
+  return (real)sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
+}
+
+static gmx_inline double dnorm(const dvec a)
+{
+  return sqrt(a[XX]*a[XX]+a[YY]*a[YY]+a[ZZ]*a[ZZ]);
+}
+
+/* WARNING:
+ * Do _not_ use these routines to calculate the angle between two vectors
+ * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
+ * is very flat close to -1 and 1, which will lead to accuracy-loss.
+ * Instead, use the new gmx_angle() function directly.
+ */
+static gmx_inline real 
+cos_angle(const rvec a,const rvec b)
+{
+  /* 
+   *                  ax*bx + ay*by + az*bz
+   * cos-vec (a,b) =  ---------------------
+   *                      ||a|| * ||b||
+   */
+  real   cosval;
+  int    m;
+  double aa,bb,ip,ipa,ipb,ipab; /* For accuracy these must be double! */
+  
+  ip=ipa=ipb=0.0;
+  for(m=0; (m<DIM); m++) {             /* 18           */
+    aa   = a[m];
+    bb   = b[m];
+    ip  += aa*bb;
+    ipa += aa*aa;
+    ipb += bb*bb;
+  }
+  ipab = ipa*ipb;
+  if (ipab > 0)
+    cosval = ip*gmx_invsqrt(ipab);             /*  7           */
+  else 
+    cosval = 1;
+                                       /* 25 TOTAL     */
+  if (cosval > 1.0) 
+    return  1.0; 
+  if (cosval <-1.0) 
+    return -1.0;
+  
+  return cosval;
+}
+
+/* WARNING:
+ * Do _not_ use these routines to calculate the angle between two vectors
+ * as acos(cos_angle(u,v)). While it might seem obvious, the acos function
+ * is very flat close to -1 and 1, which will lead to accuracy-loss.
+ * Instead, use the new gmx_angle() function directly.
+ */
+static gmx_inline real 
+cos_angle_no_table(const rvec a,const rvec b)
+{
+  /* This version does not need the invsqrt lookup table */
+  real   cosval;
+  int    m;
+  double aa,bb,ip,ipa,ipb; /* For accuracy these must be double! */
+  
+  ip=ipa=ipb=0.0;
+  for(m=0; (m<DIM); m++) {             /* 18           */
+    aa   = a[m];
+    bb   = b[m];
+    ip  += aa*bb;
+    ipa += aa*aa;
+    ipb += bb*bb;
+  }
+  cosval=ip/sqrt(ipa*ipb);             /* 12           */
+                                       /* 30 TOTAL     */
+  if (cosval > 1.0) 
+    return  1.0; 
+  if (cosval <-1.0) 
+    return -1.0;
+  
+  return cosval;
+}
+
+
+static gmx_inline void cprod(const rvec a,const rvec b,rvec c)
+{
+  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
+  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
+  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
+}
+
+static gmx_inline void dcprod(const dvec a,const dvec b,dvec c)
+{
+  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
+  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
+  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
+}
+
+/* This routine calculates the angle between a & b without any loss of accuracy close to 0/PI.
+ * If you only need cos(theta), use the cos_angle() routines to save a few cycles.
+ * This routine is faster than it might appear, since atan2 is accelerated on many CPUs (e.g. x86).
+ */
+static gmx_inline real 
+gmx_angle(const rvec a, const rvec b)
+{
+    rvec w;
+    real wlen,s;
+    
+    cprod(a,b,w);
+    
+    wlen  = norm(w);
+    s     = iprod(a,b);
+    
+    return atan2(wlen,s);
+}
+
+static gmx_inline void mmul_ur0(matrix a,matrix b,matrix dest)
+{
+  dest[XX][XX]=a[XX][XX]*b[XX][XX];
+  dest[XX][YY]=0.0;
+  dest[XX][ZZ]=0.0;
+  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX];
+  dest[YY][YY]=                    a[YY][YY]*b[YY][YY];
+  dest[YY][ZZ]=0.0;
+  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
+  dest[ZZ][YY]=                    a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
+  dest[ZZ][ZZ]=                                        a[ZZ][ZZ]*b[ZZ][ZZ];
+}
+
+static gmx_inline void mmul(matrix a,matrix b,matrix dest)
+{
+  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[YY][XX]+a[XX][ZZ]*b[ZZ][XX];
+  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[YY][ZZ]*b[ZZ][XX];
+  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
+  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[ZZ][YY];
+  dest[YY][YY]=a[YY][XX]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[ZZ][YY];
+  dest[ZZ][YY]=a[ZZ][XX]*b[XX][YY]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
+  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[XX][YY]*b[YY][ZZ]+a[XX][ZZ]*b[ZZ][ZZ];
+  dest[YY][ZZ]=a[YY][XX]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[YY][ZZ]*b[ZZ][ZZ];
+  dest[ZZ][ZZ]=a[ZZ][XX]*b[XX][ZZ]+a[ZZ][YY]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
+}
+
+static gmx_inline void transpose(matrix src,matrix dest)
+{
+  dest[XX][XX]=src[XX][XX];
+  dest[YY][XX]=src[XX][YY];
+  dest[ZZ][XX]=src[XX][ZZ];
+  dest[XX][YY]=src[YY][XX];
+  dest[YY][YY]=src[YY][YY];
+  dest[ZZ][YY]=src[YY][ZZ];
+  dest[XX][ZZ]=src[ZZ][XX];
+  dest[YY][ZZ]=src[ZZ][YY];
+  dest[ZZ][ZZ]=src[ZZ][ZZ];
+}
+
+static gmx_inline void tmmul(matrix a,matrix b,matrix dest)
+{
+  /* Computes dest=mmul(transpose(a),b,dest) - used in do_pr_pcoupl */
+  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[YY][XX]*b[YY][XX]+a[ZZ][XX]*b[ZZ][XX];
+  dest[XX][YY]=a[XX][XX]*b[XX][YY]+a[YY][XX]*b[YY][YY]+a[ZZ][XX]*b[ZZ][YY];
+  dest[XX][ZZ]=a[XX][XX]*b[XX][ZZ]+a[YY][XX]*b[YY][ZZ]+a[ZZ][XX]*b[ZZ][ZZ];
+  dest[YY][XX]=a[XX][YY]*b[XX][XX]+a[YY][YY]*b[YY][XX]+a[ZZ][YY]*b[ZZ][XX];
+  dest[YY][YY]=a[XX][YY]*b[XX][YY]+a[YY][YY]*b[YY][YY]+a[ZZ][YY]*b[ZZ][YY];
+  dest[YY][ZZ]=a[XX][YY]*b[XX][ZZ]+a[YY][YY]*b[YY][ZZ]+a[ZZ][YY]*b[ZZ][ZZ];
+  dest[ZZ][XX]=a[XX][ZZ]*b[XX][XX]+a[YY][ZZ]*b[YY][XX]+a[ZZ][ZZ]*b[ZZ][XX];
+  dest[ZZ][YY]=a[XX][ZZ]*b[XX][YY]+a[YY][ZZ]*b[YY][YY]+a[ZZ][ZZ]*b[ZZ][YY];
+  dest[ZZ][ZZ]=a[XX][ZZ]*b[XX][ZZ]+a[YY][ZZ]*b[YY][ZZ]+a[ZZ][ZZ]*b[ZZ][ZZ];
+}
+
+static gmx_inline void mtmul(matrix a,matrix b,matrix dest)
+{
+  /* Computes dest=mmul(a,transpose(b),dest) - used in do_pr_pcoupl */
+  dest[XX][XX]=a[XX][XX]*b[XX][XX]+a[XX][YY]*b[XX][YY]+a[XX][ZZ]*b[XX][ZZ];
+  dest[XX][YY]=a[XX][XX]*b[YY][XX]+a[XX][YY]*b[YY][YY]+a[XX][ZZ]*b[YY][ZZ];
+  dest[XX][ZZ]=a[XX][XX]*b[ZZ][XX]+a[XX][YY]*b[ZZ][YY]+a[XX][ZZ]*b[ZZ][ZZ];
+  dest[YY][XX]=a[YY][XX]*b[XX][XX]+a[YY][YY]*b[XX][YY]+a[YY][ZZ]*b[XX][ZZ];
+  dest[YY][YY]=a[YY][XX]*b[YY][XX]+a[YY][YY]*b[YY][YY]+a[YY][ZZ]*b[YY][ZZ];
+  dest[YY][ZZ]=a[YY][XX]*b[ZZ][XX]+a[YY][YY]*b[ZZ][YY]+a[YY][ZZ]*b[ZZ][ZZ];
+  dest[ZZ][XX]=a[ZZ][XX]*b[XX][XX]+a[ZZ][YY]*b[XX][YY]+a[ZZ][ZZ]*b[XX][ZZ];
+  dest[ZZ][YY]=a[ZZ][XX]*b[YY][XX]+a[ZZ][YY]*b[YY][YY]+a[ZZ][ZZ]*b[YY][ZZ];
+  dest[ZZ][ZZ]=a[ZZ][XX]*b[ZZ][XX]+a[ZZ][YY]*b[ZZ][YY]+a[ZZ][ZZ]*b[ZZ][ZZ];
+}
+
+static gmx_inline real det(matrix a)
+{
+  return ( a[XX][XX]*(a[YY][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[YY][ZZ])
+         -a[YY][XX]*(a[XX][YY]*a[ZZ][ZZ]-a[ZZ][YY]*a[XX][ZZ])
+         +a[ZZ][XX]*(a[XX][YY]*a[YY][ZZ]-a[YY][YY]*a[XX][ZZ]));
+}
+
+static gmx_inline void m_add(matrix a,matrix b,matrix dest)
+{
+  dest[XX][XX]=a[XX][XX]+b[XX][XX];
+  dest[XX][YY]=a[XX][YY]+b[XX][YY];
+  dest[XX][ZZ]=a[XX][ZZ]+b[XX][ZZ];
+  dest[YY][XX]=a[YY][XX]+b[YY][XX];
+  dest[YY][YY]=a[YY][YY]+b[YY][YY];
+  dest[YY][ZZ]=a[YY][ZZ]+b[YY][ZZ];
+  dest[ZZ][XX]=a[ZZ][XX]+b[ZZ][XX];
+  dest[ZZ][YY]=a[ZZ][YY]+b[ZZ][YY];
+  dest[ZZ][ZZ]=a[ZZ][ZZ]+b[ZZ][ZZ];
+}
+
+static gmx_inline void m_sub(matrix a,matrix b,matrix dest)
+{
+  dest[XX][XX]=a[XX][XX]-b[XX][XX];
+  dest[XX][YY]=a[XX][YY]-b[XX][YY];
+  dest[XX][ZZ]=a[XX][ZZ]-b[XX][ZZ];
+  dest[YY][XX]=a[YY][XX]-b[YY][XX];
+  dest[YY][YY]=a[YY][YY]-b[YY][YY];
+  dest[YY][ZZ]=a[YY][ZZ]-b[YY][ZZ];
+  dest[ZZ][XX]=a[ZZ][XX]-b[ZZ][XX];
+  dest[ZZ][YY]=a[ZZ][YY]-b[ZZ][YY];
+  dest[ZZ][ZZ]=a[ZZ][ZZ]-b[ZZ][ZZ];
+}
+
+static gmx_inline void msmul(matrix m1,real r1,matrix dest)
+{
+  dest[XX][XX]=r1*m1[XX][XX];
+  dest[XX][YY]=r1*m1[XX][YY];
+  dest[XX][ZZ]=r1*m1[XX][ZZ];
+  dest[YY][XX]=r1*m1[YY][XX];
+  dest[YY][YY]=r1*m1[YY][YY];
+  dest[YY][ZZ]=r1*m1[YY][ZZ];
+  dest[ZZ][XX]=r1*m1[ZZ][XX];
+  dest[ZZ][YY]=r1*m1[ZZ][YY];
+  dest[ZZ][ZZ]=r1*m1[ZZ][ZZ];
+}
+
+static gmx_inline void m_inv_ur0(matrix src,matrix dest)
+{
+  double tmp = src[XX][XX]*src[YY][YY]*src[ZZ][ZZ];
+  if (fabs(tmp) <= 100*GMX_REAL_MIN)
+    gmx_fatal(FARGS,"Can not invert matrix, determinant is zero");
+
+  dest[XX][XX] = 1/src[XX][XX];
+  dest[YY][YY] = 1/src[YY][YY];
+  dest[ZZ][ZZ] = 1/src[ZZ][ZZ];
+  dest[ZZ][XX] = (src[YY][XX]*src[ZZ][YY]*dest[YY][YY]
+                 - src[ZZ][XX])*dest[XX][XX]*dest[ZZ][ZZ];
+  dest[YY][XX] = -src[YY][XX]*dest[XX][XX]*dest[YY][YY];
+  dest[ZZ][YY] = -src[ZZ][YY]*dest[YY][YY]*dest[ZZ][ZZ];
+  dest[XX][YY] = 0.0;
+  dest[XX][ZZ] = 0.0;
+  dest[YY][ZZ] = 0.0;
+}
+
+static gmx_inline void m_inv(matrix src,matrix dest)
+{
+  const real smallreal = (real)1.0e-24;
+  const real largereal = (real)1.0e24;
+  real  deter,c,fc;
+
+  deter = det(src);
+  c     = (real)1.0/deter;
+  fc    = (real)fabs(c);
+  
+  if ((fc <= smallreal) || (fc >= largereal)) 
+    gmx_fatal(FARGS,"Can not invert matrix, determinant = %e",deter);
+
+  dest[XX][XX]= c*(src[YY][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[YY][ZZ]);
+  dest[XX][YY]=-c*(src[XX][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[XX][ZZ]);
+  dest[XX][ZZ]= c*(src[XX][YY]*src[YY][ZZ]-src[YY][YY]*src[XX][ZZ]);
+  dest[YY][XX]=-c*(src[YY][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[YY][ZZ]);
+  dest[YY][YY]= c*(src[XX][XX]*src[ZZ][ZZ]-src[ZZ][XX]*src[XX][ZZ]);
+  dest[YY][ZZ]=-c*(src[XX][XX]*src[YY][ZZ]-src[YY][XX]*src[XX][ZZ]);
+  dest[ZZ][XX]= c*(src[YY][XX]*src[ZZ][YY]-src[ZZ][XX]*src[YY][YY]);
+  dest[ZZ][YY]=-c*(src[XX][XX]*src[ZZ][YY]-src[ZZ][XX]*src[XX][YY]);
+  dest[ZZ][ZZ]= c*(src[XX][XX]*src[YY][YY]-src[YY][XX]*src[XX][YY]);
+}
+
+static gmx_inline void mvmul(matrix a,const rvec src,rvec dest)
+{
+  dest[XX]=a[XX][XX]*src[XX]+a[XX][YY]*src[YY]+a[XX][ZZ]*src[ZZ];
+  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY]+a[YY][ZZ]*src[ZZ];
+  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
+}
+
+static gmx_inline void mvmul_ur0(matrix a,const rvec src,rvec dest)
+{
+  dest[ZZ]=a[ZZ][XX]*src[XX]+a[ZZ][YY]*src[YY]+a[ZZ][ZZ]*src[ZZ];
+  dest[YY]=a[YY][XX]*src[XX]+a[YY][YY]*src[YY];
+  dest[XX]=a[XX][XX]*src[XX];
+}
+
+static gmx_inline void tmvmul_ur0(matrix a,const rvec src,rvec dest)
+{
+  dest[XX]=a[XX][XX]*src[XX]+a[YY][XX]*src[YY]+a[ZZ][XX]*src[ZZ];
+  dest[YY]=                  a[YY][YY]*src[YY]+a[ZZ][YY]*src[ZZ];
+  dest[ZZ]=                                    a[ZZ][ZZ]*src[ZZ];
+}
+
+static gmx_inline void unitv(const rvec src,rvec dest)
+{
+  real linv;
+  
+  linv=gmx_invsqrt(norm2(src));
+  dest[XX]=linv*src[XX];
+  dest[YY]=linv*src[YY];
+  dest[ZZ]=linv*src[ZZ];
+}
+
+static gmx_inline void unitv_no_table(const rvec src,rvec dest)
+{
+  real linv;
+  
+  linv=1.0/sqrt(norm2(src));
+  dest[XX]=linv*src[XX];
+  dest[YY]=linv*src[YY];
+  dest[ZZ]=linv*src[ZZ];
+}
+
+static void calc_lll(rvec box,rvec lll)
+{
+  lll[XX] = 2.0*M_PI/box[XX];
+  lll[YY] = 2.0*M_PI/box[YY];
+  lll[ZZ] = 2.0*M_PI/box[ZZ];
+}
+
+static gmx_inline real trace(matrix m)
+{
+  return (m[XX][XX]+m[YY][YY]+m[ZZ][ZZ]);
+}
+
+static gmx_inline real _divide_err(real a,real b,const char *file,int line)
+{
+    if (fabs(b) <= GMX_REAL_MIN) 
+        gmx_fatal(FARGS,"Dividing by zero, file %s, line %d",file,line);
+    return a/b;
+}
+
+static gmx_inline int _mod(int a,int b,char *file,int line)
+{
+  if(b==0)
+    gmx_fatal(FARGS,"Modulo zero, file %s, line %d",file,line);
+  return a % b;
+}
+
+/* Operations on multidimensional rvecs, used e.g. in edsam.c */
+static void m_rveccopy(int dim, rvec *a, rvec *b)
+{
+    /* b = a */
+    int i;
+
+    for (i=0; i<dim; i++)
+        copy_rvec(a[i],b[i]);
+} 
+
+/*computer matrix vectors from base vectors and angles */
+static void matrix_convert(matrix box, rvec vec, rvec angle)
+{
+    svmul(DEG2RAD,angle,angle);
+    box[XX][XX] = vec[XX];
+    box[YY][XX] = vec[YY]*cos(angle[ZZ]);
+    box[YY][YY] = vec[YY]*sin(angle[ZZ]);
+    box[ZZ][XX] = vec[ZZ]*cos(angle[YY]);
+    box[ZZ][YY] = vec[ZZ]
+                         *(cos(angle[XX])-cos(angle[YY])*cos(angle[ZZ]))/sin(angle[ZZ]);
+    box[ZZ][ZZ] = sqrt(sqr(vec[ZZ])
+                       -box[ZZ][XX]*box[ZZ][XX]-box[ZZ][YY]*box[ZZ][YY]);
+}
+
+#define divide_err(a,b) _divide_err((a),(b),__FILE__,__LINE__)
+#define mod(a,b)    _mod((a),(b),__FILE__,__LINE__)
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _vec_h */
diff --git a/src/gromacs/libgromacs.pc.cmakein b/src/gromacs/libgromacs.pc.cmakein
new file mode 100644 (file)
index 0000000..e8adce5
--- /dev/null
@@ -0,0 +1,12 @@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCL_INSTALL_DIR@
+
+Name: libgromacs
+Description: Gromacs library
+URL: http://www.gromacs.org
+Version: @PROJECT_VERSION@
+Requires: @PKG_FFT@ @PKG_XML@
+Libs.private: -lm @CMAKE_THREAD_LIBS_INIT@ @PKG_DL_LIBS@
+Libs: -L${libdir} -lgromacs@GMX_LIBS_SUFFIX@ @PKG_FFT_LIBS@
+Cflags: -I${includedir} @PKG_CFLAGS@
+
diff --git a/src/gromacs/mdlib/CMakeLists.txt b/src/gromacs/mdlib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ed6abec
--- /dev/null
@@ -0,0 +1,7 @@
+file(GLOB MDLIB_SOURCES *.c)
+
+# Files        called xxx_test.c are test drivers with a main() function for 
+# module xxx.c, so they should not be included in the library
+file(GLOB_RECURSE NOT_MDLIB_SOURCES *_test.c)
+list(REMOVE_ITEM MDLIB_SOURCES ${NOT_MDLIB_SOURCES})
+set(MDLIB_SOURCES ${MDLIB_SOURCES} PARENT_SCOPE)
diff --git a/src/gromacs/mdlib/domdec.c b/src/gromacs/mdlib/domdec.c
new file mode 100644 (file)
index 0000000..ec9775d
--- /dev/null
@@ -0,0 +1,8656 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ * This file is part of Gromacs        Copyright (c) 1991-2008
+ * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ *
+ * 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.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gnomes, ROck Monsters And Chili Sauce
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "vec.h"
+#include "domdec.h"
+#include "domdec_network.h"
+#include "nrnb.h"
+#include "pbc.h"
+#include "chargegroup.h"
+#include "constr.h"
+#include "mdatoms.h"
+#include "names.h"
+#include "pdbio.h"
+#include "futil.h"
+#include "force.h"
+#include "pme.h"
+#include "pull.h"
+#include "pull_rotation.h"
+#include "gmx_wallcycle.h"
+#include "mdrun.h"
+#include "nsgrid.h"
+#include "shellfc.h"
+#include "mtop_util.h"
+#include "gmxfio.h"
+#include "gmx_ga2la.h"
+#include "gmx_sort.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#define DDRANK(dd,rank)    (rank)
+#define DDMASTERRANK(dd)   (dd->masterrank)
+
+typedef struct gmx_domdec_master
+{
+    /* The cell boundaries */
+    real **cell_x;
+    /* The global charge group division */
+    int  *ncg;     /* Number of home charge groups for each node */
+    int  *index;   /* Index of nnodes+1 into cg */
+    int  *cg;      /* Global charge group index */
+    int  *nat;     /* Number of home atoms for each node. */
+    int  *ibuf;    /* Buffer for communication */
+    rvec *vbuf;    /* Buffer for state scattering and gathering */
+} gmx_domdec_master_t;
+
+typedef struct
+{
+    /* The numbers of charge groups to send and receive for each cell
+     * that requires communication, the last entry contains the total
+     * number of atoms that needs to be communicated.
+     */
+    int nsend[DD_MAXIZONE+2];
+    int nrecv[DD_MAXIZONE+2];
+    /* The charge groups to send */
+    int *index;
+    int nalloc;
+    /* The atom range for non-in-place communication */
+    int cell2at0[DD_MAXIZONE];
+    int cell2at1[DD_MAXIZONE];
+} gmx_domdec_ind_t;
+
+typedef struct
+{
+    int  np;                   /* Number of grid pulses in this dimension */
+    int  np_dlb;               /* For dlb, for use with edlbAUTO          */
+    gmx_domdec_ind_t *ind;     /* The indices to communicate, size np     */
+    int  np_nalloc;
+    gmx_bool bInPlace;             /* Can we communicate in place?            */
+} gmx_domdec_comm_dim_t;
+
+typedef struct
+{
+    gmx_bool *bCellMin;    /* Temp. var.: is this cell size at the limit     */
+    real *cell_f;      /* State var.: cell boundaries, box relative      */
+    real *old_cell_f;  /* Temp. var.: old cell size                      */
+    real *cell_f_max0; /* State var.: max lower boundary, incl neighbors */
+    real *cell_f_min1; /* State var.: min upper boundary, incl neighbors */
+    real *bound_min;   /* Temp. var.: lower limit for cell boundary      */
+    real *bound_max;   /* Temp. var.: upper limit for cell boundary      */
+    gmx_bool bLimited;     /* State var.: is DLB limited in this dim and row */
+    real *buf_ncd;     /* Temp. var.                                     */
+} gmx_domdec_root_t;
+
+#define DD_NLOAD_MAX 9
+
+/* Here floats are accurate enough, since these variables
+ * only influence the load balancing, not the actual MD results.
+ */
+typedef struct
+{
+    int  nload;
+    float *load;
+    float sum;
+    float max;
+    float sum_m;
+    float cvol_min;
+    float mdf;
+    float pme;
+    int   flags;
+} gmx_domdec_load_t;
+
+typedef struct
+{
+    int  nsc;
+    int  ind_gl;
+    int  ind;
+} gmx_cgsort_t;
+
+typedef struct
+{
+    gmx_cgsort_t *sort1,*sort2;
+    int  sort_nalloc;
+    gmx_cgsort_t *sort_new;
+    int  sort_new_nalloc;
+    int  *ibuf;
+    int  ibuf_nalloc;
+} gmx_domdec_sort_t;
+
+typedef struct
+{
+    rvec *v;
+    int  nalloc;
+} vec_rvec_t;
+
+/* This enum determines the order of the coordinates.
+ * ddnatHOME and ddnatZONE should be first and second,
+ * the others can be ordered as wanted.
+ */
+enum { ddnatHOME, ddnatZONE, ddnatVSITE, ddnatCON, ddnatNR };
+
+enum { edlbAUTO, edlbNO, edlbYES, edlbNR };
+const char *edlb_names[edlbNR] = { "auto", "no", "yes" };
+
+typedef struct
+{
+    int  dim;      /* The dimension                                          */
+    gmx_bool dim_match;/* Tells if DD and PME dims match                         */
+    int  nslab;    /* The number of PME slabs in this dimension              */
+    real *slb_dim_f; /* Cell sizes for determining the PME comm. with SLB    */
+    int  *pp_min;  /* The minimum pp node location, size nslab               */
+    int  *pp_max;  /* The maximum pp node location,size nslab                */
+    int  maxshift; /* The maximum shift for coordinate redistribution in PME */
+} gmx_ddpme_t;
+
+typedef struct
+{
+    real min0;    /* The minimum bottom of this zone                        */
+    real max1;    /* The maximum top of this zone                           */
+    real mch0;    /* The maximum bottom communicaton height for this zone   */
+    real mch1;    /* The maximum top communicaton height for this zone      */
+    real p1_0;    /* The bottom value of the first cell in this zone        */
+    real p1_1;    /* The top value of the first cell in this zone           */
+} gmx_ddzone_t;
+
+typedef struct gmx_domdec_comm
+{
+    /* All arrays are indexed with 0 to dd->ndim (not Cartesian indexing),
+     * unless stated otherwise.
+     */
+
+    /* The number of decomposition dimensions for PME, 0: no PME */
+    int  npmedecompdim;
+    /* The number of nodes doing PME (PP/PME or only PME) */
+    int  npmenodes;
+    int  npmenodes_x;
+    int  npmenodes_y;
+    /* The communication setup including the PME only nodes */
+    gmx_bool bCartesianPP_PME;
+    ivec ntot;
+    int  cartpmedim;
+    int  *pmenodes;          /* size npmenodes                         */
+    int  *ddindex2simnodeid; /* size npmenodes, only with bCartesianPP
+                              * but with bCartesianPP_PME              */
+    gmx_ddpme_t ddpme[2];
+    
+    /* The DD particle-particle nodes only */
+    gmx_bool bCartesianPP;
+    int  *ddindex2ddnodeid; /* size npmenode, only with bCartesianPP_PME */
+    
+    /* The global charge groups */
+    t_block cgs_gl;
+
+    /* Should we sort the cgs */
+    int  nstSortCG;
+    gmx_domdec_sort_t *sort;
+    
+    /* Are there bonded and multi-body interactions between charge groups? */
+    gmx_bool bInterCGBondeds;
+    gmx_bool bInterCGMultiBody;
+
+    /* Data for the optional bonded interaction atom communication range */
+    gmx_bool bBondComm;
+    t_blocka *cglink;
+    char *bLocalCG;
+
+    /* The DLB option */
+    int  eDLB;
+    /* Are we actually using DLB? */
+    gmx_bool bDynLoadBal;
+
+    /* Cell sizes for static load balancing, first index cartesian */
+    real **slb_frac;
+    
+    /* The width of the communicated boundaries */
+    real cutoff_mbody;
+    real cutoff;
+    /* The minimum cell size (including triclinic correction) */
+    rvec cellsize_min;
+    /* For dlb, for use with edlbAUTO */
+    rvec cellsize_min_dlb;
+    /* The lower limit for the DD cell size with DLB */
+    real cellsize_limit;
+    /* Effectively no NB cut-off limit with DLB for systems without PBC? */
+    gmx_bool bVacDLBNoLimit;
+
+    /* tric_dir is only stored here because dd_get_ns_ranges needs it */
+    ivec tric_dir;
+    /* box0 and box_size are required with dim's without pbc and -gcom */
+    rvec box0;
+    rvec box_size;
+    
+    /* The cell boundaries */
+    rvec cell_x0;
+    rvec cell_x1;
+
+    /* The old location of the cell boundaries, to check cg displacements */
+    rvec old_cell_x0;
+    rvec old_cell_x1;
+
+    /* The communication setup and charge group boundaries for the zones */
+    gmx_domdec_zones_t zones;
+    
+    /* The zone limits for DD dimensions 1 and 2 (not 0), determined from
+     * cell boundaries of neighboring cells for dynamic load balancing.
+     */
+    gmx_ddzone_t zone_d1[2];
+    gmx_ddzone_t zone_d2[2][2];
+    
+    /* The coordinate/force communication setup and indices */
+    gmx_domdec_comm_dim_t cd[DIM];
+    /* The maximum number of cells to communicate with in one dimension */
+    int  maxpulse;
+    
+    /* Which cg distribution is stored on the master node */
+    int master_cg_ddp_count;
+    
+    /* The number of cg's received from the direct neighbors */
+    int  zone_ncg1[DD_MAXZONE];
+    
+    /* The atom counts, the range for each type t is nat[t-1] <= at < nat[t] */
+    int  nat[ddnatNR];
+    
+    /* Communication buffer for general use */
+    int  *buf_int;
+    int  nalloc_int;
+
+     /* Communication buffer for general use */
+    vec_rvec_t vbuf;
+    
+    /* Communication buffers only used with multiple grid pulses */
+    int  *buf_int2;
+    int  nalloc_int2;
+    vec_rvec_t vbuf2;
+    
+    /* Communication buffers for local redistribution */
+    int  **cggl_flag;
+    int  cggl_flag_nalloc[DIM*2];
+    rvec **cgcm_state;
+    int  cgcm_state_nalloc[DIM*2];
+    
+    /* Cell sizes for dynamic load balancing */
+    gmx_domdec_root_t **root;
+    real *cell_f_row;
+    real cell_f0[DIM];
+    real cell_f1[DIM];
+    real cell_f_max0[DIM];
+    real cell_f_min1[DIM];
+    
+    /* Stuff for load communication */
+    gmx_bool bRecordLoad;
+    gmx_domdec_load_t *load;
+#ifdef GMX_MPI
+    MPI_Comm *mpi_comm_load;
+#endif
+
+    /* Maximum DLB scaling per load balancing step in percent */
+    int dlb_scale_lim;
+
+    /* Cycle counters */
+    float cycl[ddCyclNr];
+    int   cycl_n[ddCyclNr];
+    float cycl_max[ddCyclNr];
+    /* Flop counter (0=no,1=yes,2=with (eFlop-1)*5% noise */
+    int eFlop;
+    double flop;
+    int    flop_n;
+    /* Have often have did we have load measurements */
+    int    n_load_have;
+    /* Have often have we collected the load measurements */
+    int    n_load_collect;
+    
+    /* Statistics */
+    double sum_nat[ddnatNR-ddnatZONE];
+    int    ndecomp;
+    int    nload;
+    double load_step;
+    double load_sum;
+    double load_max;
+    ivec   load_lim;
+    double load_mdf;
+    double load_pme;
+
+    /* The last partition step */
+    gmx_large_int_t globalcomm_step;
+
+    /* Debugging */
+    int  nstDDDump;
+    int  nstDDDumpGrid;
+    int  DD_debug;
+} gmx_domdec_comm_t;
+
+/* The size per charge group of the cggl_flag buffer in gmx_domdec_comm_t */
+#define DD_CGIBS 2
+
+/* The flags for the cggl_flag buffer in gmx_domdec_comm_t */
+#define DD_FLAG_NRCG  65535
+#define DD_FLAG_FW(d) (1<<(16+(d)*2))
+#define DD_FLAG_BW(d) (1<<(16+(d)*2+1))
+
+/* Zone permutation required to obtain consecutive charge groups
+ * for neighbor searching.
+ */
+static const int zone_perm[3][4] = { {0,0,0,0},{1,0,0,0},{3,0,1,2} };
+
+/* dd_zo and dd_zp3/dd_zp2 are set up such that i zones with non-zero
+ * components see only j zones with that component 0.
+ */
+
+/* The DD zone order */
+static const ivec dd_zo[DD_MAXZONE] =
+  {{0,0,0},{1,0,0},{1,1,0},{0,1,0},{0,1,1},{0,0,1},{1,0,1},{1,1,1}};
+
+/* The 3D setup */
+#define dd_z3n  8
+#define dd_zp3n 4
+static const ivec dd_zp3[dd_zp3n] = {{0,0,8},{1,3,6},{2,5,6},{3,5,7}};
+
+/* The 2D setup */
+#define dd_z2n  4
+#define dd_zp2n 2
+static const ivec dd_zp2[dd_zp2n] = {{0,0,4},{1,3,4}};
+
+/* The 1D setup */
+#define dd_z1n  2
+#define dd_zp1n 1
+static const ivec dd_zp1[dd_zp1n] = {{0,0,2}};
+
+/* Factors used to avoid problems due to rounding issues */
+#define DD_CELL_MARGIN       1.0001
+#define DD_CELL_MARGIN2      1.00005
+/* Factor to account for pressure scaling during nstlist steps */
+#define DD_PRES_SCALE_MARGIN 1.02
+
+/* Allowed performance loss before we DLB or warn */
+#define DD_PERF_LOSS 0.05
+
+#define DD_CELL_F_SIZE(dd,di) ((dd)->nc[(dd)->dim[(di)]]+1+(di)*2+1+(di))
+
+/* Use separate MPI send and receive commands
+ * when nnodes <= GMX_DD_NNODES_SENDRECV.
+ * This saves memory (and some copying for small nnodes).
+ * For high parallelization scatter and gather calls are used.
+ */
+#define GMX_DD_NNODES_SENDRECV 4
+
+
+/*
+#define dd_index(n,i) ((((i)[ZZ]*(n)[YY] + (i)[YY])*(n)[XX]) + (i)[XX])
+
+static void index2xyz(ivec nc,int ind,ivec xyz)
+{
+  xyz[XX] = ind % nc[XX];
+  xyz[YY] = (ind / nc[XX]) % nc[YY];
+  xyz[ZZ] = ind / (nc[YY]*nc[XX]);
+}
+*/
+
+/* This order is required to minimize the coordinate communication in PME
+ * which uses decomposition in the x direction.
+ */
+#define dd_index(n,i) ((((i)[XX]*(n)[YY] + (i)[YY])*(n)[ZZ]) + (i)[ZZ])
+
+static void ddindex2xyz(ivec nc,int ind,ivec xyz)
+{
+    xyz[XX] = ind / (nc[YY]*nc[ZZ]);
+    xyz[YY] = (ind / nc[ZZ]) % nc[YY];
+    xyz[ZZ] = ind % nc[ZZ];
+}
+
+static int ddcoord2ddnodeid(gmx_domdec_t *dd,ivec c)
+{
+    int ddindex;
+    int ddnodeid=-1;
+    
+    ddindex = dd_index(dd->nc,c);
+    if (dd->comm->bCartesianPP_PME)
+    {
+        ddnodeid = dd->comm->ddindex2ddnodeid[ddindex];
+    }
+    else if (dd->comm->bCartesianPP)
+    {
+#ifdef GMX_MPI
+        MPI_Cart_rank(dd->mpi_comm_all,c,&ddnodeid);
+#endif
+    }
+    else
+    {
+        ddnodeid = ddindex;
+    }
+    
+    return ddnodeid;
+}
+
+static gmx_bool dynamic_dd_box(gmx_ddbox_t *ddbox,t_inputrec *ir)
+{
+    return (ddbox->nboundeddim < DIM || DYNAMIC_BOX(*ir));
+}
+
+int ddglatnr(gmx_domdec_t *dd,int i)
+{
+    int atnr;
+    
+    if (dd == NULL)
+    {
+        atnr = i + 1;
+    }
+    else
+    {
+        if (i >= dd->comm->nat[ddnatNR-1])
+        {
+            gmx_fatal(FARGS,"glatnr called with %d, which is larger than the local number of atoms (%d)",i,dd->comm->nat[ddnatNR-1]);
+        }
+        atnr = dd->gatindex[i] + 1;
+    }
+    
+    return atnr;
+}
+
+t_block *dd_charge_groups_global(gmx_domdec_t *dd)
+{
+    return &dd->comm->cgs_gl;
+}
+
+static void vec_rvec_init(vec_rvec_t *v)
+{
+    v->nalloc = 0;
+    v->v      = NULL;
+}
+
+static void vec_rvec_check_alloc(vec_rvec_t *v,int n)
+{
+    if (n > v->nalloc)
+    {
+        v->nalloc = over_alloc_dd(n);
+        srenew(v->v,v->nalloc);
+    }
+}
+
+void dd_store_state(gmx_domdec_t *dd,t_state *state)
+{
+    int i;
+    
+    if (state->ddp_count != dd->ddp_count)
+    {
+        gmx_incons("The state does not the domain decomposition state");
+    }
+    
+    state->ncg_gl = dd->ncg_home;
+    if (state->ncg_gl > state->cg_gl_nalloc)
+    {
+        state->cg_gl_nalloc = over_alloc_dd(state->ncg_gl);
+        srenew(state->cg_gl,state->cg_gl_nalloc);
+    }
+    for(i=0; i<state->ncg_gl; i++)
+    {
+        state->cg_gl[i] = dd->index_gl[i];
+    }
+    
+    state->ddp_count_cg_gl = dd->ddp_count;
+}
+
+gmx_domdec_zones_t *domdec_zones(gmx_domdec_t *dd)
+{
+    return &dd->comm->zones;
+}
+
+void dd_get_ns_ranges(gmx_domdec_t *dd,int icg,
+                      int *jcg0,int *jcg1,ivec shift0,ivec shift1)
+{
+    gmx_domdec_zones_t *zones;
+    int izone,d,dim;
+
+    zones = &dd->comm->zones;
+
+    izone = 0;
+    while (icg >= zones->izone[izone].cg1)
+    {
+        izone++;
+    }
+    
+    if (izone == 0)
+    {
+        *jcg0 = icg;
+    }
+    else if (izone < zones->nizone)
+    {
+        *jcg0 = zones->izone[izone].jcg0;
+    }
+    else
+    {
+        gmx_fatal(FARGS,"DD icg %d out of range: izone (%d) >= nizone (%d)",
+                  icg,izone,zones->nizone);
+    }
+        
+    *jcg1 = zones->izone[izone].jcg1;
+    
+    for(d=0; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        shift0[dim] = zones->izone[izone].shift0[dim];
+        shift1[dim] = zones->izone[izone].shift1[dim];
+        if (dd->comm->tric_dir[dim] || (dd->bGridJump && d > 0))
+        {
+            /* A conservative approach, this can be optimized */
+            shift0[dim] -= 1;
+            shift1[dim] += 1;
+        }
+    }
+}
+
+int dd_natoms_vsite(gmx_domdec_t *dd)
+{
+    return dd->comm->nat[ddnatVSITE];
+}
+
+void dd_get_constraint_range(gmx_domdec_t *dd,int *at_start,int *at_end)
+{
+    *at_start = dd->comm->nat[ddnatCON-1];
+    *at_end   = dd->comm->nat[ddnatCON];
+}
+
+void dd_move_x(gmx_domdec_t *dd,matrix box,rvec x[])
+{
+    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
+    int  *index,*cgindex;
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_comm_dim_t *cd;
+    gmx_domdec_ind_t *ind;
+    rvec shift={0,0,0},*buf,*rbuf;
+    gmx_bool bPBC,bScrew;
+    
+    comm = dd->comm;
+    
+    cgindex = dd->cgindex;
+    
+    buf = comm->vbuf.v;
+
+    nzone = 1;
+    nat_tot = dd->nat_home;
+    for(d=0; d<dd->ndim; d++)
+    {
+        bPBC   = (dd->ci[dd->dim[d]] == 0);
+        bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
+        if (bPBC)
+        {
+            copy_rvec(box[dd->dim[d]],shift);
+        }
+        cd = &comm->cd[d];
+        for(p=0; p<cd->np; p++)
+        {
+            ind = &cd->ind[p];
+            index = ind->index;
+            n = 0;
+            if (!bPBC)
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        copy_rvec(x[j],buf[n]);
+                        n++;
+                    }
+                }
+            }
+            else if (!bScrew)
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        /* We need to shift the coordinates */
+                        rvec_add(x[j],shift,buf[n]);
+                        n++;
+                    }
+                }
+            }
+            else
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        /* Shift x */
+                        buf[n][XX] = x[j][XX] + shift[XX];
+                        /* Rotate y and z.
+                         * This operation requires a special shift force
+                         * treatment, which is performed in calc_vir.
+                         */
+                        buf[n][YY] = box[YY][YY] - x[j][YY];
+                        buf[n][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
+                        n++;
+                    }
+                }
+            }
+            
+            if (cd->bInPlace)
+            {
+                rbuf = x + nat_tot;
+            }
+            else
+            {
+                rbuf = comm->vbuf2.v;
+            }
+            /* Send and receive the coordinates */
+            dd_sendrecv_rvec(dd, d, dddirBackward,
+                             buf,  ind->nsend[nzone+1],
+                             rbuf, ind->nrecv[nzone+1]);
+            if (!cd->bInPlace)
+            {
+                j = 0;
+                for(zone=0; zone<nzone; zone++)
+                {
+                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
+                    {
+                        copy_rvec(rbuf[j],x[i]);
+                        j++;
+                    }
+                }
+            }
+            nat_tot += ind->nrecv[nzone+1];
+        }
+        nzone += nzone;
+    }
+}
+
+void dd_move_f(gmx_domdec_t *dd,rvec f[],rvec *fshift)
+{
+    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
+    int  *index,*cgindex;
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_comm_dim_t *cd;
+    gmx_domdec_ind_t *ind;
+    rvec *buf,*sbuf;
+    ivec vis;
+    int  is;
+    gmx_bool bPBC,bScrew;
+    
+    comm = dd->comm;
+    
+    cgindex = dd->cgindex;
+
+    buf = comm->vbuf.v;
+
+    n = 0;
+    nzone = comm->zones.n/2;
+    nat_tot = dd->nat_tot;
+    for(d=dd->ndim-1; d>=0; d--)
+    {
+        bPBC   = (dd->ci[dd->dim[d]] == 0);
+        bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
+        if (fshift == NULL && !bScrew)
+        {
+            bPBC = FALSE;
+        }
+        /* Determine which shift vector we need */
+        clear_ivec(vis);
+        vis[dd->dim[d]] = 1;
+        is = IVEC2IS(vis);
+        
+        cd = &comm->cd[d];
+        for(p=cd->np-1; p>=0; p--) {
+            ind = &cd->ind[p];
+            nat_tot -= ind->nrecv[nzone+1];
+            if (cd->bInPlace)
+            {
+                sbuf = f + nat_tot;
+            }
+            else
+            {
+                sbuf = comm->vbuf2.v;
+                j = 0;
+                for(zone=0; zone<nzone; zone++)
+                {
+                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
+                    {
+                        copy_rvec(f[i],sbuf[j]);
+                        j++;
+                    }
+                }
+            }
+            /* Communicate the forces */
+            dd_sendrecv_rvec(dd, d, dddirForward,
+                             sbuf, ind->nrecv[nzone+1],
+                             buf,  ind->nsend[nzone+1]);
+            index = ind->index;
+            /* Add the received forces */
+            n = 0;
+            if (!bPBC)
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        rvec_inc(f[j],buf[n]);
+                        n++;
+                    }
+                } 
+            }
+            else if (!bScrew)
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        rvec_inc(f[j],buf[n]);
+                        /* Add this force to the shift force */
+                        rvec_inc(fshift[is],buf[n]);
+                        n++;
+                    }
+                }
+            }
+            else
+            {
+                for(i=0; i<ind->nsend[nzone]; i++)
+                {
+                    at0 = cgindex[index[i]];
+                    at1 = cgindex[index[i]+1];
+                    for(j=at0; j<at1; j++)
+                    {
+                        /* Rotate the force */
+                        f[j][XX] += buf[n][XX];
+                        f[j][YY] -= buf[n][YY];
+                        f[j][ZZ] -= buf[n][ZZ];
+                        if (fshift)
+                        {
+                            /* Add this force to the shift force */
+                            rvec_inc(fshift[is],buf[n]);
+                        }
+                        n++;
+                    }
+                }
+            }
+        }
+        nzone /= 2;
+    }
+}
+
+void dd_atom_spread_real(gmx_domdec_t *dd,real v[])
+{
+    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
+    int  *index,*cgindex;
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_comm_dim_t *cd;
+    gmx_domdec_ind_t *ind;
+    real *buf,*rbuf;
+    
+    comm = dd->comm;
+    
+    cgindex = dd->cgindex;
+    
+    buf = &comm->vbuf.v[0][0];
+
+    nzone = 1;
+    nat_tot = dd->nat_home;
+    for(d=0; d<dd->ndim; d++)
+    {
+        cd = &comm->cd[d];
+        for(p=0; p<cd->np; p++)
+        {
+            ind = &cd->ind[p];
+            index = ind->index;
+            n = 0;
+            for(i=0; i<ind->nsend[nzone]; i++)
+            {
+                at0 = cgindex[index[i]];
+                at1 = cgindex[index[i]+1];
+                for(j=at0; j<at1; j++)
+                {
+                    buf[n] = v[j];
+                    n++;
+                }
+            }
+            
+            if (cd->bInPlace)
+            {
+                rbuf = v + nat_tot;
+            }
+            else
+            {
+                rbuf = &comm->vbuf2.v[0][0];
+            }
+            /* Send and receive the coordinates */
+            dd_sendrecv_real(dd, d, dddirBackward,
+                             buf,  ind->nsend[nzone+1],
+                             rbuf, ind->nrecv[nzone+1]);
+            if (!cd->bInPlace)
+            {
+                j = 0;
+                for(zone=0; zone<nzone; zone++)
+                {
+                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
+                    {
+                        v[i] = rbuf[j];
+                        j++;
+                    }
+                }
+            }
+            nat_tot += ind->nrecv[nzone+1];
+        }
+        nzone += nzone;
+    }
+}
+
+void dd_atom_sum_real(gmx_domdec_t *dd,real v[])
+{
+    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
+    int  *index,*cgindex;
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_comm_dim_t *cd;
+    gmx_domdec_ind_t *ind;
+    real *buf,*sbuf;
+    
+    comm = dd->comm;
+    
+    cgindex = dd->cgindex;
+
+    buf = &comm->vbuf.v[0][0];
+
+    n = 0;
+    nzone = comm->zones.n/2;
+    nat_tot = dd->nat_tot;
+    for(d=dd->ndim-1; d>=0; d--)
+    {
+        cd = &comm->cd[d];
+        for(p=cd->np-1; p>=0; p--) {
+            ind = &cd->ind[p];
+            nat_tot -= ind->nrecv[nzone+1];
+            if (cd->bInPlace)
+            {
+                sbuf = v + nat_tot;
+            }
+            else
+            {
+                sbuf = &comm->vbuf2.v[0][0];
+                j = 0;
+                for(zone=0; zone<nzone; zone++)
+                {
+                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
+                    {
+                        sbuf[j] = v[i];
+                        j++;
+                    }
+                }
+            }
+            /* Communicate the forces */
+            dd_sendrecv_real(dd, d, dddirForward,
+                             sbuf, ind->nrecv[nzone+1],
+                             buf,  ind->nsend[nzone+1]);
+            index = ind->index;
+            /* Add the received forces */
+            n = 0;
+            for(i=0; i<ind->nsend[nzone]; i++)
+            {
+                at0 = cgindex[index[i]];
+                at1 = cgindex[index[i]+1];
+                for(j=at0; j<at1; j++)
+                {
+                    v[j] += buf[n];
+                    n++;
+                }
+            } 
+        }
+        nzone /= 2;
+    }
+}
+
+static void print_ddzone(FILE *fp,int d,int i,int j,gmx_ddzone_t *zone)
+{
+    fprintf(fp,"zone d0 %d d1 %d d2 %d  min0 %6.3f max1 %6.3f mch0 %6.3f mch1 %6.3f p1_0 %6.3f p1_1 %6.3f\n",
+            d,i,j,
+            zone->min0,zone->max1,
+            zone->mch0,zone->mch0,
+            zone->p1_0,zone->p1_1);
+}
+
+static void dd_sendrecv_ddzone(const gmx_domdec_t *dd,
+                               int ddimind,int direction,
+                               gmx_ddzone_t *buf_s,int n_s,
+                               gmx_ddzone_t *buf_r,int n_r)
+{
+    rvec vbuf_s[5*2],vbuf_r[5*2];
+    int i;
+
+    for(i=0; i<n_s; i++)
+    {
+        vbuf_s[i*2  ][0] = buf_s[i].min0;
+        vbuf_s[i*2  ][1] = buf_s[i].max1;
+        vbuf_s[i*2  ][2] = buf_s[i].mch0;
+        vbuf_s[i*2+1][0] = buf_s[i].mch1;
+        vbuf_s[i*2+1][1] = buf_s[i].p1_0;
+        vbuf_s[i*2+1][2] = buf_s[i].p1_1;
+    }
+
+    dd_sendrecv_rvec(dd, ddimind, direction,
+                     vbuf_s, n_s*2,
+                     vbuf_r, n_r*2);
+
+    for(i=0; i<n_r; i++)
+    {
+        buf_r[i].min0 = vbuf_r[i*2  ][0];
+        buf_r[i].max1 = vbuf_r[i*2  ][1];
+        buf_r[i].mch0 = vbuf_r[i*2  ][2];
+        buf_r[i].mch1 = vbuf_r[i*2+1][0];
+        buf_r[i].p1_0 = vbuf_r[i*2+1][1];
+        buf_r[i].p1_1 = vbuf_r[i*2+1][2];
+    }
+}
+
+static void dd_move_cellx(gmx_domdec_t *dd,gmx_ddbox_t *ddbox,
+                          rvec cell_ns_x0,rvec cell_ns_x1)
+{
+    int  d,d1,dim,dim1,pos,buf_size,i,j,k,p,npulse,npulse_min;
+    gmx_ddzone_t *zp,buf_s[5],buf_r[5],buf_e[5];
+    rvec extr_s[2],extr_r[2];
+    rvec dh;
+    real dist_d,c=0,det;
+    gmx_domdec_comm_t *comm;
+    gmx_bool bPBC,bUse;
+
+    comm = dd->comm;
+
+    for(d=1; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        zp = (d == 1) ? &comm->zone_d1[0] : &comm->zone_d2[0][0];
+        zp->min0 = cell_ns_x0[dim];
+        zp->max1 = cell_ns_x1[dim];
+        zp->mch0 = cell_ns_x0[dim];
+        zp->mch1 = cell_ns_x1[dim];
+        zp->p1_0 = cell_ns_x0[dim];
+        zp->p1_1 = cell_ns_x1[dim];
+    }
+    
+    for(d=dd->ndim-2; d>=0; d--)
+    {
+        dim  = dd->dim[d];
+        bPBC = (dim < ddbox->npbcdim);
+
+        /* Use an rvec to store two reals */
+        extr_s[d][0] = comm->cell_f0[d+1];
+        extr_s[d][1] = comm->cell_f1[d+1];
+        extr_s[d][2] = 0;
+
+        pos = 0;
+        /* Store the extremes in the backward sending buffer,
+         * so the get updated separately from the forward communication.
+         */
+        for(d1=d; d1<dd->ndim-1; d1++)
+        {
+            /* We invert the order to be able to use the same loop for buf_e */
+            buf_s[pos].min0 = extr_s[d1][1];
+            buf_s[pos].max1 = extr_s[d1][0];
+            buf_s[pos].mch0 = 0;
+            buf_s[pos].mch1 = 0;
+            /* Store the cell corner of the dimension we communicate along */
+            buf_s[pos].p1_0 = comm->cell_x0[dim];
+            buf_s[pos].p1_1 = 0;
+            pos++;
+        }
+
+        buf_s[pos] = (dd->ndim == 2) ? comm->zone_d1[0] : comm->zone_d2[0][0];
+        pos++;
+
+        if (dd->ndim == 3 && d == 0)
+        {
+            buf_s[pos] = comm->zone_d2[0][1];
+            pos++;
+            buf_s[pos] = comm->zone_d1[0];
+            pos++;
+        }
+
+        /* We only need to communicate the extremes
+         * in the forward direction
+         */
+        npulse = comm->cd[d].np;
+        if (bPBC)
+        {
+            /* Take the minimum to avoid double communication */
+            npulse_min = min(npulse,dd->nc[dim]-1-npulse);
+        }
+        else
+        {
+            /* Without PBC we should really not communicate over
+             * the boundaries, but implementing that complicates
+             * the communication setup and therefore we simply
+             * do all communication, but ignore some data.
+             */
+            npulse_min = npulse;
+        }
+        for(p=0; p<npulse_min; p++)
+        {
+            /* Communicate the extremes forward */
+            bUse = (bPBC || dd->ci[dim] > 0);
+
+            dd_sendrecv_rvec(dd, d, dddirForward,
+                             extr_s+d, dd->ndim-d-1,
+                             extr_r+d, dd->ndim-d-1);
+
+            if (bUse)
+            {
+                for(d1=d; d1<dd->ndim-1; d1++)
+                {
+                    extr_s[d1][0] = max(extr_s[d1][0],extr_r[d1][0]);
+                    extr_s[d1][1] = min(extr_s[d1][1],extr_r[d1][1]);
+                }
+            }
+        }
+
+        buf_size = pos;
+        for(p=0; p<npulse; p++)
+        {
+            /* Communicate all the zone information backward */
+            bUse = (bPBC || dd->ci[dim] < dd->nc[dim] - 1);
+
+            dd_sendrecv_ddzone(dd, d, dddirBackward,
+                               buf_s, buf_size,
+                               buf_r, buf_size);
+
+            clear_rvec(dh);
+            if (p > 0)
+            {
+                for(d1=d+1; d1<dd->ndim; d1++)
+                {
+                    /* Determine the decrease of maximum required
+                     * communication height along d1 due to the distance along d,
+                     * this avoids a lot of useless atom communication.
+                     */
+                    dist_d = comm->cell_x1[dim] - buf_r[0].p1_0;
+
+                    if (ddbox->tric_dir[dim])
+                    {
+                        /* c is the off-diagonal coupling between the cell planes
+                         * along directions d and d1.
+                         */
+                        c = ddbox->v[dim][dd->dim[d1]][dim];
+                    }
+                    else
+                    {
+                        c = 0;
+                    }
+                    det = (1 + c*c)*comm->cutoff*comm->cutoff - dist_d*dist_d;
+                    if (det > 0)
+                    {
+                        dh[d1] = comm->cutoff - (c*dist_d + sqrt(det))/(1 + c*c);
+                    }
+                    else
+                    {
+                        /* A negative value signals out of range */
+                        dh[d1] = -1;
+                    }
+                }
+            }
+
+            /* Accumulate the extremes over all pulses */
+            for(i=0; i<buf_size; i++)
+            {
+                if (p == 0)
+                {
+                    buf_e[i] = buf_r[i];
+                }
+                else
+                {
+                    if (bUse)
+                    {
+                        buf_e[i].min0 = min(buf_e[i].min0,buf_r[i].min0);
+                        buf_e[i].max1 = max(buf_e[i].max1,buf_r[i].max1);
+                    }
+
+                    if (dd->ndim == 3 && d == 0 && i == buf_size - 1)
+                    {
+                        d1 = 1;
+                    }
+                    else
+                    {
+                        d1 = d + 1;
+                    }
+                    if (bUse && dh[d1] >= 0)
+                    {
+                        buf_e[i].mch0 = max(buf_e[i].mch0,buf_r[i].mch0-dh[d1]);
+                        buf_e[i].mch1 = max(buf_e[i].mch1,buf_r[i].mch1-dh[d1]);
+                    }
+                }
+                /* Copy the received buffer to the send buffer,
+                 * to pass the data through with the next pulse.
+                 */
+                buf_s[i] = buf_r[i];
+            }
+            if (((bPBC || dd->ci[dim]+npulse < dd->nc[dim]) && p == npulse-1) ||
+                (!bPBC && dd->ci[dim]+1+p == dd->nc[dim]-1))
+            {
+                /* Store the extremes */ 
+                pos = 0;
+
+                for(d1=d; d1<dd->ndim-1; d1++)
+                {
+                    extr_s[d1][1] = min(extr_s[d1][1],buf_e[pos].min0);
+                    extr_s[d1][0] = max(extr_s[d1][0],buf_e[pos].max1);
+                    pos++;
+                }
+
+                if (d == 1 || (d == 0 && dd->ndim == 3))
+                {
+                    for(i=d; i<2; i++)
+                    {
+                        comm->zone_d2[1-d][i] = buf_e[pos];
+                        pos++;
+                    }
+                }
+                if (d == 0)
+                {
+                    comm->zone_d1[1] = buf_e[pos];
+                    pos++;
+                }
+            }
+        }
+    }
+    
+    if (dd->ndim >= 2)
+    {
+        dim = dd->dim[1];
+        for(i=0; i<2; i++)
+        {
+            if (debug)
+            {
+                print_ddzone(debug,1,i,0,&comm->zone_d1[i]);
+            }
+            cell_ns_x0[dim] = min(cell_ns_x0[dim],comm->zone_d1[i].min0);
+            cell_ns_x1[dim] = max(cell_ns_x1[dim],comm->zone_d1[i].max1);
+        }
+    }
+    if (dd->ndim >= 3)
+    {
+        dim = dd->dim[2];
+        for(i=0; i<2; i++)
+        {
+            for(j=0; j<2; j++)
+            {
+                if (debug)
+                {
+                    print_ddzone(debug,2,i,j,&comm->zone_d2[i][j]);
+                }
+                cell_ns_x0[dim] = min(cell_ns_x0[dim],comm->zone_d2[i][j].min0);
+                cell_ns_x1[dim] = max(cell_ns_x1[dim],comm->zone_d2[i][j].max1);
+            }
+        }
+    }
+    for(d=1; d<dd->ndim; d++)
+    {
+        comm->cell_f_max0[d] = extr_s[d-1][0];
+        comm->cell_f_min1[d] = extr_s[d-1][1];
+        if (debug)
+        {
+            fprintf(debug,"Cell fraction d %d, max0 %f, min1 %f\n",
+                    d,comm->cell_f_max0[d],comm->cell_f_min1[d]);
+        }
+    }
+}
+
+static void dd_collect_cg(gmx_domdec_t *dd,
+                          t_state *state_local)
+{
+    gmx_domdec_master_t *ma=NULL;
+    int buf2[2],*ibuf,i,ncg_home=0,*cg=NULL,nat_home=0;
+    t_block *cgs_gl;
+
+    if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
+    {
+        /* The master has the correct distribution */
+        return;
+    }
+    
+    if (state_local->ddp_count == dd->ddp_count)
+    {
+        ncg_home = dd->ncg_home;
+        cg       = dd->index_gl;
+        nat_home = dd->nat_home;
+    } 
+    else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
+    {
+        cgs_gl = &dd->comm->cgs_gl;
+
+        ncg_home = state_local->ncg_gl;
+        cg       = state_local->cg_gl;
+        nat_home = 0;
+        for(i=0; i<ncg_home; i++)
+        {
+            nat_home += cgs_gl->index[cg[i]+1] - cgs_gl->index[cg[i]];
+        }
+    }
+    else
+    {
+        gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
+    }
+    
+    buf2[0] = dd->ncg_home;
+    buf2[1] = dd->nat_home;
+    if (DDMASTER(dd))
+    {
+        ma = dd->ma;
+        ibuf = ma->ibuf;
+    }
+    else
+    {
+        ibuf = NULL;
+    }
+    /* Collect the charge group and atom counts on the master */
+    dd_gather(dd,2*sizeof(int),buf2,ibuf);
+    
+    if (DDMASTER(dd))
+    {
+        ma->index[0] = 0;
+        for(i=0; i<dd->nnodes; i++)
+        {
+            ma->ncg[i] = ma->ibuf[2*i];
+            ma->nat[i] = ma->ibuf[2*i+1];
+            ma->index[i+1] = ma->index[i] + ma->ncg[i];
+            
+        }
+        /* Make byte counts and indices */
+        for(i=0; i<dd->nnodes; i++)
+        {
+            ma->ibuf[i] = ma->ncg[i]*sizeof(int);
+            ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
+        }
+        if (debug)
+        {
+            fprintf(debug,"Initial charge group distribution: ");
+            for(i=0; i<dd->nnodes; i++)
+                fprintf(debug," %d",ma->ncg[i]);
+            fprintf(debug,"\n");
+        }
+    }
+    
+    /* Collect the charge group indices on the master */
+    dd_gatherv(dd,
+               dd->ncg_home*sizeof(int),dd->index_gl,
+               DDMASTER(dd) ? ma->ibuf : NULL,
+               DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
+               DDMASTER(dd) ? ma->cg : NULL);
+    
+    dd->comm->master_cg_ddp_count = state_local->ddp_count;
+}
+
+static void dd_collect_vec_sendrecv(gmx_domdec_t *dd,
+                                    rvec *lv,rvec *v)
+{
+    gmx_domdec_master_t *ma;
+    int  n,i,c,a,nalloc=0;
+    rvec *buf=NULL;
+    t_block *cgs_gl;
+
+    ma = dd->ma;
+    
+    if (!DDMASTER(dd))
+    {
+#ifdef GMX_MPI
+        MPI_Send(lv,dd->nat_home*sizeof(rvec),MPI_BYTE,DDMASTERRANK(dd),
+                 dd->rank,dd->mpi_comm_all);
+#endif
+    } else {
+        /* Copy the master coordinates to the global array */
+        cgs_gl = &dd->comm->cgs_gl;
+
+        n = DDMASTERRANK(dd);
+        a = 0;
+        for(i=ma->index[n]; i<ma->index[n+1]; i++)
+        {
+            for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
+            {
+                copy_rvec(lv[a++],v[c]);
+            }
+        }
+        
+        for(n=0; n<dd->nnodes; n++)
+        {
+            if (n != dd->rank)
+            {
+                if (ma->nat[n] > nalloc)
+                {
+                    nalloc = over_alloc_dd(ma->nat[n]);
+                    srenew(buf,nalloc);
+                }
+#ifdef GMX_MPI
+                MPI_Recv(buf,ma->nat[n]*sizeof(rvec),MPI_BYTE,DDRANK(dd,n),
+                         n,dd->mpi_comm_all,MPI_STATUS_IGNORE);
+#endif
+                a = 0;
+                for(i=ma->index[n]; i<ma->index[n+1]; i++)
+                {
+                    for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
+                    {
+                        copy_rvec(buf[a++],v[c]);
+                    }
+                }
+            }
+        }
+        sfree(buf);
+    }
+}
+
+static void get_commbuffer_counts(gmx_domdec_t *dd,
+                                  int **counts,int **disps)
+{
+    gmx_domdec_master_t *ma;
+    int n;
+
+    ma = dd->ma;
+    
+    /* Make the rvec count and displacment arrays */
+    *counts  = ma->ibuf;
+    *disps   = ma->ibuf + dd->nnodes;
+    for(n=0; n<dd->nnodes; n++)
+    {
+        (*counts)[n] = ma->nat[n]*sizeof(rvec);
+        (*disps)[n]  = (n == 0 ? 0 : (*disps)[n-1] + (*counts)[n-1]);
+    }
+}
+
+static void dd_collect_vec_gatherv(gmx_domdec_t *dd,
+                                   rvec *lv,rvec *v)
+{
+    gmx_domdec_master_t *ma;
+    int  *rcounts=NULL,*disps=NULL;
+    int  n,i,c,a;
+    rvec *buf=NULL;
+    t_block *cgs_gl;
+    
+    ma = dd->ma;
+    
+    if (DDMASTER(dd))
+    {
+        get_commbuffer_counts(dd,&rcounts,&disps);
+
+        buf = ma->vbuf;
+    }
+    
+    dd_gatherv(dd,dd->nat_home*sizeof(rvec),lv,rcounts,disps,buf);
+
+    if (DDMASTER(dd))
+    {
+        cgs_gl = &dd->comm->cgs_gl;
+
+        a = 0;
+        for(n=0; n<dd->nnodes; n++)
+        {
+            for(i=ma->index[n]; i<ma->index[n+1]; i++)
+            {
+                for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
+                {
+                    copy_rvec(buf[a++],v[c]);
+                }
+            }
+        }
+    }
+}
+
+void dd_collect_vec(gmx_domdec_t *dd,
+                    t_state *state_local,rvec *lv,rvec *v)
+{
+    gmx_domdec_master_t *ma;
+    int  n,i,c,a,nalloc=0;
+    rvec *buf=NULL;
+    
+    dd_collect_cg(dd,state_local);
+
+    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
+    {
+        dd_collect_vec_sendrecv(dd,lv,v);
+    }
+    else
+    {
+        dd_collect_vec_gatherv(dd,lv,v);
+    }
+}
+
+
+void dd_collect_state(gmx_domdec_t *dd,
+                      t_state *state_local,t_state *state)
+{
+    int est,i,j,nh;
+
+    nh = state->nhchainlength;
+
+    if (DDMASTER(dd))
+    {
+        state->lambda = state_local->lambda;
+        state->veta = state_local->veta;
+        state->vol0 = state_local->vol0;
+        copy_mat(state_local->box,state->box);
+        copy_mat(state_local->boxv,state->boxv);
+        copy_mat(state_local->svir_prev,state->svir_prev);
+        copy_mat(state_local->fvir_prev,state->fvir_prev);
+        copy_mat(state_local->pres_prev,state->pres_prev);
+
+
+        for(i=0; i<state_local->ngtc; i++)
+        {
+            for(j=0; j<nh; j++) {
+                state->nosehoover_xi[i*nh+j]        = state_local->nosehoover_xi[i*nh+j];
+                state->nosehoover_vxi[i*nh+j]       = state_local->nosehoover_vxi[i*nh+j];
+            }
+            state->therm_integral[i] = state_local->therm_integral[i];            
+        }
+        for(i=0; i<state_local->nnhpres; i++) 
+        {
+            for(j=0; j<nh; j++) {
+                state->nhpres_xi[i*nh+j]        = state_local->nhpres_xi[i*nh+j];
+                state->nhpres_vxi[i*nh+j]       = state_local->nhpres_vxi[i*nh+j];
+            }
+        }
+    }
+    for(est=0; est<estNR; est++)
+    {
+        if (EST_DISTR(est) && (state_local->flags & (1<<est)))
+        {
+            switch (est) {
+            case estX:
+                dd_collect_vec(dd,state_local,state_local->x,state->x);
+                break;
+            case estV:
+                dd_collect_vec(dd,state_local,state_local->v,state->v);
+                break;
+            case estSDX:
+                dd_collect_vec(dd,state_local,state_local->sd_X,state->sd_X);
+                break;
+            case estCGP:
+                dd_collect_vec(dd,state_local,state_local->cg_p,state->cg_p);
+                break;
+            case estLD_RNG:
+                if (state->nrngi == 1)
+                {
+                    if (DDMASTER(dd))
+                    {
+                        for(i=0; i<state_local->nrng; i++)
+                        {
+                            state->ld_rng[i] = state_local->ld_rng[i];
+                        }
+                    }
+                }
+                else
+                {
+                    dd_gather(dd,state_local->nrng*sizeof(state->ld_rng[0]),
+                              state_local->ld_rng,state->ld_rng);
+                }
+                break;
+            case estLD_RNGI:
+                if (state->nrngi == 1)
+                {
+                   if (DDMASTER(dd))
+                    {
+                        state->ld_rngi[0] = state_local->ld_rngi[0];
+                    } 
+                }
+                else
+                {
+                    dd_gather(dd,sizeof(state->ld_rngi[0]),
+                              state_local->ld_rngi,state->ld_rngi);
+                }
+                break;
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                break;
+            default:
+                gmx_incons("Unknown state entry encountered in dd_collect_state");
+            }
+        }
+    }
+}
+
+static void dd_realloc_fr_cg(t_forcerec *fr,int nalloc)
+{
+    if (debug)
+    {
+        fprintf(debug,"Reallocating forcerec: currently %d, required %d, allocating %d\n",fr->cg_nalloc,nalloc,over_alloc_dd(nalloc));
+    }
+    fr->cg_nalloc = over_alloc_dd(nalloc);
+    srenew(fr->cg_cm,fr->cg_nalloc);
+    srenew(fr->cginfo,fr->cg_nalloc);
+}
+
+static void dd_realloc_state(t_state *state,rvec **f,int nalloc)
+{
+    int est;
+
+    if (debug)
+    {
+        fprintf(debug,"Reallocating state: currently %d, required %d, allocating %d\n",state->nalloc,nalloc,over_alloc_dd(nalloc));
+    }
+
+    state->nalloc = over_alloc_dd(nalloc);
+    
+    for(est=0; est<estNR; est++)
+    {
+        if (EST_DISTR(est) && (state->flags & (1<<est)))
+        {
+            switch(est) {
+            case estX:
+                srenew(state->x,state->nalloc);
+                break;
+            case estV:
+                srenew(state->v,state->nalloc);
+                break;
+            case estSDX:
+                srenew(state->sd_X,state->nalloc);
+                break;
+            case estCGP:
+                srenew(state->cg_p,state->nalloc);
+                break;
+            case estLD_RNG:
+            case estLD_RNGI:
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                /* No reallocation required */
+                break;
+            default:
+                gmx_incons("Unknown state entry encountered in dd_realloc_state");            
+            }
+        }
+    }
+    
+    if (f != NULL)
+    {
+        srenew(*f,state->nalloc);
+    }
+}
+
+static void dd_distribute_vec_sendrecv(gmx_domdec_t *dd,t_block *cgs,
+                                       rvec *v,rvec *lv)
+{
+    gmx_domdec_master_t *ma;
+    int  n,i,c,a,nalloc=0;
+    rvec *buf=NULL;
+    
+    if (DDMASTER(dd))
+    {
+        ma  = dd->ma;
+        
+        for(n=0; n<dd->nnodes; n++)
+        {
+            if (n != dd->rank)
+            {
+                if (ma->nat[n] > nalloc)
+                {
+                    nalloc = over_alloc_dd(ma->nat[n]);
+                    srenew(buf,nalloc);
+                }
+                /* Use lv as a temporary buffer */
+                a = 0;
+                for(i=ma->index[n]; i<ma->index[n+1]; i++)
+                {
+                    for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
+                    {
+                        copy_rvec(v[c],buf[a++]);
+                    }
+                }
+                if (a != ma->nat[n])
+                {
+                    gmx_fatal(FARGS,"Internal error a (%d) != nat (%d)",
+                              a,ma->nat[n]);
+                }
+                
+#ifdef GMX_MPI
+                MPI_Send(buf,ma->nat[n]*sizeof(rvec),MPI_BYTE,
+                         DDRANK(dd,n),n,dd->mpi_comm_all);
+#endif
+            }
+        }
+        sfree(buf);
+        n = DDMASTERRANK(dd);
+        a = 0;
+        for(i=ma->index[n]; i<ma->index[n+1]; i++)
+        {
+            for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
+            {
+                copy_rvec(v[c],lv[a++]);
+            }
+        }
+    }
+    else
+    {
+#ifdef GMX_MPI
+        MPI_Recv(lv,dd->nat_home*sizeof(rvec),MPI_BYTE,DDMASTERRANK(dd),
+                 MPI_ANY_TAG,dd->mpi_comm_all,MPI_STATUS_IGNORE);
+#endif
+    }
+}
+
+static void dd_distribute_vec_scatterv(gmx_domdec_t *dd,t_block *cgs,
+                                       rvec *v,rvec *lv)
+{
+    gmx_domdec_master_t *ma;
+    int  *scounts=NULL,*disps=NULL;
+    int  n,i,c,a,nalloc=0;
+    rvec *buf=NULL;
+    
+    if (DDMASTER(dd))
+    {
+        ma  = dd->ma;
+     
+        get_commbuffer_counts(dd,&scounts,&disps);
+
+        buf = ma->vbuf;
+        a = 0;
+        for(n=0; n<dd->nnodes; n++)
+        {
+            for(i=ma->index[n]; i<ma->index[n+1]; i++)
+            {
+                for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
+                {
+                    copy_rvec(v[c],buf[a++]);
+                }
+            }
+        }
+    }
+
+    dd_scatterv(dd,scounts,disps,buf,dd->nat_home*sizeof(rvec),lv);
+}
+
+static void dd_distribute_vec(gmx_domdec_t *dd,t_block *cgs,rvec *v,rvec *lv)
+{
+    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
+    {
+        dd_distribute_vec_sendrecv(dd,cgs,v,lv);
+    }
+    else
+    {
+        dd_distribute_vec_scatterv(dd,cgs,v,lv);
+    }
+}
+
+static void dd_distribute_state(gmx_domdec_t *dd,t_block *cgs,
+                                t_state *state,t_state *state_local,
+                                rvec **f)
+{
+    int  i,j,ngtch,ngtcp,nh;
+
+    nh = state->nhchainlength;
+
+    if (DDMASTER(dd))
+    {
+        state_local->lambda = state->lambda;
+        state_local->veta   = state->veta;
+        state_local->vol0   = state->vol0;
+        copy_mat(state->box,state_local->box);
+        copy_mat(state->box_rel,state_local->box_rel);
+        copy_mat(state->boxv,state_local->boxv);
+        copy_mat(state->svir_prev,state_local->svir_prev);
+        copy_mat(state->fvir_prev,state_local->fvir_prev);
+        for(i=0; i<state_local->ngtc; i++)
+        {
+            for(j=0; j<nh; j++) {
+                state_local->nosehoover_xi[i*nh+j]        = state->nosehoover_xi[i*nh+j];
+                state_local->nosehoover_vxi[i*nh+j]       = state->nosehoover_vxi[i*nh+j];
+            }
+            state_local->therm_integral[i] = state->therm_integral[i];
+        }
+        for(i=0; i<state_local->nnhpres; i++)
+        {
+            for(j=0; j<nh; j++) {
+                state_local->nhpres_xi[i*nh+j]        = state->nhpres_xi[i*nh+j];
+                state_local->nhpres_vxi[i*nh+j]       = state->nhpres_vxi[i*nh+j];
+            }
+        }
+    }
+    dd_bcast(dd,sizeof(real),&state_local->lambda);
+    dd_bcast(dd,sizeof(real),&state_local->veta);
+    dd_bcast(dd,sizeof(real),&state_local->vol0);
+    dd_bcast(dd,sizeof(state_local->box),state_local->box);
+    dd_bcast(dd,sizeof(state_local->box_rel),state_local->box_rel);
+    dd_bcast(dd,sizeof(state_local->boxv),state_local->boxv);
+    dd_bcast(dd,sizeof(state_local->svir_prev),state_local->svir_prev);
+    dd_bcast(dd,sizeof(state_local->fvir_prev),state_local->fvir_prev);
+    dd_bcast(dd,((state_local->ngtc*nh)*sizeof(double)),state_local->nosehoover_xi);
+    dd_bcast(dd,((state_local->ngtc*nh)*sizeof(double)),state_local->nosehoover_vxi);
+    dd_bcast(dd,state_local->ngtc*sizeof(double),state_local->therm_integral);
+    dd_bcast(dd,((state_local->nnhpres*nh)*sizeof(double)),state_local->nhpres_xi);
+    dd_bcast(dd,((state_local->nnhpres*nh)*sizeof(double)),state_local->nhpres_vxi);
+
+    if (dd->nat_home > state_local->nalloc)
+    {
+        dd_realloc_state(state_local,f,dd->nat_home);
+    }
+    for(i=0; i<estNR; i++)
+    {
+        if (EST_DISTR(i) && (state_local->flags & (1<<i)))
+        {
+            switch (i) {
+            case estX:
+                dd_distribute_vec(dd,cgs,state->x,state_local->x);
+                break;
+            case estV:
+                dd_distribute_vec(dd,cgs,state->v,state_local->v);
+                break;
+            case estSDX:
+                dd_distribute_vec(dd,cgs,state->sd_X,state_local->sd_X);
+                break;
+            case estCGP:
+                dd_distribute_vec(dd,cgs,state->cg_p,state_local->cg_p);
+                break;
+            case estLD_RNG:
+                if (state->nrngi == 1)
+                {
+                    dd_bcastc(dd,
+                              state_local->nrng*sizeof(state_local->ld_rng[0]),
+                              state->ld_rng,state_local->ld_rng);
+                }
+                else
+                {
+                    dd_scatter(dd,
+                               state_local->nrng*sizeof(state_local->ld_rng[0]),
+                               state->ld_rng,state_local->ld_rng);
+                }
+                break;
+            case estLD_RNGI:
+                if (state->nrngi == 1)
+                {
+                    dd_bcastc(dd,sizeof(state_local->ld_rngi[0]),
+                              state->ld_rngi,state_local->ld_rngi);
+                }
+                else
+                {
+                     dd_scatter(dd,sizeof(state_local->ld_rngi[0]),
+                               state->ld_rngi,state_local->ld_rngi);
+                }   
+                break;
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                /* Not implemented yet */
+                break;
+            default:
+                gmx_incons("Unknown state entry encountered in dd_distribute_state");
+            }
+        }
+    }
+}
+
+static char dim2char(int dim)
+{
+    char c='?';
+    
+    switch (dim)
+    {
+    case XX: c = 'X'; break;
+    case YY: c = 'Y'; break;
+    case ZZ: c = 'Z'; break;
+    default: gmx_fatal(FARGS,"Unknown dim %d",dim);
+    }
+    
+    return c;
+}
+
+static void write_dd_grid_pdb(const char *fn,gmx_large_int_t step,
+                              gmx_domdec_t *dd,matrix box,gmx_ddbox_t *ddbox)
+{
+    rvec grid_s[2],*grid_r=NULL,cx,r;
+    char fname[STRLEN],format[STRLEN],buf[22];
+    FILE *out;
+    int  a,i,d,z,y,x;
+    matrix tric;
+    real vol;
+
+    copy_rvec(dd->comm->cell_x0,grid_s[0]);
+    copy_rvec(dd->comm->cell_x1,grid_s[1]);
+    
+    if (DDMASTER(dd))
+    {
+        snew(grid_r,2*dd->nnodes);
+    }
+    
+    dd_gather(dd,2*sizeof(rvec),grid_s[0],DDMASTER(dd) ? grid_r[0] : NULL);
+    
+    if (DDMASTER(dd))
+    {
+        for(d=0; d<DIM; d++)
+        {
+            for(i=0; i<DIM; i++)
+            {
+                if (d == i)
+                {
+                    tric[d][i] = 1;
+                }
+                else
+                {
+                    if (dd->nc[d] > 1 && d < ddbox->npbcdim)
+                    {
+                        tric[d][i] = box[i][d]/box[i][i];
+                    }
+                    else
+                    {
+                        tric[d][i] = 0;
+                    }
+                }
+            }
+        }
+        sprintf(fname,"%s_%s.pdb",fn,gmx_step_str(step,buf));
+        sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
+        out = gmx_fio_fopen(fname,"w");
+        gmx_write_pdb_box(out,dd->bScrewPBC ? epbcSCREW : epbcXYZ,box);
+        a = 1;
+        for(i=0; i<dd->nnodes; i++)
+        {
+            vol = dd->nnodes/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
+            for(d=0; d<DIM; d++)
+            {
+                vol *= grid_r[i*2+1][d] - grid_r[i*2][d];
+            }
+            for(z=0; z<2; z++)
+            {
+                for(y=0; y<2; y++)
+                {
+                    for(x=0; x<2; x++)
+                    {
+                        cx[XX] = grid_r[i*2+x][XX];
+                        cx[YY] = grid_r[i*2+y][YY];
+                        cx[ZZ] = grid_r[i*2+z][ZZ];
+                        mvmul(tric,cx,r);
+                        fprintf(out,format,"ATOM",a++,"CA","GLY",' ',1+i,
+                                10*r[XX],10*r[YY],10*r[ZZ],1.0,vol);
+                    }
+                }
+            }
+            for(d=0; d<DIM; d++)
+            {
+                for(x=0; x<4; x++)
+                {
+                    switch(d)
+                    {
+                    case 0: y = 1 + i*8 + 2*x; break;
+                    case 1: y = 1 + i*8 + 2*x - (x % 2); break;
+                    case 2: y = 1 + i*8 + x; break;
+                    }
+                    fprintf(out,"%6s%5d%5d\n","CONECT",y,y+(1<<d));
+                }
+            }
+        }
+        gmx_fio_fclose(out);
+        sfree(grid_r);
+    }
+}
+
+void write_dd_pdb(const char *fn,gmx_large_int_t step,const char *title,
+                  gmx_mtop_t *mtop,t_commrec *cr,
+                  int natoms,rvec x[],matrix box)
+{
+    char fname[STRLEN],format[STRLEN],format4[STRLEN],buf[22];
+    FILE *out;
+    int  i,ii,resnr,c;
+    char *atomname,*resname;
+    real b;
+    gmx_domdec_t *dd;
+    
+    dd = cr->dd;
+    if (natoms == -1)
+    {
+        natoms = dd->comm->nat[ddnatVSITE];
+    }
+    
+    sprintf(fname,"%s_%s_n%d.pdb",fn,gmx_step_str(step,buf),cr->sim_nodeid);
+    
+    sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
+    sprintf(format4,"%s%s\n",pdbformat4,"%6.2f%6.2f");
+    
+    out = gmx_fio_fopen(fname,"w");
+    
+    fprintf(out,"TITLE     %s\n",title);
+    gmx_write_pdb_box(out,dd->bScrewPBC ? epbcSCREW : epbcXYZ,box);
+    for(i=0; i<natoms; i++)
+    {
+        ii = dd->gatindex[i];
+        gmx_mtop_atominfo_global(mtop,ii,&atomname,&resnr,&resname);
+        if (i < dd->comm->nat[ddnatZONE])
+        {
+            c = 0;
+            while (i >= dd->cgindex[dd->comm->zones.cg_range[c+1]])
+            {
+                c++;
+            }
+            b = c;
+        }
+        else if (i < dd->comm->nat[ddnatVSITE])
+        {
+            b = dd->comm->zones.n;
+        }
+        else
+        {
+            b = dd->comm->zones.n + 1;
+        }
+        fprintf(out,strlen(atomname)<4 ? format : format4,
+                "ATOM",(ii+1)%100000,
+                atomname,resname,' ',resnr%10000,' ',
+                10*x[i][XX],10*x[i][YY],10*x[i][ZZ],1.0,b);
+    }
+    fprintf(out,"TER\n");
+    
+    gmx_fio_fclose(out);
+}
+
+real dd_cutoff_mbody(gmx_domdec_t *dd)
+{
+    gmx_domdec_comm_t *comm;
+    int  di;
+    real r;
+
+    comm = dd->comm;
+
+    r = -1;
+    if (comm->bInterCGBondeds)
+    {
+        if (comm->cutoff_mbody > 0)
+        {
+            r = comm->cutoff_mbody;
+        }
+        else
+        {
+            /* cutoff_mbody=0 means we do not have DLB */
+            r = comm->cellsize_min[dd->dim[0]];
+            for(di=1; di<dd->ndim; di++)
+            {
+                r = min(r,comm->cellsize_min[dd->dim[di]]);
+            }
+            if (comm->bBondComm)
+            {
+                r = max(r,comm->cutoff_mbody);
+            }
+            else
+            {
+                r = min(r,comm->cutoff);
+            }
+        }
+    }
+
+    return r;
+}
+
+real dd_cutoff_twobody(gmx_domdec_t *dd)
+{
+    real r_mb;
+
+    r_mb = dd_cutoff_mbody(dd);
+
+    return max(dd->comm->cutoff,r_mb);
+}
+
+
+static void dd_cart_coord2pmecoord(gmx_domdec_t *dd,ivec coord,ivec coord_pme)
+{
+    int nc,ntot;
+    
+    nc   = dd->nc[dd->comm->cartpmedim];
+    ntot = dd->comm->ntot[dd->comm->cartpmedim];
+    copy_ivec(coord,coord_pme);
+    coord_pme[dd->comm->cartpmedim] =
+        nc + (coord[dd->comm->cartpmedim]*(ntot - nc) + (ntot - nc)/2)/nc;
+}
+
+static int low_ddindex2pmeindex(int ndd,int npme,int ddindex)
+{
+    /* Here we assign a PME node to communicate with this DD node
+     * by assuming that the major index of both is x.
+     * We add cr->npmenodes/2 to obtain an even distribution.
+     */
+    return (ddindex*npme + npme/2)/ndd;
+}
+
+static int ddindex2pmeindex(const gmx_domdec_t *dd,int ddindex)
+{
+    return low_ddindex2pmeindex(dd->nnodes,dd->comm->npmenodes,ddindex);
+}
+
+static int cr_ddindex2pmeindex(const t_commrec *cr,int ddindex)
+{
+    return low_ddindex2pmeindex(cr->dd->nnodes,cr->npmenodes,ddindex);
+}
+
+static int *dd_pmenodes(t_commrec *cr)
+{
+    int *pmenodes;
+    int n,i,p0,p1;
+    
+    snew(pmenodes,cr->npmenodes);
+    n = 0;
+    for(i=0; i<cr->dd->nnodes; i++) {
+        p0 = cr_ddindex2pmeindex(cr,i);
+        p1 = cr_ddindex2pmeindex(cr,i+1);
+        if (i+1 == cr->dd->nnodes || p1 > p0) {
+            if (debug)
+                fprintf(debug,"pmenode[%d] = %d\n",n,i+1+n);
+            pmenodes[n] = i + 1 + n;
+            n++;
+        }
+    }
+
+    return pmenodes;
+}
+
+static int gmx_ddcoord2pmeindex(t_commrec *cr,int x,int y,int z)
+{
+    gmx_domdec_t *dd;
+    ivec coords,coords_pme,nc;
+    int  slab;
+    
+    dd = cr->dd;
+    /*
+      if (dd->comm->bCartesian) {
+      gmx_ddindex2xyz(dd->nc,ddindex,coords);
+      dd_coords2pmecoords(dd,coords,coords_pme);
+      copy_ivec(dd->ntot,nc);
+      nc[dd->cartpmedim]         -= dd->nc[dd->cartpmedim];
+      coords_pme[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
+      
+      slab = (coords_pme[XX]*nc[YY] + coords_pme[YY])*nc[ZZ] + coords_pme[ZZ];
+      } else {
+      slab = (ddindex*cr->npmenodes + cr->npmenodes/2)/dd->nnodes;
+      }
+    */
+    coords[XX] = x;
+    coords[YY] = y;
+    coords[ZZ] = z;
+    slab = ddindex2pmeindex(dd,dd_index(dd->nc,coords));
+    
+    return slab;
+}
+
+static int ddcoord2simnodeid(t_commrec *cr,int x,int y,int z)
+{
+    gmx_domdec_comm_t *comm;
+    ivec coords;
+    int  ddindex,nodeid=-1;
+    
+    comm = cr->dd->comm;
+    
+    coords[XX] = x;
+    coords[YY] = y;
+    coords[ZZ] = z;
+    if (comm->bCartesianPP_PME)
+    {
+#ifdef GMX_MPI
+        MPI_Cart_rank(cr->mpi_comm_mysim,coords,&nodeid);
+#endif
+    }
+    else
+    {
+        ddindex = dd_index(cr->dd->nc,coords);
+        if (comm->bCartesianPP)
+        {
+            nodeid = comm->ddindex2simnodeid[ddindex];
+        }
+        else
+        {
+            if (comm->pmenodes)
+            {
+                nodeid = ddindex + gmx_ddcoord2pmeindex(cr,x,y,z);
+            }
+            else
+            {
+                nodeid = ddindex;
+            }
+        }
+    }
+  
+    return nodeid;
+}
+
+static int dd_simnode2pmenode(t_commrec *cr,int sim_nodeid)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    ivec coord,coord_pme;
+    int  i;
+    int  pmenode=-1;
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+    /* This assumes a uniform x domain decomposition grid cell size */
+    if (comm->bCartesianPP_PME)
+    {
+#ifdef GMX_MPI
+        MPI_Cart_coords(cr->mpi_comm_mysim,sim_nodeid,DIM,coord);
+        if (coord[comm->cartpmedim] < dd->nc[comm->cartpmedim])
+        {
+            /* This is a PP node */
+            dd_cart_coord2pmecoord(dd,coord,coord_pme);
+            MPI_Cart_rank(cr->mpi_comm_mysim,coord_pme,&pmenode);
+        }
+#endif
+    }
+    else if (comm->bCartesianPP)
+    {
+        if (sim_nodeid < dd->nnodes)
+        {
+            pmenode = dd->nnodes + ddindex2pmeindex(dd,sim_nodeid);
+        }
+    }
+    else
+    {
+        /* This assumes DD cells with identical x coordinates
+         * are numbered sequentially.
+         */
+        if (dd->comm->pmenodes == NULL)
+        {
+            if (sim_nodeid < dd->nnodes)
+            {
+                /* The DD index equals the nodeid */
+                pmenode = dd->nnodes + ddindex2pmeindex(dd,sim_nodeid);
+            }
+        }
+        else
+        {
+            i = 0;
+            while (sim_nodeid > dd->comm->pmenodes[i])
+            {
+                i++;
+            }
+            if (sim_nodeid < dd->comm->pmenodes[i])
+            {
+                pmenode = dd->comm->pmenodes[i];
+            }
+        }
+    }
+    
+    return pmenode;
+}
+
+gmx_bool gmx_pmeonlynode(t_commrec *cr,int sim_nodeid)
+{
+    gmx_bool bPMEOnlyNode;
+    
+    if (DOMAINDECOMP(cr))
+    {
+        bPMEOnlyNode = (dd_simnode2pmenode(cr,sim_nodeid) == -1);
+    }
+    else
+    {
+        bPMEOnlyNode = FALSE;
+    }
+    
+    return bPMEOnlyNode;
+}
+
+void get_pme_ddnodes(t_commrec *cr,int pmenodeid,
+                     int *nmy_ddnodes,int **my_ddnodes,int *node_peer)
+{
+    gmx_domdec_t *dd;
+    int x,y,z;
+    ivec coord,coord_pme;
+    
+    dd = cr->dd;
+    
+    snew(*my_ddnodes,(dd->nnodes+cr->npmenodes-1)/cr->npmenodes);
+    
+    *nmy_ddnodes = 0;
+    for(x=0; x<dd->nc[XX]; x++)
+    {
+        for(y=0; y<dd->nc[YY]; y++)
+        {
+            for(z=0; z<dd->nc[ZZ]; z++)
+            {
+                if (dd->comm->bCartesianPP_PME)
+                {
+                    coord[XX] = x;
+                    coord[YY] = y;
+                    coord[ZZ] = z;
+                    dd_cart_coord2pmecoord(dd,coord,coord_pme);
+                    if (dd->ci[XX] == coord_pme[XX] &&
+                        dd->ci[YY] == coord_pme[YY] &&
+                        dd->ci[ZZ] == coord_pme[ZZ])
+                        (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr,x,y,z);
+                }
+                else
+                {
+                    /* The slab corresponds to the nodeid in the PME group */
+                    if (gmx_ddcoord2pmeindex(cr,x,y,z) == pmenodeid)
+                    {
+                        (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr,x,y,z);
+                    }
+                }
+            }
+        }
+    }
+    
+    /* The last PP-only node is the peer node */
+    *node_peer = (*my_ddnodes)[*nmy_ddnodes-1];
+    
+    if (debug)
+    {
+        fprintf(debug,"Receive coordinates from PP nodes:");
+        for(x=0; x<*nmy_ddnodes; x++)
+        {
+            fprintf(debug," %d",(*my_ddnodes)[x]);
+        }
+        fprintf(debug,"\n");
+    }
+}
+
+static gmx_bool receive_vir_ener(t_commrec *cr)
+{
+    gmx_domdec_comm_t *comm;
+    int  pmenode,coords[DIM],rank;
+    gmx_bool bReceive;
+    
+    bReceive = TRUE;
+    if (cr->npmenodes < cr->dd->nnodes)
+    {
+        comm = cr->dd->comm;
+        if (comm->bCartesianPP_PME)
+        {
+            pmenode = dd_simnode2pmenode(cr,cr->sim_nodeid);
+#ifdef GMX_MPI
+            MPI_Cart_coords(cr->mpi_comm_mysim,cr->sim_nodeid,DIM,coords);
+            coords[comm->cartpmedim]++;
+            if (coords[comm->cartpmedim] < cr->dd->nc[comm->cartpmedim])
+            {
+                MPI_Cart_rank(cr->mpi_comm_mysim,coords,&rank);
+                if (dd_simnode2pmenode(cr,rank) == pmenode)
+                {
+                    /* This is not the last PP node for pmenode */
+                    bReceive = FALSE;
+                }
+            }
+#endif  
+        }
+        else
+        {
+            pmenode = dd_simnode2pmenode(cr,cr->sim_nodeid);
+            if (cr->sim_nodeid+1 < cr->nnodes &&
+                dd_simnode2pmenode(cr,cr->sim_nodeid+1) == pmenode)
+            {
+                /* This is not the last PP node for pmenode */
+                bReceive = FALSE;
+            }
+        }
+    }
+    
+    return bReceive;
+}
+
+static void set_zones_ncg_home(gmx_domdec_t *dd)
+{
+    gmx_domdec_zones_t *zones;
+    int i;
+
+    zones = &dd->comm->zones;
+
+    zones->cg_range[0] = 0;
+    for(i=1; i<zones->n+1; i++)
+    {
+        zones->cg_range[i] = dd->ncg_home;
+    }
+}
+
+static void rebuild_cgindex(gmx_domdec_t *dd,int *gcgs_index,t_state *state)
+{
+    int nat,i,*ind,*dd_cg_gl,*cgindex,cg_gl;
+    
+    ind = state->cg_gl;
+    dd_cg_gl = dd->index_gl;
+    cgindex  = dd->cgindex;
+    nat = 0;
+    cgindex[0] = nat;
+    for(i=0; i<state->ncg_gl; i++)
+    {
+        cgindex[i] = nat;
+        cg_gl = ind[i];
+        dd_cg_gl[i] = cg_gl;
+        nat += gcgs_index[cg_gl+1] - gcgs_index[cg_gl];
+    }
+    cgindex[i] = nat;
+    
+    dd->ncg_home = state->ncg_gl;
+    dd->nat_home = nat;
+
+    set_zones_ncg_home(dd);
+}
+
+static int ddcginfo(const cginfo_mb_t *cginfo_mb,int cg)
+{
+    while (cg >= cginfo_mb->cg_end)
+    {
+        cginfo_mb++;
+    }
+
+    return cginfo_mb->cginfo[(cg - cginfo_mb->cg_start) % cginfo_mb->cg_mod];
+}
+
+static void dd_set_cginfo(int *index_gl,int cg0,int cg1,
+                          t_forcerec *fr,char *bLocalCG)
+{
+    cginfo_mb_t *cginfo_mb;
+    int *cginfo;
+    int cg;
+
+    if (fr != NULL)
+    {
+        cginfo_mb = fr->cginfo_mb;
+        cginfo    = fr->cginfo;
+
+        for(cg=cg0; cg<cg1; cg++)
+        {
+            cginfo[cg] = ddcginfo(cginfo_mb,index_gl[cg]);
+        }
+    }
+
+    if (bLocalCG != NULL)
+    {
+        for(cg=cg0; cg<cg1; cg++)
+        {
+            bLocalCG[index_gl[cg]] = TRUE;
+        }
+    }
+}
+
+static void make_dd_indices(gmx_domdec_t *dd,int *gcgs_index,int cg_start)
+{
+    int nzone,zone,zone1,cg0,cg,cg_gl,a,a_gl;
+    int *zone2cg,*zone_ncg1,*index_gl,*gatindex;
+    gmx_ga2la_t *ga2la;
+    char *bLocalCG;
+
+    bLocalCG = dd->comm->bLocalCG;
+
+    if (dd->nat_tot > dd->gatindex_nalloc)
+    {
+        dd->gatindex_nalloc = over_alloc_dd(dd->nat_tot);
+        srenew(dd->gatindex,dd->gatindex_nalloc);
+    }
+
+    nzone      = dd->comm->zones.n;
+    zone2cg    = dd->comm->zones.cg_range;
+    zone_ncg1  = dd->comm->zone_ncg1;
+    index_gl   = dd->index_gl;
+    gatindex   = dd->gatindex;
+
+    if (zone2cg[1] != dd->ncg_home)
+    {
+        gmx_incons("dd->ncg_zone is not up to date");
+    }
+    
+    /* Make the local to global and global to local atom index */
+    a = dd->cgindex[cg_start];
+    for(zone=0; zone<nzone; zone++)
+    {
+        if (zone == 0)
+        {
+            cg0 = cg_start;
+        }
+        else
+        {
+            cg0 = zone2cg[zone];
+        }
+        for(cg=cg0; cg<zone2cg[zone+1]; cg++)
+        {
+            zone1 = zone;
+            if (cg - cg0 >= zone_ncg1[zone])
+            {
+                /* Signal that this cg is from more than one zone away */
+                zone1 += nzone;
+            }
+            cg_gl = index_gl[cg];
+            for(a_gl=gcgs_index[cg_gl]; a_gl<gcgs_index[cg_gl+1]; a_gl++)
+            {
+                gatindex[a] = a_gl;
+                ga2la_set(dd->ga2la,a_gl,a,zone1);
+                a++;
+            }
+        }
+    }
+}
+
+static int check_bLocalCG(gmx_domdec_t *dd,int ncg_sys,const char *bLocalCG,
+                          const char *where)
+{
+    int ncg,i,ngl,nerr;
+
+    nerr = 0;
+    if (bLocalCG == NULL)
+    {
+        return nerr;
+    }
+    for(i=0; i<dd->ncg_tot; i++)
+    {
+        if (!bLocalCG[dd->index_gl[i]])
+        {
+            fprintf(stderr,
+                    "DD node %d, %s: cg %d, global cg %d is not marked in bLocalCG (ncg_home %d)\n",dd->rank,where,i+1,dd->index_gl[i]+1,dd->ncg_home);
+            nerr++;
+        }
+    }
+    ngl = 0;
+    for(i=0; i<ncg_sys; i++)
+    {
+        if (bLocalCG[i])
+        {
+            ngl++;
+        }
+    }
+    if (ngl != dd->ncg_tot)
+    {
+        fprintf(stderr,"DD node %d, %s: In bLocalCG %d cgs are marked as local, whereas there are %d\n",dd->rank,where,ngl,dd->ncg_tot);
+        nerr++;
+    }
+
+    return nerr;
+}
+
+static void check_index_consistency(gmx_domdec_t *dd,
+                                    int natoms_sys,int ncg_sys,
+                                    const char *where)
+{
+    int  nerr,ngl,i,a,cell;
+    int  *have;
+
+    nerr = 0;
+
+    if (dd->comm->DD_debug > 1)
+    {
+        snew(have,natoms_sys);
+        for(a=0; a<dd->nat_tot; a++)
+        {
+            if (have[dd->gatindex[a]] > 0)
+            {
+                fprintf(stderr,"DD node %d: global atom %d occurs twice: index %d and %d\n",dd->rank,dd->gatindex[a]+1,have[dd->gatindex[a]],a+1);
+            }
+            else
+            {
+                have[dd->gatindex[a]] = a + 1;
+            }
+        }
+        sfree(have);
+    }
+
+    snew(have,dd->nat_tot);
+
+    ngl  = 0;
+    for(i=0; i<natoms_sys; i++)
+    {
+        if (ga2la_get(dd->ga2la,i,&a,&cell))
+        {
+            if (a >= dd->nat_tot)
+            {
+                fprintf(stderr,"DD node %d: global atom %d marked as local atom %d, which is larger than nat_tot (%d)\n",dd->rank,i+1,a+1,dd->nat_tot);
+                nerr++;
+            }
+            else
+            {
+                have[a] = 1;
+                if (dd->gatindex[a] != i)
+                {
+                    fprintf(stderr,"DD node %d: global atom %d marked as local atom %d, which has global atom index %d\n",dd->rank,i+1,a+1,dd->gatindex[a]+1);
+                    nerr++;
+                }
+            }
+            ngl++;
+        }
+    }
+    if (ngl != dd->nat_tot)
+    {
+        fprintf(stderr,
+                "DD node %d, %s: %d global atom indices, %d local atoms\n",
+                dd->rank,where,ngl,dd->nat_tot);
+    }
+    for(a=0; a<dd->nat_tot; a++)
+    {
+        if (have[a] == 0)
+        {
+            fprintf(stderr,
+                    "DD node %d, %s: local atom %d, global %d has no global index\n",
+                    dd->rank,where,a+1,dd->gatindex[a]+1);
+        }
+    }
+    sfree(have);
+
+    nerr += check_bLocalCG(dd,ncg_sys,dd->comm->bLocalCG,where);
+
+    if (nerr > 0) {
+        gmx_fatal(FARGS,"DD node %d, %s: %d atom/cg index inconsistencies",
+                  dd->rank,where,nerr);
+    }
+}
+
+static void clear_dd_indices(gmx_domdec_t *dd,int cg_start,int a_start)
+{
+    int  i;
+    char *bLocalCG;
+
+    if (a_start == 0)
+    {
+        /* Clear the whole list without searching */
+        ga2la_clear(dd->ga2la);
+    }
+    else
+    {
+        for(i=a_start; i<dd->nat_tot; i++)
+        {
+            ga2la_del(dd->ga2la,dd->gatindex[i]);
+        }
+    }
+
+    bLocalCG = dd->comm->bLocalCG;
+    if (bLocalCG)
+    {
+        for(i=cg_start; i<dd->ncg_tot; i++)
+        {
+            bLocalCG[dd->index_gl[i]] = FALSE;
+        }
+    }
+
+    dd_clear_local_vsite_indices(dd);
+    
+    if (dd->constraints)
+    {
+        dd_clear_local_constraint_indices(dd);
+    }
+}
+
+static real grid_jump_limit(gmx_domdec_comm_t *comm,int dim_ind)
+{
+    real grid_jump_limit;
+
+    /* The distance between the boundaries of cells at distance
+     * x+-1,y+-1 or y+-1,z+-1 is limited by the cut-off restrictions
+     * and by the fact that cells should not be shifted by more than
+     * half their size, such that cg's only shift by one cell
+     * at redecomposition.
+     */
+    grid_jump_limit = comm->cellsize_limit;
+    if (!comm->bVacDLBNoLimit)
+    {
+        grid_jump_limit = max(grid_jump_limit,
+                              comm->cutoff/comm->cd[dim_ind].np);
+    }
+
+    return grid_jump_limit;
+}
+
+static void check_grid_jump(gmx_large_int_t step,gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
+{
+    gmx_domdec_comm_t *comm;
+    int  d,dim;
+    real limit,bfac;
+    
+    comm = dd->comm;
+    
+    for(d=1; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        limit = grid_jump_limit(comm,d);
+        bfac = ddbox->box_size[dim];
+        if (ddbox->tric_dir[dim])
+        {
+            bfac *= ddbox->skew_fac[dim];
+        }
+        if ((comm->cell_f1[d] - comm->cell_f_max0[d])*bfac <  limit ||
+            (comm->cell_f0[d] - comm->cell_f_min1[d])*bfac > -limit)
+        {
+            char buf[22];
+            gmx_fatal(FARGS,"Step %s: The domain decomposition grid has shifted too much in the %c-direction around cell %d %d %d\n",
+                      gmx_step_str(step,buf),
+                      dim2char(dim),dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+        }
+    }
+}
+
+static int dd_load_count(gmx_domdec_comm_t *comm)
+{
+    return (comm->eFlop ? comm->flop_n : comm->cycl_n[ddCyclF]);
+}
+
+static float dd_force_load(gmx_domdec_comm_t *comm)
+{
+    float load;
+    
+    if (comm->eFlop)
+    {
+        load = comm->flop;
+        if (comm->eFlop > 1)
+        {
+            load *= 1.0 + (comm->eFlop - 1)*(0.1*rand()/RAND_MAX - 0.05);
+        }
+    } 
+    else
+    {
+        load = comm->cycl[ddCyclF];
+        if (comm->cycl_n[ddCyclF] > 1)
+        {
+            /* Subtract the maximum of the last n cycle counts
+             * to get rid of possible high counts due to other soures,
+             * for instance system activity, that would otherwise
+             * affect the dynamic load balancing.
+             */
+            load -= comm->cycl_max[ddCyclF];
+        }
+    }
+    
+    return load;
+}
+
+static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dim,real **dim_f)
+{
+    gmx_domdec_comm_t *comm;
+    int i;
+    
+    comm = dd->comm;
+    
+    snew(*dim_f,dd->nc[dim]+1);
+    (*dim_f)[0] = 0;
+    for(i=1; i<dd->nc[dim]; i++)
+    {
+        if (comm->slb_frac[dim])
+        {
+            (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
+        }
+        else
+        {
+            (*dim_f)[i] = (real)i/(real)dd->nc[dim];
+        }
+    }
+    (*dim_f)[dd->nc[dim]] = 1;
+}
+
+static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,int dimind)
+{
+    int         pmeindex,slab,nso,i;
+    ivec xyz;
+    
+    if (dimind == 0 && dd->dim[0] == YY && dd->comm->npmenodes_x == 1)
+    {
+        ddpme->dim = YY;
+    }
+    else
+    {
+        ddpme->dim = dimind;
+    }
+    ddpme->dim_match = (ddpme->dim == dd->dim[dimind]);
+    
+    ddpme->nslab = (ddpme->dim == 0 ?
+                    dd->comm->npmenodes_x :
+                    dd->comm->npmenodes_y);
+
+    if (ddpme->nslab <= 1)
+    {
+        return;
+    }
+
+    nso = dd->comm->npmenodes/ddpme->nslab;
+    /* Determine for each PME slab the PP location range for dimension dim */
+    snew(ddpme->pp_min,ddpme->nslab);
+    snew(ddpme->pp_max,ddpme->nslab);
+    for(slab=0; slab<ddpme->nslab; slab++) {
+        ddpme->pp_min[slab] = dd->nc[dd->dim[dimind]] - 1;
+        ddpme->pp_max[slab] = 0;
+    }
+    for(i=0; i<dd->nnodes; i++) {
+        ddindex2xyz(dd->nc,i,xyz);
+        /* For y only use our y/z slab.
+         * This assumes that the PME x grid size matches the DD grid size.
+         */
+        if (dimind == 0 || xyz[XX] == dd->ci[XX]) {
+            pmeindex = ddindex2pmeindex(dd,i);
+            if (dimind == 0) {
+                slab = pmeindex/nso;
+            } else {
+                slab = pmeindex % ddpme->nslab;
+            }
+            ddpme->pp_min[slab] = min(ddpme->pp_min[slab],xyz[dimind]);
+            ddpme->pp_max[slab] = max(ddpme->pp_max[slab],xyz[dimind]);
+        }
+    }
+
+    set_slb_pme_dim_f(dd,ddpme->dim,&ddpme->slb_dim_f);
+}
+
+int dd_pme_maxshift_x(gmx_domdec_t *dd)
+{
+    if (dd->comm->ddpme[0].dim == XX)
+    {
+        return dd->comm->ddpme[0].maxshift;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+int dd_pme_maxshift_y(gmx_domdec_t *dd)
+{
+    if (dd->comm->ddpme[0].dim == YY)
+    {
+        return dd->comm->ddpme[0].maxshift;
+    }
+    else if (dd->comm->npmedecompdim >= 2 && dd->comm->ddpme[1].dim == YY)
+    {
+        return dd->comm->ddpme[1].maxshift;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
+                             gmx_bool bUniform,gmx_ddbox_t *ddbox,real *cell_f)
+{
+    gmx_domdec_comm_t *comm;
+    int  nc,ns,s;
+    int  *xmin,*xmax;
+    real range,pme_boundary;
+    int  sh;
+    
+    comm = dd->comm;
+    nc  = dd->nc[ddpme->dim];
+    ns  = ddpme->nslab;
+    
+    if (!ddpme->dim_match)
+    {
+        /* PP decomposition is not along dim: the worst situation */
+        sh = ns/2;
+    }
+    else if (ns <= 3 || (bUniform && ns == nc))
+    {
+        /* The optimal situation */
+        sh = 1;
+    }
+    else
+    {
+        /* We need to check for all pme nodes which nodes they
+         * could possibly need to communicate with.
+         */
+        xmin = ddpme->pp_min;
+        xmax = ddpme->pp_max;
+        /* Allow for atoms to be maximally 2/3 times the cut-off
+         * out of their DD cell. This is a reasonable balance between
+         * between performance and support for most charge-group/cut-off
+         * combinations.
+         */
+        range  = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
+        /* Avoid extra communication when we are exactly at a boundary */
+        range *= 0.999;
+        
+        sh = 1;
+        for(s=0; s<ns; s++)
+        {
+            /* PME slab s spreads atoms between box frac. s/ns and (s+1)/ns */
+            pme_boundary = (real)s/ns;
+            while (sh+1 < ns &&
+                   ((s-(sh+1) >= 0 &&
+                     cell_f[xmax[s-(sh+1)   ]+1]     + range > pme_boundary) ||
+                    (s-(sh+1) <  0 &&
+                     cell_f[xmax[s-(sh+1)+ns]+1] - 1 + range > pme_boundary)))
+            {
+                sh++;
+            }
+            pme_boundary = (real)(s+1)/ns;
+            while (sh+1 < ns &&
+                   ((s+(sh+1) <  ns &&
+                     cell_f[xmin[s+(sh+1)   ]  ]     - range < pme_boundary) ||
+                    (s+(sh+1) >= ns &&
+                     cell_f[xmin[s+(sh+1)-ns]  ] + 1 - range < pme_boundary)))
+            {
+                sh++;
+            }
+        }
+    }
+    
+    ddpme->maxshift = sh;
+    
+    if (debug)
+    {
+        fprintf(debug,"PME slab communication range for dim %d is %d\n",
+                ddpme->dim,ddpme->maxshift);
+    }
+}
+
+static void check_box_size(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
+{
+    int d,dim;
+    
+    for(d=0; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        if (dim < ddbox->nboundeddim &&
+            ddbox->box_size[dim]*ddbox->skew_fac[dim] <
+            dd->nc[dim]*dd->comm->cellsize_limit*DD_CELL_MARGIN)
+        {
+            gmx_fatal(FARGS,"The %c-size of the box (%f) times the triclinic skew factor (%f) is smaller than the number of DD cells (%d) times the smallest allowed cell size (%f)\n",
+                      dim2char(dim),ddbox->box_size[dim],ddbox->skew_fac[dim],
+                      dd->nc[dim],dd->comm->cellsize_limit);
+        }
+    }
+}
+
+static void set_dd_cell_sizes_slb(gmx_domdec_t *dd,gmx_ddbox_t *ddbox,
+                                  gmx_bool bMaster,ivec npulse)
+{
+    gmx_domdec_comm_t *comm;
+    int  d,j;
+    rvec cellsize_min;
+    real *cell_x,cell_dx,cellsize;
+    
+    comm = dd->comm;
+    
+    for(d=0; d<DIM; d++)
+    {
+        cellsize_min[d] = ddbox->box_size[d]*ddbox->skew_fac[d];
+        npulse[d] = 1;
+        if (dd->nc[d] == 1 || comm->slb_frac[d] == NULL)
+        {
+            /* Uniform grid */
+            cell_dx = ddbox->box_size[d]/dd->nc[d];
+            if (bMaster)
+            {
+                for(j=0; j<dd->nc[d]+1; j++)
+                {
+                    dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
+                }
+            }
+            else
+            {
+                comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d]  )*cell_dx;
+                comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
+            }
+            cellsize = cell_dx*ddbox->skew_fac[d];
+            while (cellsize*npulse[d] < comm->cutoff && npulse[d] < dd->nc[d]-1)
+            {
+                npulse[d]++;
+            }
+            cellsize_min[d] = cellsize;
+        }
+        else
+        {
+            /* Statically load balanced grid */
+            /* Also when we are not doing a master distribution we determine
+             * all cell borders in a loop to obtain identical values
+             * to the master distribution case and to determine npulse.
+             */
+            if (bMaster)
+            {
+                cell_x = dd->ma->cell_x[d];
+            }
+            else
+            {
+                snew(cell_x,dd->nc[d]+1);
+            }
+            cell_x[0] = ddbox->box0[d];
+            for(j=0; j<dd->nc[d]; j++)
+            {
+                cell_dx = ddbox->box_size[d]*comm->slb_frac[d][j];
+                cell_x[j+1] = cell_x[j] + cell_dx;
+                cellsize = cell_dx*ddbox->skew_fac[d];
+                while (cellsize*npulse[d] < comm->cutoff &&
+                       npulse[d] < dd->nc[d]-1)
+                {
+                    npulse[d]++;
+                }
+                cellsize_min[d] = min(cellsize_min[d],cellsize);
+            }
+            if (!bMaster)
+            {
+                comm->cell_x0[d] = cell_x[dd->ci[d]];
+                comm->cell_x1[d] = cell_x[dd->ci[d]+1];
+                sfree(cell_x);
+            }
+        }
+        /* The following limitation is to avoid that a cell would receive
+         * some of its own home charge groups back over the periodic boundary.
+         * Double charge groups cause trouble with the global indices.
+         */
+        if (d < ddbox->npbcdim &&
+            dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
+        {
+            gmx_fatal_collective(FARGS,NULL,dd,
+                                 "The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
+                                 dim2char(d),ddbox->box_size[d],ddbox->skew_fac[d],
+                                 comm->cutoff,
+                                 dd->nc[d],dd->nc[d],
+                                 dd->nnodes > dd->nc[d] ? "cells" : "processors");
+        }
+    }
+    
+    if (!comm->bDynLoadBal)
+    {
+        copy_rvec(cellsize_min,comm->cellsize_min);
+    }
+   
+    for(d=0; d<comm->npmedecompdim; d++)
+    {
+        set_pme_maxshift(dd,&comm->ddpme[d],
+                         comm->slb_frac[dd->dim[d]]==NULL,ddbox,
+                         comm->ddpme[d].slb_dim_f);
+    }
+}
+
+
+static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
+                                       int d,int dim,gmx_domdec_root_t *root,
+                                       gmx_ddbox_t *ddbox,
+                                       gmx_bool bUniform,gmx_large_int_t step, real cellsize_limit_f, int range[])
+{
+    gmx_domdec_comm_t *comm;
+    int  ncd,i,j,nmin,nmin_old;
+    gmx_bool bLimLo,bLimHi;
+    real *cell_size;
+    real fac,halfway,cellsize_limit_f_i,region_size;
+    gmx_bool bPBC,bLastHi=FALSE;
+    int nrange[]={range[0],range[1]};
+
+    region_size= root->cell_f[range[1]]-root->cell_f[range[0]];  
+
+    comm = dd->comm;
+
+    ncd = dd->nc[dim];
+
+    bPBC = (dim < ddbox->npbcdim);
+
+    cell_size = root->buf_ncd;
+
+    if (debug) 
+    {
+        fprintf(debug,"enforce_limits: %d %d\n",range[0],range[1]);
+    }
+
+    /* First we need to check if the scaling does not make cells
+     * smaller than the smallest allowed size.
+     * We need to do this iteratively, since if a cell is too small,
+     * it needs to be enlarged, which makes all the other cells smaller,
+     * which could in turn make another cell smaller than allowed.
+     */
+    for(i=range[0]; i<range[1]; i++)
+    {
+        root->bCellMin[i] = FALSE;
+    }
+    nmin = 0;
+    do
+    {
+        nmin_old = nmin;
+        /* We need the total for normalization */
+        fac = 0;
+        for(i=range[0]; i<range[1]; i++)
+        {
+            if (root->bCellMin[i] == FALSE)
+            {
+                fac += cell_size[i];
+            }
+        }
+        fac = ( region_size - nmin*cellsize_limit_f)/fac; /* substracting cells already set to cellsize_limit_f */
+        /* Determine the cell boundaries */
+        for(i=range[0]; i<range[1]; i++)
+        {
+            if (root->bCellMin[i] == FALSE)
+            {
+                cell_size[i] *= fac;
+                if (!bPBC && (i == 0 || i == dd->nc[dim] -1))
+                {
+                    cellsize_limit_f_i = 0;
+                }
+                else
+                {
+                    cellsize_limit_f_i = cellsize_limit_f;
+                }
+                if (cell_size[i] < cellsize_limit_f_i)
+                {
+                    root->bCellMin[i] = TRUE;
+                    cell_size[i] = cellsize_limit_f_i;
+                    nmin++;
+                }
+            }
+            root->cell_f[i+1] = root->cell_f[i] + cell_size[i];
+        }
+    }
+    while (nmin > nmin_old);
+    
+    i=range[1]-1;
+    cell_size[i] = root->cell_f[i+1] - root->cell_f[i];
+    /* For this check we should not use DD_CELL_MARGIN,
+     * but a slightly smaller factor,
+     * since rounding could get use below the limit.
+     */
+    if (bPBC && cell_size[i] < cellsize_limit_f*DD_CELL_MARGIN2/DD_CELL_MARGIN)
+    {
+        char buf[22];
+        gmx_fatal(FARGS,"Step %s: the dynamic load balancing could not balance dimension %c: box size %f, triclinic skew factor %f, #cells %d, minimum cell size %f\n",
+                  gmx_step_str(step,buf),
+                  dim2char(dim),ddbox->box_size[dim],ddbox->skew_fac[dim],
+                  ncd,comm->cellsize_min[dim]);
+    }
+    
+    root->bLimited = (nmin > 0) || (range[0]>0) || (range[1]<ncd);
+    
+    if (!bUniform)
+    {
+        /* Check if the boundary did not displace more than halfway
+         * each of the cells it bounds, as this could cause problems,
+         * especially when the differences between cell sizes are large.
+         * If changes are applied, they will not make cells smaller
+         * than the cut-off, as we check all the boundaries which
+         * might be affected by a change and if the old state was ok,
+         * the cells will at most be shrunk back to their old size.
+         */
+        for(i=range[0]+1; i<range[1]; i++)
+        {
+            halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i-1]);
+            if (root->cell_f[i] < halfway)
+            {
+                root->cell_f[i] = halfway;
+                /* Check if the change also causes shifts of the next boundaries */
+                for(j=i+1; j<range[1]; j++)
+                {
+                    if (root->cell_f[j] < root->cell_f[j-1] + cellsize_limit_f)
+                        root->cell_f[j] =  root->cell_f[j-1] + cellsize_limit_f;
+                }
+            }
+            halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i+1]);
+            if (root->cell_f[i] > halfway)
+            {
+                root->cell_f[i] = halfway;
+                /* Check if the change also causes shifts of the next boundaries */
+                for(j=i-1; j>=range[0]+1; j--)
+                {
+                    if (root->cell_f[j] > root->cell_f[j+1] - cellsize_limit_f)
+                        root->cell_f[j] = root->cell_f[j+1] - cellsize_limit_f;
+                }
+            }
+        }
+    }
+    
+    /* nrange is defined as [lower, upper) range for new call to enforce_limits */
+    /* find highest violation of LimLo (a) and the following violation of LimHi (thus the lowest following) (b)
+     * then call enforce_limits for (oldb,a), (a,b). In the next step: (b,nexta). oldb and nexta can be the boundaries.
+     * for a and b nrange is used */
+    if (d > 0)
+    {
+        /* Take care of the staggering of the cell boundaries */
+        if (bUniform)
+        {
+            for(i=range[0]; i<range[1]; i++)
+            {
+                root->cell_f_max0[i] = root->cell_f[i];
+                root->cell_f_min1[i] = root->cell_f[i+1];
+            }
+        }
+        else
+        {
+            for(i=range[0]+1; i<range[1]; i++)
+            {
+                bLimLo = (root->cell_f[i] < root->bound_min[i]);
+                bLimHi = (root->cell_f[i] > root->bound_max[i]);
+                if (bLimLo && bLimHi)
+                {
+                    /* Both limits violated, try the best we can */
+                    /* For this case we split the original range (range) in two parts and care about the other limitiations in the next iteration. */
+                    root->cell_f[i] = 0.5*(root->bound_min[i] + root->bound_max[i]);
+                    nrange[0]=range[0];
+                    nrange[1]=i;
+                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+
+                    nrange[0]=i;
+                    nrange[1]=range[1];
+                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+
+                    return;
+                }
+                else if (bLimLo)
+                {
+                    /* root->cell_f[i] = root->bound_min[i]; */
+                    nrange[1]=i;  /* only store violation location. There could be a LimLo violation following with an higher index */
+                    bLastHi=FALSE;
+                }
+                else if (bLimHi && !bLastHi)
+                {
+                    bLastHi=TRUE;
+                    if (nrange[1] < range[1])   /* found a LimLo before */
+                    {
+                        root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
+                        dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+                        nrange[0]=nrange[1];
+                    }
+                    root->cell_f[i] = root->bound_max[i];
+                    nrange[1]=i; 
+                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+                    nrange[0]=i;
+                    nrange[1]=range[1];
+                }
+            }
+            if (nrange[1] < range[1])   /* found last a LimLo */
+            {
+                root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
+                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+                nrange[0]=nrange[1];
+                nrange[1]=range[1];
+                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+            } 
+            else if (nrange[0] > range[0]) /* found at least one LimHi */
+            {
+                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
+            }
+        }
+    }
+}
+
+
+static void set_dd_cell_sizes_dlb_root(gmx_domdec_t *dd,
+                                       int d,int dim,gmx_domdec_root_t *root,
+                                       gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
+                                       gmx_bool bUniform,gmx_large_int_t step)
+{
+    gmx_domdec_comm_t *comm;
+    int  ncd,d1,i,j,pos;
+    real *cell_size;
+    real load_aver,load_i,imbalance,change,change_max,sc;
+    real cellsize_limit_f,dist_min_f,dist_min_f_hard,space;
+    real change_limit;
+    real relax = 0.5;
+    gmx_bool bPBC;
+    int range[] = { 0, 0 };
+
+    comm = dd->comm;
+
+    /* Convert the maximum change from the input percentage to a fraction */
+    change_limit = comm->dlb_scale_lim*0.01;
+
+    ncd = dd->nc[dim];
+
+    bPBC = (dim < ddbox->npbcdim);
+
+    cell_size = root->buf_ncd;
+
+    /* Store the original boundaries */
+    for(i=0; i<ncd+1; i++)
+    {
+        root->old_cell_f[i] = root->cell_f[i];
+    }
+    if (bUniform) {
+        for(i=0; i<ncd; i++)
+        {
+            cell_size[i] = 1.0/ncd;
+        }
+    }
+    else if (dd_load_count(comm))
+    {
+        load_aver = comm->load[d].sum_m/ncd;
+        change_max = 0;
+        for(i=0; i<ncd; i++)
+        {
+            /* Determine the relative imbalance of cell i */
+            load_i = comm->load[d].load[i*comm->load[d].nload+2];
+            imbalance = (load_i - load_aver)/(load_aver>0 ? load_aver : 1);
+            /* Determine the change of the cell size using underrelaxation */
+            change = -relax*imbalance;
+            change_max = max(change_max,max(change,-change));
+        }
+        /* Limit the amount of scaling.
+         * We need to use the same rescaling for all cells in one row,
+         * otherwise the load balancing might not converge.
+         */
+        sc = relax;
+        if (change_max > change_limit)
+        {
+            sc *= change_limit/change_max;
+        }
+        for(i=0; i<ncd; i++)
+        {
+            /* Determine the relative imbalance of cell i */
+            load_i = comm->load[d].load[i*comm->load[d].nload+2];
+            imbalance = (load_i - load_aver)/(load_aver>0 ? load_aver : 1);
+            /* Determine the change of the cell size using underrelaxation */
+            change = -sc*imbalance;
+            cell_size[i] = (root->cell_f[i+1]-root->cell_f[i])*(1 + change);
+        }
+    }
+    
+    cellsize_limit_f  = comm->cellsize_min[dim]/ddbox->box_size[dim];
+    cellsize_limit_f *= DD_CELL_MARGIN;
+    dist_min_f_hard        = grid_jump_limit(comm,d)/ddbox->box_size[dim];
+    dist_min_f       = dist_min_f_hard * DD_CELL_MARGIN;
+    if (ddbox->tric_dir[dim])
+    {
+        cellsize_limit_f /= ddbox->skew_fac[dim];
+        dist_min_f       /= ddbox->skew_fac[dim];
+    }
+    if (bDynamicBox && d > 0)
+    {
+        dist_min_f *= DD_PRES_SCALE_MARGIN;
+    }
+    if (d > 0 && !bUniform)
+    {
+        /* Make sure that the grid is not shifted too much */
+        for(i=1; i<ncd; i++) {
+            if (root->cell_f_min1[i] - root->cell_f_max0[i-1] < 2 * dist_min_f_hard) 
+            {
+                gmx_incons("Inconsistent DD boundary staggering limits!");
+            }
+            root->bound_min[i] = root->cell_f_max0[i-1] + dist_min_f;
+            space = root->cell_f[i] - (root->cell_f_max0[i-1] + dist_min_f);
+            if (space > 0) {
+                root->bound_min[i] += 0.5*space;
+            }
+            root->bound_max[i] = root->cell_f_min1[i] - dist_min_f;
+            space = root->cell_f[i] - (root->cell_f_min1[i] - dist_min_f);
+            if (space < 0) {
+                root->bound_max[i] += 0.5*space;
+            }
+            if (debug)
+            {
+                fprintf(debug,
+                        "dim %d boundary %d %.3f < %.3f < %.3f < %.3f < %.3f\n",
+                        d,i,
+                        root->cell_f_max0[i-1] + dist_min_f,
+                        root->bound_min[i],root->cell_f[i],root->bound_max[i],
+                        root->cell_f_min1[i] - dist_min_f);
+            }
+        }
+    }
+    range[1]=ncd;
+    root->cell_f[0] = 0;
+    root->cell_f[ncd] = 1;
+    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, range);
+
+
+    /* After the checks above, the cells should obey the cut-off
+     * restrictions, but it does not hurt to check.
+     */
+    for(i=0; i<ncd; i++)
+    {
+        if (debug)
+        {
+            fprintf(debug,"Relative bounds dim %d  cell %d: %f %f\n",
+                    dim,i,root->cell_f[i],root->cell_f[i+1]);
+        }
+
+        if ((bPBC || (i != 0 && i != dd->nc[dim]-1)) &&
+            root->cell_f[i+1] - root->cell_f[i] <
+            cellsize_limit_f/DD_CELL_MARGIN)
+        {
+            char buf[22];
+            fprintf(stderr,
+                    "\nWARNING step %s: direction %c, cell %d too small: %f\n",
+                    gmx_step_str(step,buf),dim2char(dim),i,
+                    (root->cell_f[i+1] - root->cell_f[i])
+                    *ddbox->box_size[dim]*ddbox->skew_fac[dim]);
+        }
+    }
+    
+    pos = ncd + 1;
+    /* Store the cell boundaries of the lower dimensions at the end */
+    for(d1=0; d1<d; d1++)
+    {
+        root->cell_f[pos++] = comm->cell_f0[d1];
+        root->cell_f[pos++] = comm->cell_f1[d1];
+    }
+    
+    if (d < comm->npmedecompdim)
+    {
+        /* The master determines the maximum shift for
+         * the coordinate communication between separate PME nodes.
+         */
+        set_pme_maxshift(dd,&comm->ddpme[d],bUniform,ddbox,root->cell_f);
+    }
+    root->cell_f[pos++] = comm->ddpme[0].maxshift;
+    if (d >= 1)
+    {
+        root->cell_f[pos++] = comm->ddpme[1].maxshift;
+    }
+}    
+
+static void relative_to_absolute_cell_bounds(gmx_domdec_t *dd,
+                                             gmx_ddbox_t *ddbox,int dimind)
+{
+    gmx_domdec_comm_t *comm;
+    int dim;
+
+    comm = dd->comm;
+
+    /* Set the cell dimensions */
+    dim = dd->dim[dimind];
+    comm->cell_x0[dim] = comm->cell_f0[dimind]*ddbox->box_size[dim];
+    comm->cell_x1[dim] = comm->cell_f1[dimind]*ddbox->box_size[dim];
+    if (dim >= ddbox->nboundeddim)
+    {
+        comm->cell_x0[dim] += ddbox->box0[dim];
+        comm->cell_x1[dim] += ddbox->box0[dim];
+    }
+}
+
+static void distribute_dd_cell_sizes_dlb(gmx_domdec_t *dd,
+                                         int d,int dim,real *cell_f_row,
+                                         gmx_ddbox_t *ddbox)
+{
+    gmx_domdec_comm_t *comm;
+    int d1,dim1,pos;
+
+    comm = dd->comm;
+
+#ifdef GMX_MPI
+    /* Each node would only need to know two fractions,
+     * but it is probably cheaper to broadcast the whole array.
+     */
+    MPI_Bcast(cell_f_row,DD_CELL_F_SIZE(dd,d)*sizeof(real),MPI_BYTE,
+              0,comm->mpi_comm_load[d]);
+#endif
+    /* Copy the fractions for this dimension from the buffer */
+    comm->cell_f0[d] = cell_f_row[dd->ci[dim]  ];
+    comm->cell_f1[d] = cell_f_row[dd->ci[dim]+1];
+    /* The whole array was communicated, so set the buffer position */
+    pos = dd->nc[dim] + 1;
+    for(d1=0; d1<=d; d1++)
+    {
+        if (d1 < d)
+        {
+            /* Copy the cell fractions of the lower dimensions */
+            comm->cell_f0[d1] = cell_f_row[pos++];
+            comm->cell_f1[d1] = cell_f_row[pos++];
+        }
+        relative_to_absolute_cell_bounds(dd,ddbox,d1);
+    }
+    /* Convert the communicated shift from float to int */
+    comm->ddpme[0].maxshift = (int)(cell_f_row[pos++] + 0.5);
+    if (d >= 1)
+    {
+        comm->ddpme[1].maxshift = (int)(cell_f_row[pos++] + 0.5);
+    }
+}
+
+static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
+                                         gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
+                                         gmx_bool bUniform,gmx_large_int_t step)
+{
+    gmx_domdec_comm_t *comm;
+    int d,dim,d1;
+    gmx_bool bRowMember,bRowRoot;
+    real *cell_f_row;
+    
+    comm = dd->comm;
+
+    for(d=0; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        bRowMember = TRUE;
+        bRowRoot = TRUE;
+        for(d1=d; d1<dd->ndim; d1++)
+        {
+            if (dd->ci[dd->dim[d1]] > 0)
+            {
+                if (d1 > d)
+                {
+                    bRowMember = FALSE;
+                }
+                bRowRoot = FALSE;
+            }
+        }
+        if (bRowMember)
+        {
+            if (bRowRoot)
+            {
+                set_dd_cell_sizes_dlb_root(dd,d,dim,comm->root[d],
+                                           ddbox,bDynamicBox,bUniform,step);
+                cell_f_row = comm->root[d]->cell_f;
+            }
+            else
+            {
+                cell_f_row = comm->cell_f_row;
+            }
+            distribute_dd_cell_sizes_dlb(dd,d,dim,cell_f_row,ddbox);
+        }
+    }
+}    
+
+static void set_dd_cell_sizes_dlb_nochange(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
+{
+    int d;
+
+    /* This function assumes the box is static and should therefore
+     * not be called when the box has changed since the last
+     * call to dd_partition_system.
+     */
+    for(d=0; d<dd->ndim; d++)
+    {
+        relative_to_absolute_cell_bounds(dd,ddbox,d); 
+    }
+}
+
+
+
+static void set_dd_cell_sizes_dlb(gmx_domdec_t *dd,
+                                  gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
+                                  gmx_bool bUniform,gmx_bool bDoDLB,gmx_large_int_t step,
+                                  gmx_wallcycle_t wcycle)
+{
+    gmx_domdec_comm_t *comm;
+    int dim;
+
+    comm = dd->comm;
+    
+    if (bDoDLB)
+    {
+        wallcycle_start(wcycle,ewcDDCOMMBOUND);
+        set_dd_cell_sizes_dlb_change(dd,ddbox,bDynamicBox,bUniform,step);
+        wallcycle_stop(wcycle,ewcDDCOMMBOUND);
+    }
+    else if (bDynamicBox)
+    {
+        set_dd_cell_sizes_dlb_nochange(dd,ddbox);
+    }
+    
+    /* Set the dimensions for which no DD is used */
+    for(dim=0; dim<DIM; dim++) {
+        if (dd->nc[dim] == 1) {
+            comm->cell_x0[dim] = 0;
+            comm->cell_x1[dim] = ddbox->box_size[dim];
+            if (dim >= ddbox->nboundeddim)
+            {
+                comm->cell_x0[dim] += ddbox->box0[dim];
+                comm->cell_x1[dim] += ddbox->box0[dim];
+            }
+        }
+    }
+}
+
+static void realloc_comm_ind(gmx_domdec_t *dd,ivec npulse)
+{
+    int d,np,i;
+    gmx_domdec_comm_dim_t *cd;
+    
+    for(d=0; d<dd->ndim; d++)
+    {
+        cd = &dd->comm->cd[d];
+        np = npulse[dd->dim[d]];
+        if (np > cd->np_nalloc)
+        {
+            if (debug)
+            {
+                fprintf(debug,"(Re)allocing cd for %c to %d pulses\n",
+                        dim2char(dd->dim[d]),np);
+            }
+            if (DDMASTER(dd) && cd->np_nalloc > 0)
+            {
+                fprintf(stderr,"\nIncreasing the number of cell to communicate in dimension %c to %d for the first time\n",dim2char(dd->dim[d]),np);
+            }
+            srenew(cd->ind,np);
+            for(i=cd->np_nalloc; i<np; i++)
+            {
+                cd->ind[i].index  = NULL;
+                cd->ind[i].nalloc = 0;
+            }
+            cd->np_nalloc = np;
+        }
+        cd->np = np;
+    }
+}
+
+
+static void set_dd_cell_sizes(gmx_domdec_t *dd,
+                              gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
+                              gmx_bool bUniform,gmx_bool bDoDLB,gmx_large_int_t step,
+                              gmx_wallcycle_t wcycle)
+{
+    gmx_domdec_comm_t *comm;
+    int  d;
+    ivec npulse;
+    
+    comm = dd->comm;
+
+    /* Copy the old cell boundaries for the cg displacement check */
+    copy_rvec(comm->cell_x0,comm->old_cell_x0);
+    copy_rvec(comm->cell_x1,comm->old_cell_x1);
+    
+    if (comm->bDynLoadBal)
+    {
+        if (DDMASTER(dd))
+        {
+            check_box_size(dd,ddbox);
+        }
+        set_dd_cell_sizes_dlb(dd,ddbox,bDynamicBox,bUniform,bDoDLB,step,wcycle);
+    }
+    else
+    {
+        set_dd_cell_sizes_slb(dd,ddbox,FALSE,npulse);
+        realloc_comm_ind(dd,npulse);
+    }
+    
+    if (debug)
+    {
+        for(d=0; d<DIM; d++)
+        {
+            fprintf(debug,"cell_x[%d] %f - %f skew_fac %f\n",
+                    d,comm->cell_x0[d],comm->cell_x1[d],ddbox->skew_fac[d]);
+        }
+    }
+}
+
+static void comm_dd_ns_cell_sizes(gmx_domdec_t *dd,
+                                  gmx_ddbox_t *ddbox,
+                                  rvec cell_ns_x0,rvec cell_ns_x1,
+                                  gmx_large_int_t step)
+{
+    gmx_domdec_comm_t *comm;
+    int dim_ind,dim;
+    
+    comm = dd->comm;
+
+    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
+    {
+        dim = dd->dim[dim_ind];
+        
+        /* Without PBC we don't have restrictions on the outer cells */
+        if (!(dim >= ddbox->npbcdim && 
+              (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1)) &&
+            comm->bDynLoadBal &&
+            (comm->cell_x1[dim] - comm->cell_x0[dim])*ddbox->skew_fac[dim] <
+            comm->cellsize_min[dim])
+        {
+            char buf[22];
+            gmx_fatal(FARGS,"Step %s: The %c-size (%f) times the triclinic skew factor (%f) is smaller than the smallest allowed cell size (%f) for domain decomposition grid cell %d %d %d",
+                      gmx_step_str(step,buf),dim2char(dim),
+                      comm->cell_x1[dim] - comm->cell_x0[dim],
+                      ddbox->skew_fac[dim],
+                      dd->comm->cellsize_min[dim],
+                      dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+        }
+    }
+    
+    if ((dd->bGridJump && dd->ndim > 1) || ddbox->nboundeddim < DIM)
+    {
+        /* Communicate the boundaries and update cell_ns_x0/1 */
+        dd_move_cellx(dd,ddbox,cell_ns_x0,cell_ns_x1);
+        if (dd->bGridJump && dd->ndim > 1)
+        {
+            check_grid_jump(step,dd,ddbox);
+        }
+    }
+}
+
+static void make_tric_corr_matrix(int npbcdim,matrix box,matrix tcm)
+{
+    if (YY < npbcdim)
+    {
+        tcm[YY][XX] = -box[YY][XX]/box[YY][YY];
+    }
+    else
+    {
+        tcm[YY][XX] = 0;
+    }
+    if (ZZ < npbcdim)
+    {
+        tcm[ZZ][XX] = -(box[ZZ][YY]*tcm[YY][XX] + box[ZZ][XX])/box[ZZ][ZZ];
+        tcm[ZZ][YY] = -box[ZZ][YY]/box[ZZ][ZZ];
+    }
+    else
+    {
+        tcm[ZZ][XX] = 0;
+        tcm[ZZ][YY] = 0;
+    }
+}
+
+static void check_screw_box(matrix box)
+{
+    /* Mathematical limitation */
+    if (box[YY][XX] != 0 || box[ZZ][XX] != 0)
+    {
+        gmx_fatal(FARGS,"With screw pbc the unit cell can not have non-zero off-diagonal x-components");
+    }
+    
+    /* Limitation due to the asymmetry of the eighth shell method */
+    if (box[ZZ][YY] != 0)
+    {
+        gmx_fatal(FARGS,"pbc=screw with non-zero box_zy is not supported");
+    }
+}
+
+static void distribute_cg(FILE *fplog,gmx_large_int_t step,
+                          matrix box,ivec tric_dir,t_block *cgs,rvec pos[],
+                          gmx_domdec_t *dd)
+{
+    gmx_domdec_master_t *ma;
+    int **tmp_ind=NULL,*tmp_nalloc=NULL;
+    int  i,icg,j,k,k0,k1,d,npbcdim;
+    matrix tcm;
+    rvec box_size,cg_cm;
+    ivec ind;
+    real nrcg,inv_ncg,pos_d;
+    atom_id *cgindex;
+    gmx_bool bUnbounded,bScrew;
+
+    ma = dd->ma;
+    
+    if (tmp_ind == NULL)
+    {
+        snew(tmp_nalloc,dd->nnodes);
+        snew(tmp_ind,dd->nnodes);
+        for(i=0; i<dd->nnodes; i++)
+        {
+            tmp_nalloc[i] = over_alloc_large(cgs->nr/dd->nnodes+1);
+            snew(tmp_ind[i],tmp_nalloc[i]);
+        }
+    }
+    
+    /* Clear the count */
+    for(i=0; i<dd->nnodes; i++)
+    {
+        ma->ncg[i] = 0;
+        ma->nat[i] = 0;
+    }
+    
+    make_tric_corr_matrix(dd->npbcdim,box,tcm);
+    
+    cgindex = cgs->index;
+    
+    /* Compute the center of geometry for all charge groups */
+    for(icg=0; icg<cgs->nr; icg++)
+    {
+        k0      = cgindex[icg];
+        k1      = cgindex[icg+1];
+        nrcg    = k1 - k0;
+        if (nrcg == 1)
+        {
+            copy_rvec(pos[k0],cg_cm);
+        }
+        else
+        {
+            inv_ncg = 1.0/nrcg;
+            
+            clear_rvec(cg_cm);
+            for(k=k0; (k<k1); k++)
+            {
+                rvec_inc(cg_cm,pos[k]);
+            }
+            for(d=0; (d<DIM); d++)
+            {
+                cg_cm[d] *= inv_ncg;
+            }
+        }
+        /* Put the charge group in the box and determine the cell index */
+        for(d=DIM-1; d>=0; d--) {
+            pos_d = cg_cm[d];
+            if (d < dd->npbcdim)
+            {
+                bScrew = (dd->bScrewPBC && d == XX);
+                if (tric_dir[d] && dd->nc[d] > 1)
+                {
+                    /* Use triclinic coordintates for this dimension */
+                    for(j=d+1; j<DIM; j++)
+                    {
+                        pos_d += cg_cm[j]*tcm[j][d];
+                    }
+                }
+                while(pos_d >= box[d][d])
+                {
+                    pos_d -= box[d][d];
+                    rvec_dec(cg_cm,box[d]);
+                    if (bScrew)
+                    {
+                        cg_cm[YY] = box[YY][YY] - cg_cm[YY];
+                        cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
+                    }
+                    for(k=k0; (k<k1); k++)
+                    {
+                        rvec_dec(pos[k],box[d]);
+                        if (bScrew)
+                        {
+                            pos[k][YY] = box[YY][YY] - pos[k][YY];
+                            pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
+                        }
+                    }
+                }
+                while(pos_d < 0)
+                {
+                    pos_d += box[d][d];
+                    rvec_inc(cg_cm,box[d]);
+                    if (bScrew)
+                    {
+                        cg_cm[YY] = box[YY][YY] - cg_cm[YY];
+                        cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
+                    }
+                    for(k=k0; (k<k1); k++)
+                    {
+                        rvec_inc(pos[k],box[d]);
+                        if (bScrew) {
+                            pos[k][YY] = box[YY][YY] - pos[k][YY];
+                            pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
+                        }
+                    }
+                }
+            }
+            /* This could be done more efficiently */
+            ind[d] = 0;
+            while(ind[d]+1 < dd->nc[d] && pos_d >= ma->cell_x[d][ind[d]+1])
+            {
+                ind[d]++;
+            }
+        }
+        i = dd_index(dd->nc,ind);
+        if (ma->ncg[i] == tmp_nalloc[i])
+        {
+            tmp_nalloc[i] = over_alloc_large(ma->ncg[i]+1);
+            srenew(tmp_ind[i],tmp_nalloc[i]);
+        }
+        tmp_ind[i][ma->ncg[i]] = icg;
+        ma->ncg[i]++;
+        ma->nat[i] += cgindex[icg+1] - cgindex[icg];
+    }
+    
+    k1 = 0;
+    for(i=0; i<dd->nnodes; i++)
+    {
+        ma->index[i] = k1;
+        for(k=0; k<ma->ncg[i]; k++)
+        {
+            ma->cg[k1++] = tmp_ind[i][k];
+        }
+    }
+    ma->index[dd->nnodes] = k1;
+    
+    for(i=0; i<dd->nnodes; i++)
+    {
+        sfree(tmp_ind[i]);
+    }
+    sfree(tmp_ind);
+    sfree(tmp_nalloc);
+    
+    if (fplog)
+    {
+        char buf[22];
+        fprintf(fplog,"Charge group distribution at step %s:",
+                gmx_step_str(step,buf));
+        for(i=0; i<dd->nnodes; i++)
+        {
+            fprintf(fplog," %d",ma->ncg[i]);
+        }
+        fprintf(fplog,"\n");
+    }
+}
+
+static void get_cg_distribution(FILE *fplog,gmx_large_int_t step,gmx_domdec_t *dd,
+                                t_block *cgs,matrix box,gmx_ddbox_t *ddbox,
+                                rvec pos[])
+{
+    gmx_domdec_master_t *ma=NULL;
+    ivec npulse;
+    int  i,cg_gl;
+    int  *ibuf,buf2[2] = { 0, 0 };
+    
+    if (DDMASTER(dd))
+    {
+        ma = dd->ma;
+        
+        if (dd->bScrewPBC)
+        {
+            check_screw_box(box);
+        }
+    
+        set_dd_cell_sizes_slb(dd,ddbox,TRUE,npulse);
+    
+        distribute_cg(fplog,step,box,ddbox->tric_dir,cgs,pos,dd);
+        for(i=0; i<dd->nnodes; i++)
+        {
+            ma->ibuf[2*i]   = ma->ncg[i];
+            ma->ibuf[2*i+1] = ma->nat[i];
+        }
+        ibuf = ma->ibuf;
+    }
+    else
+    {
+        ibuf = NULL;
+    }
+    dd_scatter(dd,2*sizeof(int),ibuf,buf2);
+    
+    dd->ncg_home = buf2[0];
+    dd->nat_home = buf2[1];
+    dd->ncg_tot  = dd->ncg_home;
+    dd->nat_tot  = dd->nat_home;
+    if (dd->ncg_home > dd->cg_nalloc || dd->cg_nalloc == 0)
+    {
+        dd->cg_nalloc = over_alloc_dd(dd->ncg_home);
+        srenew(dd->index_gl,dd->cg_nalloc);
+        srenew(dd->cgindex,dd->cg_nalloc+1);
+    }
+    if (DDMASTER(dd))
+    {
+        for(i=0; i<dd->nnodes; i++)
+        {
+            ma->ibuf[i] = ma->ncg[i]*sizeof(int);
+            ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
+        }
+    }
+    
+    dd_scatterv(dd,
+                DDMASTER(dd) ? ma->ibuf : NULL,
+                DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
+                DDMASTER(dd) ? ma->cg : NULL,
+                dd->ncg_home*sizeof(int),dd->index_gl);
+    
+    /* Determine the home charge group sizes */
+    dd->cgindex[0] = 0;
+    for(i=0; i<dd->ncg_home; i++)
+    {
+        cg_gl = dd->index_gl[i];
+        dd->cgindex[i+1] =
+            dd->cgindex[i] + cgs->index[cg_gl+1] - cgs->index[cg_gl];
+    }
+    
+    if (debug)
+    {
+        fprintf(debug,"Home charge groups:\n");
+        for(i=0; i<dd->ncg_home; i++)
+        {
+            fprintf(debug," %d",dd->index_gl[i]);
+            if (i % 10 == 9) 
+                fprintf(debug,"\n");
+        }
+        fprintf(debug,"\n");
+    }
+}
+
+static int compact_and_copy_vec_at(int ncg,int *move,
+                                   int *cgindex,
+                                   int nvec,int vec,
+                                   rvec *src,gmx_domdec_comm_t *comm,
+                                   gmx_bool bCompact)
+{
+    int m,icg,i,i0,i1,nrcg;
+    int home_pos;
+    int pos_vec[DIM*2];
+    
+    home_pos = 0;
+
+    for(m=0; m<DIM*2; m++)
+    {
+        pos_vec[m] = 0;
+    }
+    
+    i0 = 0;
+    for(icg=0; icg<ncg; icg++)
+    {
+        i1 = cgindex[icg+1];
+        m = move[icg];
+        if (m == -1)
+        {
+            if (bCompact)
+            {
+                /* Compact the home array in place */
+                for(i=i0; i<i1; i++)
+                {
+                    copy_rvec(src[i],src[home_pos++]);
+                }
+            }
+        }
+        else
+        {
+            /* Copy to the communication buffer */
+            nrcg = i1 - i0;
+            pos_vec[m] += 1 + vec*nrcg;
+            for(i=i0; i<i1; i++)
+            {
+                copy_rvec(src[i],comm->cgcm_state[m][pos_vec[m]++]);
+            }
+            pos_vec[m] += (nvec - vec - 1)*nrcg;
+        }
+        if (!bCompact)
+        {
+            home_pos += i1 - i0;
+        }
+        i0 = i1;
+    }
+    
+    return home_pos;
+}
+
+static int compact_and_copy_vec_cg(int ncg,int *move,
+                                   int *cgindex,
+                                   int nvec,rvec *src,gmx_domdec_comm_t *comm,
+                                   gmx_bool bCompact)
+{
+    int m,icg,i0,i1,nrcg;
+    int home_pos;
+    int pos_vec[DIM*2];
+    
+    home_pos = 0;
+    
+    for(m=0; m<DIM*2; m++)
+    {
+        pos_vec[m] = 0;
+    }
+    
+    i0 = 0;
+    for(icg=0; icg<ncg; icg++)
+    {
+        i1 = cgindex[icg+1];
+        m = move[icg];
+        if (m == -1)
+        {
+            if (bCompact)
+            {
+                /* Compact the home array in place */
+                copy_rvec(src[icg],src[home_pos++]);
+            }
+        }
+        else
+        {
+            nrcg = i1 - i0;
+            /* Copy to the communication buffer */
+            copy_rvec(src[icg],comm->cgcm_state[m][pos_vec[m]]);
+            pos_vec[m] += 1 + nrcg*nvec;
+        }
+        i0 = i1;
+    }
+    if (!bCompact)
+    {
+        home_pos = ncg;
+    }
+    
+    return home_pos;
+}
+
+static int compact_ind(int ncg,int *move,
+                       int *index_gl,int *cgindex,
+                       int *gatindex,
+                       gmx_ga2la_t ga2la,char *bLocalCG,
+                       int *cginfo)
+{
+    int cg,nat,a0,a1,a,a_gl;
+    int home_pos;
+
+    home_pos = 0;
+    nat = 0;
+    for(cg=0; cg<ncg; cg++)
+    {
+        a0 = cgindex[cg];
+        a1 = cgindex[cg+1];
+        if (move[cg] == -1)
+        {
+            /* Compact the home arrays in place.
+             * Anything that can be done here avoids access to global arrays.
+             */
+            cgindex[home_pos] = nat;
+            for(a=a0; a<a1; a++)
+            {
+                a_gl = gatindex[a];
+                gatindex[nat] = a_gl;
+                /* The cell number stays 0, so we don't need to set it */
+                ga2la_change_la(ga2la,a_gl,nat);
+                nat++;
+            }
+            index_gl[home_pos] = index_gl[cg];
+            cginfo[home_pos]   = cginfo[cg];
+            /* The charge group remains local, so bLocalCG does not change */
+            home_pos++;
+        }
+        else
+        {
+            /* Clear the global indices */
+            for(a=a0; a<a1; a++)
+            {
+                ga2la_del(ga2la,gatindex[a]);
+            }
+            if (bLocalCG)
+            {
+                bLocalCG[index_gl[cg]] = FALSE;
+            }
+        }
+    }
+    cgindex[home_pos] = nat;
+    
+    return home_pos;
+}
+
+static void clear_and_mark_ind(int ncg,int *move,
+                               int *index_gl,int *cgindex,int *gatindex,
+                               gmx_ga2la_t ga2la,char *bLocalCG,
+                               int *cell_index)
+{
+    int cg,a0,a1,a;
+    
+    for(cg=0; cg<ncg; cg++)
+    {
+        if (move[cg] >= 0)
+        {
+            a0 = cgindex[cg];
+            a1 = cgindex[cg+1];
+            /* Clear the global indices */
+            for(a=a0; a<a1; a++)
+            {
+                ga2la_del(ga2la,gatindex[a]);
+            }
+            if (bLocalCG)
+            {
+                bLocalCG[index_gl[cg]] = FALSE;
+            }
+            /* Signal that this cg has moved using the ns cell index.
+             * Here we set it to -1.
+             * fill_grid will change it from -1 to 4*grid->ncells.
+             */
+            cell_index[cg] = -1;
+        }
+    }
+}
+
+static void print_cg_move(FILE *fplog,
+                          gmx_domdec_t *dd,
+                          gmx_large_int_t step,int cg,int dim,int dir,
+                          gmx_bool bHaveLimitdAndCMOld,real limitd,
+                          rvec cm_old,rvec cm_new,real pos_d)
+{
+    gmx_domdec_comm_t *comm;
+    char buf[22];
+
+    comm = dd->comm;
+
+    fprintf(fplog,"\nStep %s:\n",gmx_step_str(step,buf));
+    if (bHaveLimitdAndCMOld)
+    {
+        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
+                ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
+    }
+    else
+    {
+        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition in direction %c\n",
+                ddglatnr(dd,dd->cgindex[cg]),dim2char(dim));
+    }
+    fprintf(fplog,"distance out of cell %f\n",
+            dir==1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
+    if (bHaveLimitdAndCMOld)
+    {
+        fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
+                cm_old[XX],cm_old[YY],cm_old[ZZ]);
+    }
+    fprintf(fplog,"New coordinates: %8.3f %8.3f %8.3f\n",
+            cm_new[XX],cm_new[YY],cm_new[ZZ]);
+    fprintf(fplog,"Old cell boundaries in direction %c: %8.3f %8.3f\n",
+            dim2char(dim),
+            comm->old_cell_x0[dim],comm->old_cell_x1[dim]);
+    fprintf(fplog,"New cell boundaries in direction %c: %8.3f %8.3f\n",
+            dim2char(dim),
+            comm->cell_x0[dim],comm->cell_x1[dim]);
+}
+
+static void cg_move_error(FILE *fplog,
+                          gmx_domdec_t *dd,
+                          gmx_large_int_t step,int cg,int dim,int dir,
+                          gmx_bool bHaveLimitdAndCMOld,real limitd,
+                          rvec cm_old,rvec cm_new,real pos_d)
+{
+    if (fplog)
+    {
+        print_cg_move(fplog, dd,step,cg,dim,dir,
+                      bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
+    }
+    print_cg_move(stderr,dd,step,cg,dim,dir,
+                  bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
+    gmx_fatal(FARGS,
+              "A charge group moved too far between two domain decomposition steps\n"
+              "This usually means that your system is not well equilibrated");
+}
+
+static void rotate_state_atom(t_state *state,int a)
+{
+    int est;
+
+    for(est=0; est<estNR; est++)
+    {
+        if (EST_DISTR(est) && (state->flags & (1<<est))) {
+            switch (est) {
+            case estX:
+                /* Rotate the complete state; for a rectangular box only */
+                state->x[a][YY] = state->box[YY][YY] - state->x[a][YY];
+                state->x[a][ZZ] = state->box[ZZ][ZZ] - state->x[a][ZZ];
+                break;
+            case estV:
+                state->v[a][YY] = -state->v[a][YY];
+                state->v[a][ZZ] = -state->v[a][ZZ];
+                break;
+            case estSDX:
+                state->sd_X[a][YY] = -state->sd_X[a][YY];
+                state->sd_X[a][ZZ] = -state->sd_X[a][ZZ];
+                break;
+            case estCGP:
+                state->cg_p[a][YY] = -state->cg_p[a][YY];
+                state->cg_p[a][ZZ] = -state->cg_p[a][ZZ];
+                break;
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                /* These are distances, so not affected by rotation */
+                break;
+            default:
+                gmx_incons("Unknown state entry encountered in rotate_state_atom");            
+            }
+        }
+    }
+}
+
+static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
+                              gmx_domdec_t *dd,ivec tric_dir,
+                              t_state *state,rvec **f,
+                              t_forcerec *fr,t_mdatoms *md,
+                              gmx_bool bCompact,
+                              t_nrnb *nrnb)
+{
+    int  *move;
+    int  npbcdim;
+    int  ncg[DIM*2],nat[DIM*2];
+    int  c,i,cg,k,k0,k1,d,dim,dim2,dir,d2,d3,d4,cell_d;
+    int  mc,cdd,nrcg,ncg_recv,nat_recv,nvs,nvr,nvec,vec;
+    int  sbuf[2],rbuf[2];
+    int  home_pos_cg,home_pos_at,ncg_stay_home,buf_pos;
+    int  flag;
+    gmx_bool bV=FALSE,bSDX=FALSE,bCGP=FALSE;
+    gmx_bool bScrew;
+    ivec dev;
+    real inv_ncg,pos_d;
+    matrix tcm;
+    rvec *cg_cm,cell_x0,cell_x1,limitd,limit0,limit1,cm_new;
+    atom_id *cgindex;
+    cginfo_mb_t *cginfo_mb;
+    gmx_domdec_comm_t *comm;
+    
+    if (dd->bScrewPBC)
+    {
+        check_screw_box(state->box);
+    }
+    
+    comm  = dd->comm;
+    cg_cm = fr->cg_cm;
+    
+    for(i=0; i<estNR; i++)
+    {
+        if (EST_DISTR(i))
+        {
+            switch (i)
+            {
+            case estX:   /* Always present */            break;
+            case estV:   bV   = (state->flags & (1<<i)); break;
+            case estSDX: bSDX = (state->flags & (1<<i)); break;
+            case estCGP: bCGP = (state->flags & (1<<i)); break;
+            case estLD_RNG:
+            case estLD_RNGI:
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                /* No processing required */
+                break;
+            default:
+            gmx_incons("Unknown state entry encountered in dd_redistribute_cg");
+            }
+        }
+    }
+    
+    if (dd->ncg_tot > comm->nalloc_int)
+    {
+        comm->nalloc_int = over_alloc_dd(dd->ncg_tot);
+        srenew(comm->buf_int,comm->nalloc_int);
+    }
+    move = comm->buf_int;
+    
+    /* Clear the count */
+    for(c=0; c<dd->ndim*2; c++)
+    {
+        ncg[c] = 0;
+        nat[c] = 0;
+    }
+
+    npbcdim = dd->npbcdim;
+
+    for(d=0; (d<DIM); d++)
+    {
+        limitd[d] = dd->comm->cellsize_min[d];
+        if (d >= npbcdim && dd->ci[d] == 0)
+        {
+            cell_x0[d] = -GMX_FLOAT_MAX;
+        }
+        else
+        {
+            cell_x0[d] = comm->cell_x0[d];
+        }
+        if (d >= npbcdim && dd->ci[d] == dd->nc[d] - 1)
+        {
+            cell_x1[d] = GMX_FLOAT_MAX;
+        }
+        else
+        {
+            cell_x1[d] = comm->cell_x1[d];
+        }
+        if (d < npbcdim)
+        {
+            limit0[d] = comm->old_cell_x0[d] - limitd[d];
+            limit1[d] = comm->old_cell_x1[d] + limitd[d];
+        }
+        else
+        {
+            /* We check after communication if a charge group moved
+             * more than one cell. Set the pre-comm check limit to float_max.
+             */
+            limit0[d] = -GMX_FLOAT_MAX;
+            limit1[d] =  GMX_FLOAT_MAX;
+        }
+    }
+    
+    make_tric_corr_matrix(npbcdim,state->box,tcm);
+    
+    cgindex = dd->cgindex;
+    
+    /* Compute the center of geometry for all home charge groups
+     * and put them in the box and determine where they should go.
+     */
+    for(cg=0; cg<dd->ncg_home; cg++)
+    {
+        k0   = cgindex[cg];
+        k1   = cgindex[cg+1];
+        nrcg = k1 - k0;
+        if (nrcg == 1)
+        {
+            copy_rvec(state->x[k0],cm_new);
+        }
+        else
+        {
+            inv_ncg = 1.0/nrcg;
+            
+            clear_rvec(cm_new);
+            for(k=k0; (k<k1); k++)
+            {
+                rvec_inc(cm_new,state->x[k]);
+            }
+            for(d=0; (d<DIM); d++)
+            {
+                cm_new[d] = inv_ncg*cm_new[d];
+            }
+        }
+        
+        clear_ivec(dev);
+        /* Do pbc and check DD cell boundary crossings */
+        for(d=DIM-1; d>=0; d--)
+        {
+            if (dd->nc[d] > 1)
+            {
+                bScrew = (dd->bScrewPBC && d == XX);
+                /* Determine the location of this cg in lattice coordinates */
+                pos_d = cm_new[d];
+                if (tric_dir[d])
+                {
+                    for(d2=d+1; d2<DIM; d2++)
+                    {
+                        pos_d += cm_new[d2]*tcm[d2][d];
+                    }
+                }
+                /* Put the charge group in the triclinic unit-cell */
+                if (pos_d >= cell_x1[d])
+                {
+                    if (pos_d >= limit1[d])
+                    {
+                        cg_move_error(fplog,dd,step,cg,d,1,TRUE,limitd[d],
+                                      cg_cm[cg],cm_new,pos_d);
+                    }
+                    dev[d] = 1;
+                    if (dd->ci[d] == dd->nc[d] - 1)
+                    {
+                        rvec_dec(cm_new,state->box[d]);
+                        if (bScrew)
+                        {
+                            cm_new[YY] = state->box[YY][YY] - cm_new[YY];
+                            cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
+                        }
+                        for(k=k0; (k<k1); k++)
+                        {
+                            rvec_dec(state->x[k],state->box[d]);
+                            if (bScrew)
+                            {
+                                rotate_state_atom(state,k);
+                            }
+                        }
+                    }
+                }
+                else if (pos_d < cell_x0[d])
+                {
+                    if (pos_d < limit0[d])
+                    {
+                        cg_move_error(fplog,dd,step,cg,d,-1,TRUE,limitd[d],
+                                      cg_cm[cg],cm_new,pos_d);
+                    }
+                    dev[d] = -1;
+                    if (dd->ci[d] == 0)
+                    {
+                        rvec_inc(cm_new,state->box[d]);
+                        if (bScrew)
+                        {
+                            cm_new[YY] = state->box[YY][YY] - cm_new[YY];
+                            cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
+                        }
+                        for(k=k0; (k<k1); k++)
+                        {
+                            rvec_inc(state->x[k],state->box[d]);
+                            if (bScrew)
+                            {
+                                rotate_state_atom(state,k);
+                            }
+                        }
+                    }
+                }
+            }
+            else if (d < npbcdim)
+            {
+                /* Put the charge group in the rectangular unit-cell */
+                while (cm_new[d] >= state->box[d][d])
+                {
+                    rvec_dec(cm_new,state->box[d]);
+                    for(k=k0; (k<k1); k++)
+                    {
+                        rvec_dec(state->x[k],state->box[d]);
+                    }
+                }
+                while (cm_new[d] < 0)
+                {
+                    rvec_inc(cm_new,state->box[d]);
+                    for(k=k0; (k<k1); k++)
+                    {
+                        rvec_inc(state->x[k],state->box[d]);
+                    }
+                }
+            }
+        }
+    
+        copy_rvec(cm_new,cg_cm[cg]);
+        
+        /* Determine where this cg should go */
+        flag = 0;
+        mc = -1;
+        for(d=0; d<dd->ndim; d++)
+        {
+            dim = dd->dim[d];
+            if (dev[dim] == 1)
+            {
+                flag |= DD_FLAG_FW(d);
+                if (mc == -1)
+                {
+                    mc = d*2;
+                }
+            }
+            else if (dev[dim] == -1)
+            {
+                flag |= DD_FLAG_BW(d);
+                if (mc == -1) {
+                    if (dd->nc[dim] > 2)
+                    {
+                        mc = d*2 + 1;
+                    }
+                    else
+                    {
+                        mc = d*2;
+                    }
+                }
+            }
+        }
+        move[cg] = mc;
+        if (mc >= 0)
+        {
+            if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
+            {
+                comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
+                srenew(comm->cggl_flag[mc],comm->cggl_flag_nalloc[mc]*DD_CGIBS);
+            }
+            comm->cggl_flag[mc][ncg[mc]*DD_CGIBS  ] = dd->index_gl[cg];
+            /* We store the cg size in the lower 16 bits
+             * and the place where the charge group should go
+             * in the next 6 bits. This saves some communication volume.
+             */
+            comm->cggl_flag[mc][ncg[mc]*DD_CGIBS+1] = nrcg | flag;
+            ncg[mc] += 1;
+            nat[mc] += nrcg;
+        }
+    }
+    
+    inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
+    inc_nrnb(nrnb,eNR_RESETX,dd->ncg_home);
+    
+    nvec = 1;
+    if (bV)
+    {
+        nvec++;
+    }
+    if (bSDX)
+    {
+        nvec++;
+    }
+    if (bCGP)
+    {
+        nvec++;
+    }
+    
+    /* Make sure the communication buffers are large enough */
+    for(mc=0; mc<dd->ndim*2; mc++)
+    {
+        nvr = ncg[mc] + nat[mc]*nvec;
+        if (nvr > comm->cgcm_state_nalloc[mc])
+        {
+            comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr);
+            srenew(comm->cgcm_state[mc],comm->cgcm_state_nalloc[mc]);
+        }
+    }
+    
+    /* Recalculating cg_cm might be cheaper than communicating,
+     * but that could give rise to rounding issues.
+     */
+    home_pos_cg =
+        compact_and_copy_vec_cg(dd->ncg_home,move,cgindex,
+                                nvec,cg_cm,comm,bCompact);
+    
+    vec = 0;
+    home_pos_at =
+        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
+                                nvec,vec++,state->x,comm,bCompact);
+    if (bV)
+    {
+        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
+                                nvec,vec++,state->v,comm,bCompact);
+    }
+    if (bSDX)
+    {
+        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
+                                nvec,vec++,state->sd_X,comm,bCompact);
+    }
+    if (bCGP)
+    {
+        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
+                                nvec,vec++,state->cg_p,comm,bCompact);
+    }
+    
+    if (bCompact)
+    {
+        compact_ind(dd->ncg_home,move,
+                    dd->index_gl,dd->cgindex,dd->gatindex,
+                    dd->ga2la,comm->bLocalCG,
+                    fr->cginfo);
+    }
+    else
+    {
+        clear_and_mark_ind(dd->ncg_home,move,
+                           dd->index_gl,dd->cgindex,dd->gatindex,
+                           dd->ga2la,comm->bLocalCG,
+                           fr->ns.grid->cell_index);
+    }
+    
+    cginfo_mb = fr->cginfo_mb;
+
+    ncg_stay_home = home_pos_cg;
+    for(d=0; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        ncg_recv = 0;
+        nat_recv = 0;
+        nvr      = 0;
+        for(dir=0; dir<(dd->nc[dim]==2 ? 1 : 2); dir++)
+        {
+            cdd = d*2 + dir;
+            /* Communicate the cg and atom counts */
+            sbuf[0] = ncg[cdd];
+            sbuf[1] = nat[cdd];
+            if (debug)
+            {
+                fprintf(debug,"Sending ddim %d dir %d: ncg %d nat %d\n",
+                        d,dir,sbuf[0],sbuf[1]);
+            }
+            dd_sendrecv_int(dd, d, dir, sbuf, 2, rbuf, 2);
+            
+            if ((ncg_recv+rbuf[0])*DD_CGIBS > comm->nalloc_int)
+            {
+                comm->nalloc_int = over_alloc_dd((ncg_recv+rbuf[0])*DD_CGIBS);
+                srenew(comm->buf_int,comm->nalloc_int);
+            }
+            
+            /* Communicate the charge group indices, sizes and flags */
+            dd_sendrecv_int(dd, d, dir,
+                            comm->cggl_flag[cdd], sbuf[0]*DD_CGIBS,
+                            comm->buf_int+ncg_recv*DD_CGIBS, rbuf[0]*DD_CGIBS);
+            
+            nvs = ncg[cdd] + nat[cdd]*nvec;
+            i   = rbuf[0]  + rbuf[1] *nvec;
+            vec_rvec_check_alloc(&comm->vbuf,nvr+i);
+            
+            /* Communicate cgcm and state */
+            dd_sendrecv_rvec(dd, d, dir,
+                             comm->cgcm_state[cdd], nvs,
+                             comm->vbuf.v+nvr, i);
+            ncg_recv += rbuf[0];
+            nat_recv += rbuf[1];
+            nvr      += i;
+        }
+        
+        /* Process the received charge groups */
+        buf_pos = 0;
+        for(cg=0; cg<ncg_recv; cg++)
+        {
+            flag = comm->buf_int[cg*DD_CGIBS+1];
+
+            if (dim >= npbcdim && dd->nc[dim] > 2)
+            {
+                /* No pbc in this dim and more than one domain boundary.
+                 * We to a separate check if a charge did not move too far.
+                 */
+                if (((flag & DD_FLAG_FW(d)) &&
+                     comm->vbuf.v[buf_pos][d] > cell_x1[dim]) ||
+                    ((flag & DD_FLAG_BW(d)) &&
+                     comm->vbuf.v[buf_pos][d] < cell_x0[dim]))
+                {
+                    cg_move_error(fplog,dd,step,cg,d,
+                                  (flag & DD_FLAG_FW(d)) ? 1 : 0,
+                                   FALSE,0,
+                                   comm->vbuf.v[buf_pos],
+                                   comm->vbuf.v[buf_pos],
+                                   comm->vbuf.v[buf_pos][d]);
+                }
+            }
+
+            mc = -1;
+            if (d < dd->ndim-1)
+            {
+                /* Check which direction this cg should go */
+                for(d2=d+1; (d2<dd->ndim && mc==-1); d2++)
+                {
+                    if (dd->bGridJump)
+                    {
+                        /* The cell boundaries for dimension d2 are not equal
+                         * for each cell row of the lower dimension(s),
+                         * therefore we might need to redetermine where
+                         * this cg should go.
+                         */
+                        dim2 = dd->dim[d2];
+                        /* If this cg crosses the box boundary in dimension d2
+                         * we can use the communicated flag, so we do not
+                         * have to worry about pbc.
+                         */
+                        if (!((dd->ci[dim2] == dd->nc[dim2]-1 &&
+                               (flag & DD_FLAG_FW(d2))) ||
+                              (dd->ci[dim2] == 0 &&
+                               (flag & DD_FLAG_BW(d2)))))
+                        {
+                            /* Clear the two flags for this dimension */
+                            flag &= ~(DD_FLAG_FW(d2) | DD_FLAG_BW(d2));
+                            /* Determine the location of this cg
+                             * in lattice coordinates
+                             */
+                            pos_d = comm->vbuf.v[buf_pos][dim2];
+                            if (tric_dir[dim2])
+                            {
+                                for(d3=dim2+1; d3<DIM; d3++)
+                                {
+                                    pos_d +=
+                                        comm->vbuf.v[buf_pos][d3]*tcm[d3][dim2];
+                                }
+                            }
+                            /* Check of we are not at the box edge.
+                             * pbc is only handled in the first step above,
+                             * but this check could move over pbc while
+                             * the first step did not due to different rounding.
+                             */
+                            if (pos_d >= cell_x1[dim2] &&
+                                dd->ci[dim2] != dd->nc[dim2]-1)
+                            {
+                                flag |= DD_FLAG_FW(d2);
+                            }
+                            else if (pos_d < cell_x0[dim2] &&
+                                     dd->ci[dim2] != 0)
+                            {
+                                flag |= DD_FLAG_BW(d2);
+                            }
+                            comm->buf_int[cg*DD_CGIBS+1] = flag;
+                        }
+                    }
+                    /* Set to which neighboring cell this cg should go */
+                    if (flag & DD_FLAG_FW(d2))
+                    {
+                        mc = d2*2;
+                    }
+                    else if (flag & DD_FLAG_BW(d2))
+                    {
+                        if (dd->nc[dd->dim[d2]] > 2)
+                        {
+                            mc = d2*2+1;
+                        }
+                        else
+                        {
+                            mc = d2*2;
+                        }
+                    }
+                }
+            }
+            
+            nrcg = flag & DD_FLAG_NRCG;
+            if (mc == -1)
+            {
+                if (home_pos_cg+1 > dd->cg_nalloc)
+                {
+                    dd->cg_nalloc = over_alloc_dd(home_pos_cg+1);
+                    srenew(dd->index_gl,dd->cg_nalloc);
+                    srenew(dd->cgindex,dd->cg_nalloc+1);
+                }
+                /* Set the global charge group index and size */
+                dd->index_gl[home_pos_cg] = comm->buf_int[cg*DD_CGIBS];
+                dd->cgindex[home_pos_cg+1] = dd->cgindex[home_pos_cg] + nrcg;
+                /* Copy the state from the buffer */
+                if (home_pos_cg >= fr->cg_nalloc)
+                {
+                    dd_realloc_fr_cg(fr,home_pos_cg+1);
+                    cg_cm = fr->cg_cm;
+                }
+                copy_rvec(comm->vbuf.v[buf_pos++],cg_cm[home_pos_cg]);
+                /* Set the cginfo */
+                fr->cginfo[home_pos_cg] = ddcginfo(cginfo_mb,
+                                                   dd->index_gl[home_pos_cg]);
+                if (comm->bLocalCG)
+                {
+                    comm->bLocalCG[dd->index_gl[home_pos_cg]] = TRUE;
+                }
+
+                if (home_pos_at+nrcg > state->nalloc)
+                {
+                    dd_realloc_state(state,f,home_pos_at+nrcg);
+                }
+                for(i=0; i<nrcg; i++)
+                {
+                    copy_rvec(comm->vbuf.v[buf_pos++],
+                              state->x[home_pos_at+i]);
+                }
+                if (bV)
+                {
+                    for(i=0; i<nrcg; i++)
+                    {
+                        copy_rvec(comm->vbuf.v[buf_pos++],
+                                  state->v[home_pos_at+i]);
+                    }
+                }
+                if (bSDX)
+                {
+                    for(i=0; i<nrcg; i++)
+                    {
+                        copy_rvec(comm->vbuf.v[buf_pos++],
+                                  state->sd_X[home_pos_at+i]);
+                    }
+                }
+                if (bCGP)
+                {
+                    for(i=0; i<nrcg; i++)
+                    {
+                        copy_rvec(comm->vbuf.v[buf_pos++],
+                                  state->cg_p[home_pos_at+i]);
+                    }
+                }
+                home_pos_cg += 1;
+                home_pos_at += nrcg;
+            }
+            else
+            {
+                /* Reallocate the buffers if necessary  */
+                if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
+                {
+                    comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
+                    srenew(comm->cggl_flag[mc],comm->cggl_flag_nalloc[mc]*DD_CGIBS);
+                }
+                nvr = ncg[mc] + nat[mc]*nvec;
+                if (nvr + 1 + nrcg*nvec > comm->cgcm_state_nalloc[mc])
+                {
+                    comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr + 1 + nrcg*nvec);
+                    srenew(comm->cgcm_state[mc],comm->cgcm_state_nalloc[mc]);
+                }
+                /* Copy from the receive to the send buffers */
+                memcpy(comm->cggl_flag[mc] + ncg[mc]*DD_CGIBS,
+                       comm->buf_int + cg*DD_CGIBS,
+                       DD_CGIBS*sizeof(int));
+                memcpy(comm->cgcm_state[mc][nvr],
+                       comm->vbuf.v[buf_pos],
+                       (1+nrcg*nvec)*sizeof(rvec));
+                buf_pos += 1 + nrcg*nvec;
+                ncg[mc] += 1;
+                nat[mc] += nrcg;
+            }
+        }
+    }
+    
+    /* With sorting (!bCompact) the indices are now only partially up to date
+     * and ncg_home and nat_home are not the real count, since there are
+     * "holes" in the arrays for the charge groups that moved to neighbors.
+     */
+    dd->ncg_home = home_pos_cg;
+    dd->nat_home = home_pos_at;
+
+    if (debug)
+    {
+        fprintf(debug,"Finished repartitioning\n");
+    }
+
+    return ncg_stay_home;
+}
+
+void dd_cycles_add(gmx_domdec_t *dd,float cycles,int ddCycl)
+{
+    dd->comm->cycl[ddCycl] += cycles;
+    dd->comm->cycl_n[ddCycl]++;
+    if (cycles > dd->comm->cycl_max[ddCycl])
+    {
+        dd->comm->cycl_max[ddCycl] = cycles;
+    }
+}
+
+static double force_flop_count(t_nrnb *nrnb)
+{
+    int i;
+    double sum;
+    const char *name;
+
+    sum = 0;
+    for(i=eNR_NBKERNEL010; i<eNR_NBKERNEL_FREE_ENERGY; i++)
+    {
+        /* To get closer to the real timings, we half the count
+         * for the normal loops and again half it for water loops.
+         */
+        name = nrnb_str(i);
+        if (strstr(name,"W3") != NULL || strstr(name,"W4") != NULL)
+        {
+            sum += nrnb->n[i]*0.25*cost_nrnb(i);
+        }
+        else
+        {
+            sum += nrnb->n[i]*0.50*cost_nrnb(i);
+        }
+    }
+    for(i=eNR_NBKERNEL_FREE_ENERGY; i<=eNR_NB14; i++)
+    {
+        name = nrnb_str(i);
+        if (strstr(name,"W3") != NULL || strstr(name,"W4") != NULL)
+        sum += nrnb->n[i]*cost_nrnb(i);
+    }
+    for(i=eNR_BONDS; i<=eNR_WALLS; i++)
+    {
+        sum += nrnb->n[i]*cost_nrnb(i);
+    }
+
+    return sum;
+}
+
+void dd_force_flop_start(gmx_domdec_t *dd,t_nrnb *nrnb)
+{
+    if (dd->comm->eFlop)
+    {
+        dd->comm->flop -= force_flop_count(nrnb);
+    }
+}
+void dd_force_flop_stop(gmx_domdec_t *dd,t_nrnb *nrnb)
+{
+    if (dd->comm->eFlop)
+    {
+        dd->comm->flop += force_flop_count(nrnb);
+        dd->comm->flop_n++;
+    }
+}  
+
+static void clear_dd_cycle_counts(gmx_domdec_t *dd)
+{
+    int i;
+    
+    for(i=0; i<ddCyclNr; i++)
+    {
+        dd->comm->cycl[i] = 0;
+        dd->comm->cycl_n[i] = 0;
+        dd->comm->cycl_max[i] = 0;
+    }
+    dd->comm->flop = 0;
+    dd->comm->flop_n = 0;
+}
+
+static void get_load_distribution(gmx_domdec_t *dd,gmx_wallcycle_t wcycle)
+{
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_load_t *load;
+    gmx_domdec_root_t *root=NULL;
+    int  d,dim,cid,i,pos;
+    float cell_frac=0,sbuf[DD_NLOAD_MAX];
+    gmx_bool bSepPME;
+    
+    if (debug)
+    {
+        fprintf(debug,"get_load_distribution start\n");
+    }
+
+    wallcycle_start(wcycle,ewcDDCOMMLOAD);
+    
+    comm = dd->comm;
+    
+    bSepPME = (dd->pme_nodeid >= 0);
+    
+    for(d=dd->ndim-1; d>=0; d--)
+    {
+        dim = dd->dim[d];
+        /* Check if we participate in the communication in this dimension */
+        if (d == dd->ndim-1 || 
+            (dd->ci[dd->dim[d+1]]==0 && dd->ci[dd->dim[dd->ndim-1]]==0))
+        {
+            load = &comm->load[d];
+            if (dd->bGridJump)
+            {
+                cell_frac = comm->cell_f1[d] - comm->cell_f0[d];
+            }
+            pos = 0;
+            if (d == dd->ndim-1)
+            {
+                sbuf[pos++] = dd_force_load(comm);
+                sbuf[pos++] = sbuf[0];
+                if (dd->bGridJump)
+                {
+                    sbuf[pos++] = sbuf[0];
+                    sbuf[pos++] = cell_frac;
+                    if (d > 0)
+                    {
+                        sbuf[pos++] = comm->cell_f_max0[d];
+                        sbuf[pos++] = comm->cell_f_min1[d];
+                    }
+                }
+                if (bSepPME)
+                {
+                    sbuf[pos++] = comm->cycl[ddCyclPPduringPME];
+                    sbuf[pos++] = comm->cycl[ddCyclPME];
+                }
+            }
+            else
+            {
+                sbuf[pos++] = comm->load[d+1].sum;
+                sbuf[pos++] = comm->load[d+1].max;
+                if (dd->bGridJump)
+                {
+                    sbuf[pos++] = comm->load[d+1].sum_m;
+                    sbuf[pos++] = comm->load[d+1].cvol_min*cell_frac;
+                    sbuf[pos++] = comm->load[d+1].flags;
+                    if (d > 0)
+                    {
+                        sbuf[pos++] = comm->cell_f_max0[d];
+                        sbuf[pos++] = comm->cell_f_min1[d];
+                    }
+                }
+                if (bSepPME)
+                {
+                    sbuf[pos++] = comm->load[d+1].mdf;
+                    sbuf[pos++] = comm->load[d+1].pme;
+                }
+            }
+            load->nload = pos;
+            /* Communicate a row in DD direction d.
+             * The communicators are setup such that the root always has rank 0.
+             */
+#ifdef GMX_MPI
+            MPI_Gather(sbuf      ,load->nload*sizeof(float),MPI_BYTE,
+                       load->load,load->nload*sizeof(float),MPI_BYTE,
+                       0,comm->mpi_comm_load[d]);
+#endif
+            if (dd->ci[dim] == dd->master_ci[dim])
+            {
+                /* We are the root, process this row */
+                if (comm->bDynLoadBal)
+                {
+                    root = comm->root[d];
+                }
+                load->sum = 0;
+                load->max = 0;
+                load->sum_m = 0;
+                load->cvol_min = 1;
+                load->flags = 0;
+                load->mdf = 0;
+                load->pme = 0;
+                pos = 0;
+                for(i=0; i<dd->nc[dim]; i++)
+                {
+                    load->sum += load->load[pos++];
+                    load->max = max(load->max,load->load[pos]);
+                    pos++;
+                    if (dd->bGridJump)
+                    {
+                        if (root->bLimited)
+                        {
+                            /* This direction could not be load balanced properly,
+                             * therefore we need to use the maximum iso the average load.
+                             */
+                            load->sum_m = max(load->sum_m,load->load[pos]);
+                        }
+                        else
+                        {
+                            load->sum_m += load->load[pos];
+                        }
+                        pos++;
+                        load->cvol_min = min(load->cvol_min,load->load[pos]);
+                        pos++;
+                        if (d < dd->ndim-1)
+                        {
+                            load->flags = (int)(load->load[pos++] + 0.5);
+                        }
+                        if (d > 0)
+                        {
+                            root->cell_f_max0[i] = load->load[pos++];
+                            root->cell_f_min1[i] = load->load[pos++];
+                        }
+                    }
+                    if (bSepPME)
+                    {
+                        load->mdf = max(load->mdf,load->load[pos]);
+                        pos++;
+                        load->pme = max(load->pme,load->load[pos]);
+                        pos++;
+                    }
+                }
+                if (comm->bDynLoadBal && root->bLimited)
+                {
+                    load->sum_m *= dd->nc[dim];
+                    load->flags |= (1<<d);
+                }
+            }
+        }
+    }
+
+    if (DDMASTER(dd))
+    {
+        comm->nload      += dd_load_count(comm);
+        comm->load_step  += comm->cycl[ddCyclStep];
+        comm->load_sum   += comm->load[0].sum;
+        comm->load_max   += comm->load[0].max;
+        if (comm->bDynLoadBal)
+        {
+            for(d=0; d<dd->ndim; d++)
+            {
+                if (comm->load[0].flags & (1<<d))
+                {
+                    comm->load_lim[d]++;
+                }
+            }
+        }
+        if (bSepPME)
+        {
+            comm->load_mdf += comm->load[0].mdf;
+            comm->load_pme += comm->load[0].pme;
+        }
+    }
+
+    wallcycle_stop(wcycle,ewcDDCOMMLOAD);
+    
+    if (debug)
+    {
+        fprintf(debug,"get_load_distribution finished\n");
+    }
+}
+
+static float dd_force_imb_perf_loss(gmx_domdec_t *dd)
+{
+    /* Return the relative performance loss on the total run time
+     * due to the force calculation load imbalance.
+     */
+    if (dd->comm->nload > 0)
+    {
+        return
+            (dd->comm->load_max*dd->nnodes - dd->comm->load_sum)/
+            (dd->comm->load_step*dd->nnodes);
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static void print_dd_load_av(FILE *fplog,gmx_domdec_t *dd)
+{
+    char  buf[STRLEN];
+    int   npp,npme,nnodes,d,limp;
+    float imbal,pme_f_ratio,lossf,lossp=0;
+    gmx_bool  bLim;
+    gmx_domdec_comm_t *comm;
+
+    comm = dd->comm;
+    if (DDMASTER(dd) && comm->nload > 0)
+    {
+        npp    = dd->nnodes;
+        npme   = (dd->pme_nodeid >= 0) ? comm->npmenodes : 0;
+        nnodes = npp + npme;
+        imbal = comm->load_max*npp/comm->load_sum - 1;
+        lossf = dd_force_imb_perf_loss(dd);
+        sprintf(buf," Average load imbalance: %.1f %%\n",imbal*100);
+        fprintf(fplog,"%s",buf);
+        fprintf(stderr,"\n");
+        fprintf(stderr,"%s",buf);
+        sprintf(buf," Part of the total run time spent waiting due to load imbalance: %.1f %%\n",lossf*100);
+        fprintf(fplog,"%s",buf);
+        fprintf(stderr,"%s",buf);
+        bLim = FALSE;
+        if (comm->bDynLoadBal)
+        {
+            sprintf(buf," Steps where the load balancing was limited by -rdd, -rcon and/or -dds:");
+            for(d=0; d<dd->ndim; d++)
+            {
+                limp = (200*comm->load_lim[d]+1)/(2*comm->nload);
+                sprintf(buf+strlen(buf)," %c %d %%",dim2char(dd->dim[d]),limp);
+                if (limp >= 50)
+                {
+                    bLim = TRUE;
+                }
+            }
+            sprintf(buf+strlen(buf),"\n");
+            fprintf(fplog,"%s",buf);
+            fprintf(stderr,"%s",buf);
+        }
+        if (npme > 0)
+        {
+            pme_f_ratio = comm->load_pme/comm->load_mdf;
+            lossp = (comm->load_pme -comm->load_mdf)/comm->load_step;
+            if (lossp <= 0)
+            {
+                lossp *= (float)npme/(float)nnodes;
+            }
+            else
+            {
+                lossp *= (float)npp/(float)nnodes;
+            }
+            sprintf(buf," Average PME mesh/force load: %5.3f\n",pme_f_ratio);
+            fprintf(fplog,"%s",buf);
+            fprintf(stderr,"%s",buf);
+            sprintf(buf," Part of the total run time spent waiting due to PP/PME imbalance: %.1f %%\n",fabs(lossp)*100);
+            fprintf(fplog,"%s",buf);
+            fprintf(stderr,"%s",buf);
+        }
+        fprintf(fplog,"\n");
+        fprintf(stderr,"\n");
+        
+        if (lossf >= DD_PERF_LOSS)
+        {
+            sprintf(buf,
+                    "NOTE: %.1f %% performance was lost due to load imbalance\n"
+                    "      in the domain decomposition.\n",lossf*100);
+            if (!comm->bDynLoadBal)
+            {
+                sprintf(buf+strlen(buf),"      You might want to use dynamic load balancing (option -dlb.)\n");
+            }
+            else if (bLim)
+            {
+                sprintf(buf+strlen(buf),"      You might want to decrease the cell size limit (options -rdd, -rcon and/or -dds).\n");
+            }
+            fprintf(fplog,"%s\n",buf);
+            fprintf(stderr,"%s\n",buf);
+        }
+        if (npme > 0 && fabs(lossp) >= DD_PERF_LOSS)
+        {
+            sprintf(buf,
+                    "NOTE: %.1f %% performance was lost because the PME nodes\n"
+                    "      had %s work to do than the PP nodes.\n"
+                    "      You might want to %s the number of PME nodes\n"
+                    "      or %s the cut-off and the grid spacing.\n",
+                    fabs(lossp*100),
+                    (lossp < 0) ? "less"     : "more",
+                    (lossp < 0) ? "decrease" : "increase",
+                    (lossp < 0) ? "decrease" : "increase");
+            fprintf(fplog,"%s\n",buf);
+            fprintf(stderr,"%s\n",buf);
+        }
+    }
+}
+
+static float dd_vol_min(gmx_domdec_t *dd)
+{
+    return dd->comm->load[0].cvol_min*dd->nnodes;
+}
+
+static gmx_bool dd_load_flags(gmx_domdec_t *dd)
+{
+    return dd->comm->load[0].flags;
+}
+
+static float dd_f_imbal(gmx_domdec_t *dd)
+{
+    return dd->comm->load[0].max*dd->nnodes/dd->comm->load[0].sum - 1;
+}
+
+static float dd_pme_f_ratio(gmx_domdec_t *dd)
+{
+    return dd->comm->load[0].pme/dd->comm->load[0].mdf;
+}
+
+static void dd_print_load(FILE *fplog,gmx_domdec_t *dd,gmx_large_int_t step)
+{
+    int flags,d;
+    char buf[22];
+    
+    flags = dd_load_flags(dd);
+    if (flags)
+    {
+        fprintf(fplog,
+                "DD  load balancing is limited by minimum cell size in dimension");
+        for(d=0; d<dd->ndim; d++)
+        {
+            if (flags & (1<<d))
+            {
+                fprintf(fplog," %c",dim2char(dd->dim[d]));
+            }
+        }
+        fprintf(fplog,"\n");
+    }
+    fprintf(fplog,"DD  step %s",gmx_step_str(step,buf));
+    if (dd->comm->bDynLoadBal)
+    {
+        fprintf(fplog,"  vol min/aver %5.3f%c",
+                dd_vol_min(dd),flags ? '!' : ' ');
+    }
+    fprintf(fplog," load imb.: force %4.1f%%",dd_f_imbal(dd)*100);
+    if (dd->comm->cycl_n[ddCyclPME])
+    {
+        fprintf(fplog,"  pme mesh/force %5.3f",dd_pme_f_ratio(dd));
+    }
+    fprintf(fplog,"\n\n");
+}
+
+static void dd_print_load_verbose(gmx_domdec_t *dd)
+{
+    if (dd->comm->bDynLoadBal)
+    {
+        fprintf(stderr,"vol %4.2f%c ",
+                dd_vol_min(dd),dd_load_flags(dd) ? '!' : ' ');
+    }
+    fprintf(stderr,"imb F %2d%% ",(int)(dd_f_imbal(dd)*100+0.5));
+    if (dd->comm->cycl_n[ddCyclPME])
+    {
+        fprintf(stderr,"pme/F %4.2f ",dd_pme_f_ratio(dd));
+    }
+}
+
+#ifdef GMX_MPI
+static void make_load_communicator(gmx_domdec_t *dd,MPI_Group g_all,
+                                   int dim_ind,ivec loc)
+{
+    MPI_Group g_row = MPI_GROUP_EMPTY;
+    MPI_Comm  c_row;
+    int  dim,i,*rank;
+    ivec loc_c;
+    gmx_domdec_root_t *root;
+    gmx_bool bPartOfGroup = FALSE;
+    
+    dim = dd->dim[dim_ind];
+    copy_ivec(loc,loc_c);
+    snew(rank,dd->nc[dim]);
+    for(i=0; i<dd->nc[dim]; i++)
+    {
+        loc_c[dim] = i;
+        rank[i] = dd_index(dd->nc,loc_c);
+        if (rank[i] == dd->rank)
+        {
+            /* This process is part of the group */
+            bPartOfGroup = TRUE;
+        }
+    }
+    if (bPartOfGroup)
+    {
+        MPI_Group_incl(g_all,dd->nc[dim],rank,&g_row);
+    }
+    MPI_Comm_create(dd->mpi_comm_all,g_row,&c_row);
+    if (bPartOfGroup)
+    {
+        dd->comm->mpi_comm_load[dim_ind] = c_row;
+        if (dd->comm->eDLB != edlbNO)
+        {
+            if (dd->ci[dim] == dd->master_ci[dim])
+            {
+                /* This is the root process of this row */
+                snew(dd->comm->root[dim_ind],1);
+                root = dd->comm->root[dim_ind];
+                snew(root->cell_f,DD_CELL_F_SIZE(dd,dim_ind));
+                snew(root->old_cell_f,dd->nc[dim]+1);
+                snew(root->bCellMin,dd->nc[dim]);
+                if (dim_ind > 0)
+                {
+                    snew(root->cell_f_max0,dd->nc[dim]);
+                    snew(root->cell_f_min1,dd->nc[dim]);
+                    snew(root->bound_min,dd->nc[dim]);
+                    snew(root->bound_max,dd->nc[dim]);
+                }
+                snew(root->buf_ncd,dd->nc[dim]);
+            }
+            else
+            {
+                /* This is not a root process, we only need to receive cell_f */
+                snew(dd->comm->cell_f_row,DD_CELL_F_SIZE(dd,dim_ind));
+            }
+        }
+        if (dd->ci[dim] == dd->master_ci[dim])
+        {
+            snew(dd->comm->load[dim_ind].load,dd->nc[dim]*DD_NLOAD_MAX);
+        }
+    }
+    sfree(rank);
+}
+#endif
+
+static void make_load_communicators(gmx_domdec_t *dd)
+{
+#ifdef GMX_MPI
+  MPI_Group g_all;
+  int  dim0,dim1,i,j;
+  ivec loc;
+
+  if (debug)
+    fprintf(debug,"Making load communicators\n");
+
+  MPI_Comm_group(dd->mpi_comm_all,&g_all);
+  
+  snew(dd->comm->load,dd->ndim);
+  snew(dd->comm->mpi_comm_load,dd->ndim);
+  
+  clear_ivec(loc);
+  make_load_communicator(dd,g_all,0,loc);
+  if (dd->ndim > 1) {
+    dim0 = dd->dim[0];
+    for(i=0; i<dd->nc[dim0]; i++) {
+      loc[dim0] = i;
+      make_load_communicator(dd,g_all,1,loc);
+    }
+  }
+  if (dd->ndim > 2) {
+    dim0 = dd->dim[0];
+    for(i=0; i<dd->nc[dim0]; i++) {
+      loc[dim0] = i;
+      dim1 = dd->dim[1];
+      for(j=0; j<dd->nc[dim1]; j++) {
+         loc[dim1] = j;
+         make_load_communicator(dd,g_all,2,loc);
+      }
+    }
+  }
+
+  MPI_Group_free(&g_all);
+
+  if (debug)
+    fprintf(debug,"Finished making load communicators\n");
+#endif
+}
+
+void setup_dd_grid(FILE *fplog,gmx_domdec_t *dd)
+{
+    gmx_bool bZYX;
+    int  d,dim,i,j,m;
+    ivec tmp,s;
+    int  nzone,nzonep;
+    ivec dd_zp[DD_MAXIZONE];
+    gmx_domdec_zones_t *zones;
+    gmx_domdec_ns_ranges_t *izone;
+    
+    for(d=0; d<dd->ndim; d++)
+    {
+        dim = dd->dim[d];
+        copy_ivec(dd->ci,tmp);
+        tmp[dim] = (tmp[dim] + 1) % dd->nc[dim];
+        dd->neighbor[d][0] = ddcoord2ddnodeid(dd,tmp);
+        copy_ivec(dd->ci,tmp);
+        tmp[dim] = (tmp[dim] - 1 + dd->nc[dim]) % dd->nc[dim];
+        dd->neighbor[d][1] = ddcoord2ddnodeid(dd,tmp);
+        if (debug)
+        {
+            fprintf(debug,"DD rank %d neighbor ranks in dir %d are + %d - %d\n",
+                    dd->rank,dim,
+                    dd->neighbor[d][0],
+                    dd->neighbor[d][1]);
+        }
+    }
+    
+    if (DDMASTER(dd))
+    {
+        fprintf(stderr,"Making %dD domain decomposition %d x %d x %d\n",
+           dd->ndim,dd->nc[XX],dd->nc[YY],dd->nc[ZZ]);
+    }
+    if (fplog)
+    {
+        fprintf(fplog,"\nMaking %dD domain decomposition grid %d x %d x %d, home cell index %d %d %d\n\n",
+                dd->ndim,
+                dd->nc[XX],dd->nc[YY],dd->nc[ZZ],
+                dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+    }
+    switch (dd->ndim)
+    {
+    case 3:
+        nzone  = dd_z3n;
+        nzonep = dd_zp3n;
+        for(i=0; i<nzonep; i++)
+        {
+            copy_ivec(dd_zp3[i],dd_zp[i]);
+        }
+        break;
+    case 2:
+        nzone  = dd_z2n;
+        nzonep = dd_zp2n;
+        for(i=0; i<nzonep; i++)
+        {
+            copy_ivec(dd_zp2[i],dd_zp[i]);
+        }
+        break;
+    case 1:
+        nzone  = dd_z1n;
+        nzonep = dd_zp1n;
+        for(i=0; i<nzonep; i++)
+        {
+            copy_ivec(dd_zp1[i],dd_zp[i]);
+        }
+        break;
+    default:
+        gmx_fatal(FARGS,"Can only do 1, 2 or 3D domain decomposition");
+        nzone = 0;
+        nzonep = 0;
+    }
+
+    zones = &dd->comm->zones;
+
+    for(i=0; i<nzone; i++)
+    {
+        m = 0;
+        clear_ivec(zones->shift[i]);
+        for(d=0; d<dd->ndim; d++)
+        {
+            zones->shift[i][dd->dim[d]] = dd_zo[i][m++];
+        }
+    }
+    
+    zones->n = nzone;
+    for(i=0; i<nzone; i++)
+    {
+        for(d=0; d<DIM; d++)
+        {
+            s[d] = dd->ci[d] - zones->shift[i][d];
+            if (s[d] < 0)
+            {
+                s[d] += dd->nc[d];
+            }
+            else if (s[d] >= dd->nc[d])
+            {
+                s[d] -= dd->nc[d];
+            }
+        }
+    }
+    zones->nizone = nzonep;
+    for(i=0; i<zones->nizone; i++)
+    {
+        if (dd_zp[i][0] != i)
+        {
+            gmx_fatal(FARGS,"Internal inconsistency in the dd grid setup");
+        }
+        izone = &zones->izone[i];
+        izone->j0 = dd_zp[i][1];
+        izone->j1 = dd_zp[i][2];
+        for(dim=0; dim<DIM; dim++)
+        {
+            if (dd->nc[dim] == 1)
+            {
+                /* All shifts should be allowed */
+                izone->shift0[dim] = -1;
+                izone->shift1[dim] = 1;
+            }
+            else
+            {
+                /*
+                  izone->shift0[d] = 0;
+                  izone->shift1[d] = 0;
+                  for(j=izone->j0; j<izone->j1; j++) {
+                  if (dd->shift[j][d] > dd->shift[i][d])
+                  izone->shift0[d] = -1;
+                  if (dd->shift[j][d] < dd->shift[i][d])
+                  izone->shift1[d] = 1;
+                  }
+                */
+                
+                int shift_diff;
+                
+                /* Assume the shift are not more than 1 cell */
+                izone->shift0[dim] = 1;
+                izone->shift1[dim] = -1;
+                for(j=izone->j0; j<izone->j1; j++)
+                {
+                    shift_diff = zones->shift[j][dim] - zones->shift[i][dim];
+                    if (shift_diff < izone->shift0[dim])
+                    {
+                        izone->shift0[dim] = shift_diff;
+                    }
+                    if (shift_diff > izone->shift1[dim])
+                    {
+                        izone->shift1[dim] = shift_diff;
+                    }
+                }
+            }
+        }
+    }
+    
+    if (dd->comm->eDLB != edlbNO)
+    {
+        snew(dd->comm->root,dd->ndim);
+    }
+    
+    if (dd->comm->bRecordLoad)
+    {
+        make_load_communicators(dd);
+    }
+}
+
+static void make_pp_communicator(FILE *fplog,t_commrec *cr,int reorder)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    int  i,rank,*buf;
+    ivec periods;
+#ifdef GMX_MPI
+    MPI_Comm comm_cart;
+#endif
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+#ifdef GMX_MPI
+    if (comm->bCartesianPP)
+    {
+        /* Set up cartesian communication for the particle-particle part */
+        if (fplog)
+        {
+            fprintf(fplog,"Will use a Cartesian communicator: %d x %d x %d\n",
+                    dd->nc[XX],dd->nc[YY],dd->nc[ZZ]);
+        }
+        
+        for(i=0; i<DIM; i++)
+        {
+            periods[i] = TRUE;
+        }
+        MPI_Cart_create(cr->mpi_comm_mygroup,DIM,dd->nc,periods,reorder,
+                        &comm_cart);
+        /* We overwrite the old communicator with the new cartesian one */
+        cr->mpi_comm_mygroup = comm_cart;
+    }
+    
+    dd->mpi_comm_all = cr->mpi_comm_mygroup;
+    MPI_Comm_rank(dd->mpi_comm_all,&dd->rank);
+    
+    if (comm->bCartesianPP_PME)
+    {
+        /* Since we want to use the original cartesian setup for sim,
+         * and not the one after split, we need to make an index.
+         */
+        snew(comm->ddindex2ddnodeid,dd->nnodes);
+        comm->ddindex2ddnodeid[dd_index(dd->nc,dd->ci)] = dd->rank;
+        gmx_sumi(dd->nnodes,comm->ddindex2ddnodeid,cr);
+        /* Get the rank of the DD master,
+         * above we made sure that the master node is a PP node.
+         */
+        if (MASTER(cr))
+        {
+            rank = dd->rank;
+        }
+        else
+        {
+            rank = 0;
+        }
+        MPI_Allreduce(&rank,&dd->masterrank,1,MPI_INT,MPI_SUM,dd->mpi_comm_all);
+    }
+    else if (comm->bCartesianPP)
+    {
+        if (cr->npmenodes == 0)
+        {
+            /* The PP communicator is also
+             * the communicator for this simulation
+             */
+            cr->mpi_comm_mysim = cr->mpi_comm_mygroup;
+        }
+        cr->nodeid = dd->rank;
+        
+        MPI_Cart_coords(dd->mpi_comm_all,dd->rank,DIM,dd->ci);
+        
+        /* We need to make an index to go from the coordinates
+         * to the nodeid of this simulation.
+         */
+        snew(comm->ddindex2simnodeid,dd->nnodes);
+        snew(buf,dd->nnodes);
+        if (cr->duty & DUTY_PP)
+        {
+            buf[dd_index(dd->nc,dd->ci)] = cr->sim_nodeid;
+        }
+        /* Communicate the ddindex to simulation nodeid index */
+        MPI_Allreduce(buf,comm->ddindex2simnodeid,dd->nnodes,MPI_INT,MPI_SUM,
+                      cr->mpi_comm_mysim);
+        sfree(buf);
+        
+        /* Determine the master coordinates and rank.
+         * The DD master should be the same node as the master of this sim.
+         */
+        for(i=0; i<dd->nnodes; i++)
+        {
+            if (comm->ddindex2simnodeid[i] == 0)
+            {
+                ddindex2xyz(dd->nc,i,dd->master_ci);
+                MPI_Cart_rank(dd->mpi_comm_all,dd->master_ci,&dd->masterrank);
+            }
+        }
+        if (debug)
+        {
+            fprintf(debug,"The master rank is %d\n",dd->masterrank);
+        }
+    }
+    else
+    {
+        /* No Cartesian communicators */
+        /* We use the rank in dd->comm->all as DD index */
+        ddindex2xyz(dd->nc,dd->rank,dd->ci);
+        /* The simulation master nodeid is 0, so the DD master rank is also 0 */
+        dd->masterrank = 0;
+        clear_ivec(dd->master_ci);
+    }
+#endif
+  
+    if (fplog)
+    {
+        fprintf(fplog,
+                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
+                dd->rank,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+    }
+    if (debug)
+    {
+        fprintf(debug,
+                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
+                dd->rank,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+    }
+}
+
+static void receive_ddindex2simnodeid(t_commrec *cr)
+{
+    gmx_domdec_t *dd;
+    
+    gmx_domdec_comm_t *comm;
+    int  *buf;
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+#ifdef GMX_MPI
+    if (!comm->bCartesianPP_PME && comm->bCartesianPP)
+    {
+        snew(comm->ddindex2simnodeid,dd->nnodes);
+        snew(buf,dd->nnodes);
+        if (cr->duty & DUTY_PP)
+        {
+            buf[dd_index(dd->nc,dd->ci)] = cr->sim_nodeid;
+        }
+#ifdef GMX_MPI
+        /* Communicate the ddindex to simulation nodeid index */
+        MPI_Allreduce(buf,comm->ddindex2simnodeid,dd->nnodes,MPI_INT,MPI_SUM,
+                      cr->mpi_comm_mysim);
+#endif
+        sfree(buf);
+    }
+#endif
+}
+
+static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
+                                                     int ncg,int natoms)
+{
+    gmx_domdec_master_t *ma;
+    int i;
+
+    snew(ma,1);
+    
+    snew(ma->ncg,dd->nnodes);
+    snew(ma->index,dd->nnodes+1);
+    snew(ma->cg,ncg);
+    snew(ma->nat,dd->nnodes);
+    snew(ma->ibuf,dd->nnodes*2);
+    snew(ma->cell_x,DIM);
+    for(i=0; i<DIM; i++)
+    {
+        snew(ma->cell_x[i],dd->nc[i]+1);
+    }
+
+    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
+    {
+        ma->vbuf = NULL;
+    }
+    else
+    {
+        snew(ma->vbuf,natoms);
+    }
+
+    return ma;
+}
+
+static void split_communicator(FILE *fplog,t_commrec *cr,int dd_node_order,
+                               int reorder)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    int  i,rank;
+    gmx_bool bDiv[DIM];
+    ivec periods;
+#ifdef GMX_MPI
+    MPI_Comm comm_cart;
+#endif
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+    if (comm->bCartesianPP)
+    {
+        for(i=1; i<DIM; i++)
+        {
+            bDiv[i] = ((cr->npmenodes*dd->nc[i]) % (dd->nnodes) == 0);
+        }
+        if (bDiv[YY] || bDiv[ZZ])
+        {
+            comm->bCartesianPP_PME = TRUE;
+            /* If we have 2D PME decomposition, which is always in x+y,
+             * we stack the PME only nodes in z.
+             * Otherwise we choose the direction that provides the thinnest slab
+             * of PME only nodes as this will have the least effect
+             * on the PP communication.
+             * But for the PME communication the opposite might be better.
+             */
+            if (bDiv[ZZ] && (comm->npmenodes_y > 1 ||
+                             !bDiv[YY] ||
+                             dd->nc[YY] > dd->nc[ZZ]))
+            {
+                comm->cartpmedim = ZZ;
+            }
+            else
+            {
+                comm->cartpmedim = YY;
+            }
+            comm->ntot[comm->cartpmedim]
+                += (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
+        }
+        else if (fplog)
+        {
+            fprintf(fplog,"#pmenodes (%d) is not a multiple of nx*ny (%d*%d) or nx*nz (%d*%d)\n",cr->npmenodes,dd->nc[XX],dd->nc[YY],dd->nc[XX],dd->nc[ZZ]);
+            fprintf(fplog,
+                    "Will not use a Cartesian communicator for PP <-> PME\n\n");
+        }
+    }
+    
+#ifdef GMX_MPI
+    if (comm->bCartesianPP_PME)
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"Will use a Cartesian communicator for PP <-> PME: %d x %d x %d\n",comm->ntot[XX],comm->ntot[YY],comm->ntot[ZZ]);
+        }
+        
+        for(i=0; i<DIM; i++)
+        {
+            periods[i] = TRUE;
+        }
+        MPI_Cart_create(cr->mpi_comm_mysim,DIM,comm->ntot,periods,reorder,
+                        &comm_cart);
+        
+        MPI_Comm_rank(comm_cart,&rank);
+        if (MASTERNODE(cr) && rank != 0)
+        {
+            gmx_fatal(FARGS,"MPI rank 0 was renumbered by MPI_Cart_create, we do not allow this");
+        }
+        
+        /* With this assigment we loose the link to the original communicator
+         * which will usually be MPI_COMM_WORLD, unless have multisim.
+         */
+        cr->mpi_comm_mysim = comm_cart;
+        cr->sim_nodeid = rank;
+        
+        MPI_Cart_coords(cr->mpi_comm_mysim,cr->sim_nodeid,DIM,dd->ci);
+        
+        if (fplog)
+        {
+            fprintf(fplog,"Cartesian nodeid %d, coordinates %d %d %d\n\n",
+                    cr->sim_nodeid,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
+        }
+        
+        if (dd->ci[comm->cartpmedim] < dd->nc[comm->cartpmedim])
+        {
+            cr->duty = DUTY_PP;
+        }
+        if (cr->npmenodes == 0 ||
+            dd->ci[comm->cartpmedim] >= dd->nc[comm->cartpmedim])
+        {
+            cr->duty = DUTY_PME;
+        }
+        
+        /* Split the sim communicator into PP and PME only nodes */
+        MPI_Comm_split(cr->mpi_comm_mysim,
+                       cr->duty,
+                       dd_index(comm->ntot,dd->ci),
+                       &cr->mpi_comm_mygroup);
+    }
+    else
+    {
+        switch (dd_node_order)
+        {
+        case ddnoPP_PME:
+            if (fplog)
+            {
+                fprintf(fplog,"Order of the nodes: PP first, PME last\n");
+            }
+            break;
+        case ddnoINTERLEAVE:
+            /* Interleave the PP-only and PME-only nodes,
+             * as on clusters with dual-core machines this will double
+             * the communication bandwidth of the PME processes
+             * and thus speed up the PP <-> PME and inter PME communication.
+             */
+            if (fplog)
+            {
+                fprintf(fplog,"Interleaving PP and PME nodes\n");
+            }
+            comm->pmenodes = dd_pmenodes(cr);
+            break;
+        case ddnoCARTESIAN:
+            break;
+        default:
+            gmx_fatal(FARGS,"Unknown dd_node_order=%d",dd_node_order);
+        }
+    
+        if (dd_simnode2pmenode(cr,cr->sim_nodeid) == -1)
+        {
+            cr->duty = DUTY_PME;
+        }
+        else
+        {
+            cr->duty = DUTY_PP;
+        }
+        
+        /* Split the sim communicator into PP and PME only nodes */
+        MPI_Comm_split(cr->mpi_comm_mysim,
+                       cr->duty,
+                       cr->nodeid,
+                       &cr->mpi_comm_mygroup);
+        MPI_Comm_rank(cr->mpi_comm_mygroup,&cr->nodeid);
+    }
+#endif
+
+    if (fplog)
+    {
+        fprintf(fplog,"This is a %s only node\n\n",
+                (cr->duty & DUTY_PP) ? "particle-particle" : "PME-mesh");
+    }
+}
+
+void make_dd_communicators(FILE *fplog,t_commrec *cr,int dd_node_order)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    int CartReorder;
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+    copy_ivec(dd->nc,comm->ntot);
+    
+    comm->bCartesianPP = (dd_node_order == ddnoCARTESIAN);
+    comm->bCartesianPP_PME = FALSE;
+    
+    /* Reorder the nodes by default. This might change the MPI ranks.
+     * Real reordering is only supported on very few architectures,
+     * Blue Gene is one of them.
+     */
+    CartReorder = (getenv("GMX_NO_CART_REORDER") == NULL);
+    
+    if (cr->npmenodes > 0)
+    {
+        /* Split the communicator into a PP and PME part */
+        split_communicator(fplog,cr,dd_node_order,CartReorder);
+        if (comm->bCartesianPP_PME)
+        {
+            /* We (possibly) reordered the nodes in split_communicator,
+             * so it is no longer required in make_pp_communicator.
+             */
+            CartReorder = FALSE;
+        }
+    }
+    else
+    {
+        /* All nodes do PP and PME */
+#ifdef GMX_MPI    
+        /* We do not require separate communicators */
+        cr->mpi_comm_mygroup = cr->mpi_comm_mysim;
+#endif
+    }
+    
+    if (cr->duty & DUTY_PP)
+    {
+        /* Copy or make a new PP communicator */
+        make_pp_communicator(fplog,cr,CartReorder);
+    }
+    else
+    {
+        receive_ddindex2simnodeid(cr);
+    }
+    
+    if (!(cr->duty & DUTY_PME))
+    {
+        /* Set up the commnuication to our PME node */
+        dd->pme_nodeid = dd_simnode2pmenode(cr,cr->sim_nodeid);
+        dd->pme_receive_vir_ener = receive_vir_ener(cr);
+        if (debug)
+        {
+            fprintf(debug,"My pme_nodeid %d receive ener %d\n",
+                    dd->pme_nodeid,dd->pme_receive_vir_ener);
+        }
+    }
+    else
+    {
+        dd->pme_nodeid = -1;
+    }
+
+    if (DDMASTER(dd))
+    {
+        dd->ma = init_gmx_domdec_master_t(dd,
+                                          comm->cgs_gl.nr,
+                                          comm->cgs_gl.index[comm->cgs_gl.nr]);
+    }
+}
+
+static real *get_slb_frac(FILE *fplog,const char *dir,int nc,const char *size_string)
+{
+    real *slb_frac,tot;
+    int  i,n;
+    double dbl;
+    
+    slb_frac = NULL;
+    if (nc > 1 && size_string != NULL)
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"Using static load balancing for the %s direction\n",
+                    dir);
+        }
+        snew(slb_frac,nc);
+        tot = 0;
+        for (i=0; i<nc; i++)
+        {
+            dbl = 0;
+            sscanf(size_string,"%lf%n",&dbl,&n);
+            if (dbl == 0)
+            {
+                gmx_fatal(FARGS,"Incorrect or not enough DD cell size entries for direction %s: '%s'",dir,size_string);
+            }
+            slb_frac[i] = dbl;
+            size_string += n;
+            tot += slb_frac[i];
+        }
+        /* Normalize */
+        if (fplog)
+        {
+            fprintf(fplog,"Relative cell sizes:");
+        }
+        for (i=0; i<nc; i++)
+        {
+            slb_frac[i] /= tot;
+            if (fplog)
+            {
+                fprintf(fplog," %5.3f",slb_frac[i]);
+            }
+        }
+        if (fplog)
+        {
+            fprintf(fplog,"\n");
+        }
+    }
+    
+    return slb_frac;
+}
+
+static int multi_body_bondeds_count(gmx_mtop_t *mtop)
+{
+    int n,nmol,ftype;
+    gmx_mtop_ilistloop_t iloop;
+    t_ilist *il;
+    
+    n = 0;
+    iloop = gmx_mtop_ilistloop_init(mtop);
+    while (gmx_mtop_ilistloop_next(iloop,&il,&nmol))
+    {
+        for(ftype=0; ftype<F_NRE; ftype++)
+        {
+            if ((interaction_function[ftype].flags & IF_BOND) &&
+                NRAL(ftype) >  2)
+            {
+                n += nmol*il[ftype].nr/(1 + NRAL(ftype));
+            }
+        }
+  }
+
+  return n;
+}
+
+static int dd_nst_env(FILE *fplog,const char *env_var,int def)
+{
+    char *val;
+    int  nst;
+    
+    nst = def;
+    val = getenv(env_var);
+    if (val)
+    {
+        if (sscanf(val,"%d",&nst) <= 0)
+        {
+            nst = 1;
+        }
+        if (fplog)
+        {
+            fprintf(fplog,"Found env.var. %s = %s, using value %d\n",
+                    env_var,val,nst);
+        }
+    }
+    
+    return nst;
+}
+
+static void dd_warning(t_commrec *cr,FILE *fplog,const char *warn_string)
+{
+    if (MASTER(cr))
+    {
+        fprintf(stderr,"\n%s\n",warn_string);
+    }
+    if (fplog)
+    {
+        fprintf(fplog,"\n%s\n",warn_string);
+    }
+}
+
+static void check_dd_restrictions(t_commrec *cr,gmx_domdec_t *dd,
+                                  t_inputrec *ir,FILE *fplog)
+{
+    if (ir->ePBC == epbcSCREW &&
+        (dd->nc[XX] == 1 || dd->nc[YY] > 1 || dd->nc[ZZ] > 1))
+    {
+        gmx_fatal(FARGS,"With pbc=%s can only do domain decomposition in the x-direction",epbc_names[ir->ePBC]);
+    }
+
+    if (ir->ns_type == ensSIMPLE)
+    {
+        gmx_fatal(FARGS,"Domain decomposition does not support simple neighbor searching, use grid searching or use particle decomposition");
+    }
+
+    if (ir->nstlist == 0)
+    {
+        gmx_fatal(FARGS,"Domain decomposition does not work with nstlist=0");
+    }
+
+    if (ir->comm_mode == ecmANGULAR && ir->ePBC != epbcNONE)
+    {
+        dd_warning(cr,fplog,"comm-mode angular will give incorrect results when the comm group partially crosses a periodic boundary");
+    }
+}
+
+static real average_cellsize_min(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
+{
+    int  di,d;
+    real r;
+
+    r = ddbox->box_size[XX];
+    for(di=0; di<dd->ndim; di++)
+    {
+        d = dd->dim[di];
+        /* Check using the initial average cell size */
+        r = min(r,ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
+    }
+
+    return r;
+}
+
+static int check_dlb_support(FILE *fplog,t_commrec *cr,
+                             const char *dlb_opt,gmx_bool bRecordLoad,
+                             unsigned long Flags,t_inputrec *ir)
+{
+    gmx_domdec_t *dd;
+    int  eDLB=-1;
+    char buf[STRLEN];
+
+    switch (dlb_opt[0])
+    {
+    case 'a': eDLB = edlbAUTO; break;
+    case 'n': eDLB = edlbNO;   break;
+    case 'y': eDLB = edlbYES;  break;
+    default: gmx_incons("Unknown dlb_opt");
+    }
+
+    if (Flags & MD_RERUN)
+    {
+        return edlbNO;
+    }
+
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        if (eDLB == edlbYES)
+        {
+            sprintf(buf,"NOTE: dynamic load balancing is only supported with dynamics, not with integrator '%s'\n",EI(ir->eI));
+            dd_warning(cr,fplog,buf);
+        }
+            
+        return edlbNO;
+    }
+
+    if (!bRecordLoad)
+    {
+        dd_warning(cr,fplog,"NOTE: Cycle counting is not supported on this architecture, will not use dynamic load balancing\n");
+
+        return edlbNO;
+    }
+
+    if (Flags & MD_REPRODUCIBLE)
+    {
+        switch (eDLB)
+        {
+                       case edlbNO: 
+                               break;
+                       case edlbAUTO:
+                               dd_warning(cr,fplog,"NOTE: reproducibility requested, will not use dynamic load balancing\n");
+                               eDLB = edlbNO;
+                               break;
+                       case edlbYES:
+                               dd_warning(cr,fplog,"WARNING: reproducibility requested with dynamic load balancing, the simulation will NOT be binary reproducible\n");
+                               break;
+                       default:
+                               gmx_fatal(FARGS,"Death horror: undefined case (%d) for load balancing choice",eDLB);
+                               break;
+        }
+    }
+
+    return eDLB;
+}
+
+static void set_dd_dim(FILE *fplog,gmx_domdec_t *dd)
+{
+    int dim;
+
+    dd->ndim = 0;
+    if (getenv("GMX_DD_ORDER_ZYX") != NULL)
+    {
+        /* Decomposition order z,y,x */
+        if (fplog)
+        {
+            fprintf(fplog,"Using domain decomposition order z, y, x\n");
+        }
+        for(dim=DIM-1; dim>=0; dim--)
+        {
+            if (dd->nc[dim] > 1)
+            {
+                dd->dim[dd->ndim++] = dim;
+            }
+        }
+    }
+    else
+    {
+        /* Decomposition order x,y,z */
+        for(dim=0; dim<DIM; dim++)
+        {
+            if (dd->nc[dim] > 1)
+            {
+                dd->dim[dd->ndim++] = dim;
+            }
+        }
+    }
+}
+
+static gmx_domdec_comm_t *init_dd_comm()
+{
+    gmx_domdec_comm_t *comm;
+    int  i;
+
+    snew(comm,1);
+    snew(comm->cggl_flag,DIM*2);
+    snew(comm->cgcm_state,DIM*2);
+    for(i=0; i<DIM*2; i++)
+    {
+        comm->cggl_flag_nalloc[i]  = 0;
+        comm->cgcm_state_nalloc[i] = 0;
+    }
+    
+    comm->nalloc_int = 0;
+    comm->buf_int    = NULL;
+
+    vec_rvec_init(&comm->vbuf);
+
+    comm->n_load_have    = 0;
+    comm->n_load_collect = 0;
+
+    for(i=0; i<ddnatNR-ddnatZONE; i++)
+    {
+        comm->sum_nat[i] = 0;
+    }
+    comm->ndecomp = 0;
+    comm->nload   = 0;
+    comm->load_step = 0;
+    comm->load_sum  = 0;
+    comm->load_max  = 0;
+    clear_ivec(comm->load_lim);
+    comm->load_mdf  = 0;
+    comm->load_pme  = 0;
+
+    return comm;
+}
+
+gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
+                                        unsigned long Flags,
+                                        ivec nc,
+                                        real comm_distance_min,real rconstr,
+                                        const char *dlb_opt,real dlb_scale,
+                                        const char *sizex,const char *sizey,const char *sizez,
+                                        gmx_mtop_t *mtop,t_inputrec *ir,
+                                        matrix box,rvec *x,
+                                        gmx_ddbox_t *ddbox,
+                                        int *npme_x,int *npme_y)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    int  recload;
+    int  d,i,j;
+    real r_2b,r_mb,r_bonded=-1,r_bonded_limit=-1,limit,acs;
+    gmx_bool bC;
+    char buf[STRLEN];
+    
+    if (fplog)
+    {
+        fprintf(fplog,
+                "\nInitializing Domain Decomposition on %d nodes\n",cr->nnodes);
+    }
+    
+    snew(dd,1);
+
+    dd->comm = init_dd_comm();
+    comm = dd->comm;
+    snew(comm->cggl_flag,DIM*2);
+    snew(comm->cgcm_state,DIM*2);
+
+    dd->npbcdim   = ePBC2npbcdim(ir->ePBC);
+    dd->bScrewPBC = (ir->ePBC == epbcSCREW);
+    
+    dd->bSendRecv2      = dd_nst_env(fplog,"GMX_DD_SENDRECV2",0);
+    comm->dlb_scale_lim = dd_nst_env(fplog,"GMX_DLB_MAX",10);
+    comm->eFlop         = dd_nst_env(fplog,"GMX_DLB_FLOP",0);
+    recload             = dd_nst_env(fplog,"GMX_DD_LOAD",1);
+    comm->nstSortCG     = dd_nst_env(fplog,"GMX_DD_SORT",1);
+    comm->nstDDDump     = dd_nst_env(fplog,"GMX_DD_DUMP",0);
+    comm->nstDDDumpGrid = dd_nst_env(fplog,"GMX_DD_DUMP_GRID",0);
+    comm->DD_debug      = dd_nst_env(fplog,"GMX_DD_DEBUG",0);
+
+    dd->pme_recv_f_alloc = 0;
+    dd->pme_recv_f_buf = NULL;
+
+    if (dd->bSendRecv2 && fplog)
+    {
+        fprintf(fplog,"Will use two sequential MPI_Sendrecv calls instead of two simultaneous non-blocking MPI_Irecv and MPI_Isend pairs for constraint and vsite communication\n");
+    }
+    if (comm->eFlop)
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"Will load balance based on FLOP count\n");
+        }
+        if (comm->eFlop > 1)
+        {
+            srand(1+cr->nodeid);
+        }
+        comm->bRecordLoad = TRUE;
+    }
+    else
+    {
+        comm->bRecordLoad = (wallcycle_have_counter() && recload > 0);
+                             
+    }
+    
+    comm->eDLB = check_dlb_support(fplog,cr,dlb_opt,comm->bRecordLoad,Flags,ir);
+    
+    comm->bDynLoadBal = (comm->eDLB == edlbYES);
+    if (fplog)
+    {
+        fprintf(fplog,"Dynamic load balancing: %s\n",edlb_names[comm->eDLB]);
+    }
+    dd->bGridJump = comm->bDynLoadBal;
+    
+    if (comm->nstSortCG)
+    {
+        if (fplog)
+        {
+            if (comm->nstSortCG == 1)
+            {
+                fprintf(fplog,"Will sort the charge groups at every domain (re)decomposition\n");
+            }
+            else
+            {
+                fprintf(fplog,"Will sort the charge groups every %d steps\n",
+                        comm->nstSortCG);
+            }
+        }
+        snew(comm->sort,1);
+    }
+    else
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"Will not sort the charge groups\n");
+        }
+    }
+    
+    comm->bInterCGBondeds = (ncg_mtop(mtop) > mtop->mols.nr);
+    if (comm->bInterCGBondeds)
+    {
+        comm->bInterCGMultiBody = (multi_body_bondeds_count(mtop) > 0);
+    }
+    else
+    {
+        comm->bInterCGMultiBody = FALSE;
+    }
+    
+    dd->bInterCGcons = inter_charge_group_constraints(mtop);
+
+    if (ir->rlistlong == 0)
+    {
+        /* Set the cut-off to some very large value,
+         * so we don't need if statements everywhere in the code.
+         * We use sqrt, since the cut-off is squared in some places.
+         */
+        comm->cutoff   = GMX_CUTOFF_INF;
+    }
+    else
+    {
+        comm->cutoff   = ir->rlistlong;
+    }
+    comm->cutoff_mbody = 0;
+    
+    comm->cellsize_limit = 0;
+    comm->bBondComm = FALSE;
+
+    if (comm->bInterCGBondeds)
+    {
+        if (comm_distance_min > 0)
+        {
+            comm->cutoff_mbody = comm_distance_min;
+            if (Flags & MD_DDBONDCOMM)
+            {
+                comm->bBondComm = (comm->cutoff_mbody > comm->cutoff);
+            }
+            else
+            {
+                comm->cutoff = max(comm->cutoff,comm->cutoff_mbody);
+            }
+            r_bonded_limit = comm->cutoff_mbody;
+        }
+        else if (ir->bPeriodicMols)
+        {
+            /* Can not easily determine the required cut-off */
+            dd_warning(cr,fplog,"NOTE: Periodic molecules: can not easily determine the required minimum bonded cut-off, using half the non-bonded cut-off\n");
+            comm->cutoff_mbody = comm->cutoff/2;
+            r_bonded_limit = comm->cutoff_mbody;
+        }
+        else
+        {
+            if (MASTER(cr))
+            {
+                dd_bonded_cg_distance(fplog,dd,mtop,ir,x,box,
+                                      Flags & MD_DDBONDCHECK,&r_2b,&r_mb);
+            }
+            gmx_bcast(sizeof(r_2b),&r_2b,cr);
+            gmx_bcast(sizeof(r_mb),&r_mb,cr);
+
+            /* We use an initial margin of 10% for the minimum cell size,
+             * except when we are just below the non-bonded cut-off.
+             */
+            if (Flags & MD_DDBONDCOMM)
+            {
+                if (max(r_2b,r_mb) > comm->cutoff)
+                {
+                    r_bonded       = max(r_2b,r_mb);
+                    r_bonded_limit = 1.1*r_bonded;
+                    comm->bBondComm = TRUE;
+                }
+                else
+                {
+                    r_bonded       = r_mb;
+                    r_bonded_limit = min(1.1*r_bonded,comm->cutoff);
+                }
+                /* We determine cutoff_mbody later */
+            }
+            else
+            {
+                /* No special bonded communication,
+                 * simply increase the DD cut-off.
+                 */
+                r_bonded_limit     = 1.1*max(r_2b,r_mb);
+                comm->cutoff_mbody = r_bonded_limit;
+                comm->cutoff       = max(comm->cutoff,comm->cutoff_mbody);
+            }
+        }
+        comm->cellsize_limit = max(comm->cellsize_limit,r_bonded_limit);
+        if (fplog)
+        {
+            fprintf(fplog,
+                    "Minimum cell size due to bonded interactions: %.3f nm\n",
+                    comm->cellsize_limit);
+        }
+    }
+
+    if (dd->bInterCGcons && rconstr <= 0)
+    {
+        /* There is a cell size limit due to the constraints (P-LINCS) */
+        rconstr = constr_r_max(fplog,mtop,ir);
+        if (fplog)
+        {
+            fprintf(fplog,
+                    "Estimated maximum distance required for P-LINCS: %.3f nm\n",
+                    rconstr);
+            if (rconstr > comm->cellsize_limit)
+            {
+                fprintf(fplog,"This distance will limit the DD cell size, you can override this with -rcon\n");
+            }
+        }
+    }
+    else if (rconstr > 0 && fplog)
+    {
+        /* Here we do not check for dd->bInterCGcons,
+         * because one can also set a cell size limit for virtual sites only
+         * and at this point we don't know yet if there are intercg v-sites.
+         */
+        fprintf(fplog,
+                "User supplied maximum distance required for P-LINCS: %.3f nm\n",
+                rconstr);
+    }
+    comm->cellsize_limit = max(comm->cellsize_limit,rconstr);
+
+    comm->cgs_gl = gmx_mtop_global_cgs(mtop);
+
+    if (nc[XX] > 0)
+    {
+        copy_ivec(nc,dd->nc);
+        set_dd_dim(fplog,dd);
+        set_ddbox_cr(cr,&dd->nc,ir,box,&comm->cgs_gl,x,ddbox);
+
+        if (cr->npmenodes == -1)
+        {
+            cr->npmenodes = 0;
+        }
+        acs = average_cellsize_min(dd,ddbox);
+        if (acs < comm->cellsize_limit)
+        {
+            if (fplog)
+            {
+                fprintf(fplog,"ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n",acs,comm->cellsize_limit);
+            }
+            gmx_fatal_collective(FARGS,cr,NULL,
+                                 "The initial cell size (%f) is smaller than the cell size limit (%f), change options -dd, -rdd or -rcon, see the log file for details",
+                                 acs,comm->cellsize_limit);
+        }
+    }
+    else
+    {
+        set_ddbox_cr(cr,NULL,ir,box,&comm->cgs_gl,x,ddbox);
+
+        /* We need to choose the optimal DD grid and possibly PME nodes */
+        limit = dd_choose_grid(fplog,cr,dd,ir,mtop,box,ddbox,
+                               comm->eDLB!=edlbNO,dlb_scale,
+                               comm->cellsize_limit,comm->cutoff,
+                               comm->bInterCGBondeds,comm->bInterCGMultiBody);
+        
+        if (dd->nc[XX] == 0)
+        {
+            bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
+            sprintf(buf,"Change the number of nodes or mdrun option %s%s%s",
+                    !bC ? "-rdd" : "-rcon",
+                    comm->eDLB!=edlbNO ? " or -dds" : "",
+                    bC ? " or your LINCS settings" : "");
+
+            gmx_fatal_collective(FARGS,cr,NULL,
+                                 "There is no domain decomposition for %d nodes that is compatible with the given box and a minimum cell size of %g nm\n"
+                                 "%s\n"
+                                 "Look in the log file for details on the domain decomposition",
+                                 cr->nnodes-cr->npmenodes,limit,buf);
+        }
+        set_dd_dim(fplog,dd);
+    }
+
+    if (fplog)
+    {
+        fprintf(fplog,
+                "Domain decomposition grid %d x %d x %d, separate PME nodes %d\n",
+                dd->nc[XX],dd->nc[YY],dd->nc[ZZ],cr->npmenodes);
+    }
+    
+    dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
+    if (cr->nnodes - dd->nnodes != cr->npmenodes)
+    {
+        gmx_fatal_collective(FARGS,cr,NULL,
+                             "The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
+                             dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
+    }
+    if (cr->npmenodes > dd->nnodes)
+    {
+        gmx_fatal_collective(FARGS,cr,NULL,
+                             "The number of separate PME nodes (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
+    }
+    if (cr->npmenodes > 0)
+    {
+        comm->npmenodes = cr->npmenodes;
+    }
+    else
+    {
+        comm->npmenodes = dd->nnodes;
+    }
+
+    if (EEL_PME(ir->coulombtype))
+    {
+        /* The following choices should match those
+         * in comm_cost_est in domdec_setup.c.
+         * Note that here the checks have to take into account
+         * that the decomposition might occur in a different order than xyz
+         * (for instance through the env.var. GMX_DD_ORDER_ZYX),
+         * in which case they will not match those in comm_cost_est,
+         * but since that is mainly for testing purposes that's fine.
+         */
+        if (dd->ndim >= 2 && dd->dim[0] == XX && dd->dim[1] == YY &&
+            comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
+            getenv("GMX_PMEONEDD") == NULL)
+        {
+            comm->npmedecompdim = 2;
+            comm->npmenodes_x   = dd->nc[XX];
+            comm->npmenodes_y   = comm->npmenodes/comm->npmenodes_x;
+        }
+        else
+        {
+            /* In case nc is 1 in both x and y we could still choose to
+             * decompose pme in y instead of x, but we use x for simplicity.
+             */
+            comm->npmedecompdim = 1;
+            if (dd->dim[0] == YY)
+            {
+                comm->npmenodes_x = 1;
+                comm->npmenodes_y = comm->npmenodes;
+            }
+            else
+            {
+                comm->npmenodes_x = comm->npmenodes;
+                comm->npmenodes_y = 1;
+            }
+        }    
+        if (fplog)
+        {
+            fprintf(fplog,"PME domain decomposition: %d x %d x %d\n",
+                    comm->npmenodes_x,comm->npmenodes_y,1);
+        }
+    }
+    else
+    {
+        comm->npmedecompdim = 0;
+        comm->npmenodes_x   = 0;
+        comm->npmenodes_y   = 0;
+    }
+    
+    /* Technically we don't need both of these,
+     * but it simplifies code not having to recalculate it.
+     */
+    *npme_x = comm->npmenodes_x;
+    *npme_y = comm->npmenodes_y;
+        
+    snew(comm->slb_frac,DIM);
+    if (comm->eDLB == edlbNO)
+    {
+        comm->slb_frac[XX] = get_slb_frac(fplog,"x",dd->nc[XX],sizex);
+        comm->slb_frac[YY] = get_slb_frac(fplog,"y",dd->nc[YY],sizey);
+        comm->slb_frac[ZZ] = get_slb_frac(fplog,"z",dd->nc[ZZ],sizez);
+    }
+
+    if (comm->bInterCGBondeds && comm->cutoff_mbody == 0)
+    {
+        if (comm->bBondComm || comm->eDLB != edlbNO)
+        {
+            /* Set the bonded communication distance to halfway
+             * the minimum and the maximum,
+             * since the extra communication cost is nearly zero.
+             */
+            acs = average_cellsize_min(dd,ddbox);
+            comm->cutoff_mbody = 0.5*(r_bonded + acs);
+            if (comm->eDLB != edlbNO)
+            {
+                /* Check if this does not limit the scaling */
+                comm->cutoff_mbody = min(comm->cutoff_mbody,dlb_scale*acs);
+            }
+            if (!comm->bBondComm)
+            {
+                /* Without bBondComm do not go beyond the n.b. cut-off */
+                comm->cutoff_mbody = min(comm->cutoff_mbody,comm->cutoff);
+                if (comm->cellsize_limit >= comm->cutoff)
+                {
+                    /* We don't loose a lot of efficieny
+                     * when increasing it to the n.b. cut-off.
+                     * It can even be slightly faster, because we need
+                     * less checks for the communication setup.
+                     */
+                    comm->cutoff_mbody = comm->cutoff;
+                }
+            }
+            /* Check if we did not end up below our original limit */
+            comm->cutoff_mbody = max(comm->cutoff_mbody,r_bonded_limit);
+
+            if (comm->cutoff_mbody > comm->cellsize_limit)
+            {
+                comm->cellsize_limit = comm->cutoff_mbody;
+            }
+        }
+        /* Without DLB and cutoff_mbody<cutoff, cutoff_mbody is dynamic */
+    }
+
+    if (debug)
+    {
+        fprintf(debug,"Bonded atom communication beyond the cut-off: %d\n"
+                "cellsize limit %f\n",
+                comm->bBondComm,comm->cellsize_limit);
+    }
+    
+    if (MASTER(cr))
+    {
+        check_dd_restrictions(cr,dd,ir,fplog);
+    }
+
+    comm->globalcomm_step = INT_MIN;
+    dd->ddp_count = 0;
+
+    clear_dd_cycle_counts(dd);
+
+    return dd;
+}
+
+static void set_dlb_limits(gmx_domdec_t *dd)
+
+{
+    int d;
+
+    for(d=0; d<dd->ndim; d++)
+    {
+        dd->comm->cd[d].np = dd->comm->cd[d].np_dlb;
+        dd->comm->cellsize_min[dd->dim[d]] =
+            dd->comm->cellsize_min_dlb[dd->dim[d]];
+    }
+}
+
+
+static void turn_on_dlb(FILE *fplog,t_commrec *cr,gmx_large_int_t step)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    real cellsize_min;
+    int  d,nc,i;
+    char buf[STRLEN];
+    
+    dd = cr->dd;
+    comm = dd->comm;
+    
+    if (fplog)
+    {
+        fprintf(fplog,"At step %s the performance loss due to force load imbalance is %.1f %%\n",gmx_step_str(step,buf),dd_force_imb_perf_loss(dd)*100);
+    }
+
+    cellsize_min = comm->cellsize_min[dd->dim[0]];
+    for(d=1; d<dd->ndim; d++)
+    {
+        cellsize_min = min(cellsize_min,comm->cellsize_min[dd->dim[d]]);
+    }
+
+    if (cellsize_min < comm->cellsize_limit*1.05)
+    {
+        dd_warning(cr,fplog,"NOTE: the minimum cell size is smaller than 1.05 times the cell size limit, will not turn on dynamic load balancing\n");
+
+        /* Change DLB from "auto" to "no". */
+        comm->eDLB = edlbNO;
+
+        return;
+    }
+
+    dd_warning(cr,fplog,"NOTE: Turning on dynamic load balancing\n");
+    comm->bDynLoadBal = TRUE;
+    dd->bGridJump = TRUE;
+    
+    set_dlb_limits(dd);
+
+    /* We can set the required cell size info here,
+     * so we do not need to communicate this.
+     * The grid is completely uniform.
+     */
+    for(d=0; d<dd->ndim; d++)
+    {
+        if (comm->root[d])
+        {
+            comm->load[d].sum_m = comm->load[d].sum;
+
+            nc = dd->nc[dd->dim[d]];
+            for(i=0; i<nc; i++)
+            {
+                comm->root[d]->cell_f[i]    = i/(real)nc;
+                if (d > 0)
+                {
+                    comm->root[d]->cell_f_max0[i] =  i   /(real)nc;
+                    comm->root[d]->cell_f_min1[i] = (i+1)/(real)nc;
+                }
+            }
+            comm->root[d]->cell_f[nc] = 1.0;
+        }
+    }
+}
+
+static char *init_bLocalCG(gmx_mtop_t *mtop)
+{
+    int  ncg,cg;
+    char *bLocalCG;
+    
+    ncg = ncg_mtop(mtop);
+    snew(bLocalCG,ncg);
+    for(cg=0; cg<ncg; cg++)
+    {
+        bLocalCG[cg] = FALSE;
+    }
+
+    return bLocalCG;
+}
+
+void dd_init_bondeds(FILE *fplog,
+                     gmx_domdec_t *dd,gmx_mtop_t *mtop,
+                     gmx_vsite_t *vsite,gmx_constr_t constr,
+                     t_inputrec *ir,gmx_bool bBCheck,cginfo_mb_t *cginfo_mb)
+{
+    gmx_domdec_comm_t *comm;
+    gmx_bool bBondComm;
+    int  d;
+
+    dd_make_reverse_top(fplog,dd,mtop,vsite,constr,ir,bBCheck);
+
+    comm = dd->comm;
+
+    if (comm->bBondComm)
+    {
+        /* Communicate atoms beyond the cut-off for bonded interactions */
+        comm = dd->comm;
+
+        comm->cglink = make_charge_group_links(mtop,dd,cginfo_mb);
+
+        comm->bLocalCG = init_bLocalCG(mtop);
+    }
+    else
+    {
+        /* Only communicate atoms based on cut-off */
+        comm->cglink   = NULL;
+        comm->bLocalCG = NULL;
+    }
+}
+
+static void print_dd_settings(FILE *fplog,gmx_domdec_t *dd,
+                              t_inputrec *ir,
+                              gmx_bool bDynLoadBal,real dlb_scale,
+                              gmx_ddbox_t *ddbox)
+{
+    gmx_domdec_comm_t *comm;
+    int  d;
+    ivec np;
+    real limit,shrink;
+    char buf[64];
+
+    if (fplog == NULL)
+    {
+        return;
+    }
+
+    comm = dd->comm;
+
+    if (bDynLoadBal)
+    {
+        fprintf(fplog,"The maximum number of communication pulses is:");
+        for(d=0; d<dd->ndim; d++)
+        {
+            fprintf(fplog," %c %d",dim2char(dd->dim[d]),comm->cd[d].np_dlb);
+        }
+        fprintf(fplog,"\n");
+        fprintf(fplog,"The minimum size for domain decomposition cells is %.3f nm\n",comm->cellsize_limit);
+        fprintf(fplog,"The requested allowed shrink of DD cells (option -dds) is: %.2f\n",dlb_scale);
+        fprintf(fplog,"The allowed shrink of domain decomposition cells is:");
+        for(d=0; d<DIM; d++)
+        {
+            if (dd->nc[d] > 1)
+            {
+                if (d >= ddbox->npbcdim && dd->nc[d] == 2)
+                {
+                    shrink = 0;
+                }
+                else
+                {
+                    shrink =
+                        comm->cellsize_min_dlb[d]/
+                        (ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
+                }
+                fprintf(fplog," %c %.2f",dim2char(d),shrink);
+            }
+        }
+        fprintf(fplog,"\n");
+    }
+    else
+    {
+        set_dd_cell_sizes_slb(dd,ddbox,FALSE,np);
+        fprintf(fplog,"The initial number of communication pulses is:");
+        for(d=0; d<dd->ndim; d++)
+        {
+            fprintf(fplog," %c %d",dim2char(dd->dim[d]),np[dd->dim[d]]);
+        }
+        fprintf(fplog,"\n");
+        fprintf(fplog,"The initial domain decomposition cell size is:");
+        for(d=0; d<DIM; d++) {
+            if (dd->nc[d] > 1)
+            {
+                fprintf(fplog," %c %.2f nm",
+                        dim2char(d),dd->comm->cellsize_min[d]);
+            }
+        }
+        fprintf(fplog,"\n\n");
+    }
+    
+    if (comm->bInterCGBondeds || dd->vsite_comm || dd->constraint_comm)
+    {
+        fprintf(fplog,"The maximum allowed distance for charge groups involved in interactions is:\n");
+        fprintf(fplog,"%40s  %-7s %6.3f nm\n",
+                "non-bonded interactions","",comm->cutoff);
+
+        if (bDynLoadBal)
+        {
+            limit = dd->comm->cellsize_limit;
+        }
+        else
+        {
+            if (dynamic_dd_box(ddbox,ir))
+            {
+                fprintf(fplog,"(the following are initial values, they could change due to box deformation)\n");
+            }
+            limit = dd->comm->cellsize_min[XX];
+            for(d=1; d<DIM; d++)
+            {
+                limit = min(limit,dd->comm->cellsize_min[d]);
+            }
+        }
+
+        if (comm->bInterCGBondeds)
+        {
+            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
+                    "two-body bonded interactions","(-rdd)",
+                    max(comm->cutoff,comm->cutoff_mbody));
+            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
+                    "multi-body bonded interactions","(-rdd)",
+                    (comm->bBondComm || dd->bGridJump) ? comm->cutoff_mbody : min(comm->cutoff,limit));
+        }
+        if (dd->vsite_comm)
+        {
+            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
+                    "virtual site constructions","(-rcon)",limit);
+        }
+        if (dd->constraint_comm)
+        {
+            sprintf(buf,"atoms separated by up to %d constraints",
+                    1+ir->nProjOrder);
+            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
+                    buf,"(-rcon)",limit);
+        }
+        fprintf(fplog,"\n");
+    }
+    
+    fflush(fplog);
+}
+
+void set_dd_parameters(FILE *fplog,gmx_domdec_t *dd,real dlb_scale,
+                       t_inputrec *ir,t_forcerec *fr,
+                       gmx_ddbox_t *ddbox)
+{
+    gmx_domdec_comm_t *comm;
+    int  d,dim,npulse,npulse_d_max,npulse_d;
+    gmx_bool bNoCutOff;
+    int  natoms_tot;
+    real vol_frac;
+
+    comm = dd->comm;
+
+    bNoCutOff = (ir->rvdw == 0 || ir->rcoulomb == 0);
+
+    if (EEL_PME(ir->coulombtype))
+    {
+        init_ddpme(dd,&comm->ddpme[0],0);
+        if (comm->npmedecompdim >= 2)
+        {
+            init_ddpme(dd,&comm->ddpme[1],1);
+        }
+    }
+    else
+    {
+        comm->npmenodes = 0;
+        if (dd->pme_nodeid >= 0)
+        {
+            gmx_fatal_collective(FARGS,NULL,dd,
+                                 "Can not have separate PME nodes without PME electrostatics");
+        }
+    }
+    
+    /* If each molecule is a single charge group
+     * or we use domain decomposition for each periodic dimension,
+     * we do not need to take pbc into account for the bonded interactions.
+     */
+    if (fr->ePBC == epbcNONE || !comm->bInterCGBondeds ||
+        (dd->nc[XX]>1 && dd->nc[YY]>1 && (dd->nc[ZZ]>1 || fr->ePBC==epbcXY)))
+    {
+        fr->bMolPBC = FALSE;
+    }
+    else
+    {
+        fr->bMolPBC = TRUE;
+    }
+        
+    if (debug)
+    {
+        fprintf(debug,"The DD cut-off is %f\n",comm->cutoff);
+    }
+    if (comm->eDLB != edlbNO)
+    {
+        /* Determine the maximum number of comm. pulses in one dimension */
+        
+        comm->cellsize_limit = max(comm->cellsize_limit,comm->cutoff_mbody);
+        
+        /* Determine the maximum required number of grid pulses */
+        if (comm->cellsize_limit >= comm->cutoff)
+        {
+            /* Only a single pulse is required */
+            npulse = 1;
+        }
+        else if (!bNoCutOff && comm->cellsize_limit > 0)
+        {
+            /* We round down slightly here to avoid overhead due to the latency
+             * of extra communication calls when the cut-off
+             * would be only slightly longer than the cell size.
+             * Later cellsize_limit is redetermined,
+             * so we can not miss interactions due to this rounding.
+             */
+            npulse = (int)(0.96 + comm->cutoff/comm->cellsize_limit);
+        }
+        else
+        {
+            /* There is no cell size limit */
+            npulse = max(dd->nc[XX]-1,max(dd->nc[YY]-1,dd->nc[ZZ]-1));
+        }
+
+        if (!bNoCutOff && npulse > 1)
+        {
+            /* See if we can do with less pulses, based on dlb_scale */
+            npulse_d_max = 0;
+            for(d=0; d<dd->ndim; d++)
+            {
+                dim = dd->dim[d];
+                npulse_d = (int)(1 + dd->nc[dim]*comm->cutoff
+                                 /(ddbox->box_size[dim]*ddbox->skew_fac[dim]*dlb_scale));
+                npulse_d_max = max(npulse_d_max,npulse_d);
+            }
+            npulse = min(npulse,npulse_d_max);
+        }
+        
+        /* This env var can override npulse */
+        d = dd_nst_env(fplog,"GMX_DD_NPULSE",0);
+        if (d > 0)
+        {
+            npulse = d;
+        }
+
+        comm->maxpulse = 1;
+        comm->bVacDLBNoLimit = (ir->ePBC == epbcNONE);
+        for(d=0; d<dd->ndim; d++)
+        {
+            comm->cd[d].np_dlb = min(npulse,dd->nc[dd->dim[d]]-1);
+            comm->cd[d].np_nalloc = comm->cd[d].np_dlb;
+            snew(comm->cd[d].ind,comm->cd[d].np_nalloc);
+            comm->maxpulse = max(comm->maxpulse,comm->cd[d].np_dlb);
+            if (comm->cd[d].np_dlb < dd->nc[dd->dim[d]]-1)
+            {
+                comm->bVacDLBNoLimit = FALSE;
+            }
+        }
+        
+        /* cellsize_limit is set for LINCS in init_domain_decomposition */
+        if (!comm->bVacDLBNoLimit)
+        {
+            comm->cellsize_limit = max(comm->cellsize_limit,
+                                       comm->cutoff/comm->maxpulse);
+        }
+        comm->cellsize_limit = max(comm->cellsize_limit,comm->cutoff_mbody);
+        /* Set the minimum cell size for each DD dimension */
+        for(d=0; d<dd->ndim; d++)
+        {
+            if (comm->bVacDLBNoLimit ||
+                comm->cd[d].np_dlb*comm->cellsize_limit >= comm->cutoff)
+            {
+                comm->cellsize_min_dlb[dd->dim[d]] = comm->cellsize_limit;
+            }
+            else
+            {
+                comm->cellsize_min_dlb[dd->dim[d]] =
+                    comm->cutoff/comm->cd[d].np_dlb;
+            }
+        }
+        if (comm->cutoff_mbody <= 0)
+        {
+            comm->cutoff_mbody = min(comm->cutoff,comm->cellsize_limit);
+        }
+        if (comm->bDynLoadBal)
+        {
+            set_dlb_limits(dd);
+        }
+    }
+    
+    print_dd_settings(fplog,dd,ir,comm->bDynLoadBal,dlb_scale,ddbox);
+    if (comm->eDLB == edlbAUTO)
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"When dynamic load balancing gets turned on, these settings will change to:\n");
+        }
+        print_dd_settings(fplog,dd,ir,TRUE,dlb_scale,ddbox);
+    }
+
+    if (ir->ePBC == epbcNONE)
+    {
+        vol_frac = 1 - 1/(double)dd->nnodes;
+    }
+    else
+    {
+        vol_frac =
+            (1 + comm_box_frac(dd->nc,comm->cutoff,ddbox))/(double)dd->nnodes;
+    }
+    if (debug)
+    {
+        fprintf(debug,"Volume fraction for all DD zones: %f\n",vol_frac);
+    }
+    natoms_tot = comm->cgs_gl.index[comm->cgs_gl.nr];
+   
+    dd->ga2la = ga2la_init(natoms_tot,vol_frac*natoms_tot);
+}
+
+static void merge_cg_buffers(int ncell,
+                             gmx_domdec_comm_dim_t *cd, int pulse,
+                             int  *ncg_cell,
+                             int  *index_gl, int  *recv_i,
+                             rvec *cg_cm,    rvec *recv_vr,
+                             int *cgindex,
+                             cginfo_mb_t *cginfo_mb,int *cginfo)
+{
+    gmx_domdec_ind_t *ind,*ind_p;
+    int p,cell,c,cg,cg0,cg1,cg_gl,nat;
+    int shift,shift_at;
+    
+    ind = &cd->ind[pulse];
+    
+    /* First correct the already stored data */
+    shift = ind->nrecv[ncell];
+    for(cell=ncell-1; cell>=0; cell--)
+    {
+        shift -= ind->nrecv[cell];
+        if (shift > 0)
+        {
+            /* Move the cg's present from previous grid pulses */
+            cg0 = ncg_cell[ncell+cell];
+            cg1 = ncg_cell[ncell+cell+1];
+            cgindex[cg1+shift] = cgindex[cg1];
+            for(cg=cg1-1; cg>=cg0; cg--)
+            {
+                index_gl[cg+shift] = index_gl[cg];
+                copy_rvec(cg_cm[cg],cg_cm[cg+shift]);
+                cgindex[cg+shift] = cgindex[cg];
+                cginfo[cg+shift] = cginfo[cg];
+            }
+            /* Correct the already stored send indices for the shift */
+            for(p=1; p<=pulse; p++)
+            {
+                ind_p = &cd->ind[p];
+                cg0 = 0;
+                for(c=0; c<cell; c++)
+                {
+                    cg0 += ind_p->nsend[c];
+                }
+                cg1 = cg0 + ind_p->nsend[cell];
+                for(cg=cg0; cg<cg1; cg++)
+                {
+                    ind_p->index[cg] += shift;
+                }
+            }
+        }
+    }
+
+    /* Merge in the communicated buffers */
+    shift = 0;
+    shift_at = 0;
+    cg0 = 0;
+    for(cell=0; cell<ncell; cell++)
+    {
+        cg1 = ncg_cell[ncell+cell+1] + shift;
+        if (shift_at > 0)
+        {
+            /* Correct the old cg indices */
+            for(cg=ncg_cell[ncell+cell]; cg<cg1; cg++)
+            {
+                cgindex[cg+1] += shift_at;
+            }
+        }
+        for(cg=0; cg<ind->nrecv[cell]; cg++)
+        {
+            /* Copy this charge group from the buffer */
+            index_gl[cg1] = recv_i[cg0];
+            copy_rvec(recv_vr[cg0],cg_cm[cg1]);
+            /* Add it to the cgindex */
+            cg_gl = index_gl[cg1];
+            cginfo[cg1] = ddcginfo(cginfo_mb,cg_gl);
+            nat = GET_CGINFO_NATOMS(cginfo[cg1]);
+            cgindex[cg1+1] = cgindex[cg1] + nat;
+            cg0++;
+            cg1++;
+            shift_at += nat;
+        }
+        shift += ind->nrecv[cell];
+        ncg_cell[ncell+cell+1] = cg1;
+    }
+}
+
+static void make_cell2at_index(gmx_domdec_comm_dim_t *cd,
+                               int nzone,int cg0,const int *cgindex)
+{
+    int cg,zone,p;
+    
+    /* Store the atom block boundaries for easy copying of communication buffers
+     */
+    cg = cg0;
+    for(zone=0; zone<nzone; zone++)
+    {
+        for(p=0; p<cd->np; p++) {
+            cd->ind[p].cell2at0[zone] = cgindex[cg];
+            cg += cd->ind[p].nrecv[zone];
+            cd->ind[p].cell2at1[zone] = cgindex[cg];
+        }
+    }
+}
+
+static gmx_bool missing_link(t_blocka *link,int cg_gl,char *bLocalCG)
+{
+    int  i;
+    gmx_bool bMiss;
+
+    bMiss = FALSE;
+    for(i=link->index[cg_gl]; i<link->index[cg_gl+1]; i++)
+    {
+        if (!bLocalCG[link->a[i]])
+        {
+            bMiss = TRUE;
+        }
+    }
+
+    return bMiss;
+}
+
+static void setup_dd_communication(gmx_domdec_t *dd,
+                                   matrix box,gmx_ddbox_t *ddbox,t_forcerec *fr)
+{
+    int dim_ind,dim,dim0,dim1=-1,dim2=-1,dimd,p,nat_tot;
+    int nzone,nzone_send,zone,zonei,cg0,cg1;
+    int c,i,j,cg,cg_gl,nrcg;
+    int *zone_cg_range,pos_cg,*index_gl,*cgindex,*recv_i;
+    gmx_domdec_comm_t *comm;
+    gmx_domdec_zones_t *zones;
+    gmx_domdec_comm_dim_t *cd;
+    gmx_domdec_ind_t *ind;
+    cginfo_mb_t *cginfo_mb;
+    gmx_bool bBondComm,bDist2B,bDistMB,bDistMB_pulse,bDistBonded,bScrew;
+    real r_mb,r_comm2,r_scomm2,r_bcomm2,r,r_0,r_1,r2,rb2,r2inc,inv_ncg,tric_sh;
+    rvec rb,rn;
+    real corner[DIM][4],corner_round_0=0,corner_round_1[4];
+    real bcorner[DIM],bcorner_round_1=0;
+    ivec tric_dist;
+    rvec *cg_cm,*normal,*v_d,*v_0=NULL,*v_1=NULL,*recv_vr;
+    real skew_fac2_d,skew_fac_01;
+    rvec sf2_round;
+    int  nsend,nat;
+    
+    if (debug)
+    {
+        fprintf(debug,"Setting up DD communication\n");
+    }
+    
+    comm  = dd->comm;
+    cg_cm = fr->cg_cm;
+
+    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
+    {
+        dim = dd->dim[dim_ind];
+
+        /* Check if we need to use triclinic distances */
+        tric_dist[dim_ind] = 0;
+        for(i=0; i<=dim_ind; i++)
+        {
+            if (ddbox->tric_dir[dd->dim[i]])
+            {
+                tric_dist[dim_ind] = 1;
+            }
+        }
+    }
+
+    bBondComm = comm->bBondComm;
+
+    /* Do we need to determine extra distances for multi-body bondeds? */
+    bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
+    
+    /* Do we need to determine extra distances for only two-body bondeds? */
+    bDist2B = (bBondComm && !bDistMB);
+
+    r_comm2  = sqr(comm->cutoff);
+    r_bcomm2 = sqr(comm->cutoff_mbody);
+
+    if (debug)
+    {
+        fprintf(debug,"bBondComm %d, r_bc %f\n",bBondComm,sqrt(r_bcomm2));
+    }
+
+    zones = &comm->zones;
+    
+    dim0 = dd->dim[0];
+    /* The first dimension is equal for all cells */
+    corner[0][0] = comm->cell_x0[dim0];
+    if (bDistMB)
+    {
+        bcorner[0] = corner[0][0];
+    }
+    if (dd->ndim >= 2)
+    {
+        dim1 = dd->dim[1];
+        /* This cell row is only seen from the first row */
+        corner[1][0] = comm->cell_x0[dim1];
+        /* All rows can see this row */
+        corner[1][1] = comm->cell_x0[dim1];
+        if (dd->bGridJump)
+        {
+            corner[1][1] = max(comm->cell_x0[dim1],comm->zone_d1[1].mch0);
+            if (bDistMB)
+            {
+                /* For the multi-body distance we need the maximum */
+                bcorner[1] = max(comm->cell_x0[dim1],comm->zone_d1[1].p1_0);
+            }
+        }
+        /* Set the upper-right corner for rounding */
+        corner_round_0 = comm->cell_x1[dim0];
+        
+        if (dd->ndim >= 3)
+        {
+            dim2 = dd->dim[2];
+            for(j=0; j<4; j++)
+            {
+                corner[2][j] = comm->cell_x0[dim2];
+            }
+            if (dd->bGridJump)
+            {
+                /* Use the maximum of the i-cells that see a j-cell */
+                for(i=0; i<zones->nizone; i++)
+                {
+                    for(j=zones->izone[i].j0; j<zones->izone[i].j1; j++)
+                    {
+                        if (j >= 4)
+                        {
+                            corner[2][j-4] =
+                                max(corner[2][j-4],
+                                    comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0);
+                        }
+                    }
+                }
+                if (bDistMB)
+                {
+                    /* For the multi-body distance we need the maximum */
+                    bcorner[2] = comm->cell_x0[dim2];
+                    for(i=0; i<2; i++)
+                    {
+                        for(j=0; j<2; j++)
+                        {
+                            bcorner[2] = max(bcorner[2],
+                                             comm->zone_d2[i][j].p1_0);
+                        }
+                    }
+                }
+            }
+            
+            /* Set the upper-right corner for rounding */
+            /* Cell (0,0,0) and cell (1,0,0) can see cell 4 (0,1,1)
+             * Only cell (0,0,0) can see cell 7 (1,1,1)
+             */
+            corner_round_1[0] = comm->cell_x1[dim1];
+            corner_round_1[3] = comm->cell_x1[dim1];
+            if (dd->bGridJump)
+            {
+                corner_round_1[0] = max(comm->cell_x1[dim1],
+                                        comm->zone_d1[1].mch1);
+                if (bDistMB)
+                {
+                    /* For the multi-body distance we need the maximum */
+                    bcorner_round_1 = max(comm->cell_x1[dim1],
+                                          comm->zone_d1[1].p1_1);
+                }
+            }
+        }
+    }
+    
+    /* Triclinic stuff */
+    normal = ddbox->normal;
+    skew_fac_01 = 0;
+    if (dd->ndim >= 2)
+    {
+        v_0 = ddbox->v[dim0];
+        if (ddbox->tric_dir[dim0] && ddbox->tric_dir[dim1])
+        {
+            /* Determine the coupling coefficient for the distances
+             * to the cell planes along dim0 and dim1 through dim2.
+             * This is required for correct rounding.
+             */
+            skew_fac_01 =
+                ddbox->v[dim0][dim1+1][dim0]*ddbox->v[dim1][dim1+1][dim1];
+            if (debug)
+            {
+                fprintf(debug,"\nskew_fac_01 %f\n",skew_fac_01);
+            }
+        }
+    }
+    if (dd->ndim >= 3)
+    {
+        v_1 = ddbox->v[dim1];
+    }
+    
+    zone_cg_range = zones->cg_range;
+    index_gl = dd->index_gl;
+    cgindex  = dd->cgindex;
+    cginfo_mb = fr->cginfo_mb;
+    
+    zone_cg_range[0]   = 0;
+    zone_cg_range[1]   = dd->ncg_home;
+    comm->zone_ncg1[0] = dd->ncg_home;
+    pos_cg             = dd->ncg_home;
+    
+    nat_tot = dd->nat_home;
+    nzone = 1;
+    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
+    {
+        dim = dd->dim[dim_ind];
+        cd = &comm->cd[dim_ind];
+        
+        if (dim >= ddbox->npbcdim && dd->ci[dim] == 0)
+        {
+            /* No pbc in this dimension, the first node should not comm. */
+            nzone_send = 0;
+        }
+        else
+        {
+            nzone_send = nzone;
+        }
+
+        bScrew = (dd->bScrewPBC && dim == XX);
+        
+        v_d = ddbox->v[dim];
+        skew_fac2_d = sqr(ddbox->skew_fac[dim]);
+
+        cd->bInPlace = TRUE;
+        for(p=0; p<cd->np; p++)
+        {
+            /* Only atoms communicated in the first pulse are used
+             * for multi-body bonded interactions or for bBondComm.
+             */
+            bDistBonded   = ((bDistMB || bDist2B) && p == 0);
+            bDistMB_pulse = (bDistMB && bDistBonded);
+
+            ind = &cd->ind[p];
+            nsend = 0;
+            nat = 0;
+            for(zone=0; zone<nzone_send; zone++)
+            {
+                if (tric_dist[dim_ind] && dim_ind > 0)
+                {
+                    /* Determine slightly more optimized skew_fac's
+                     * for rounding.
+                     * This reduces the number of communicated atoms
+                     * by about 10% for 3D DD of rhombic dodecahedra.
+                     */
+                    for(dimd=0; dimd<dim; dimd++)
+                    {
+                        sf2_round[dimd] = 1;
+                        if (ddbox->tric_dir[dimd])
+                        {
+                            for(i=dd->dim[dimd]+1; i<DIM; i++)
+                            {
+                                /* If we are shifted in dimension i
+                                 * and the cell plane is tilted forward
+                                 * in dimension i, skip this coupling.
+                                 */
+                                if (!(zones->shift[nzone+zone][i] &&
+                                      ddbox->v[dimd][i][dimd] >= 0))
+                                {
+                                    sf2_round[dimd] +=
+                                        sqr(ddbox->v[dimd][i][dimd]);
+                                }
+                            }
+                            sf2_round[dimd] = 1/sf2_round[dimd];
+                        }
+                    }
+                }
+
+                zonei = zone_perm[dim_ind][zone];
+                if (p == 0)
+                {
+                    /* Here we permutate the zones to obtain a convenient order
+                     * for neighbor searching
+                     */
+                    cg0 = zone_cg_range[zonei];
+                    cg1 = zone_cg_range[zonei+1];
+                }
+                else
+                {
+                    /* Look only at the cg's received in the previous grid pulse
+                     */
+                    cg1 = zone_cg_range[nzone+zone+1];
+                    cg0 = cg1 - cd->ind[p-1].nrecv[zone];
+                }
+                ind->nsend[zone] = 0;
+                for(cg=cg0; cg<cg1; cg++)
+                {
+                    r2  = 0;
+                    rb2 = 0;
+                    if (tric_dist[dim_ind] == 0)
+                    {
+                        /* Rectangular direction, easy */
+                        r = cg_cm[cg][dim] - corner[dim_ind][zone];
+                        if (r > 0)
+                        {
+                            r2 += r*r;
+                        }
+                        if (bDistMB_pulse)
+                        {
+                            r = cg_cm[cg][dim] - bcorner[dim_ind];
+                            if (r > 0)
+                            {
+                                rb2 += r*r;
+                            }
+                        }
+                        /* Rounding gives at most a 16% reduction
+                         * in communicated atoms
+                         */
+                        if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
+                        {
+                            r = cg_cm[cg][dim0] - corner_round_0;
+                            /* This is the first dimension, so always r >= 0 */
+                            r2 += r*r;
+                            if (bDistMB_pulse)
+                            {
+                                rb2 += r*r;
+                            }
+                        }
+                        if (dim_ind == 2 && (zonei == 2 || zonei == 3))
+                        {
+                            r = cg_cm[cg][dim1] - corner_round_1[zone];
+                            if (r > 0)
+                            {
+                                r2 += r*r;
+                            }
+                            if (bDistMB_pulse)
+                            {
+                                r = cg_cm[cg][dim1] - bcorner_round_1;
+                                if (r > 0)
+                                {
+                                    rb2 += r*r;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        /* Triclinic direction, more complicated */
+                        clear_rvec(rn);
+                        clear_rvec(rb);
+                        /* Rounding, conservative as the skew_fac multiplication
+                         * will slightly underestimate the distance.
+                         */
+                        if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
+                        {
+                            rn[dim0] = cg_cm[cg][dim0] - corner_round_0;
+                            for(i=dim0+1; i<DIM; i++)
+                            {
+                                rn[dim0] -= cg_cm[cg][i]*v_0[i][dim0];
+                            }
+                            r2 = rn[dim0]*rn[dim0]*sf2_round[dim0];
+                            if (bDistMB_pulse)
+                            {
+                                rb[dim0] = rn[dim0];
+                                rb2 = r2;
+                            }
+                            /* Take care that the cell planes along dim0 might not
+                             * be orthogonal to those along dim1 and dim2.
+                             */
+                            for(i=1; i<=dim_ind; i++)
+                            {
+                                dimd = dd->dim[i];
+                                if (normal[dim0][dimd] > 0)
+                                {
+                                    rn[dimd] -= rn[dim0]*normal[dim0][dimd];
+                                    if (bDistMB_pulse)
+                                    {
+                                        rb[dimd] -= rb[dim0]*normal[dim0][dimd];
+                                    }
+                                }
+                            }
+                        }
+                        if (dim_ind == 2 && (zonei == 2 || zonei == 3))
+                        {
+                            rn[dim1] += cg_cm[cg][dim1] - corner_round_1[zone];
+                            tric_sh = 0;
+                            for(i=dim1+1; i<DIM; i++)
+                            {
+                                tric_sh -= cg_cm[cg][i]*v_1[i][dim1];
+                            }
+                            rn[dim1] += tric_sh;
+                            if (rn[dim1] > 0)
+                            {
+                                r2 += rn[dim1]*rn[dim1]*sf2_round[dim1];
+                                /* Take care of coupling of the distances
+                                 * to the planes along dim0 and dim1 through dim2.
+                                 */
+                                r2 -= rn[dim0]*rn[dim1]*skew_fac_01;
+                                /* Take care that the cell planes along dim1
+                                 * might not be orthogonal to that along dim2.
+                                 */
+                                if (normal[dim1][dim2] > 0)
+                                {
+                                    rn[dim2] -= rn[dim1]*normal[dim1][dim2];
+                                }
+                            }
+                            if (bDistMB_pulse)
+                            {
+                                rb[dim1] +=
+                                    cg_cm[cg][dim1] - bcorner_round_1 + tric_sh;
+                                if (rb[dim1] > 0)
+                                {
+                                    rb2 += rb[dim1]*rb[dim1]*sf2_round[dim1];
+                                    /* Take care of coupling of the distances
+                                     * to the planes along dim0 and dim1 through dim2.
+                                     */
+                                    rb2 -= rb[dim0]*rb[dim1]*skew_fac_01;
+                                    /* Take care that the cell planes along dim1
+                                     * might not be orthogonal to that along dim2.
+                                     */
+                                    if (normal[dim1][dim2] > 0)
+                                    {
+                                        rb[dim2] -= rb[dim1]*normal[dim1][dim2];
+                                    }
+                                }
+                            }
+                        }
+                        /* The distance along the communication direction */
+                        rn[dim] += cg_cm[cg][dim] - corner[dim_ind][zone];
+                        tric_sh = 0;
+                        for(i=dim+1; i<DIM; i++)
+                        {
+                            tric_sh -= cg_cm[cg][i]*v_d[i][dim];
+                        }
+                        rn[dim] += tric_sh;
+                        if (rn[dim] > 0)
+                        {
+                            r2 += rn[dim]*rn[dim]*skew_fac2_d;
+                            /* Take care of coupling of the distances
+                             * to the planes along dim0 and dim1 through dim2.
+                             */
+                            if (dim_ind == 1 && zonei == 1)
+                            {
+                                r2 -= rn[dim0]*rn[dim]*skew_fac_01;
+                            }
+                        }
+                        if (bDistMB_pulse)
+                        {
+                            clear_rvec(rb);
+                            rb[dim] += cg_cm[cg][dim] - bcorner[dim_ind] + tric_sh;
+                            if (rb[dim] > 0)
+                            {
+                                rb2 += rb[dim]*rb[dim]*skew_fac2_d;
+                                /* Take care of coupling of the distances
+                                 * to the planes along dim0 and dim1 through dim2.
+                                 */
+                                if (dim_ind == 1 && zonei == 1)
+                                {
+                                    rb2 -= rb[dim0]*rb[dim]*skew_fac_01;
+                                }
+                            }
+                        }
+                    }
+                    
+                    if (r2 < r_comm2 ||
+                        (bDistBonded &&
+                         ((bDistMB && rb2 < r_bcomm2) ||
+                          (bDist2B && r2  < r_bcomm2)) &&
+                         (!bBondComm ||
+                          (GET_CGINFO_BOND_INTER(fr->cginfo[cg]) &&
+                           missing_link(comm->cglink,index_gl[cg],
+                                        comm->bLocalCG)))))
+                    {
+                        /* Make an index to the local charge groups */
+                        if (nsend+1 > ind->nalloc)
+                        {
+                            ind->nalloc = over_alloc_large(nsend+1);
+                            srenew(ind->index,ind->nalloc);
+                        }
+                        if (nsend+1 > comm->nalloc_int)
+                        {
+                            comm->nalloc_int = over_alloc_large(nsend+1);
+                            srenew(comm->buf_int,comm->nalloc_int);
+                        }
+                        ind->index[nsend] = cg;
+                        comm->buf_int[nsend] = index_gl[cg];
+                        ind->nsend[zone]++;
+                        vec_rvec_check_alloc(&comm->vbuf,nsend+1);
+
+                        if (dd->ci[dim] == 0)
+                        {
+                            /* Correct cg_cm for pbc */
+                            rvec_add(cg_cm[cg],box[dim],comm->vbuf.v[nsend]);
+                            if (bScrew)
+                            {
+                                comm->vbuf.v[nsend][YY] =
+                                    box[YY][YY]-comm->vbuf.v[nsend][YY];
+                                comm->vbuf.v[nsend][ZZ] =
+                                    box[ZZ][ZZ]-comm->vbuf.v[nsend][ZZ];
+                            }
+                        }
+                        else
+                        {
+                            copy_rvec(cg_cm[cg],comm->vbuf.v[nsend]);
+                        }
+                        nsend++;
+                        nat += cgindex[cg+1] - cgindex[cg];
+                    }
+                }
+            }
+            /* Clear the counts in case we do not have pbc */
+            for(zone=nzone_send; zone<nzone; zone++)
+            {
+                ind->nsend[zone] = 0;
+            }
+            ind->nsend[nzone]   = nsend;
+            ind->nsend[nzone+1] = nat;
+            /* Communicate the number of cg's and atoms to receive */
+            dd_sendrecv_int(dd, dim_ind, dddirBackward,
+                            ind->nsend, nzone+2,
+                            ind->nrecv, nzone+2);
+            
+            /* The rvec buffer is also required for atom buffers of size nsend
+             * in dd_move_x and dd_move_f.
+             */
+            vec_rvec_check_alloc(&comm->vbuf,ind->nsend[nzone+1]);
+
+            if (p > 0)
+            {
+                /* We can receive in place if only the last zone is not empty */
+                for(zone=0; zone<nzone-1; zone++)
+                {
+                    if (ind->nrecv[zone] > 0)
+                    {
+                        cd->bInPlace = FALSE;
+                    }
+                }
+                if (!cd->bInPlace)
+                {
+                    /* The int buffer is only required here for the cg indices */
+                    if (ind->nrecv[nzone] > comm->nalloc_int2)
+                    {
+                        comm->nalloc_int2 = over_alloc_dd(ind->nrecv[nzone]);
+                        srenew(comm->buf_int2,comm->nalloc_int2);
+                    }
+                    /* The rvec buffer is also required for atom buffers
+                     * of size nrecv in dd_move_x and dd_move_f.
+                     */
+                    i = max(cd->ind[0].nrecv[nzone+1],ind->nrecv[nzone+1]);
+                    vec_rvec_check_alloc(&comm->vbuf2,i);
+                }
+            }
+            
+            /* Make space for the global cg indices */
+            if (pos_cg + ind->nrecv[nzone] > dd->cg_nalloc
+                || dd->cg_nalloc == 0)
+            {
+                dd->cg_nalloc = over_alloc_dd(pos_cg + ind->nrecv[nzone]);
+                srenew(index_gl,dd->cg_nalloc);
+                srenew(cgindex,dd->cg_nalloc+1);
+            }
+            /* Communicate the global cg indices */
+            if (cd->bInPlace)
+            {
+                recv_i = index_gl + pos_cg;
+            }
+            else
+            {
+                recv_i = comm->buf_int2;
+            }
+            dd_sendrecv_int(dd, dim_ind, dddirBackward,
+                            comm->buf_int, nsend,
+                            recv_i,        ind->nrecv[nzone]);
+
+            /* Make space for cg_cm */
+            if (pos_cg + ind->nrecv[nzone] > fr->cg_nalloc)
+            {
+                dd_realloc_fr_cg(fr,pos_cg + ind->nrecv[nzone]);
+                cg_cm = fr->cg_cm;
+            }
+            /* Communicate cg_cm */
+            if (cd->bInPlace)
+            {
+                recv_vr = cg_cm + pos_cg;
+            }
+            else
+            {
+                recv_vr = comm->vbuf2.v;
+            }
+            dd_sendrecv_rvec(dd, dim_ind, dddirBackward,
+                             comm->vbuf.v, nsend,
+                             recv_vr,      ind->nrecv[nzone]);
+            
+            /* Make the charge group index */
+            if (cd->bInPlace)
+            {
+                zone = (p == 0 ? 0 : nzone - 1);
+                while (zone < nzone)
+                {
+                    for(cg=0; cg<ind->nrecv[zone]; cg++)
+                    {
+                        cg_gl = index_gl[pos_cg];
+                        fr->cginfo[pos_cg] = ddcginfo(cginfo_mb,cg_gl);
+                        nrcg = GET_CGINFO_NATOMS(fr->cginfo[pos_cg]);
+                        cgindex[pos_cg+1] = cgindex[pos_cg] + nrcg;
+                        if (bBondComm)
+                        {
+                            /* Update the charge group presence,
+                             * so we can use it in the next pass of the loop.
+                             */
+                            comm->bLocalCG[cg_gl] = TRUE;
+                        }
+                        pos_cg++;
+                    }
+                    if (p == 0)
+                    {
+                        comm->zone_ncg1[nzone+zone] = ind->nrecv[zone];
+                    }
+                    zone++;
+                    zone_cg_range[nzone+zone] = pos_cg;
+                }
+            }
+            else
+            {
+                /* This part of the code is never executed with bBondComm. */
+                merge_cg_buffers(nzone,cd,p,zone_cg_range,
+                                 index_gl,recv_i,cg_cm,recv_vr,
+                                 cgindex,fr->cginfo_mb,fr->cginfo);
+                pos_cg += ind->nrecv[nzone];
+            }
+            nat_tot += ind->nrecv[nzone+1];
+        }
+        if (!cd->bInPlace)
+        {
+            /* Store the atom block for easy copying of communication buffers */
+            make_cell2at_index(cd,nzone,zone_cg_range[nzone],cgindex);
+        }
+        nzone += nzone;
+    }
+    dd->index_gl = index_gl;
+    dd->cgindex  = cgindex;
+    
+    dd->ncg_tot = zone_cg_range[zones->n];
+    dd->nat_tot = nat_tot;
+    comm->nat[ddnatHOME] = dd->nat_home;
+    for(i=ddnatZONE; i<ddnatNR; i++)
+    {
+        comm->nat[i] = dd->nat_tot;
+    }
+
+    if (!bBondComm)
+    {
+        /* We don't need to update cginfo, since that was alrady done above.
+         * So we pass NULL for the forcerec.
+         */
+        dd_set_cginfo(dd->index_gl,dd->ncg_home,dd->ncg_tot,
+                      NULL,comm->bLocalCG);
+    }
+
+    if (debug)
+    {
+        fprintf(debug,"Finished setting up DD communication, zones:");
+        for(c=0; c<zones->n; c++)
+        {
+            fprintf(debug," %d",zones->cg_range[c+1]-zones->cg_range[c]);
+        }
+        fprintf(debug,"\n");
+    }
+}
+
+static void set_cg_boundaries(gmx_domdec_zones_t *zones)
+{
+    int c;
+    
+    for(c=0; c<zones->nizone; c++)
+    {
+        zones->izone[c].cg1  = zones->cg_range[c+1];
+        zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0];
+        zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1];
+    }
+}
+
+static int comp_cgsort(const void *a,const void *b)
+{
+    int comp;
+    
+    gmx_cgsort_t *cga,*cgb;
+    cga = (gmx_cgsort_t *)a;
+    cgb = (gmx_cgsort_t *)b;
+    
+    comp = cga->nsc - cgb->nsc;
+    if (comp == 0)
+    {
+        comp = cga->ind_gl - cgb->ind_gl;
+    }
+    
+    return comp;
+}
+
+static void order_int_cg(int n,gmx_cgsort_t *sort,
+                         int *a,int *buf)
+{
+    int i;
+    
+    /* Order the data */
+    for(i=0; i<n; i++)
+    {
+        buf[i] = a[sort[i].ind];
+    }
+    
+    /* Copy back to the original array */
+    for(i=0; i<n; i++)
+    {
+        a[i] = buf[i];
+    }
+}
+
+static void order_vec_cg(int n,gmx_cgsort_t *sort,
+                         rvec *v,rvec *buf)
+{
+    int i;
+    
+    /* Order the data */
+    for(i=0; i<n; i++)
+    {
+        copy_rvec(v[sort[i].ind],buf[i]);
+    }
+    
+    /* Copy back to the original array */
+    for(i=0; i<n; i++)
+    {
+        copy_rvec(buf[i],v[i]);
+    }
+}
+
+static void order_vec_atom(int ncg,int *cgindex,gmx_cgsort_t *sort,
+                           rvec *v,rvec *buf)
+{
+    int a,atot,cg,cg0,cg1,i;
+    
+    /* Order the data */
+    a = 0;
+    for(cg=0; cg<ncg; cg++)
+    {
+        cg0 = cgindex[sort[cg].ind];
+        cg1 = cgindex[sort[cg].ind+1];
+        for(i=cg0; i<cg1; i++)
+        {
+            copy_rvec(v[i],buf[a]);
+            a++;
+        }
+    }
+    atot = a;
+    
+    /* Copy back to the original array */
+    for(a=0; a<atot; a++)
+    {
+        copy_rvec(buf[a],v[a]);
+    }
+}
+
+static void ordered_sort(int nsort2,gmx_cgsort_t *sort2,
+                         int nsort_new,gmx_cgsort_t *sort_new,
+                         gmx_cgsort_t *sort1)
+{
+    int i1,i2,i_new;
+    
+    /* The new indices are not very ordered, so we qsort them */
+    qsort_threadsafe(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
+    
+    /* sort2 is already ordered, so now we can merge the two arrays */
+    i1 = 0;
+    i2 = 0;
+    i_new = 0;
+    while(i2 < nsort2 || i_new < nsort_new)
+    {
+        if (i2 == nsort2)
+        {
+            sort1[i1++] = sort_new[i_new++];
+        }
+        else if (i_new == nsort_new)
+        {
+            sort1[i1++] = sort2[i2++];
+        }
+        else if (sort2[i2].nsc < sort_new[i_new].nsc ||
+                 (sort2[i2].nsc == sort_new[i_new].nsc &&
+                  sort2[i2].ind_gl < sort_new[i_new].ind_gl))
+        {
+            sort1[i1++] = sort2[i2++];
+        }
+        else
+        {
+            sort1[i1++] = sort_new[i_new++];
+        }
+    }
+}
+
+static void dd_sort_state(gmx_domdec_t *dd,int ePBC,
+                          rvec *cgcm,t_forcerec *fr,t_state *state,
+                          int ncg_home_old)
+{
+    gmx_domdec_sort_t *sort;
+    gmx_cgsort_t *cgsort,*sort_i;
+    int  ncg_new,nsort2,nsort_new,i,cell_index,*ibuf,cgsize;
+    rvec *vbuf;
+    
+    sort = dd->comm->sort;
+    
+    if (dd->ncg_home > sort->sort_nalloc)
+    {
+        sort->sort_nalloc = over_alloc_dd(dd->ncg_home);
+        srenew(sort->sort1,sort->sort_nalloc);
+        srenew(sort->sort2,sort->sort_nalloc);
+    }
+    
+    if (ncg_home_old >= 0)
+    {
+        /* The charge groups that remained in the same ns grid cell
+         * are completely ordered. So we can sort efficiently by sorting
+         * the charge groups that did move into the stationary list.
+         */
+        ncg_new = 0;
+        nsort2 = 0;
+        nsort_new = 0;
+        for(i=0; i<dd->ncg_home; i++)
+        {
+            /* Check if this cg did not move to another node */
+            cell_index = fr->ns.grid->cell_index[i];
+            if (cell_index !=  4*fr->ns.grid->ncells)
+            {
+                if (i >= ncg_home_old || cell_index != sort->sort1[i].nsc)
+                {
+                    /* This cg is new on this node or moved ns grid cell */
+                    if (nsort_new >= sort->sort_new_nalloc)
+                    {
+                        sort->sort_new_nalloc = over_alloc_dd(nsort_new+1);
+                        srenew(sort->sort_new,sort->sort_new_nalloc);
+                    }
+                    sort_i = &(sort->sort_new[nsort_new++]);
+                }
+                else
+                {
+                    /* This cg did not move */
+                    sort_i = &(sort->sort2[nsort2++]);
+                }
+                /* Sort on the ns grid cell indices
+                 * and the global topology index
+                 */
+                sort_i->nsc    = cell_index;
+                sort_i->ind_gl = dd->index_gl[i];
+                sort_i->ind    = i;
+                ncg_new++;
+            }
+        }
+        if (debug)
+        {
+            fprintf(debug,"ordered sort cgs: stationary %d moved %d\n",
+                    nsort2,nsort_new);
+        }
+        /* Sort efficiently */
+        ordered_sort(nsort2,sort->sort2,nsort_new,sort->sort_new,sort->sort1);
+    }
+    else
+    {
+        cgsort = sort->sort1;
+        ncg_new = 0;
+        for(i=0; i<dd->ncg_home; i++)
+        {
+            /* Sort on the ns grid cell indices
+             * and the global topology index
+             */
+            cgsort[i].nsc    = fr->ns.grid->cell_index[i];
+            cgsort[i].ind_gl = dd->index_gl[i];
+            cgsort[i].ind    = i;
+            if (cgsort[i].nsc != 4*fr->ns.grid->ncells)
+            {
+                ncg_new++;
+            }
+        }
+        if (debug)
+        {
+            fprintf(debug,"qsort cgs: %d new home %d\n",dd->ncg_home,ncg_new);
+        }
+        /* Determine the order of the charge groups using qsort */
+        qsort_threadsafe(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
+    }
+    cgsort = sort->sort1;
+    
+    /* We alloc with the old size, since cgindex is still old */
+    vec_rvec_check_alloc(&dd->comm->vbuf,dd->cgindex[dd->ncg_home]);
+    vbuf = dd->comm->vbuf.v;
+    
+    /* Remove the charge groups which are no longer at home here */
+    dd->ncg_home = ncg_new;
+    
+    /* Reorder the state */
+    for(i=0; i<estNR; i++)
+    {
+        if (EST_DISTR(i) && (state->flags & (1<<i)))
+        {
+            switch (i)
+            {
+            case estX:
+                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->x,vbuf);
+                break;
+            case estV:
+                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->v,vbuf);
+                break;
+            case estSDX:
+                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->sd_X,vbuf);
+                break;
+            case estCGP:
+                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->cg_p,vbuf);
+                break;
+            case estLD_RNG:
+            case estLD_RNGI:
+            case estDISRE_INITF:
+            case estDISRE_RM3TAV:
+            case estORIRE_INITF:
+            case estORIRE_DTAV:
+                /* No ordering required */
+                break;
+            default:
+                gmx_incons("Unknown state entry encountered in dd_sort_state");
+                break;
+            }
+        }
+    }
+    /* Reorder cgcm */
+    order_vec_cg(dd->ncg_home,cgsort,cgcm,vbuf);
+    
+    if (dd->ncg_home+1 > sort->ibuf_nalloc)
+    {
+        sort->ibuf_nalloc = over_alloc_dd(dd->ncg_home+1);
+        srenew(sort->ibuf,sort->ibuf_nalloc);
+    }
+    ibuf = sort->ibuf;
+    /* Reorder the global cg index */
+    order_int_cg(dd->ncg_home,cgsort,dd->index_gl,ibuf);
+    /* Reorder the cginfo */
+    order_int_cg(dd->ncg_home,cgsort,fr->cginfo,ibuf);
+    /* Rebuild the local cg index */
+    ibuf[0] = 0;
+    for(i=0; i<dd->ncg_home; i++)
+    {
+        cgsize = dd->cgindex[cgsort[i].ind+1] - dd->cgindex[cgsort[i].ind];
+        ibuf[i+1] = ibuf[i] + cgsize;
+    }
+    for(i=0; i<dd->ncg_home+1; i++)
+    {
+        dd->cgindex[i] = ibuf[i];
+    }
+    /* Set the home atom number */
+    dd->nat_home = dd->cgindex[dd->ncg_home];
+    
+    /* Copy the sorted ns cell indices back to the ns grid struct */
+    for(i=0; i<dd->ncg_home; i++)
+    {
+        fr->ns.grid->cell_index[i] = cgsort[i].nsc;
+    }
+    fr->ns.grid->nr = dd->ncg_home;
+}
+
+static void add_dd_statistics(gmx_domdec_t *dd)
+{
+    gmx_domdec_comm_t *comm;
+    int ddnat;
+    
+    comm = dd->comm;
+    
+    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
+    {
+        comm->sum_nat[ddnat-ddnatZONE] +=
+            comm->nat[ddnat] - comm->nat[ddnat-1];
+    }
+    comm->ndecomp++;
+}
+
+void reset_dd_statistics_counters(gmx_domdec_t *dd)
+{
+    gmx_domdec_comm_t *comm;
+    int ddnat;
+    
+    comm = dd->comm;
+
+    /* Reset all the statistics and counters for total run counting */
+    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
+    {
+        comm->sum_nat[ddnat-ddnatZONE] = 0;
+    }
+    comm->ndecomp = 0;
+    comm->nload = 0;
+    comm->load_step = 0;
+    comm->load_sum = 0;
+    comm->load_max = 0;
+    clear_ivec(comm->load_lim);
+    comm->load_mdf = 0;
+    comm->load_pme = 0;
+}
+
+void print_dd_statistics(t_commrec *cr,t_inputrec *ir,FILE *fplog)
+{
+    gmx_domdec_comm_t *comm;
+    int ddnat;
+    double av;
+   
+    comm = cr->dd->comm;
+    
+    gmx_sumd(ddnatNR-ddnatZONE,comm->sum_nat,cr);
+    
+    if (fplog == NULL)
+    {
+        return;
+    }
+    
+    fprintf(fplog,"\n    D O M A I N   D E C O M P O S I T I O N   S T A T I S T I C S\n\n");
+            
+    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
+    {
+        av = comm->sum_nat[ddnat-ddnatZONE]/comm->ndecomp;
+        switch(ddnat)
+        {
+        case ddnatZONE:
+            fprintf(fplog,
+                    " av. #atoms communicated per step for force:  %d x %.1f\n",
+                    2,av);
+            break;
+        case ddnatVSITE:
+            if (cr->dd->vsite_comm)
+            {
+                fprintf(fplog,
+                        " av. #atoms communicated per step for vsites: %d x %.1f\n",
+                        (EEL_PME(ir->coulombtype) || ir->coulombtype==eelEWALD) ? 3 : 2,
+                        av);
+            }
+            break;
+        case ddnatCON:
+            if (cr->dd->constraint_comm)
+            {
+                fprintf(fplog,
+                        " av. #atoms communicated per step for LINCS:  %d x %.1f\n",
+                        1 + ir->nLincsIter,av);
+            }
+            break;
+        default:
+            gmx_incons(" Unknown type for DD statistics");
+        }
+    }
+    fprintf(fplog,"\n");
+    
+    if (comm->bRecordLoad && EI_DYNAMICS(ir->eI))
+    {
+        print_dd_load_av(fplog,cr->dd);
+    }
+}
+
+void dd_partition_system(FILE            *fplog,
+                         gmx_large_int_t      step,
+                         t_commrec       *cr,
+                         gmx_bool            bMasterState,
+                         int             nstglobalcomm,
+                         t_state         *state_global,
+                         gmx_mtop_t      *top_global,
+                         t_inputrec      *ir,
+                         t_state         *state_local,
+                         rvec            **f,
+                         t_mdatoms       *mdatoms,
+                         gmx_localtop_t  *top_local,
+                         t_forcerec      *fr,
+                         gmx_vsite_t     *vsite,
+                         gmx_shellfc_t   shellfc,
+                         gmx_constr_t    constr,
+                         t_nrnb          *nrnb,
+                         gmx_wallcycle_t wcycle,
+                         gmx_bool            bVerbose)
+{
+    gmx_domdec_t *dd;
+    gmx_domdec_comm_t *comm;
+    gmx_ddbox_t ddbox={0};
+    t_block *cgs_gl;
+    gmx_large_int_t step_pcoupl;
+    rvec cell_ns_x0,cell_ns_x1;
+    int  i,j,n,cg0=0,ncg_home_old=-1,nat_f_novirsum;
+    gmx_bool bBoxChanged,bNStGlobalComm,bDoDLB,bCheckDLB,bTurnOnDLB,bLogLoad;
+    gmx_bool bRedist,bSortCG,bResortAll;
+    ivec ncells_old,np;
+    real grid_density;
+    char sbuf[22];
+       
+    dd = cr->dd;
+    comm = dd->comm;
+
+    bBoxChanged = (bMasterState || DEFORM(*ir));
+    if (ir->epc != epcNO)
+    {
+        /* With nstpcouple > 1 pressure coupling happens.
+         * one step after calculating the pressure.
+         * Box scaling happens at the end of the MD step,
+         * after the DD partitioning.
+         * We therefore have to do DLB in the first partitioning
+         * after an MD step where P-coupling occured.
+         * We need to determine the last step in which p-coupling occurred.
+         * MRS -- need to validate this for vv?
+         */
+        n = ir->nstpcouple;
+        if (n == 1)
+        {
+            step_pcoupl = step - 1;
+        }
+        else
+        {
+            step_pcoupl = ((step - 1)/n)*n + 1;
+        }
+        if (step_pcoupl >= comm->globalcomm_step)
+        {
+            bBoxChanged = TRUE;
+        }
+    }
+
+    bNStGlobalComm = (step >= comm->globalcomm_step + nstglobalcomm);
+
+    if (!comm->bDynLoadBal)
+    {
+        bDoDLB = FALSE;
+    }
+    else
+    {
+        /* Should we do dynamic load balacing this step?
+         * Since it requires (possibly expensive) global communication,
+         * we might want to do DLB less frequently.
+         */
+        if (bBoxChanged || ir->epc != epcNO)
+        {
+            bDoDLB = bBoxChanged;
+        }
+        else
+        {
+            bDoDLB = bNStGlobalComm;
+        }
+    }
+
+    /* Check if we have recorded loads on the nodes */
+    if (comm->bRecordLoad && dd_load_count(comm))
+    {
+        if (comm->eDLB == edlbAUTO && !comm->bDynLoadBal)
+        {
+            /* Check if we should use DLB at the second partitioning
+             * and every 100 partitionings,
+             * so the extra communication cost is negligible.
+             */
+            n = max(100,nstglobalcomm);
+            bCheckDLB = (comm->n_load_collect == 0 ||
+                         comm->n_load_have % n == n-1);
+        }
+        else
+        {
+            bCheckDLB = FALSE;
+        }
+        
+        /* Print load every nstlog, first and last step to the log file */
+        bLogLoad = ((ir->nstlog > 0 && step % ir->nstlog == 0) ||
+                    comm->n_load_collect == 0 ||
+                    (ir->nsteps >= 0 &&
+                     (step + ir->nstlist > ir->init_step + ir->nsteps)));
+
+        /* Avoid extra communication due to verbose screen output
+         * when nstglobalcomm is set.
+         */
+        if (bDoDLB || bLogLoad || bCheckDLB ||
+            (bVerbose && (ir->nstlist == 0 || nstglobalcomm <= ir->nstlist)))
+        {
+            get_load_distribution(dd,wcycle);
+            if (DDMASTER(dd))
+            {
+                if (bLogLoad)
+                {
+                    dd_print_load(fplog,dd,step-1);
+                }
+                if (bVerbose)
+                {
+                    dd_print_load_verbose(dd);
+                }
+            }
+            comm->n_load_collect++;
+
+            if (bCheckDLB) {
+                /* Since the timings are node dependent, the master decides */
+                if (DDMASTER(dd))
+                {
+                    bTurnOnDLB =
+                        (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS);
+                    if (debug)
+                    {
+                        fprintf(debug,"step %s, imb loss %f\n",
+                                gmx_step_str(step,sbuf),
+                                dd_force_imb_perf_loss(dd));
+                    }
+                }
+                dd_bcast(dd,sizeof(bTurnOnDLB),&bTurnOnDLB);
+                if (bTurnOnDLB)
+                {
+                    turn_on_dlb(fplog,cr,step);
+                    bDoDLB = TRUE;
+                }
+            }
+        }
+        comm->n_load_have++;
+    }
+
+    cgs_gl = &comm->cgs_gl;
+
+    bRedist = FALSE;
+    if (bMasterState)
+    {
+        /* Clear the old state */
+        clear_dd_indices(dd,0,0);
+
+        set_ddbox(dd,bMasterState,cr,ir,state_global->box,
+                  TRUE,cgs_gl,state_global->x,&ddbox);
+    
+        get_cg_distribution(fplog,step,dd,cgs_gl,
+                            state_global->box,&ddbox,state_global->x);
+        
+        dd_distribute_state(dd,cgs_gl,
+                            state_global,state_local,f);
+        
+        dd_make_local_cgs(dd,&top_local->cgs);
+        
+        if (dd->ncg_home > fr->cg_nalloc)
+        {
+            dd_realloc_fr_cg(fr,dd->ncg_home);
+        }
+        calc_cgcm(fplog,0,dd->ncg_home,
+                  &top_local->cgs,state_local->x,fr->cg_cm);
+        
+        inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
+        
+        dd_set_cginfo(dd->index_gl,0,dd->ncg_home,fr,comm->bLocalCG);
+
+        cg0 = 0;
+    }
+    else if (state_local->ddp_count != dd->ddp_count)
+    {
+        if (state_local->ddp_count > dd->ddp_count)
+        {
+            gmx_fatal(FARGS,"Internal inconsistency state_local->ddp_count (%d) > dd->ddp_count (%d)",state_local->ddp_count,dd->ddp_count);
+        }
+        
+        if (state_local->ddp_count_cg_gl != state_local->ddp_count)
+        {
+            gmx_fatal(FARGS,"Internal inconsistency state_local->ddp_count_cg_gl (%d) != state_local->ddp_count (%d)",state_local->ddp_count_cg_gl,state_local->ddp_count);
+        }
+        
+        /* Clear the old state */
+        clear_dd_indices(dd,0,0);
+        
+        /* Build the new indices */
+        rebuild_cgindex(dd,cgs_gl->index,state_local);
+        make_dd_indices(dd,cgs_gl->index,0);
+        
+        /* Redetermine the cg COMs */
+        calc_cgcm(fplog,0,dd->ncg_home,
+                  &top_local->cgs,state_local->x,fr->cg_cm);
+        
+        inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
+
+        dd_set_cginfo(dd->index_gl,0,dd->ncg_home,fr,comm->bLocalCG);
+
+        set_ddbox(dd,bMasterState,cr,ir,state_local->box,
+                  TRUE,&top_local->cgs,state_local->x,&ddbox);
+
+        bRedist = comm->bDynLoadBal;
+    }
+    else
+    {
+        /* We have the full state, only redistribute the cgs */
+
+        /* Clear the non-home indices */
+        clear_dd_indices(dd,dd->ncg_home,dd->nat_home);
+
+        /* Avoid global communication for dim's without pbc and -gcom */
+        if (!bNStGlobalComm)
+        {
+            copy_rvec(comm->box0    ,ddbox.box0    );
+            copy_rvec(comm->box_size,ddbox.box_size);
+        }
+        set_ddbox(dd,bMasterState,cr,ir,state_local->box,
+                  bNStGlobalComm,&top_local->cgs,state_local->x,&ddbox);
+
+        bBoxChanged = TRUE;
+        bRedist = TRUE;
+    }
+    /* For dim's without pbc and -gcom */
+    copy_rvec(ddbox.box0    ,comm->box0    );
+    copy_rvec(ddbox.box_size,comm->box_size);
+    
+    set_dd_cell_sizes(dd,&ddbox,dynamic_dd_box(&ddbox,ir),bMasterState,bDoDLB,
+                      step,wcycle);
+    
+    if (comm->nstDDDumpGrid > 0 && step % comm->nstDDDumpGrid == 0)
+    {
+        write_dd_grid_pdb("dd_grid",step,dd,state_local->box,&ddbox);
+    }
+    
+    /* Check if we should sort the charge groups */
+    if (comm->nstSortCG > 0)
+    {
+        bSortCG = (bMasterState ||
+                   (bRedist && (step % comm->nstSortCG == 0)));
+    }
+    else
+    {
+        bSortCG = FALSE;
+    }
+
+    ncg_home_old = dd->ncg_home;
+
+    if (bRedist)
+    {
+        cg0 = dd_redistribute_cg(fplog,step,dd,ddbox.tric_dir,
+                                 state_local,f,fr,mdatoms,
+                                 !bSortCG,nrnb);
+    }
+    
+    get_nsgrid_boundaries(fr->ns.grid,dd,
+                          state_local->box,&ddbox,&comm->cell_x0,&comm->cell_x1,
+                          dd->ncg_home,fr->cg_cm,
+                          cell_ns_x0,cell_ns_x1,&grid_density);
+
+    if (bBoxChanged)
+    {
+        comm_dd_ns_cell_sizes(dd,&ddbox,cell_ns_x0,cell_ns_x1,step);
+    }
+
+    copy_ivec(fr->ns.grid->n,ncells_old);
+    grid_first(fplog,fr->ns.grid,dd,&ddbox,fr->ePBC,
+               state_local->box,cell_ns_x0,cell_ns_x1,
+               fr->rlistlong,grid_density);
+    /* We need to store tric_dir for dd_get_ns_ranges called from ns.c */
+    copy_ivec(ddbox.tric_dir,comm->tric_dir);
+
+    if (bSortCG)
+    {
+        /* Sort the state on charge group position.
+         * This enables exact restarts from this step.
+         * It also improves performance by about 15% with larger numbers
+         * of atoms per node.
+         */
+        
+        /* Fill the ns grid with the home cell,
+         * so we can sort with the indices.
+         */
+        set_zones_ncg_home(dd);
+        fill_grid(fplog,&comm->zones,fr->ns.grid,dd->ncg_home,
+                  0,dd->ncg_home,fr->cg_cm);
+        
+        /* Check if we can user the old order and ns grid cell indices
+         * of the charge groups to sort the charge groups efficiently.
+         */
+        bResortAll = (bMasterState ||
+                      fr->ns.grid->n[XX] != ncells_old[XX] ||
+                      fr->ns.grid->n[YY] != ncells_old[YY] ||
+                      fr->ns.grid->n[ZZ] != ncells_old[ZZ]);
+
+        if (debug)
+        {
+            fprintf(debug,"Step %s, sorting the %d home charge groups\n",
+                    gmx_step_str(step,sbuf),dd->ncg_home);
+        }
+        dd_sort_state(dd,ir->ePBC,fr->cg_cm,fr,state_local,
+                      bResortAll ? -1 : ncg_home_old);
+        /* Rebuild all the indices */
+        cg0 = 0;
+        ga2la_clear(dd->ga2la);
+    }
+    
+    /* Setup up the communication and communicate the coordinates */
+    setup_dd_communication(dd,state_local->box,&ddbox,fr);
+    
+    /* Set the indices */
+    make_dd_indices(dd,cgs_gl->index,cg0);
+
+    /* Set the charge group boundaries for neighbor searching */
+    set_cg_boundaries(&comm->zones);
+    
+    /*
+    write_dd_pdb("dd_home",step,"dump",top_global,cr,
+                 -1,state_local->x,state_local->box);
+    */
+    
+    /* Extract a local topology from the global topology */
+    for(i=0; i<dd->ndim; i++)
+    {
+        np[dd->dim[i]] = comm->cd[i].np;
+    }
+    dd_make_local_top(fplog,dd,&comm->zones,dd->npbcdim,state_local->box,
+                      comm->cellsize_min,np,
+                      fr,vsite,top_global,top_local);
+    
+    /* Set up the special atom communication */
+    n = comm->nat[ddnatZONE];
+    for(i=ddnatZONE+1; i<ddnatNR; i++)
+    {
+        switch(i)
+        {
+        case ddnatVSITE:
+            if (vsite && vsite->n_intercg_vsite)
+            {
+                n = dd_make_local_vsites(dd,n,top_local->idef.il);
+            }
+            break;
+        case ddnatCON:
+            if (dd->bInterCGcons)
+            {
+                /* Only for inter-cg constraints we need special code */
+                n = dd_make_local_constraints(dd,n,top_global,
+                                              constr,ir->nProjOrder,
+                                              &top_local->idef.il[F_CONSTR]);
+            }
+            break;
+        default:
+            gmx_incons("Unknown special atom type setup");
+        }
+        comm->nat[i] = n;
+    }
+    
+    /* Make space for the extra coordinates for virtual site
+     * or constraint communication.
+     */
+    state_local->natoms = comm->nat[ddnatNR-1];
+    if (state_local->natoms > state_local->nalloc)
+    {
+        dd_realloc_state(state_local,f,state_local->natoms);
+    }
+
+    if (fr->bF_NoVirSum)
+    {
+        if (vsite && vsite->n_intercg_vsite)
+        {
+            nat_f_novirsum = comm->nat[ddnatVSITE];
+        }
+        else
+        {
+            if (EEL_FULL(ir->coulombtype) && dd->n_intercg_excl > 0)
+            {
+                nat_f_novirsum = dd->nat_tot;
+            }
+            else
+            {
+                nat_f_novirsum = dd->nat_home;
+            }
+        }
+    }
+    else
+    {
+        nat_f_novirsum = 0;
+    }
+
+    /* Set the number of atoms required for the force calculation.
+     * Forces need to be constrained when using a twin-range setup
+     * or with energy minimization. For simple simulations we could
+     * avoid some allocation, zeroing and copying, but this is
+     * probably not worth the complications ande checking.
+     */
+    forcerec_set_ranges(fr,dd->ncg_home,dd->ncg_tot,
+                        dd->nat_tot,comm->nat[ddnatCON],nat_f_novirsum);
+
+    /* We make the all mdatoms up to nat_tot_con.
+     * We could save some work by only setting invmass
+     * between nat_tot and nat_tot_con.
+     */
+    /* This call also sets the new number of home particles to dd->nat_home */
+    atoms2md(top_global,ir,
+             comm->nat[ddnatCON],dd->gatindex,0,dd->nat_home,mdatoms);
+
+    /* Now we have the charges we can sort the FE interactions */
+    dd_sort_local_top(dd,mdatoms,top_local);
+
+    if (shellfc)
+    {
+        /* Make the local shell stuff, currently no communication is done */
+        make_local_shells(cr,mdatoms,shellfc);
+    }
+    
+       if (ir->implicit_solvent)
+    {
+        make_local_gb(cr,fr->born,ir->gb_algorithm);
+    }
+       
+    if (!(cr->duty & DUTY_PME))
+    {
+        /* Send the charges to our PME only node */
+        gmx_pme_send_q(cr,mdatoms->nChargePerturbed,
+                       mdatoms->chargeA,mdatoms->chargeB,
+                       dd_pme_maxshift_x(dd),dd_pme_maxshift_y(dd));
+    }
+    
+    if (constr)
+    {
+        set_constraints(constr,top_local,ir,mdatoms,cr);
+    }
+    
+    if (ir->ePull != epullNO)
+    {
+        /* Update the local pull groups */
+        dd_make_local_pull_groups(dd,ir->pull,mdatoms);
+    }
+    
+    if (ir->bRot)
+    {
+        /* Update the local rotation groups */
+        dd_make_local_rotation_groups(dd,ir->rot);
+    }
+
+
+    add_dd_statistics(dd);
+    
+    /* Make sure we only count the cycles for this DD partitioning */
+    clear_dd_cycle_counts(dd);
+    
+    /* Because the order of the atoms might have changed since
+     * the last vsite construction, we need to communicate the constructing
+     * atom coordinates again (for spreading the forces this MD step).
+     */
+    dd_move_x_vsites(dd,state_local->box,state_local->x);
+    
+    if (comm->nstDDDump > 0 && step % comm->nstDDDump == 0)
+    {
+        dd_move_x(dd,state_local->box,state_local->x);
+        write_dd_pdb("dd_dump",step,"dump",top_global,cr,
+                     -1,state_local->x,state_local->box);
+    }
+
+    if (bNStGlobalComm)
+    {
+        /* Store the global communication step */
+        comm->globalcomm_step = step;
+    }
+    
+    /* Increase the DD partitioning counter */
+    dd->ddp_count++;
+    /* The state currently matches this DD partitioning count, store it */
+    state_local->ddp_count = dd->ddp_count;
+    if (bMasterState)
+    {
+        /* The DD master node knows the complete cg distribution,
+         * store the count so we can possibly skip the cg info communication.
+         */
+        comm->master_cg_ddp_count = (bSortCG ? 0 : dd->ddp_count);
+    }
+
+    if (comm->DD_debug > 0)
+    {
+        /* Set the env var GMX_DD_DEBUG if you suspect corrupted indices */
+        check_index_consistency(dd,top_global->natoms,ncg_mtop(top_global),
+                                "after partitioning");
+    }
+}
similarity index 100%
rename from src/mdlib/ebin.c
rename to src/gromacs/mdlib/ebin.c
diff --git a/src/gromacs/mdlib/edsam.c b/src/gromacs/mdlib/edsam.c
new file mode 100644 (file)
index 0000000..e7e168a
--- /dev/null
@@ -0,0 +1,2575 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include "typedefs.h"
+#include "string2.h"
+#include "smalloc.h"
+#include "names.h"
+#include "confio.h"
+#include "mvdata.h"
+#include "txtdump.h"
+#include "vec.h"
+#include "time.h"
+#include "nrnb.h"
+#include "mshift.h"
+#include "mdrun.h"
+#include "update.h"
+#include "physics.h"
+#include "nrjac.h"
+#include "mtop_util.h"
+#include "edsam.h"
+#include "gmxfio.h"
+#include "groupcoord.h"
+
+
+/* We use the same defines as in mvdata.c here */
+#define  block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
+#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
+#define   snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
+
+
+/* enum to identify the type of ED: none, normal ED, flooding */
+enum {eEDnone, eEDedsam, eEDflood, eEDnr};
+
+/* enum to identify operations on reference, average, origin, target structures */
+enum {eedREF, eedAV, eedORI, eedTAR, eedNR};
+
+
+typedef struct
+{
+    int    neig;     /* nr of eigenvectors             */
+    int   *ieig;     /* index nrs of eigenvectors      */
+    real  *stpsz;    /* stepsizes (per eigenvector)    */
+    rvec  **vec;     /* eigenvector components         */
+    real  *xproj;    /* instantaneous x projections    */
+    real  *fproj;    /* instantaneous f projections    */
+    real  radius;    /* instantaneous radius           */
+    real  *refproj;  /* starting or target projecions  */
+    /* When using flooding as harmonic restraint: The current reference projection
+     * is at each step calculated from the initial refproj0 and the slope. */
+    real  *refproj0,*refprojslope;
+} t_eigvec;
+
+
+typedef struct
+{
+    t_eigvec      mon;            /* only monitored, no constraints       */
+    t_eigvec      linfix;         /* fixed linear constraints             */
+    t_eigvec      linacc;         /* acceptance linear constraints        */
+    t_eigvec      radfix;         /* fixed radial constraints (exp)       */
+    t_eigvec      radacc;         /* acceptance radial constraints (exp)  */
+    t_eigvec      radcon;         /* acceptance rad. contraction constr.  */
+} t_edvecs;
+
+
+typedef struct
+{
+    real deltaF0;
+    gmx_bool bHarmonic;           /* Use flooding for harmonic restraint on
+                                     the eigenvector                          */
+    gmx_bool bConstForce;         /* Do not calculate a flooding potential,
+                                     instead flood with a constant force      */
+    real tau;
+    real deltaF;
+    real Efl;
+    real kT;
+    real Vfl;
+    real dt;
+    real constEfl;
+    real alpha2;
+    int flood_id;
+    rvec *forces_cartesian;
+    t_eigvec vecs;         /* use flooding for these */
+} t_edflood;
+
+
+/* This type is for the average, reference, target, and origin structure    */
+typedef struct gmx_edx
+{
+    int           nr;             /* number of atoms this structure contains  */
+    int           nr_loc;         /* number of atoms on local node            */
+    int           *anrs;          /* atom index numbers                       */
+    int           *anrs_loc;      /* local atom index numbers                 */
+    int           nalloc_loc;     /* allocation size of anrs_loc              */
+    int           *c_ind;         /* at which position of the whole anrs
+                                   * array is a local atom?, i.e.
+                                   * c_ind[0...nr_loc-1] gives the atom index
+                                   * with respect to the collective
+                                   * anrs[0...nr-1] array                     */
+    rvec          *x;             /* positions for this structure             */
+    rvec          *x_old;         /* used to keep track of the shift vectors
+                                     such that the ED molecule can always be
+                                     made whole in the parallel case          */
+    real          *m;             /* masses                                   */
+    real          mtot;           /* total mass (only used in sref)           */
+    real          *sqrtm;         /* sqrt of the masses used for mass-
+                                   * weighting of analysis (only used in sav) */
+} t_gmx_edx;
+
+
+typedef struct edpar
+{
+    int            nini;           /* total Nr of atoms                    */
+    gmx_bool       fitmas;         /* true if trans fit with cm            */
+    gmx_bool       pcamas;         /* true if mass-weighted PCA            */
+    int            presteps;       /* number of steps to run without any
+                                    *    perturbations ... just monitoring */
+    int            outfrq;         /* freq (in steps) of writing to edo    */
+    int            maxedsteps;     /* max nr of steps per cycle            */
+
+    /* all gmx_edx datasets are copied to all nodes in the parallel case   */
+    struct gmx_edx sref;           /* reference positions, to these fitting
+                                    * will be done                         */
+    gmx_bool       bRefEqAv;       /* If true, reference & average indices
+                                    * are the same. Used for optimization  */
+    struct gmx_edx sav;            /* average positions                    */
+    struct gmx_edx star;           /* target positions                     */
+    struct gmx_edx sori;           /* origin positions                     */
+
+    t_edvecs       vecs;           /* eigenvectors                         */
+    real           slope;          /* minimal slope in acceptance radexp   */
+
+    gmx_bool       bNeedDoEdsam;   /* if any of the options mon, linfix, ...
+                                    * is used (i.e. apart from flooding)   */
+    t_edflood      flood;          /* parameters especially for flooding   */
+    struct t_ed_buffer *buf;       /* handle to local buffers              */
+    struct edpar   *next_edi;      /* Pointer to another ed dataset        */
+} t_edpar;
+
+
+typedef struct gmx_edsam
+{
+    int           eEDtype;        /* Type of ED: see enums above          */
+    const char    *edinam;        /* name of ED sampling input file       */
+    const char    *edonam;        /*                     output           */
+    FILE          *edo;           /* output file pointer                  */
+    t_edpar       *edpar;
+    gmx_bool      bFirst;
+    gmx_bool      bStartFromCpt;
+} t_gmx_edsam;
+
+
+struct t_do_edsam
+{
+    matrix old_rotmat;
+    real oldrad;
+    rvec old_transvec,older_transvec,transvec_compact;
+    rvec *xcoll;         /* Positions from all nodes, this is the
+                            collective set we work on.
+                            These are the positions of atoms with
+                            average structure indices */
+    rvec *xc_ref;        /* same but with reference structure indices */
+    ivec *shifts_xcoll;        /* Shifts for xcoll  */
+    ivec *extra_shifts_xcoll;  /* xcoll shift changes since last NS step */
+    ivec *shifts_xc_ref;       /* Shifts for xc_ref */
+    ivec *extra_shifts_xc_ref; /* xc_ref shift changes since last NS step */
+    gmx_bool bUpdateShifts;    /* TRUE in NS steps to indicate that the
+                                  ED shifts for this ED dataset need to
+                                  be updated */
+};
+
+
+/* definition of ED buffer structure */
+struct t_ed_buffer
+{
+    struct t_fit_to_ref *           fit_to_ref;
+    struct t_do_edfit *             do_edfit;
+    struct t_do_edsam *             do_edsam;
+    struct t_do_radcon *            do_radcon;
+};
+
+
+/* Function declarations */
+static void fit_to_reference(rvec *xcoll,rvec transvec,matrix rotmat,t_edpar *edi);
+
+static void translate_and_rotate(rvec *x,int nat,rvec transvec,matrix rotmat);
+/* End function declarations */
+
+
+/* Does not subtract average positions, projection on single eigenvector is returned
+ * used by: do_linfix, do_linacc, do_radfix, do_radacc, do_radcon
+ * Average position is subtracted in ed_apply_constraints prior to calling projectx
+ */
+static real projectx(t_edpar *edi, rvec *xcoll, rvec *vec)
+{
+    int  i;
+    real proj=0.0;
+
+
+    for (i=0; i<edi->sav.nr; i++)
+        proj += edi->sav.sqrtm[i]*iprod(vec[i], xcoll[i]);
+
+    return proj;
+}
+
+
+/* Specialized: projection is stored in vec->refproj
+ * -> used for radacc, radfix, radcon  and center of flooding potential
+ * subtracts average positions, projects vector x */
+static void rad_project(t_edpar *edi, rvec *x, t_eigvec *vec, t_commrec *cr)
+{
+    int i;
+    real rad=0.0;
+
+    /* Subtract average positions */
+    for (i = 0; i < edi->sav.nr; i++)
+        rvec_dec(x[i], edi->sav.x[i]);
+
+    for (i = 0; i < vec->neig; i++)
+    {
+        vec->refproj[i] = projectx(edi,x,vec->vec[i]);
+        rad += pow((vec->refproj[i]-vec->xproj[i]),2);
+    }
+    vec->radius=sqrt(rad);
+
+    /* Add average positions */
+    for (i = 0; i < edi->sav.nr; i++)
+        rvec_inc(x[i], edi->sav.x[i]);
+}
+
+
+/* Project vector x, subtract average positions prior to projection and add
+ * them afterwards to retain the unchanged vector. Store in xproj. Mass-weighting
+ * is applied. */
+static void project_to_eigvectors(rvec       *x,    /* The positions to project to an eigenvector */
+                                  t_eigvec   *vec,  /* The eigenvectors */
+                                  t_edpar    *edi)
+{
+    int  i;
+
+
+    if (!vec->neig) return;
+
+    /* Subtract average positions */
+    for (i=0; i<edi->sav.nr; i++)
+        rvec_dec(x[i], edi->sav.x[i]);
+
+    for (i=0; i<vec->neig; i++)
+        vec->xproj[i] = projectx(edi, x, vec->vec[i]);
+
+    /* Add average positions */
+    for (i=0; i<edi->sav.nr; i++)
+        rvec_inc(x[i], edi->sav.x[i]);
+}
+
+
+/* Project vector x onto all edi->vecs (mon, linfix,...) */
+static void project(rvec      *x,     /* positions to project */
+                    t_edpar   *edi)   /* edi data set */
+{
+    /* It is not more work to subtract the average position in every
+     * subroutine again, because these routines are rarely used simultanely */
+    project_to_eigvectors(x, &edi->vecs.mon   , edi);
+    project_to_eigvectors(x, &edi->vecs.linfix, edi);
+    project_to_eigvectors(x, &edi->vecs.linacc, edi);
+    project_to_eigvectors(x, &edi->vecs.radfix, edi);
+    project_to_eigvectors(x, &edi->vecs.radacc, edi);
+    project_to_eigvectors(x, &edi->vecs.radcon, edi);
+}
+
+
+static real calc_radius(t_eigvec *vec)
+{
+    int i;
+    real rad=0.0;
+
+
+    for (i=0; i<vec->neig; i++)
+        rad += pow((vec->refproj[i]-vec->xproj[i]),2);
+
+    return rad=sqrt(rad);
+}
+
+
+/* Debug helper */
+#ifdef DEBUGHELPERS
+static void dump_xcoll(t_edpar *edi, struct t_do_edsam *buf, t_commrec *cr,
+                       int step)
+{
+    int i;
+    FILE *fp;
+    char fn[STRLEN];
+    rvec *xcoll;
+    ivec *shifts, *eshifts;
+
+
+    if (!MASTER(cr))
+        return;
+
+    xcoll   = buf->xcoll;
+    shifts  = buf->shifts_xcoll;
+    eshifts = buf->extra_shifts_xcoll;
+
+    sprintf(fn, "xcolldump_step%d.txt", step);
+    fp = fopen(fn, "w");
+
+    for (i=0; i<edi->sav.nr; i++)
+        fprintf(fp, "%d %9.5f %9.5f %9.5f   %d %d %d   %d %d %d\n",
+                edi->sav.anrs[i]+1,
+                xcoll[i][XX]  , xcoll[i][YY]  , xcoll[i][ZZ],
+                shifts[i][XX] , shifts[i][YY] , shifts[i][ZZ],
+                eshifts[i][XX], eshifts[i][YY], eshifts[i][ZZ]);
+
+    fclose(fp);
+}
+
+
+/* Debug helper */
+static void dump_edi_positions(FILE *out, struct gmx_edx *s, const char name[])
+{
+    int i;
+
+
+    fprintf(out, "#%s positions:\n%d\n", name, s->nr);
+    if (s->nr == 0)
+        return;
+
+    fprintf(out, "#index, x, y, z");
+    if (s->sqrtm)
+        fprintf(out, ", sqrt(m)");
+    for (i=0; i<s->nr; i++)
+    {
+        fprintf(out, "\n%6d  %11.6f %11.6f %11.6f",s->anrs[i], s->x[i][XX], s->x[i][YY], s->x[i][ZZ]);
+        if (s->sqrtm)
+            fprintf(out,"%9.3f",s->sqrtm[i]);
+    }
+    fprintf(out, "\n");
+}
+
+
+/* Debug helper */
+static void dump_edi_eigenvecs(FILE *out, t_eigvec *ev,
+                               const char name[], int length)
+{
+    int i,j;
+
+
+    fprintf(out, "#%s eigenvectors:\n%d\n", name, ev->neig);
+    /* Dump the data for every eigenvector: */
+    for (i=0; i<ev->neig; i++)
+    {
+        fprintf(out, "EV %4d\ncomponents %d\nstepsize %f\nxproj %f\nfproj %f\nrefproj %f\nradius %f\nComponents:\n",
+                ev->ieig[i], length, ev->stpsz[i], ev->xproj[i], ev->fproj[i], ev->refproj[i], ev->radius);
+        for (j=0; j<length; j++)
+            fprintf(out, "%11.6f %11.6f %11.6f\n", ev->vec[i][j][XX], ev->vec[i][j][YY], ev->vec[i][j][ZZ]);
+    }
+}
+
+
+/* Debug helper */
+static void dump_edi(t_edpar *edpars, t_commrec *cr, int nr_edi)
+{
+    FILE  *out;
+    char  fn[STRLEN];
+
+
+    sprintf(fn, "EDdump_node%d_edi%d", cr->nodeid, nr_edi);
+    out = ffopen(fn, "w");
+
+    fprintf(out,"#NINI\n %d\n#FITMAS\n %d\n#ANALYSIS_MAS\n %d\n",
+            edpars->nini,edpars->fitmas,edpars->pcamas);
+    fprintf(out,"#OUTFRQ\n %d\n#MAXLEN\n %d\n#SLOPECRIT\n %f\n",
+            edpars->outfrq,edpars->maxedsteps,edpars->slope);
+    fprintf(out,"#PRESTEPS\n %d\n#DELTA_F0\n %f\n#TAU\n %f\n#EFL_NULL\n %f\n#ALPHA2\n %f\n",
+            edpars->presteps,edpars->flood.deltaF0,edpars->flood.tau,
+            edpars->flood.constEfl,edpars->flood.alpha2);
+
+    /* Dump reference, average, target, origin positions */
+    dump_edi_positions(out, &edpars->sref, "REFERENCE");
+    dump_edi_positions(out, &edpars->sav , "AVERAGE"  );
+    dump_edi_positions(out, &edpars->star, "TARGET"   );
+    dump_edi_positions(out, &edpars->sori, "ORIGIN"   );
+
+    /* Dump eigenvectors */
+    dump_edi_eigenvecs(out, &edpars->vecs.mon   , "MONITORED", edpars->sav.nr);
+    dump_edi_eigenvecs(out, &edpars->vecs.linfix, "LINFIX"   , edpars->sav.nr);
+    dump_edi_eigenvecs(out, &edpars->vecs.linacc, "LINACC"   , edpars->sav.nr);
+    dump_edi_eigenvecs(out, &edpars->vecs.radfix, "RADFIX"   , edpars->sav.nr);
+    dump_edi_eigenvecs(out, &edpars->vecs.radacc, "RADACC"   , edpars->sav.nr);
+    dump_edi_eigenvecs(out, &edpars->vecs.radcon, "RADCON"   , edpars->sav.nr);
+
+    /* Dump flooding eigenvectors */
+    dump_edi_eigenvecs(out, &edpars->flood.vecs, "FLOODING"  , edpars->sav.nr);
+
+    /* Dump ed local buffer */
+    fprintf(out, "buf->do_edfit         =%p\n", (void*)edpars->buf->do_edfit  );
+    fprintf(out, "buf->do_edsam         =%p\n", (void*)edpars->buf->do_edsam  );
+    fprintf(out, "buf->do_radcon        =%p\n", (void*)edpars->buf->do_radcon );
+
+    ffclose(out);
+}
+
+
+/* Debug helper */
+static void dump_rotmat(FILE* out,matrix rotmat)
+{
+    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[XX][XX],rotmat[XX][YY],rotmat[XX][ZZ]);
+    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[YY][XX],rotmat[YY][YY],rotmat[YY][ZZ]);
+    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[ZZ][XX],rotmat[ZZ][YY],rotmat[ZZ][ZZ]);
+}
+
+
+/* Debug helper */
+static void dump_rvec(FILE *out, int dim, rvec *x)
+{
+    int i;
+
+
+    for (i=0; i<dim; i++)
+        fprintf(out,"%4d   %f %f %f\n",i,x[i][XX],x[i][YY],x[i][ZZ]);
+}
+
+
+/* Debug helper */
+static void dump_mat(FILE* out, int dim, double** mat)
+{
+    int i,j;
+
+
+    fprintf(out,"MATRIX:\n");
+    for (i=0;i<dim;i++)
+    {
+        for (j=0;j<dim;j++)
+            fprintf(out,"%f ",mat[i][j]);
+        fprintf(out,"\n");
+    }
+}
+#endif
+
+
+struct t_do_edfit {
+    double **omega;
+    double **om;
+};
+
+static void do_edfit(int natoms,rvec *xp,rvec *x,matrix R,t_edpar *edi)
+{
+    /* this is a copy of do_fit with some modifications */
+    int    c,r,n,j,i,irot;
+    double d[6],xnr,xpc;
+    matrix vh,vk,u;
+    int    index;
+    real   max_d;
+
+    struct t_do_edfit *loc;
+    gmx_bool bFirst;
+
+    if(edi->buf->do_edfit != NULL)
+        bFirst = FALSE;
+    else
+    {
+        bFirst = TRUE;
+        snew(edi->buf->do_edfit,1);
+    }
+    loc = edi->buf->do_edfit;
+
+    if (bFirst)
+    {
+        snew(loc->omega,2*DIM);
+        snew(loc->om,2*DIM);
+        for(i=0; i<2*DIM; i++)
+        {
+            snew(loc->omega[i],2*DIM);
+            snew(loc->om[i],2*DIM);
+        }
+    }
+
+    for(i=0;(i<6);i++)
+    {
+        d[i]=0;
+        for(j=0;(j<6);j++)
+        {
+            loc->omega[i][j]=0;
+            loc->om[i][j]=0;
+        }
+    }
+
+    /* calculate the matrix U */
+    clear_mat(u);
+    for(n=0;(n<natoms);n++)
+    {
+        for(c=0; (c<DIM); c++)
+        {
+            xpc=xp[n][c];
+            for(r=0; (r<DIM); r++)
+            {
+                xnr=x[n][r];
+                u[c][r]+=xnr*xpc;
+            }
+        }
+    }
+
+    /* construct loc->omega */
+    /* loc->omega is symmetric -> loc->omega==loc->omega' */
+    for(r=0;(r<6);r++)
+        for(c=0;(c<=r);c++)
+            if ((r>=3) && (c<3))
+            {
+                loc->omega[r][c]=u[r-3][c];
+                loc->omega[c][r]=u[r-3][c];
+            }
+            else
+            {
+                loc->omega[r][c]=0;
+                loc->omega[c][r]=0;
+            }
+
+    /* determine h and k */
+#ifdef DEBUG
+    {
+        int i;
+        dump_mat(stderr,2*DIM,loc->omega);
+        for (i=0; i<6; i++)
+            fprintf(stderr,"d[%d] = %f\n",i,d[i]);
+    }
+#endif
+    jacobi(loc->omega,6,d,loc->om,&irot);
+
+    if (irot==0)
+        fprintf(stderr,"IROT=0\n");
+
+    index=0; /* For the compiler only */
+
+    for(j=0;(j<3);j++)
+    {
+        max_d=-1000;
+        for(i=0;(i<6);i++)
+            if (d[i]>max_d)
+            {
+                max_d=d[i];
+                index=i;
+            }
+        d[index]=-10000;
+        for(i=0;(i<3);i++)
+        {
+            vh[j][i]=M_SQRT2*loc->om[i][index];
+            vk[j][i]=M_SQRT2*loc->om[i+DIM][index];
+        }
+    }
+
+    /* determine R */
+    for(c=0;(c<3);c++)
+        for(r=0;(r<3);r++)
+            R[c][r]=vk[0][r]*vh[0][c]+
+            vk[1][r]*vh[1][c]+
+            vk[2][r]*vh[2][c];
+    if (det(R) < 0)
+        for(c=0;(c<3);c++)
+            for(r=0;(r<3);r++)
+                R[c][r]=vk[0][r]*vh[0][c]+
+                vk[1][r]*vh[1][c]-
+                vk[2][r]*vh[2][c];
+}
+
+
+static void rmfit(int nat, rvec *xcoll, rvec transvec, matrix rotmat)
+{
+    rvec vec;
+    matrix tmat;
+
+
+    /* Remove rotation.
+     * The inverse rotation is described by the transposed rotation matrix */
+    transpose(rotmat,tmat);
+    rotate_x(xcoll, nat, tmat);
+
+    /* Remove translation */
+    vec[XX]=-transvec[XX];
+    vec[YY]=-transvec[YY];
+    vec[ZZ]=-transvec[ZZ];
+    translate_x(xcoll, nat, vec);
+}
+
+
+/**********************************************************************************
+ ******************** FLOODING ****************************************************
+ **********************************************************************************
+
+The flooding ability was added later to edsam. Many of the edsam functionality could be reused for that purpose.
+The flooding covariance matrix, i.e. the selected eigenvectors and their corresponding eigenvalues are
+read as 7th Component Group. The eigenvalues are coded into the stepsize parameter (as used by -linfix or -linacc).
+
+do_md clls right in the beginning the function init_edsam, which reads the edi file, saves all the necessary information in
+the edi structure and calls init_flood, to initialise some extra fields in the edi->flood structure.
+
+since the flooding acts on forces do_flood is called from the function force() (force.c), while the other
+edsam functionality is hooked into md via the update() (update.c) function acting as constraint on positions.
+
+do_flood makes a copy of the positions,
+fits them, projects them computes flooding_energy, and flooding forces. The forces are computed in the
+space of the eigenvectors and are then blown up to the full cartesian space and rotated back to remove the
+fit. Then do_flood adds these forces to the forcefield-forces
+(given as parameter) and updates the adaptive flooding parameters Efl and deltaF.
+
+To center the flooding potential at a different location one can use the -ori option in make_edi. The ori
+structure is projected to the system of eigenvectors and then this position in the subspace is used as
+center of the flooding potential.   If the option is not used, the center will be zero in the subspace,
+i.e. the average structure as given in the make_edi file.
+
+To use the flooding potential as restraint, make_edi has the option -restrain, which leads to inverted
+signs of alpha2 and Efl, such that the sign in the exponential of Vfl is not inverted but the sign of
+Vfl is inverted. Vfl = Efl * exp (- .../Efl/alpha2*x^2...) With tau>0 the negative Efl will grow slowly
+so that the restraint is switched off slowly. When Efl==0 and inverted flooding is ON is reached no
+ further adaption is applied, Efl will stay constant at zero.
+
+To use restraints with harmonic potentials switch -restrain and -harmonic. Then the eigenvalues are
+used as spring constants for the harmonic potential.
+Note that eq3 in the flooding paper (J. Comp. Chem. 2006, 27, 1693-1702) defines the parameter lambda \
+as the inverse of the spring constant, whereas the implementation uses lambda as the spring constant.
+
+To use more than one flooding matrix just concatenate several .edi files (cat flood1.edi flood2.edi > flood_all.edi)
+the routine read_edi_file reads all of theses flooding files.
+The structure t_edi is now organized as a list of t_edis and the function do_flood cycles through the list
+calling the do_single_flood() routine for every single entry. Since every state variables have been kept in one
+edi there is no interdependence whatsoever. The forces are added together.
+
+  To write energies into the .edr file, call the function
+        get_flood_enx_names(char**, int *nnames) to get the Header (Vfl1 Vfl2... Vfln)
+and call
+        get_flood_energies(real Vfl[],int nnames);
+
+  TODO:
+- one could program the whole thing such that Efl, Vfl and deltaF is written to the .edr file. -- i dont know how to do that, yet.
+
+  Maybe one should give a range of atoms for which to remove motion, so that motion is removed with
+  two edsam files from two peptide chains
+*/
+
+static void write_edo_flood(t_edpar *edi, FILE *fp, gmx_large_int_t step)
+{
+    int i;
+    char buf[22];
+    gmx_bool bOutputRef=FALSE;
+
+
+    fprintf(fp,"%d.th FL: %s %12.5e %12.5e %12.5e\n",
+            edi->flood.flood_id, gmx_step_str(step,buf),
+            edi->flood.Efl, edi->flood.Vfl, edi->flood.deltaF);
+
+
+    /* Check whether any of the references changes with time (this can happen
+     * in case flooding is used as harmonic restraint). If so, output all the
+     * current reference projections. */
+    if (edi->flood.bHarmonic)
+    {
+        for (i = 0; i < edi->flood.vecs.neig; i++)
+        {
+            if (edi->flood.vecs.refprojslope[i] != 0.0)
+                bOutputRef=TRUE;
+        }
+        if (bOutputRef)
+        {
+            fprintf(fp, "Ref. projs.: ");
+            for (i = 0; i < edi->flood.vecs.neig; i++)
+            {
+                fprintf(fp, "%12.5e ", edi->flood.vecs.refproj[i]);
+            }
+            fprintf(fp, "\n");
+        }
+    }
+    fprintf(fp,"FL_FORCES: ");
+
+    for (i=0; i<edi->flood.vecs.neig; i++)
+        fprintf(fp," %12.5e",edi->flood.vecs.fproj[i]);
+
+    fprintf(fp,"\n");
+}
+
+
+/* From flood.xproj compute the Vfl(x) at this point */
+static real flood_energy(t_edpar *edi, gmx_large_int_t step)
+{
+    /* compute flooding energy Vfl
+     Vfl = Efl * exp( - \frac {kT} {2Efl alpha^2} * sum_i { \lambda_i c_i^2 } )
+     \lambda_i is the reciprocal eigenvalue 1/\sigma_i
+         it is already computed by make_edi and stored in stpsz[i]
+     bHarmonic:
+       Vfl = - Efl * 1/2(sum _i {\frac 1{\lambda_i} c_i^2})
+     */
+    real sum;
+    real Vfl;
+    int i;
+
+
+    /* Each time this routine is called (i.e. each time step), we add a small
+     * value to the reference projection. This way a harmonic restraint towards
+     * a moving reference is realized. If no value for the additive constant
+     * is provided in the edi file, the reference will not change. */
+    if (edi->flood.bHarmonic)
+    {
+        for (i=0; i<edi->flood.vecs.neig; i++)
+        {
+            edi->flood.vecs.refproj[i] = edi->flood.vecs.refproj0[i] + step * edi->flood.vecs.refprojslope[i];
+        }
+    }
+
+    sum=0.0;
+    /* Compute sum which will be the exponent of the exponential */
+    for (i=0; i<edi->flood.vecs.neig; i++)
+    {
+        /* stpsz stores the reciprocal eigenvalue 1/sigma_i */
+        sum += edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i])*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
+    }
+
+    /* Compute the Gauss function*/
+    if (edi->flood.bHarmonic)
+    {
+        Vfl = -0.5*edi->flood.Efl*sum;  /* minus sign because Efl is negative, if restrain is on. */
+    }
+    else
+    {
+        Vfl = edi->flood.Efl!=0 ? edi->flood.Efl*exp(-edi->flood.kT/2/edi->flood.Efl/edi->flood.alpha2*sum) :0;
+    }
+
+    return Vfl;
+}
+
+
+/* From the position and from Vfl compute forces in subspace -> store in edi->vec.flood.fproj */
+static void flood_forces(t_edpar *edi)
+{
+    /* compute the forces in the subspace of the flooding eigenvectors
+     * by the formula F_i= V_{fl}(c) * ( \frac {kT} {E_{fl}} \lambda_i c_i */
+
+    int i;
+    real energy=edi->flood.Vfl;
+
+
+    if (edi->flood.bHarmonic)
+        for (i=0; i<edi->flood.vecs.neig; i++)
+        {
+            edi->flood.vecs.fproj[i] = edi->flood.Efl* edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
+        }
+    else
+        for (i=0; i<edi->flood.vecs.neig; i++)
+        {
+            /* if Efl is zero the forces are zero if not use the formula */
+            edi->flood.vecs.fproj[i] = edi->flood.Efl!=0 ? edi->flood.kT/edi->flood.Efl/edi->flood.alpha2*energy*edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]) : 0;
+        }
+}
+
+
+/* Raise forces from subspace into cartesian space */
+static void flood_blowup(t_edpar *edi, rvec *forces_cart)
+{
+    /* this function lifts the forces from the subspace to the cartesian space
+     all the values not contained in the subspace are assumed to be zero and then
+     a coordinate transformation from eigenvector to cartesian vectors is performed
+     The nonexistent values don't have to be set to zero explicitly, they would occur
+     as zero valued summands, hence we just stop to compute this part of the sum.
+
+     for every atom we add all the contributions to this atom from all the different eigenvectors.
+
+     NOTE: one could add directly to the forcefield forces, would mean we wouldn't have to clear the
+     field forces_cart prior the computation, but we compute the forces separately
+     to have them accessible for diagnostics
+     */
+    int  j,eig;
+    rvec dum;
+    real *forces_sub;
+
+
+    forces_sub = edi->flood.vecs.fproj;
+
+
+    /* Calculate the cartesian forces for the local atoms */
+
+    /* Clear forces first */
+    for (j=0; j<edi->sav.nr_loc; j++)
+        clear_rvec(forces_cart[j]);
+
+    /* Now compute atomwise */
+    for (j=0; j<edi->sav.nr_loc; j++)
+    {
+        /* Compute forces_cart[edi->sav.anrs[j]] */
+        for (eig=0; eig<edi->flood.vecs.neig; eig++)
+        {
+            /* Force vector is force * eigenvector (compute only atom j) */
+            svmul(forces_sub[eig],edi->flood.vecs.vec[eig][edi->sav.c_ind[j]],dum);
+            /* Add this vector to the cartesian forces */
+            rvec_inc(forces_cart[j],dum);
+        }
+    }
+}
+
+
+/* Update the values of Efl, deltaF depending on tau and Vfl */
+static void update_adaption(t_edpar *edi)
+{
+    /* this function updates the parameter Efl and deltaF according to the rules given in
+     * 'predicting unimolecular chemical reactions: chemical flooding' M Mueller et al,
+     * J. chem Phys. */
+
+    if ((edi->flood.tau < 0 ? -edi->flood.tau : edi->flood.tau ) > 0.00000001)
+    {
+        edi->flood.Efl = edi->flood.Efl+edi->flood.dt/edi->flood.tau*(edi->flood.deltaF0-edi->flood.deltaF);
+        /* check if restrain (inverted flooding) -> don't let EFL become positive */
+        if (edi->flood.alpha2<0 && edi->flood.Efl>-0.00000001)
+            edi->flood.Efl = 0;
+
+        edi->flood.deltaF = (1-edi->flood.dt/edi->flood.tau)*edi->flood.deltaF+edi->flood.dt/edi->flood.tau*edi->flood.Vfl;
+    }
+}
+
+
+static void do_single_flood(
+        FILE *edo,
+        rvec x[],
+        rvec force[],
+        t_edpar *edi,
+        gmx_large_int_t step,
+        matrix box,
+        t_commrec *cr)
+{
+    int i;
+    matrix  rotmat;         /* rotation matrix */
+    matrix  tmat;           /* inverse rotation */
+    rvec    transvec;       /* translation vector */
+    struct t_do_edsam *buf;
+
+
+    buf=edi->buf->do_edsam;
+
+    /* Broadcast the positions of the AVERAGE structure such that they are known on
+     * every processor. Each node contributes its local positions x and stores them in
+     * the collective ED array buf->xcoll */
+    communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, buf->bUpdateShifts, x,
+                    edi->sav.nr, edi->sav.nr_loc, edi->sav.anrs_loc, edi->sav.c_ind, edi->sav.x_old, box);
+
+    /* Only assembly REFERENCE positions if their indices differ from the average ones */
+    if (!edi->bRefEqAv)
+        communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, buf->bUpdateShifts, x,
+                edi->sref.nr, edi->sref.nr_loc, edi->sref.anrs_loc, edi->sref.c_ind, edi->sref.x_old, box);
+
+    /* If bUpdateShifts was TRUE, the shifts have just been updated in get_positions.
+     * We do not need to update the shifts until the next NS step */
+    buf->bUpdateShifts = FALSE;
+
+    /* Now all nodes have all of the ED/flooding positions in edi->sav->xcoll,
+     * as well as the indices in edi->sav.anrs */
+
+    /* Fit the reference indices to the reference structure */
+    if (edi->bRefEqAv)
+        fit_to_reference(buf->xcoll , transvec, rotmat, edi);
+    else
+        fit_to_reference(buf->xc_ref, transvec, rotmat, edi);
+
+    /* Now apply the translation and rotation to the ED structure */
+    translate_and_rotate(buf->xcoll, edi->sav.nr, transvec, rotmat);
+
+    /* Project fitted structure onto supbspace -> store in edi->flood.vecs.xproj */
+    project_to_eigvectors(buf->xcoll,&edi->flood.vecs,edi);
+
+    if (FALSE == edi->flood.bConstForce)
+    {
+        /* Compute Vfl(x) from flood.xproj */
+        edi->flood.Vfl = flood_energy(edi, step);
+
+        update_adaption(edi);
+
+        /* Compute the flooding forces */
+        flood_forces(edi);
+    }
+
+    /* Translate them into cartesian positions */
+    flood_blowup(edi, edi->flood.forces_cartesian);
+
+    /* Rotate forces back so that they correspond to the given structure and not to the fitted one */
+    /* Each node rotates back its local forces */
+    transpose(rotmat,tmat);
+    rotate_x(edi->flood.forces_cartesian, edi->sav.nr_loc, tmat);
+
+    /* Finally add forces to the main force variable */
+    for (i=0; i<edi->sav.nr_loc; i++)
+        rvec_inc(force[edi->sav.anrs_loc[i]],edi->flood.forces_cartesian[i]);
+
+    /* Output is written by the master process */
+    if (do_per_step(step,edi->outfrq) && MASTER(cr))
+        write_edo_flood(edi,edo,step);
+}
+
+
+/* Main flooding routine, called from do_force */
+extern void do_flood(
+        FILE            *log,    /* md.log file */
+        t_commrec       *cr,     /* Communication record */
+        rvec            x[],     /* Positions on the local processor */
+        rvec            force[], /* forcefield forces, to these the flooding forces are added */
+        gmx_edsam_t     ed,      /* ed data structure contains all ED and flooding datasets */
+        matrix          box,     /* the box */
+        gmx_large_int_t step)    /* The relative time step since ir->init_step is already subtracted */
+{
+    t_edpar *edi;
+
+
+    if (ed->eEDtype != eEDflood)
+        return;
+
+    edi = ed->edpar;
+    while (edi)
+    {
+        /* Call flooding for one matrix */
+        if (edi->flood.vecs.neig)
+            do_single_flood(ed->edo,x,force,edi,step,box,cr);
+        edi = edi->next_edi;
+    }
+}
+
+
+/* Called by init_edi, configure some flooding related variables and structures,
+ * print headers to output files */
+static void init_flood(t_edpar *edi, gmx_edsam_t ed, real dt, t_commrec *cr)
+{
+    int i;
+
+
+    edi->flood.Efl = edi->flood.constEfl;
+    edi->flood.Vfl = 0;
+    edi->flood.dt  = dt;
+
+    if (edi->flood.vecs.neig)
+    {
+        /* If in any of the datasets we find a flooding vector, flooding is turned on */
+        ed->eEDtype = eEDflood;
+
+        fprintf(stderr,"ED: Flooding of matrix %d is switched on.\n", edi->flood.flood_id);
+
+        if (edi->flood.bConstForce)
+        {
+            /* We have used stpsz as a vehicle to carry the fproj values for constant
+             * force flooding. Now we copy that to flood.vecs.fproj. Note that
+             * in const force flooding, fproj is never changed. */
+            for (i=0; i<edi->flood.vecs.neig; i++)
+            {
+                edi->flood.vecs.fproj[i] = edi->flood.vecs.stpsz[i];
+
+                fprintf(stderr, "ED: applying on eigenvector %d a constant force of %g\n",
+                        edi->flood.vecs.ieig[i], edi->flood.vecs.fproj[i]);
+            }
+        }
+        fprintf(ed->edo,"FL_HEADER: Flooding of matrix %d is switched on! The flooding output will have the following format:\n",
+                edi->flood.flood_id);
+        fprintf(ed->edo,"FL_HEADER: Step     Efl          Vfl       deltaF\n");
+    }
+}
+
+
+#ifdef DEBUGHELPERS
+/*********** Energy book keeping ******/
+static void get_flood_enx_names(t_edpar *edi, char** names, int *nnames)  /* get header of energies */
+{
+    t_edpar *actual;
+    int count;
+    char buf[STRLEN];
+    actual=edi;
+    count = 1;
+    while (actual)
+    {
+        srenew(names,count);
+        sprintf(buf,"Vfl_%d",count);
+        names[count-1]=strdup(buf);
+        actual=actual->next_edi;
+        count++;
+    }
+    *nnames=count-1;
+}
+
+
+static void get_flood_energies(t_edpar *edi, real Vfl[],int nnames)
+{
+    /*fl has to be big enough to capture nnames-many entries*/
+    t_edpar *actual;
+    int count;
+
+
+    actual=edi;
+    count = 1;
+    while (actual)
+    {
+        Vfl[count-1]=actual->flood.Vfl;
+        actual=actual->next_edi;
+        count++;
+    }
+    if (nnames!=count-1)
+        gmx_fatal(FARGS,"Number of energies is not consistent with t_edi structure");
+}
+/************* END of FLOODING IMPLEMENTATION ****************************/
+#endif
+
+
+gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr)
+{
+    gmx_edsam_t ed;
+
+
+    /* Allocate space for the ED data structure */
+    snew(ed, 1);
+
+    /* We want to perform ED (this switch might later be upgraded to eEDflood) */
+    ed->eEDtype = eEDedsam;
+
+    if (MASTER(cr))
+    {
+        /* Open .edi input file: */
+        ed->edinam=ftp2fn(efEDI,nfile,fnm);
+        /* The master opens the .edo output file */
+        fprintf(stderr,"ED sampling will be performed!\n");
+        ed->edonam = ftp2fn(efEDO,nfile,fnm);
+        ed->edo    = gmx_fio_fopen(ed->edonam,(Flags & MD_APPENDFILES)? "a+" : "w+");
+        ed->bStartFromCpt = Flags & MD_STARTFROMCPT;
+    }
+    return ed;
+}
+
+
+/* Broadcasts the structure data */
+static void bc_ed_positions(t_commrec *cr, struct gmx_edx *s, int stype)
+{
+    snew_bc(cr, s->anrs, s->nr   );    /* Index numbers     */
+    snew_bc(cr, s->x   , s->nr   );    /* Positions         */
+    nblock_bc(cr, s->nr, s->anrs );
+    nblock_bc(cr, s->nr, s->x    );
+
+    /* For the average & reference structures we need an array for the collective indices,
+     * and we need to broadcast the masses as well */
+    if (stype == eedAV || stype == eedREF)
+    {
+        /* We need these additional variables in the parallel case: */
+        snew(s->c_ind    , s->nr   );   /* Collective indices */
+        /* Local atom indices get assigned in dd_make_local_group_indices.
+         * There, also memory is allocated */
+        s->nalloc_loc = 0;              /* allocation size of s->anrs_loc */
+        snew_bc(cr, s->x_old, s->nr);   /* To be able to always make the ED molecule whole, ...        */
+        nblock_bc(cr, s->nr, s->x_old); /* ... keep track of shift changes with the help of old coords */
+    }
+
+    /* broadcast masses for the reference structure (for mass-weighted fitting) */
+    if (stype == eedREF)
+    {
+        snew_bc(cr, s->m, s->nr);
+        nblock_bc(cr, s->nr, s->m);
+    }
+
+    /* For the average structure we might need the masses for mass-weighting */
+    if (stype == eedAV)
+    {
+        snew_bc(cr, s->sqrtm, s->nr);
+        nblock_bc(cr, s->nr, s->sqrtm);
+        snew_bc(cr, s->m, s->nr);
+        nblock_bc(cr, s->nr, s->m);
+    }
+}
+
+
+/* Broadcasts the eigenvector data */
+static void bc_ed_vecs(t_commrec *cr, t_eigvec *ev, int length, gmx_bool bHarmonic)
+{
+    int i;
+
+    snew_bc(cr, ev->ieig   , ev->neig);  /* index numbers of eigenvector  */
+    snew_bc(cr, ev->stpsz  , ev->neig);  /* stepsizes per eigenvector     */
+    snew_bc(cr, ev->xproj  , ev->neig);  /* instantaneous x projection    */
+    snew_bc(cr, ev->fproj  , ev->neig);  /* instantaneous f projection    */
+    snew_bc(cr, ev->refproj, ev->neig);  /* starting or target projection */
+
+    nblock_bc(cr, ev->neig, ev->ieig   );
+    nblock_bc(cr, ev->neig, ev->stpsz  );
+    nblock_bc(cr, ev->neig, ev->xproj  );
+    nblock_bc(cr, ev->neig, ev->fproj  );
+    nblock_bc(cr, ev->neig, ev->refproj);
+
+    snew_bc(cr, ev->vec, ev->neig);      /* Eigenvector components        */
+    for (i=0; i<ev->neig; i++)
+    {
+        snew_bc(cr, ev->vec[i], length);
+        nblock_bc(cr, length, ev->vec[i]);
+    }
+
+    /* For harmonic restraints the reference projections can change with time */
+    if (bHarmonic)
+    {
+        snew_bc(cr, ev->refproj0    , ev->neig);
+        snew_bc(cr, ev->refprojslope, ev->neig);
+        nblock_bc(cr, ev->neig, ev->refproj0    );
+        nblock_bc(cr, ev->neig, ev->refprojslope);
+    }
+}
+
+
+/* Broadcasts the ED / flooding data to other nodes
+ * and allocates memory where needed */
+static void broadcast_ed_data(t_commrec *cr, gmx_edsam_t ed, int numedis)
+{
+    int     nr;
+    t_edpar *edi;
+
+
+    /* Master lets the other nodes know if its ED only or also flooding */
+    gmx_bcast(sizeof(ed->eEDtype), &(ed->eEDtype), cr);
+
+    snew_bc(cr, ed->edpar,1);
+    /* Now transfer the ED data set(s) */
+    edi = ed->edpar;
+    for (nr=0; nr<numedis; nr++)
+    {
+        /* Broadcast a single ED data set */
+        block_bc(cr, *edi);
+
+        /* Broadcast positions */
+        bc_ed_positions(cr, &(edi->sref), eedREF); /* reference positions (don't broadcast masses)    */
+        bc_ed_positions(cr, &(edi->sav ), eedAV ); /* average positions (do broadcast masses as well) */
+        bc_ed_positions(cr, &(edi->star), eedTAR); /* target positions                                */
+        bc_ed_positions(cr, &(edi->sori), eedORI); /* origin positions                                */
+
+        /* Broadcast eigenvectors */
+        bc_ed_vecs(cr, &edi->vecs.mon   , edi->sav.nr, FALSE);
+        bc_ed_vecs(cr, &edi->vecs.linfix, edi->sav.nr, FALSE);
+        bc_ed_vecs(cr, &edi->vecs.linacc, edi->sav.nr, FALSE);
+        bc_ed_vecs(cr, &edi->vecs.radfix, edi->sav.nr, FALSE);
+        bc_ed_vecs(cr, &edi->vecs.radacc, edi->sav.nr, FALSE);
+        bc_ed_vecs(cr, &edi->vecs.radcon, edi->sav.nr, FALSE);
+        /* Broadcast flooding eigenvectors and, if needed, values for the moving reference */
+        bc_ed_vecs(cr, &edi->flood.vecs,  edi->sav.nr, edi->flood.bHarmonic);
+
+        /* Set the pointer to the next ED dataset */
+        if (edi->next_edi)
+        {
+          snew_bc(cr, edi->next_edi, 1);
+          edi = edi->next_edi;
+        }
+    }
+}
+
+
+/* init-routine called for every *.edi-cycle, initialises t_edpar structure */
+static void init_edi(gmx_mtop_t *mtop,t_inputrec *ir,
+                     t_commrec *cr,gmx_edsam_t ed,t_edpar *edi)
+{
+    int  i;
+    real totalmass = 0.0;
+    rvec com;
+    t_atom *atom;
+
+    /* NOTE Init_edi is executed on the master process only
+     * The initialized data sets are then transmitted to the
+     * other nodes in broadcast_ed_data */
+
+    edi->bNeedDoEdsam = edi->vecs.mon.neig
+                     || edi->vecs.linfix.neig
+                     || edi->vecs.linacc.neig
+                     || edi->vecs.radfix.neig
+                     || edi->vecs.radacc.neig
+                     || edi->vecs.radcon.neig;
+
+    /* evaluate masses (reference structure) */
+    snew(edi->sref.m, edi->sref.nr);
+    for (i = 0; i < edi->sref.nr; i++)
+    {
+        if (edi->fitmas)
+        {
+            gmx_mtop_atomnr_to_atom(mtop,edi->sref.anrs[i],&atom);
+            edi->sref.m[i] = atom->m;
+        }
+        else
+        {
+            edi->sref.m[i] = 1.0;
+        }
+
+        /* Check that every m > 0. Bad things will happen otherwise. */
+        if (edi->sref.m[i] <= 0.0)
+        {
+            gmx_fatal(FARGS, "Reference structure atom %d (sam.edi index %d) has a mass of %g.\n"
+                             "For a mass-weighted fit, all reference structure atoms need to have a mass >0.\n"
+                             "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
+                             "atoms from the reference structure by creating a proper index group.\n",
+                      i, edi->sref.anrs[i]+1, edi->sref.m[i]);
+        }
+
+        totalmass += edi->sref.m[i];
+    }
+    edi->sref.mtot = totalmass;
+
+    /* Masses m and sqrt(m) for the average structure. Note that m
+     * is needed if forces have to be evaluated in do_edsam */
+    snew(edi->sav.sqrtm, edi->sav.nr );
+    snew(edi->sav.m    , edi->sav.nr );
+    for (i = 0; i < edi->sav.nr; i++)
+    {
+        gmx_mtop_atomnr_to_atom(mtop,edi->sav.anrs[i],&atom);
+        edi->sav.m[i] = atom->m;
+        if (edi->pcamas)
+        {
+            edi->sav.sqrtm[i] = sqrt(atom->m);
+        }
+        else
+        {
+            edi->sav.sqrtm[i] = 1.0;
+        }
+
+        /* Check that every m > 0. Bad things will happen otherwise. */
+        if (edi->sav.sqrtm[i] <= 0.0)
+        {
+            gmx_fatal(FARGS, "Average structure atom %d (sam.edi index %d) has a mass of %g.\n"
+                             "For ED with mass-weighting, all average structure atoms need to have a mass >0.\n"
+                             "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
+                             "atoms from the average structure by creating a proper index group.\n",
+                      i, edi->sav.anrs[i]+1, atom->m);
+        }
+    }
+
+    /* put reference structure in origin */
+    get_center(edi->sref.x, edi->sref.m, edi->sref.nr, com);
+    com[XX] = -com[XX];
+    com[YY] = -com[YY];
+    com[ZZ] = -com[ZZ];
+    translate_x(edi->sref.x, edi->sref.nr, com);
+
+    /* Init ED buffer */
+    snew(edi->buf, 1);
+}
+
+
+static void check(const char *line, const char *label)
+{
+    if (!strstr(line,label))
+        gmx_fatal(FARGS,"Could not find input parameter %s at expected position in edsam input-file (.edi)\nline read instead is %s",label,line);
+}
+
+
+static int read_checked_edint(FILE *file,const char *label)
+{
+    char line[STRLEN+1];
+    int idum;
+
+
+    fgets2 (line,STRLEN,file);
+    check(line,label);
+    fgets2 (line,STRLEN,file);
+    sscanf (line,"%d",&idum);
+    return idum;
+}
+
+
+static int read_edint(FILE *file,gmx_bool *bEOF)
+{
+    char line[STRLEN+1];
+    int idum;
+    char *eof;
+
+
+    eof=fgets2 (line,STRLEN,file);
+    if (eof==NULL)
+    {
+        *bEOF = TRUE;
+        return -1;
+    }
+    eof=fgets2 (line,STRLEN,file);
+    if (eof==NULL)
+    {
+        *bEOF = TRUE;
+        return -1;
+    }
+    sscanf (line,"%d",&idum);
+    *bEOF = FALSE;
+    return idum;
+}
+
+
+static real read_checked_edreal(FILE *file,const char *label)
+{
+    char line[STRLEN+1];
+    double rdum;
+
+
+    fgets2 (line,STRLEN,file);
+    check(line,label);
+    fgets2 (line,STRLEN,file);
+    sscanf (line,"%lf",&rdum);
+    return (real) rdum; /* always read as double and convert to single */
+}
+
+
+static void read_edx(FILE *file,int number,int *anrs,rvec *x)
+{
+    int i,j;
+    char line[STRLEN+1];
+    double d[3];
+
+
+    for(i=0; i<number; i++)
+    {
+        fgets2 (line,STRLEN,file);
+        sscanf (line,"%d%lf%lf%lf",&anrs[i],&d[0],&d[1],&d[2]);
+        anrs[i]--; /* we are reading FORTRAN indices */
+        for(j=0; j<3; j++)
+            x[i][j]=d[j]; /* always read as double and convert to single */
+    }
+}
+
+
+static void scan_edvec(FILE *in,int nr,rvec *vec)
+{
+    char line[STRLEN+1];
+    int i;
+    double x,y,z;
+
+
+    for(i=0; (i < nr); i++)
+    {
+        fgets2 (line,STRLEN,in);
+        sscanf (line,"%le%le%le",&x,&y,&z);
+        vec[i][XX]=x;
+        vec[i][YY]=y;
+        vec[i][ZZ]=z;
+    }
+}
+
+
+static void read_edvec(FILE *in,int nr,t_eigvec *tvec,gmx_bool bReadRefproj, gmx_bool *bHaveReference)
+{
+    int i,idum,nscan;
+    double rdum,refproj_dum=0.0,refprojslope_dum=0.0;
+    char line[STRLEN+1];
+
+
+    tvec->neig=read_checked_edint(in,"NUMBER OF EIGENVECTORS");
+    if (tvec->neig >0)
+    {
+        snew(tvec->ieig   ,tvec->neig);
+        snew(tvec->stpsz  ,tvec->neig);
+        snew(tvec->vec    ,tvec->neig);
+        snew(tvec->xproj  ,tvec->neig);
+        snew(tvec->fproj  ,tvec->neig);
+        snew(tvec->refproj,tvec->neig);
+        if (bReadRefproj)
+        {
+            snew(tvec->refproj0    ,tvec->neig);
+            snew(tvec->refprojslope,tvec->neig);
+        }
+
+        for(i=0; (i < tvec->neig); i++)
+        {
+            fgets2 (line,STRLEN,in);
+            if (bReadRefproj) /* ONLY when using flooding as harmonic restraint */
+            {
+                nscan = sscanf(line,"%d%lf%lf%lf",&idum,&rdum,&refproj_dum,&refprojslope_dum);
+                /* Zero out values which were not scanned */
+                switch(nscan)
+                {
+                    case 4:
+                        /* Every 4 values read, including reference position */
+                        *bHaveReference = TRUE;
+                        break;
+                    case 3:
+                        /* A reference position is provided */
+                        *bHaveReference = TRUE;
+                        /* No value for slope, set to 0 */
+                        refprojslope_dum = 0.0;
+                        break;
+                    case 2:
+                        /* No values for reference projection and slope, set to 0 */
+                        refproj_dum      = 0.0;
+                        refprojslope_dum = 0.0;
+                        break;
+                    default:
+                        gmx_fatal(FARGS,"Expected 2 - 4 (not %d) values for flooding vec: <nr> <spring const> <refproj> <refproj-slope>\n", nscan);
+                        break;
+                }
+                tvec->refproj[i]=refproj_dum;
+                tvec->refproj0[i]=refproj_dum;
+                tvec->refprojslope[i]=refprojslope_dum;
+            }
+            else /* Normal flooding */
+            {
+                nscan = sscanf(line,"%d%lf",&idum,&rdum);
+                if (nscan != 2)
+                    gmx_fatal(FARGS,"Expected 2 values for flooding vec: <nr> <stpsz>\n");
+            }
+            tvec->ieig[i]=idum;
+            tvec->stpsz[i]=rdum;
+        } /* end of loop over eigenvectors */
+
+        for(i=0; (i < tvec->neig); i++)
+        {
+            snew(tvec->vec[i],nr);
+            scan_edvec(in,nr,tvec->vec[i]);
+        }
+    }
+}
+
+
+/* calls read_edvec for the vector groups, only for flooding there is an extra call */
+static void read_edvecs(FILE *in,int nr,t_edvecs *vecs)
+{
+       gmx_bool bHaveReference = FALSE;
+
+
+    read_edvec(in, nr, &vecs->mon   , FALSE, &bHaveReference);
+    read_edvec(in, nr, &vecs->linfix, FALSE, &bHaveReference);
+    read_edvec(in, nr, &vecs->linacc, FALSE, &bHaveReference);
+    read_edvec(in, nr, &vecs->radfix, FALSE, &bHaveReference);
+    read_edvec(in, nr, &vecs->radacc, FALSE, &bHaveReference);
+    read_edvec(in, nr, &vecs->radcon, FALSE, &bHaveReference);
+}
+
+
+/* Check if the same atom indices are used for reference and average positions */
+static gmx_bool check_if_same(struct gmx_edx sref, struct gmx_edx sav)
+{
+    int i;
+
+
+    /* If the number of atoms differs between the two structures,
+     * they cannot be identical */
+    if (sref.nr != sav.nr)
+        return FALSE;
+
+    /* Now that we know that both stuctures have the same number of atoms,
+     * check if also the indices are identical */
+    for (i=0; i < sav.nr; i++)
+    {
+        if (sref.anrs[i] != sav.anrs[i])
+            return FALSE;
+    }
+    fprintf(stderr, "ED: Note: Reference and average structure are composed of the same atom indices.\n");
+
+    return TRUE;
+}
+
+
+static int read_edi(FILE* in, gmx_edsam_t ed,t_edpar *edi,int nr_mdatoms, int edi_nr, t_commrec *cr)
+{
+    int readmagic;
+    const int magic=670;
+    gmx_bool bEOF;
+
+    /* Was a specific reference point for the flooding/umbrella potential provided in the edi file? */
+    gmx_bool bHaveReference = FALSE;
+
+
+    /* the edi file is not free format, so expect problems if the input is corrupt. */
+
+    /* check the magic number */
+    readmagic=read_edint(in,&bEOF);
+    /* Check whether we have reached the end of the input file */
+    if (bEOF)
+        return 0;
+
+    if (readmagic != magic)
+    {
+        if (readmagic==666 || readmagic==667 || readmagic==668)
+            gmx_fatal(FARGS,"Wrong magic number: Use newest version of make_edi to produce edi file");
+        else if (readmagic != 669)
+            gmx_fatal(FARGS,"Wrong magic number %d in %s",readmagic,ed->edinam);
+    }
+
+    /* check the number of atoms */
+    edi->nini=read_edint(in,&bEOF);
+    if (edi->nini != nr_mdatoms)
+        gmx_fatal(FARGS,"Nr of atoms in %s (%d) does not match nr of md atoms (%d)",
+                ed->edinam,edi->nini,nr_mdatoms);
+
+    /* Done checking. For the rest we blindly trust the input */
+    edi->fitmas          = read_checked_edint(in,"FITMAS");
+    edi->pcamas          = read_checked_edint(in,"ANALYSIS_MAS");
+    edi->outfrq          = read_checked_edint(in,"OUTFRQ");
+    edi->maxedsteps      = read_checked_edint(in,"MAXLEN");
+    edi->slope           = read_checked_edreal(in,"SLOPECRIT");
+
+    edi->presteps        = read_checked_edint(in,"PRESTEPS");
+    edi->flood.deltaF0   = read_checked_edreal(in,"DELTA_F0");
+    edi->flood.deltaF    = read_checked_edreal(in,"INIT_DELTA_F");
+    edi->flood.tau       = read_checked_edreal(in,"TAU");
+    edi->flood.constEfl  = read_checked_edreal(in,"EFL_NULL");
+    edi->flood.alpha2    = read_checked_edreal(in,"ALPHA2");
+    edi->flood.kT        = read_checked_edreal(in,"KT");
+    edi->flood.bHarmonic = read_checked_edint(in,"HARMONIC");
+    if (readmagic > 669)
+        edi->flood.bConstForce = read_checked_edint(in,"CONST_FORCE_FLOODING");
+    else
+        edi->flood.bConstForce = FALSE;
+    edi->flood.flood_id  = edi_nr;
+    edi->sref.nr         = read_checked_edint(in,"NREF");
+
+    /* allocate space for reference positions and read them */
+    snew(edi->sref.anrs,edi->sref.nr);
+    snew(edi->sref.x   ,edi->sref.nr);
+    if (PAR(cr))
+        snew(edi->sref.x_old,edi->sref.nr);
+    edi->sref.sqrtm    =NULL;
+    read_edx(in,edi->sref.nr,edi->sref.anrs,edi->sref.x);
+
+    /* average positions. they define which atoms will be used for ED sampling */
+    edi->sav.nr=read_checked_edint(in,"NAV");
+    snew(edi->sav.anrs,edi->sav.nr);
+    snew(edi->sav.x   ,edi->sav.nr);
+    if (PAR(cr))
+        snew(edi->sav.x_old,edi->sav.nr);
+    read_edx(in,edi->sav.nr,edi->sav.anrs,edi->sav.x);
+
+    /* Check if the same atom indices are used for reference and average positions */
+    edi->bRefEqAv = check_if_same(edi->sref, edi->sav);
+
+    /* eigenvectors */
+    read_edvecs(in,edi->sav.nr,&edi->vecs);
+    read_edvec(in,edi->sav.nr,&edi->flood.vecs,edi->flood.bHarmonic, &bHaveReference);
+
+    /* target positions */
+    edi->star.nr=read_edint(in,&bEOF);
+    if (edi->star.nr > 0)
+    {
+        snew(edi->star.anrs,edi->star.nr);
+        snew(edi->star.x   ,edi->star.nr);
+        edi->star.sqrtm    =NULL;
+        read_edx(in,edi->star.nr,edi->star.anrs,edi->star.x);
+    }
+
+    /* positions defining origin of expansion circle */
+    edi->sori.nr=read_edint(in,&bEOF);
+    if (edi->sori.nr > 0)
+    {
+       if (bHaveReference)
+       {
+               /* Both an -ori structure and a at least one manual reference point have been
+                * specified. That's ambiguous and probably not intentional. */
+               gmx_fatal(FARGS, "ED: An origin structure has been provided and a at least one (moving) reference\n"
+                                "    point was manually specified in the edi file. That is ambiguous. Aborting.\n");
+       }
+        snew(edi->sori.anrs,edi->sori.nr);
+        snew(edi->sori.x   ,edi->sori.nr);
+        edi->sori.sqrtm    =NULL;
+        read_edx(in,edi->sori.nr,edi->sori.anrs,edi->sori.x);
+    }
+
+    /* all done */
+    return 1;
+}
+
+
+
+/* Read in the edi input file. Note that it may contain several ED data sets which were
+ * achieved by concatenating multiple edi files. The standard case would be a single ED
+ * data set, though. */
+static void read_edi_file(gmx_edsam_t ed, t_edpar *edi, int nr_mdatoms, t_commrec *cr)
+{
+    FILE    *in;
+    t_edpar *curr_edi,*last_edi;
+    t_edpar *edi_read;
+    int     edi_nr = 0;
+
+
+    /* This routine is executed on the master only */
+
+    /* Open the .edi parameter input file */
+    in = gmx_fio_fopen(ed->edinam,"r");
+    fprintf(stderr, "ED: Reading edi file %s\n", ed->edinam);
+
+    /* Now read a sequence of ED input parameter sets from the edi file */
+    curr_edi=edi;
+    last_edi=edi;
+    while( read_edi(in, ed, curr_edi, nr_mdatoms, edi_nr, cr) )
+    {
+        edi_nr++;
+        /* Make shure that the number of atoms in each dataset is the same as in the tpr file */
+        if (edi->nini != nr_mdatoms)
+            gmx_fatal(FARGS,"edi file %s (dataset #%d) was made for %d atoms, but the simulation contains %d atoms.",
+                    ed->edinam, edi_nr, edi->nini, nr_mdatoms);
+        /* Since we arrived within this while loop we know that there is still another data set to be read in */
+        /* We need to allocate space for the data: */
+        snew(edi_read,1);
+        /* Point the 'next_edi' entry to the next edi: */
+        curr_edi->next_edi=edi_read;
+        /* Keep the curr_edi pointer for the case that the next dataset is empty: */
+        last_edi = curr_edi;
+        /* Let's prepare to read in the next edi data set: */
+        curr_edi = edi_read;
+    }
+    if (edi_nr == 0)
+        gmx_fatal(FARGS, "No complete ED data set found in edi file %s.", ed->edinam);
+
+    /* Terminate the edi dataset list with a NULL pointer: */
+    last_edi->next_edi = NULL;
+
+    fprintf(stderr, "ED: Found %d ED dataset%s.\n", edi_nr, edi_nr>1? "s" : "");
+
+    /* Close the .edi file again */
+    gmx_fio_fclose(in);
+}
+
+
+struct t_fit_to_ref {
+    rvec *xcopy;       /* Working copy of the positions in fit_to_reference */
+};
+
+/* Fit the current positions to the reference positions
+ * Do not actually do the fit, just return rotation and translation.
+ * Note that the COM of the reference structure was already put into
+ * the origin by init_edi. */
+static void fit_to_reference(rvec      *xcoll,    /* The positions to be fitted */
+                             rvec      transvec,  /* The translation vector */
+                             matrix    rotmat,    /* The rotation matrix */
+                             t_edpar   *edi)      /* Just needed for do_edfit */
+{
+    rvec com;          /* center of mass */
+    int  i;
+    struct t_fit_to_ref *loc;
+
+
+    /* Allocate memory the first time this routine is called for each edi dataset */
+    if (NULL == edi->buf->fit_to_ref)
+    {
+        snew(edi->buf->fit_to_ref, 1);
+        snew(edi->buf->fit_to_ref->xcopy, edi->sref.nr);
+    }
+    loc = edi->buf->fit_to_ref;
+
+    /* We do not touch the original positions but work on a copy. */
+    for (i=0; i<edi->sref.nr; i++)
+        copy_rvec(xcoll[i], loc->xcopy[i]);
+
+    /* Calculate the center of mass */
+    get_center(loc->xcopy, edi->sref.m, edi->sref.nr, com);
+
+    transvec[XX] = -com[XX];
+    transvec[YY] = -com[YY];
+    transvec[ZZ] = -com[ZZ];
+
+    /* Subtract the center of mass from the copy */
+    translate_x(loc->xcopy, edi->sref.nr, transvec);
+
+    /* Determine the rotation matrix */
+    do_edfit(edi->sref.nr, edi->sref.x, loc->xcopy, rotmat, edi);
+}
+
+
+static void translate_and_rotate(rvec *x,         /* The positions to be translated and rotated */
+                                 int nat,         /* How many positions are there? */
+                                 rvec transvec,   /* The translation vector */
+                                 matrix rotmat)   /* The rotation matrix */
+{
+    /* Translation */
+    translate_x(x, nat, transvec);
+
+    /* Rotation */
+    rotate_x(x, nat, rotmat);
+}
+
+
+/* Gets the rms deviation of the positions to the structure s */
+/* fit_to_structure has to be called before calling this routine! */
+static real rmsd_from_structure(rvec           *x,  /* The positions under consideration */
+                                struct gmx_edx *s)  /* The structure from which the rmsd shall be computed */
+{
+    real  rmsd=0.0;
+    int   i;
+
+
+    for (i=0; i < s->nr; i++)
+        rmsd += distance2(s->x[i], x[i]);
+
+    rmsd /= (real) s->nr;
+    rmsd = sqrt(rmsd);
+
+    return rmsd;
+}
+
+
+void dd_make_local_ed_indices(gmx_domdec_t *dd, struct gmx_edsam *ed)
+{
+    t_edpar *edi;
+
+
+    if (ed->eEDtype != eEDnone)
+    {
+        /* Loop over ED datasets (usually there is just one dataset, though) */
+        edi=ed->edpar;
+        while (edi)
+        {
+            /* Local atoms of the reference structure (for fitting), need only be assembled
+             * if their indices differ from the average ones */
+            if (!edi->bRefEqAv)
+                dd_make_local_group_indices(dd->ga2la, edi->sref.nr, edi->sref.anrs,
+                        &edi->sref.nr_loc, &edi->sref.anrs_loc, &edi->sref.nalloc_loc, edi->sref.c_ind);
+
+            /* Local atoms of the average structure (on these ED will be performed) */
+            dd_make_local_group_indices(dd->ga2la, edi->sav.nr, edi->sav.anrs,
+                    &edi->sav.nr_loc, &edi->sav.anrs_loc, &edi->sav.nalloc_loc, edi->sav.c_ind);
+
+            /* Indicate that the ED shift vectors for this structure need to be updated
+             * at the next call to communicate_group_positions, since obviously we are in a NS step */
+            edi->buf->do_edsam->bUpdateShifts = TRUE;
+
+            /* Set the pointer to the next ED dataset (if any) */
+            edi=edi->next_edi;
+        }
+    }
+}
+
+
+static inline void ed_unshift_single_coord(matrix box, const rvec x, const ivec is, rvec xu)
+{
+    int tx,ty,tz;
+
+
+    tx=is[XX];
+    ty=is[YY];
+    tz=is[ZZ];
+
+    if(TRICLINIC(box))
+    {
+        xu[XX] = x[XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
+        xu[YY] = x[YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
+        xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
+    } else
+    {
+        xu[XX] = x[XX]-tx*box[XX][XX];
+        xu[YY] = x[YY]-ty*box[YY][YY];
+        xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
+    }
+}
+
+
+static void do_linfix(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
+{
+    int  i, j;
+    real proj, add;
+    rvec vec_dum;
+
+
+    /* loop over linfix vectors */
+    for (i=0; i<edi->vecs.linfix.neig; i++)
+    {
+        /* calculate the projection */
+        proj = projectx(edi, xcoll, edi->vecs.linfix.vec[i]);
+
+        /* calculate the correction */
+        add = edi->vecs.linfix.refproj[i] + step*edi->vecs.linfix.stpsz[i] - proj;
+
+        /* apply the correction */
+        add /= edi->sav.sqrtm[i];
+        for (j=0; j<edi->sav.nr; j++)
+        {
+            svmul(add, edi->vecs.linfix.vec[i][j], vec_dum);
+            rvec_inc(xcoll[j], vec_dum);
+        }
+    }
+}
+
+
+static void do_linacc(rvec *xcoll, t_edpar *edi, t_commrec *cr)
+{
+    int  i, j;
+    real proj, add;
+    rvec vec_dum;
+
+
+    /* loop over linacc vectors */
+    for (i=0; i<edi->vecs.linacc.neig; i++)
+    {
+        /* calculate the projection */
+        proj=projectx(edi, xcoll, edi->vecs.linacc.vec[i]);
+
+        /* calculate the correction */
+        add = 0.0;
+        if (edi->vecs.linacc.stpsz[i] > 0.0)
+        {
+            if ((proj-edi->vecs.linacc.refproj[i]) < 0.0)
+                add = edi->vecs.linacc.refproj[i] - proj;
+        }
+        if (edi->vecs.linacc.stpsz[i] < 0.0)
+        {
+            if ((proj-edi->vecs.linacc.refproj[i]) > 0.0)
+                add = edi->vecs.linacc.refproj[i] - proj;
+        }
+
+        /* apply the correction */
+        add /= edi->sav.sqrtm[i];
+        for (j=0; j<edi->sav.nr; j++)
+        {
+            svmul(add, edi->vecs.linacc.vec[i][j], vec_dum);
+            rvec_inc(xcoll[j], vec_dum);
+        }
+
+        /* new positions will act as reference */
+        edi->vecs.linacc.refproj[i] = proj + add;
+    }
+}
+
+
+static void do_radfix(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
+{
+    int  i,j;
+    real *proj, rad=0.0, ratio;
+    rvec vec_dum;
+
+
+    if (edi->vecs.radfix.neig == 0)
+        return;
+
+    snew(proj, edi->vecs.radfix.neig);
+
+    /* loop over radfix vectors */
+    for (i=0; i<edi->vecs.radfix.neig; i++)
+    {
+        /* calculate the projections, radius */
+        proj[i] = projectx(edi, xcoll, edi->vecs.radfix.vec[i]);
+        rad += pow(proj[i] - edi->vecs.radfix.refproj[i], 2);
+    }
+
+    rad   = sqrt(rad);
+    ratio = (edi->vecs.radfix.stpsz[0]+edi->vecs.radfix.radius)/rad - 1.0;
+    edi->vecs.radfix.radius += edi->vecs.radfix.stpsz[0];
+
+    /* loop over radfix vectors */
+    for (i=0; i<edi->vecs.radfix.neig; i++)
+    {
+        proj[i] -= edi->vecs.radfix.refproj[i];
+
+        /* apply the correction */
+        proj[i] /= edi->sav.sqrtm[i];
+        proj[i] *= ratio;
+        for (j=0; j<edi->sav.nr; j++) {
+            svmul(proj[i], edi->vecs.radfix.vec[i][j], vec_dum);
+            rvec_inc(xcoll[j], vec_dum);
+        }
+    }
+
+    sfree(proj);
+}
+
+
+static void do_radacc(rvec *xcoll, t_edpar *edi, t_commrec *cr)
+{
+    int  i,j;
+    real *proj, rad=0.0, ratio=0.0;
+    rvec vec_dum;
+
+
+    if (edi->vecs.radacc.neig == 0)
+        return;
+
+    snew(proj,edi->vecs.radacc.neig);
+
+    /* loop over radacc vectors */
+    for (i=0; i<edi->vecs.radacc.neig; i++)
+    {
+        /* calculate the projections, radius */
+        proj[i] = projectx(edi, xcoll, edi->vecs.radacc.vec[i]);
+        rad += pow(proj[i] - edi->vecs.radacc.refproj[i], 2);
+    }
+    rad = sqrt(rad);
+
+    /* only correct when radius decreased */
+    if (rad < edi->vecs.radacc.radius)
+    {
+        ratio = edi->vecs.radacc.radius/rad - 1.0;
+        rad   = edi->vecs.radacc.radius;
+    }
+    else
+        edi->vecs.radacc.radius = rad;
+
+    /* loop over radacc vectors */
+    for (i=0; i<edi->vecs.radacc.neig; i++)
+    {
+        proj[i] -= edi->vecs.radacc.refproj[i];
+
+        /* apply the correction */
+        proj[i] /= edi->sav.sqrtm[i];
+        proj[i] *= ratio;
+        for (j=0; j<edi->sav.nr; j++)
+        {
+            svmul(proj[i], edi->vecs.radacc.vec[i][j], vec_dum);
+            rvec_inc(xcoll[j], vec_dum);
+        }
+    }
+    sfree(proj);
+}
+
+
+struct t_do_radcon {
+    real *proj;
+};
+
+static void do_radcon(rvec *xcoll, t_edpar *edi, t_commrec *cr)
+{
+    int  i,j;
+    real rad=0.0, ratio=0.0;
+    struct t_do_radcon *loc;
+    gmx_bool bFirst;
+    rvec vec_dum;
+
+
+    if(edi->buf->do_radcon != NULL)
+    {
+        bFirst = FALSE;
+        loc    = edi->buf->do_radcon;
+    }
+    else
+    {
+        bFirst = TRUE;
+        snew(edi->buf->do_radcon, 1);
+    }
+    loc = edi->buf->do_radcon;
+
+    if (edi->vecs.radcon.neig == 0)
+        return;
+
+    if (bFirst)
+        snew(loc->proj, edi->vecs.radcon.neig);
+
+    /* loop over radcon vectors */
+    for (i=0; i<edi->vecs.radcon.neig; i++)
+    {
+        /* calculate the projections, radius */
+        loc->proj[i] = projectx(edi, xcoll, edi->vecs.radcon.vec[i]);
+        rad += pow(loc->proj[i] - edi->vecs.radcon.refproj[i], 2);
+    }
+    rad = sqrt(rad);
+    /* only correct when radius increased */
+    if (rad > edi->vecs.radcon.radius)
+    {
+        ratio = edi->vecs.radcon.radius/rad - 1.0;
+
+        /* loop over radcon vectors */
+        for (i=0; i<edi->vecs.radcon.neig; i++)
+        {
+            /* apply the correction */
+            loc->proj[i] -= edi->vecs.radcon.refproj[i];
+            loc->proj[i] /= edi->sav.sqrtm[i];
+            loc->proj[i] *= ratio;
+
+            for (j=0; j<edi->sav.nr; j++)
+            {
+                svmul(loc->proj[i], edi->vecs.radcon.vec[i][j], vec_dum);
+                rvec_inc(xcoll[j], vec_dum);
+            }
+        }
+    }
+    else
+        edi->vecs.radcon.radius = rad;
+
+    if (rad != edi->vecs.radcon.radius)
+    {
+        rad = 0.0;
+        for (i=0; i<edi->vecs.radcon.neig; i++)
+        {
+            /* calculate the projections, radius */
+            loc->proj[i] = projectx(edi, xcoll, edi->vecs.radcon.vec[i]);
+            rad += pow(loc->proj[i] - edi->vecs.radcon.refproj[i], 2);
+        }
+        rad = sqrt(rad);
+    }
+}
+
+
+static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, gmx_large_int_t step, t_commrec *cr)
+{
+    int i;
+
+
+    /* subtract the average positions */
+    for (i=0; i<edi->sav.nr; i++)
+        rvec_dec(xcoll[i], edi->sav.x[i]);
+
+    /* apply the constraints */
+    if (step >= 0)
+        do_linfix(xcoll, edi, step, cr);
+    do_linacc(xcoll, edi, cr);
+    if (step >= 0)
+        do_radfix(xcoll, edi, step, cr);
+    do_radacc(xcoll, edi, cr);
+    do_radcon(xcoll, edi, cr);
+
+    /* add back the average positions */
+    for (i=0; i<edi->sav.nr; i++)
+        rvec_inc(xcoll[i], edi->sav.x[i]);
+}
+
+
+/* Write out the projections onto the eigenvectors */
+static void write_edo(int nr_edi, t_edpar *edi, gmx_edsam_t ed, gmx_large_int_t step,real rmsd)
+{
+    int i;
+    char buf[22];
+
+
+    if (edi->bNeedDoEdsam)
+    {
+        if (step == -1)
+            fprintf(ed->edo, "Initial projections:\n");
+        else
+        {
+            fprintf(ed->edo,"Step %s, ED #%d  ", gmx_step_str(step, buf), nr_edi);
+            fprintf(ed->edo,"  RMSD %f nm\n",rmsd);
+        }
+
+        if (edi->vecs.mon.neig)
+        {
+            fprintf(ed->edo,"  Monitor eigenvectors");
+            for (i=0; i<edi->vecs.mon.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.mon.ieig[i],edi->vecs.mon.xproj[i]);
+            fprintf(ed->edo,"\n");
+        }
+        if (edi->vecs.linfix.neig)
+        {
+            fprintf(ed->edo,"  Linfix  eigenvectors");
+            for (i=0; i<edi->vecs.linfix.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.linfix.ieig[i],edi->vecs.linfix.xproj[i]);
+            fprintf(ed->edo,"\n");
+        }
+        if (edi->vecs.linacc.neig)
+        {
+            fprintf(ed->edo,"  Linacc  eigenvectors");
+            for (i=0; i<edi->vecs.linacc.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.linacc.ieig[i],edi->vecs.linacc.xproj[i]);
+            fprintf(ed->edo,"\n");
+        }
+        if (edi->vecs.radfix.neig)
+        {
+            fprintf(ed->edo,"  Radfix  eigenvectors");
+            for (i=0; i<edi->vecs.radfix.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radfix.ieig[i],edi->vecs.radfix.xproj[i]);
+            fprintf(ed->edo,"\n");
+            fprintf(ed->edo,"  fixed increment radius = %f\n", calc_radius(&edi->vecs.radfix));
+        }
+        if (edi->vecs.radacc.neig)
+        {
+            fprintf(ed->edo,"  Radacc  eigenvectors");
+            for (i=0; i<edi->vecs.radacc.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radacc.ieig[i],edi->vecs.radacc.xproj[i]);
+            fprintf(ed->edo,"\n");
+            fprintf(ed->edo,"  acceptance radius      = %f\n", calc_radius(&edi->vecs.radacc));
+        }
+        if (edi->vecs.radcon.neig)
+        {
+            fprintf(ed->edo,"  Radcon  eigenvectors");
+            for (i=0; i<edi->vecs.radcon.neig; i++)
+                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radcon.ieig[i],edi->vecs.radcon.xproj[i]);
+            fprintf(ed->edo,"\n");
+            fprintf(ed->edo,"  contracting radius     = %f\n", calc_radius(&edi->vecs.radcon));
+        }
+    }
+}
+
+/* Returns if any constraints are switched on */
+static int ed_constraints(gmx_bool edtype, t_edpar *edi)
+{
+    if (edtype == eEDedsam || edtype == eEDflood)
+    {
+        return (edi->vecs.linfix.neig || edi->vecs.linacc.neig ||
+                edi->vecs.radfix.neig || edi->vecs.radacc.neig ||
+                edi->vecs.radcon.neig);
+    }
+    return 0;
+}
+
+
+/* Copies reference projection 'refproj' to fixed 'refproj0' variable for flooding/
+ * umbrella sampling simulations. */
+static void copyEvecReference(t_eigvec* floodvecs)
+{
+       int i;
+
+
+       for (i=0; i<floodvecs->neig; i++)
+       {
+               floodvecs->refproj0[i] = floodvecs->refproj[i];
+       }
+}
+
+
+void init_edsam(gmx_mtop_t  *mtop,   /* global topology                    */
+                t_inputrec  *ir,     /* input record                       */
+                t_commrec   *cr,     /* communication record               */
+                gmx_edsam_t ed,      /* contains all ED data               */
+                rvec        x[],     /* positions of the whole MD system   */
+                matrix      box)     /* the box                            */
+{
+    t_edpar *edi = NULL;    /* points to a single edi data set */
+    int     numedis=0;      /* keep track of the number of ED data sets in edi file */
+    int     i,nr_edi;
+    rvec    *x_pbc  = NULL; /* positions of the whole MD system with pbc removed  */
+    rvec    *xfit   = NULL; /* the positions which will be fitted to the reference structure  */
+    rvec    *xstart = NULL; /* the positions which are subject to ED sampling */
+    rvec    fit_transvec;   /* translation ... */
+    matrix  fit_rotmat;     /* ... and rotation from fit to reference structure */
+
+
+    if (!DOMAINDECOMP(cr) && PAR(cr) && MASTER(cr))
+        gmx_fatal(FARGS, "Please switch on domain decomposition to use essential dynamics in parallel.");
+
+    if (MASTER(cr))
+        fprintf(stderr, "ED: Initializing essential dynamics constraints.\n");
+
+    /* Needed for initializing radacc radius in do_edsam */
+    ed->bFirst = 1;
+
+    /* The input file is read by the master and the edi structures are
+     * initialized here. Input is stored in ed->edpar. Then the edi
+     * structures are transferred to the other nodes */
+    if (MASTER(cr))
+    {
+        snew(ed->edpar,1);
+        /* Read the whole edi file at once: */
+        read_edi_file(ed,ed->edpar,mtop->natoms,cr);
+
+        /* Initialization for every ED/flooding dataset. Flooding uses one edi dataset per
+         * flooding vector, Essential dynamics can be applied to more than one structure
+         * as well, but will be done in the order given in the edi file, so
+         * expect different results for different order of edi file concatenation! */
+        edi=ed->edpar;
+        while(edi != NULL)
+        {
+            init_edi(mtop,ir,cr,ed,edi);
+
+            /* Init flooding parameters if needed */
+            init_flood(edi,ed,ir->delta_t,cr);
+
+            edi=edi->next_edi;
+            numedis++;
+        }
+    }
+
+    /* The master does the work here. The other nodes get the positions
+     * not before dd_partition_system which is called after init_edsam */
+    if (MASTER(cr))
+    {
+        /* Remove pbc, make molecule whole.
+         * When ir->bContinuation=TRUE this has already been done, but ok.
+         */
+        snew(x_pbc,mtop->natoms);
+        m_rveccopy(mtop->natoms,x,x_pbc);
+        do_pbc_first_mtop(NULL,ir->ePBC,box,mtop,x_pbc);
+
+        /* Reset pointer to first ED data set which contains the actual ED data */
+        edi=ed->edpar;
+
+        /* Loop over all ED/flooding data sets (usually only one, though) */
+        for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
+        {
+            /* We use srenew to allocate memory since the size of the buffers
+             * is likely to change with every ED dataset */
+            srenew(xfit  , edi->sref.nr );
+            srenew(xstart, edi->sav.nr  );
+
+            /* Extract the positions of the atoms to which will be fitted */
+            for (i=0; i < edi->sref.nr; i++)
+            {
+                copy_rvec(x_pbc[edi->sref.anrs[i]], xfit[i]);
+
+                /* Save the sref positions such that in the next time step the molecule can
+                 * be made whole again (in the parallel case) */
+                if (PAR(cr))
+                    copy_rvec(xfit[i], edi->sref.x_old[i]);
+            }
+
+            /* Extract the positions of the atoms subject to ED sampling */
+            for (i=0; i < edi->sav.nr; i++)
+            {
+                copy_rvec(x_pbc[edi->sav.anrs[i]], xstart[i]);
+
+                /* Save the sav positions such that in the next time step the molecule can
+                 * be made whole again (in the parallel case) */
+                if (PAR(cr))
+                    copy_rvec(xstart[i], edi->sav.x_old[i]);
+            }
+
+            /* Make the fit to the REFERENCE structure, get translation and rotation */
+            fit_to_reference(xfit, fit_transvec, fit_rotmat, edi);
+
+            /* Output how well we fit to the reference at the start */
+            translate_and_rotate(xfit, edi->sref.nr, fit_transvec, fit_rotmat);
+            fprintf(stderr, "ED: Initial RMSD from reference after fit = %f nm (dataset #%d)\n",
+                    rmsd_from_structure(xfit, &edi->sref), nr_edi);
+
+            /* Now apply the translation and rotation to the atoms on which ED sampling will be performed */
+            translate_and_rotate(xstart, edi->sav.nr, fit_transvec, fit_rotmat);
+
+            /* calculate initial projections */
+            project(xstart, edi);
+
+            /* process target structure, if required */
+            if (edi->star.nr > 0)
+            {
+                fprintf(stderr, "ED: Fitting target structure to reference structure\n");
+                /* get translation & rotation for fit of target structure to reference structure */
+                fit_to_reference(edi->star.x, fit_transvec, fit_rotmat, edi);
+                /* do the fit */
+                translate_and_rotate(edi->star.x, edi->sav.nr, fit_transvec, fit_rotmat);
+                rad_project(edi, edi->star.x, &edi->vecs.radcon, cr);
+            } else
+                rad_project(edi, xstart, &edi->vecs.radcon, cr);
+
+            /* process structure that will serve as origin of expansion circle */
+            if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
+                fprintf(stderr, "ED: Setting center of flooding potential (0 = average structure)\n");
+            if (edi->sori.nr > 0)
+            {
+                fprintf(stderr, "ED: Fitting origin structure to reference structure\n");
+                /* fit this structure to reference structure */
+                fit_to_reference(edi->sori.x, fit_transvec, fit_rotmat, edi);
+                /* do the fit */
+                translate_and_rotate(edi->sori.x, edi->sav.nr, fit_transvec, fit_rotmat);
+                rad_project(edi, edi->sori.x, &edi->vecs.radacc, cr);
+                rad_project(edi, edi->sori.x, &edi->vecs.radfix, cr);
+                if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
+                {
+                    fprintf(stderr, "ED: The ORIGIN structure will define the flooding potential center.\n");
+                    /* Set center of flooding potential to the ORIGIN structure */
+                    rad_project(edi, edi->sori.x, &edi->flood.vecs, cr);
+                    /* We already know that no (moving) reference position was provided,
+                     * therefore we can overwrite refproj[0]*/
+                    copyEvecReference(&edi->flood.vecs);
+                }
+            }
+            else /* No origin structure given */
+            {
+                rad_project(edi, xstart, &edi->vecs.radacc, cr);
+                rad_project(edi, xstart, &edi->vecs.radfix, cr);
+                if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
+                {
+                    if (edi->flood.bHarmonic)
+                    {
+                        fprintf(stderr, "ED: A (possibly changing) ref. projection will define the flooding potential center.\n");
+                        for (i=0; i<edi->flood.vecs.neig; i++)
+                            edi->flood.vecs.refproj[i] = edi->flood.vecs.refproj0[i];
+                    }
+                    else
+                    {
+                        fprintf(stderr, "ED: The AVERAGE structure will define the flooding potential center.\n");
+                        /* Set center of flooding potential to the center of the covariance matrix,
+                         * i.e. the average structure, i.e. zero in the projected system */
+                        for (i=0; i<edi->flood.vecs.neig; i++)
+                            edi->flood.vecs.refproj[i] = 0.0;
+                    }
+                }
+            }
+            /* For convenience, output the center of the flooding potential for the eigenvectors */
+            if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
+            {
+                for (i=0; i<edi->flood.vecs.neig; i++)
+                {
+                    fprintf(stdout, "ED: EV %d flooding potential center: %11.4e", i, edi->flood.vecs.refproj[i]);
+                    if (edi->flood.bHarmonic)
+                        fprintf(stdout, " (adding %11.4e/timestep)", edi->flood.vecs.refprojslope[i]);
+                    fprintf(stdout, "\n");
+                }
+            }
+
+            /* set starting projections for linsam */
+            rad_project(edi, xstart, &edi->vecs.linacc, cr);
+            rad_project(edi, xstart, &edi->vecs.linfix, cr);
+
+            /* Output to file, set the step to -1 so that write_edo knows it was called from init_edsam */
+            if (ed->edo && !(ed->bStartFromCpt))
+                write_edo(nr_edi, edi, ed, -1, 0);
+
+            /* Prepare for the next edi data set: */
+            edi=edi->next_edi;
+        }
+        /* Cleaning up on the master node: */
+        sfree(x_pbc);
+        sfree(xfit);
+        sfree(xstart);
+
+    } /* end of MASTER only section */
+
+    if (PAR(cr))
+    {
+        /* First let everybody know how many ED data sets to expect */
+        gmx_bcast(sizeof(numedis), &numedis, cr);
+        /* Broadcast the essential dynamics / flooding data to all nodes */
+        broadcast_ed_data(cr, ed, numedis);
+    }
+    else
+    {
+        /* In the single-CPU case, point the local atom numbers pointers to the global
+         * one, so that we can use the same notation in serial and parallel case: */
+
+        /* Loop over all ED data sets (usually only one, though) */
+        edi=ed->edpar;
+        for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
+        {
+            edi->sref.anrs_loc = edi->sref.anrs;
+            edi->sav.anrs_loc  = edi->sav.anrs;
+            edi->star.anrs_loc = edi->star.anrs;
+            edi->sori.anrs_loc = edi->sori.anrs;
+            /* For the same reason as above, make a dummy c_ind array: */
+            snew(edi->sav.c_ind, edi->sav.nr);
+            /* Initialize the array */
+            for (i=0; i<edi->sav.nr; i++)
+                edi->sav.c_ind[i] = i;
+            /* In the general case we will need a different-sized array for the reference indices: */
+            if (!edi->bRefEqAv)
+            {
+                snew(edi->sref.c_ind, edi->sref.nr);
+                for (i=0; i<edi->sref.nr; i++)
+                    edi->sref.c_ind[i] = i;
+            }
+            /* Point to the very same array in case of other structures: */
+            edi->star.c_ind = edi->sav.c_ind;
+            edi->sori.c_ind = edi->sav.c_ind;
+            /* In the serial case, the local number of atoms is the global one: */
+            edi->sref.nr_loc = edi->sref.nr;
+            edi->sav.nr_loc  = edi->sav.nr;
+            edi->star.nr_loc = edi->star.nr;
+            edi->sori.nr_loc = edi->sori.nr;
+
+            /* An on we go to the next edi dataset */
+            edi=edi->next_edi;
+        }
+    }
+
+    /* Allocate space for ED buffer variables */
+    /* Again, loop over ED data sets */
+    edi=ed->edpar;
+    for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
+    {
+        /* Allocate space for ED buffer */
+        snew(edi->buf, 1);
+        snew(edi->buf->do_edsam, 1);
+
+        /* Space for collective ED buffer variables */
+
+        /* Collective positions of atoms with the average indices */
+        snew(edi->buf->do_edsam->xcoll                  , edi->sav.nr);
+        snew(edi->buf->do_edsam->shifts_xcoll           , edi->sav.nr); /* buffer for xcoll shifts */
+        snew(edi->buf->do_edsam->extra_shifts_xcoll     , edi->sav.nr);
+        /* Collective positions of atoms with the reference indices */
+        if (!edi->bRefEqAv)
+        {
+            snew(edi->buf->do_edsam->xc_ref             , edi->sref.nr);
+            snew(edi->buf->do_edsam->shifts_xc_ref      , edi->sref.nr); /* To store the shifts in */
+            snew(edi->buf->do_edsam->extra_shifts_xc_ref, edi->sref.nr);
+        }
+
+        /* Get memory for flooding forces */
+        snew(edi->flood.forces_cartesian                , edi->sav.nr);
+
+#ifdef DUMPEDI
+        /* Dump it all into one file per process */
+        dump_edi(edi, cr, nr_edi);
+#endif
+
+        /* An on we go to the next edi dataset */
+        edi=edi->next_edi;
+    }
+
+    /* Flush the edo file so that the user can check some things
+     * when the simulation has started */
+    if (ed->edo)
+        fflush(ed->edo);
+}
+
+
+void do_edsam(t_inputrec  *ir,
+              gmx_large_int_t step,
+              t_mdatoms   *md,
+              t_commrec   *cr,
+              rvec        xs[],   /* The local current positions on this processor */
+              rvec        v[],    /* The velocities */
+              matrix      box,
+              gmx_edsam_t ed)
+{
+    int     i,edinr,iupdate=500;
+    matrix  rotmat;         /* rotation matrix */
+    rvec    transvec;       /* translation vector */
+    rvec    dv,dx,x_unsh;   /* tmp vectors for velocity, distance, unshifted x coordinate */
+    real    dt_1;           /* 1/dt */
+    struct t_do_edsam *buf;
+    t_edpar *edi;
+    real    rmsdev=-1;      /* RMSD from reference structure prior to applying the constraints */
+    gmx_bool bSuppress=FALSE; /* Write .edo file on master? */
+
+
+    /* Check if ED sampling has to be performed */
+    if ( ed->eEDtype==eEDnone )
+        return;
+
+    /* Suppress output on first call of do_edsam if
+     * two-step sd2 integrator is used */
+    if ( (ir->eI==eiSD2) && (v != NULL) )
+        bSuppress = TRUE;
+
+    dt_1 = 1.0/ir->delta_t;
+
+    /* Loop over all ED datasets (usually one) */
+    edi  = ed->edpar;
+    edinr = 0;
+    while (edi != NULL)
+    {
+        edinr++;
+        if (edi->bNeedDoEdsam)
+        {
+
+            buf=edi->buf->do_edsam;
+
+            if (ed->bFirst)
+                /* initialise radacc radius for slope criterion */
+                buf->oldrad=calc_radius(&edi->vecs.radacc);
+
+            /* Copy the positions into buf->xc* arrays and after ED
+             * feed back corrections to the official positions */
+
+            /* Broadcast the ED positions such that every node has all of them
+             * Every node contributes its local positions xs and stores it in
+             * the collective buf->xcoll array. Note that for edinr > 1
+             * xs could already have been modified by an earlier ED */
+
+            communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, buf->bUpdateShifts, xs,
+                    edi->sav.nr, edi->sav.nr_loc, edi->sav.anrs_loc, edi->sav.c_ind, edi->sav.x_old,  box);
+
+#ifdef DEBUG_ED
+            dump_xcoll(edi, buf, cr, step);
+#endif
+            /* Only assembly reference positions if their indices differ from the average ones */
+            if (!edi->bRefEqAv)
+                communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, buf->bUpdateShifts, xs,
+                        edi->sref.nr, edi->sref.nr_loc, edi->sref.anrs_loc, edi->sref.c_ind, edi->sref.x_old, box);
+
+            /* If bUpdateShifts was TRUE then the shifts have just been updated in get_positions.
+             * We do not need to uptdate the shifts until the next NS step */
+            buf->bUpdateShifts = FALSE;
+
+            /* Now all nodes have all of the ED positions in edi->sav->xcoll,
+             * as well as the indices in edi->sav.anrs */
+
+            /* Fit the reference indices to the reference structure */
+            if (edi->bRefEqAv)
+                fit_to_reference(buf->xcoll , transvec, rotmat, edi);
+            else
+                fit_to_reference(buf->xc_ref, transvec, rotmat, edi);
+
+            /* Now apply the translation and rotation to the ED structure */
+            translate_and_rotate(buf->xcoll, edi->sav.nr, transvec, rotmat);
+
+            /* Find out how well we fit to the reference (just for output steps) */
+            if (do_per_step(step,edi->outfrq) && MASTER(cr))
+            {
+                if (edi->bRefEqAv)
+                {
+                    /* Indices of reference and average structures are identical,
+                     * thus we can calculate the rmsd to SREF using xcoll */
+                    rmsdev = rmsd_from_structure(buf->xcoll,&edi->sref);
+                }
+                else
+                {
+                    /* We have to translate & rotate the reference atoms first */
+                    translate_and_rotate(buf->xc_ref, edi->sref.nr, transvec, rotmat);
+                    rmsdev = rmsd_from_structure(buf->xc_ref,&edi->sref);
+                }
+            }
+
+            /* update radsam references, when required */
+            if (do_per_step(step,edi->maxedsteps) && step >= edi->presteps)
+            {
+                project(buf->xcoll, edi);
+                rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
+                rad_project(edi, buf->xcoll, &edi->vecs.radfix, cr);
+                buf->oldrad=-1.e5;
+            }
+
+            /* update radacc references, when required */
+            if (do_per_step(step,iupdate) && step >= edi->presteps)
+            {
+                edi->vecs.radacc.radius = calc_radius(&edi->vecs.radacc);
+                if (edi->vecs.radacc.radius - buf->oldrad < edi->slope)
+                {
+                    project(buf->xcoll, edi);
+                    rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
+                    buf->oldrad = 0.0;
+                } else
+                    buf->oldrad = edi->vecs.radacc.radius;
+            }
+
+            /* apply the constraints */
+            if (step >= edi->presteps && ed_constraints(ed->eEDtype, edi))
+            {
+                /* ED constraints should be applied already in the first MD step
+                 * (which is step 0), therefore we pass step+1 to the routine */
+                ed_apply_constraints(buf->xcoll, edi, step+1 - ir->init_step, cr);
+            }
+
+            /* write to edo, when required */
+            if (do_per_step(step,edi->outfrq))
+            {
+                project(buf->xcoll, edi);
+                if (MASTER(cr) && !bSuppress)
+                    write_edo(edinr, edi, ed, step, rmsdev);
+            }
+
+            /* Copy back the positions unless monitoring only */
+            if (ed_constraints(ed->eEDtype, edi))
+            {
+                /* remove fitting */
+                rmfit(edi->sav.nr, buf->xcoll, transvec, rotmat);
+
+                /* Copy the ED corrected positions into the coordinate array */
+                /* Each node copies its local part. In the serial case, nat_loc is the
+                 * total number of ED atoms */
+                for (i=0; i<edi->sav.nr_loc; i++)
+                {
+                    /* Unshift local ED coordinate and store in x_unsh */
+                    ed_unshift_single_coord(box, buf->xcoll[edi->sav.c_ind[i]],
+                                            buf->shifts_xcoll[edi->sav.c_ind[i]], x_unsh);
+
+                    /* dx is the ED correction to the positions: */
+                    rvec_sub(x_unsh, xs[edi->sav.anrs_loc[i]], dx);
+
+                    if (v != NULL)
+                    {
+                        /* dv is the ED correction to the velocity: */
+                        svmul(dt_1, dx, dv);
+                        /* apply the velocity correction: */
+                        rvec_inc(v[edi->sav.anrs_loc[i]], dv);
+                    }
+                    /* Finally apply the position correction due to ED: */
+                    copy_rvec(x_unsh, xs[edi->sav.anrs_loc[i]]);
+                }
+            }
+        } /* END of if (edi->bNeedDoEdsam) */
+
+        /* Prepare for the next ED dataset */
+        edi = edi->next_edi;
+
+    } /* END of loop over ED datasets */
+
+    ed->bFirst = FALSE;
+}
similarity index 100%
rename from src/mdlib/ewald.c
rename to src/gromacs/mdlib/ewald.c
similarity index 100%
rename from src/mdlib/fft5d.c
rename to src/gromacs/mdlib/fft5d.c
similarity index 100%
rename from src/mdlib/fft5d.h
rename to src/gromacs/mdlib/fft5d.h
diff --git a/src/gromacs/mdlib/force.c b/src/gromacs/mdlib/force.c
new file mode 100644 (file)
index 0000000..de28448
--- /dev/null
@@ -0,0 +1,739 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+#include "sysstuff.h"
+#include "typedefs.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "macros.h"
+#include "physics.h"
+#include "force.h"
+#include "nonbonded.h"
+#include "names.h"
+#include "network.h"
+#include "pbc.h"
+#include "ns.h"
+#include "nrnb.h"
+#include "bondf.h"
+#include "mshift.h"
+#include "txtdump.h"
+#include "coulomb.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdrun.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "qmmm.h"
+
+
+void ns(FILE *fp,
+        t_forcerec *fr,
+        rvec       x[],
+        matrix     box,
+        gmx_groups_t *groups,
+        t_grpopts  *opts,
+        gmx_localtop_t *top,
+        t_mdatoms  *md,
+        t_commrec  *cr,
+        t_nrnb     *nrnb,
+        real       lambda,
+        real       *dvdlambda,
+        gmx_grppairener_t *grppener,
+        gmx_bool       bFillGrid,
+        gmx_bool       bDoLongRange,
+        gmx_bool       bDoForces,
+        rvec       *f)
+{
+  char   *ptr;
+  int    nsearch;
+
+
+  if (!fr->ns.nblist_initialized)
+  {
+      init_neighbor_list(fp, fr, md->homenr);
+  }
+    
+  if (fr->bTwinRange) 
+    fr->nlr=0;
+
+    nsearch = search_neighbours(fp,fr,x,box,top,groups,cr,nrnb,md,
+                                lambda,dvdlambda,grppener,
+                                bFillGrid,bDoLongRange,
+                                bDoForces,f);
+  if (debug)
+    fprintf(debug,"nsearch = %d\n",nsearch);
+    
+  /* Check whether we have to do dynamic load balancing */
+  /*if ((nsb->nstDlb > 0) && (mod(step,nsb->nstDlb) == 0))
+    count_nb(cr,nsb,&(top->blocks[ebCGS]),nns,fr->nlr,
+    &(top->idef),opts->ngener);
+  */
+  if (fr->ns.dump_nl > 0)
+    dump_nblist(fp,cr,fr,fr->ns.dump_nl);
+}
+
+void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
+                       t_forcerec *fr,      t_inputrec *ir,
+                       t_idef     *idef,    t_commrec  *cr,
+                       t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
+                       t_mdatoms  *md,
+                       t_grpopts  *opts,
+                       rvec       x[],      history_t  *hist,
+                       rvec       f[],
+                       gmx_enerdata_t *enerd,
+                       t_fcdata   *fcd,
+                       gmx_mtop_t     *mtop,
+                       gmx_localtop_t *top,
+                       gmx_genborn_t *born,
+                       t_atomtypes *atype,
+                       gmx_bool       bBornRadii,
+                       matrix     box,
+                       real       lambda,  
+                       t_graph    *graph,
+                       t_blocka   *excl,    
+                       rvec       mu_tot[],
+                       int        flags,
+                       float      *cycles_pme)
+{
+    int     i,status;
+    int     donb_flags;
+    gmx_bool    bDoEpot,bSepDVDL,bSB;
+    int     pme_flags;
+    matrix  boxs;
+    rvec    box_size;
+    real    dvdlambda,Vsr,Vlr,Vcorr=0,vdip,vcharge;
+    t_pbc   pbc;
+    real    dvdgb;
+    char    buf[22];
+    gmx_enerdata_t ed_lam;
+    double  lam_i;
+    real    dvdl_dum;
+
+#ifdef GMX_MPI
+    double  t0=0.0,t1,t2,t3; /* time measurement for coarse load balancing */
+#endif
+    
+#define PRINT_SEPDVDL(s,v,dvdl) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdl);
+    
+
+    set_pbc(&pbc,fr->ePBC,box);
+    
+    /* Reset box */
+    for(i=0; (i<DIM); i++)
+    {
+        box_size[i]=box[i][i];
+    }
+    
+    bSepDVDL=(fr->bSepDVDL && do_per_step(step,ir->nstlog));
+    debug_gmx();
+    
+    /* do QMMM first if requested */
+    if(fr->bQMMM)
+    {
+        enerd->term[F_EQM] = calculate_QMMM(cr,x,f,fr,md);
+    }
+    
+    if (bSepDVDL)
+    {
+        fprintf(fplog,"Step %s: non-bonded V and dVdl for node %d:\n",
+                gmx_step_str(step,buf),cr->nodeid);
+    }
+    
+    /* Call the short range functions all in one go. */
+    
+    dvdlambda = 0;
+    
+#ifdef GMX_MPI
+    /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
+#define TAKETIME FALSE
+    if (TAKETIME)
+    {
+        MPI_Barrier(cr->mpi_comm_mygroup);
+        t0=MPI_Wtime();
+    }
+#endif
+    
+    if (ir->nwall)
+    {
+        dvdlambda = do_walls(ir,fr,box,md,x,f,lambda,
+                             enerd->grpp.ener[egLJSR],nrnb);
+        PRINT_SEPDVDL("Walls",0.0,dvdlambda);
+        enerd->dvdl_lin += dvdlambda;
+    }
+               
+       /* If doing GB, reset dvda and calculate the Born radii */
+       if (ir->implicit_solvent)
+       {
+               /* wallcycle_start(wcycle,ewcGB); */
+               
+               for(i=0;i<born->nr;i++)
+               {
+                       fr->dvda[i]=0;
+               }
+               
+               if(bBornRadii)
+               {
+                       calc_gb_rad(cr,fr,ir,top,atype,x,&(fr->gblist),born,md,nrnb);
+               }
+               
+               /* wallcycle_stop(wcycle, ewcGB); */
+       }
+       
+    where();
+    donb_flags = 0;
+    if (flags & GMX_FORCE_FORCES)
+    {
+        donb_flags |= GMX_DONB_FORCES;
+    }
+    do_nonbonded(cr,fr,x,f,md,excl,
+                 fr->bBHAM ?
+                 enerd->grpp.ener[egBHAMSR] :
+                 enerd->grpp.ener[egLJSR],
+                 enerd->grpp.ener[egCOULSR],
+                                enerd->grpp.ener[egGB],box_size,nrnb,
+                 lambda,&dvdlambda,-1,-1,donb_flags);
+    /* If we do foreign lambda and we have soft-core interactions
+     * we have to recalculate the (non-linear) energies contributions.
+     */
+    if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && ir->sc_alpha != 0)
+    {
+        init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
+        
+        for(i=0; i<enerd->n_lambda; i++)
+        {
+            lam_i = (i==0 ? lambda : ir->flambda[i-1]);
+            dvdl_dum = 0;
+            reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
+            do_nonbonded(cr,fr,x,f,md,excl,
+                         fr->bBHAM ?
+                         ed_lam.grpp.ener[egBHAMSR] :
+                         ed_lam.grpp.ener[egLJSR],
+                         ed_lam.grpp.ener[egCOULSR],
+                         enerd->grpp.ener[egGB], box_size,nrnb,
+                         lam_i,&dvdl_dum,-1,-1,
+                         GMX_DONB_FOREIGNLAMBDA);
+            sum_epot(&ir->opts,&ed_lam);
+            enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
+        }
+        destroy_enerdata(&ed_lam);
+    }
+    where();
+       
+       /* If we are doing GB, calculate bonded forces and apply corrections 
+        * to the solvation forces */
+       if (ir->implicit_solvent)  {
+               calc_gb_forces(cr,md,born,top,atype,x,f,fr,idef,
+                       ir->gb_algorithm,ir->sa_algorithm,nrnb,bBornRadii,&pbc,graph,enerd);
+    }
+
+#ifdef GMX_MPI
+    if (TAKETIME)
+    {
+        t1=MPI_Wtime();
+        fr->t_fnbf += t1-t0;
+    }
+#endif
+    
+    if (ir->sc_alpha != 0)
+    {
+        enerd->dvdl_nonlin += dvdlambda;
+    }
+    else
+    {
+        enerd->dvdl_lin    += dvdlambda;
+    }
+    Vsr = 0;
+    if (bSepDVDL)
+    {
+        for(i=0; i<enerd->grpp.nener; i++)
+        {
+            Vsr +=
+                (fr->bBHAM ?
+                 enerd->grpp.ener[egBHAMSR][i] :
+                 enerd->grpp.ener[egLJSR][i])
+                + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
+        }
+    }
+    PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlambda);
+    debug_gmx();
+    
+    if (debug)
+    {
+        pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS);
+    }
+    
+    /* Shift the coordinates. Must be done before bonded forces and PPPM, 
+     * but is also necessary for SHAKE and update, therefore it can NOT 
+     * go when no bonded forces have to be evaluated.
+     */
+    
+    /* Here sometimes we would not need to shift with NBFonly,
+     * but we do so anyhow for consistency of the returned coordinates.
+     */
+    if (graph)
+    {
+        shift_self(graph,box,x);
+        if (TRICLINIC(box))
+        {
+            inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes);
+        }
+        else
+        {
+            inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes);
+        }
+    }
+    /* Check whether we need to do bondeds or correct for exclusions */
+    if (fr->bMolPBC &&
+        ((flags & GMX_FORCE_BONDED)
+         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
+    {
+        /* Since all atoms are in the rectangular or triclinic unit-cell,
+         * only single box vector shifts (2 in x) are required.
+         */
+        set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box);
+    }
+    debug_gmx();
+    
+    if (flags & GMX_FORCE_BONDED)
+    {
+        calc_bonds(fplog,cr->ms,
+                   idef,x,hist,f,fr,&pbc,graph,enerd,nrnb,lambda,md,fcd,
+                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
+                   fr->bSepDVDL && do_per_step(step,ir->nstlog),step);
+        
+        /* Check if we have to determine energy differences
+         * at foreign lambda's.
+         */
+        if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) &&
+            idef->ilsort != ilsortNO_FE)
+        {
+            if (idef->ilsort != ilsortFE_SORTED)
+            {
+                gmx_incons("The bonded interactions are not sorted for free energy");
+            }
+            init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
+            
+            for(i=0; i<enerd->n_lambda; i++)
+            {
+                lam_i = (i==0 ? lambda : ir->flambda[i-1]);
+                dvdl_dum = 0;
+                reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
+                calc_bonds_lambda(fplog,
+                                  idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md,
+                                  fcd,
+                                  DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
+                sum_epot(&ir->opts,&ed_lam);
+                enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
+            }
+            destroy_enerdata(&ed_lam);
+        }
+        debug_gmx();
+    }
+
+    where();
+
+    *cycles_pme = 0;
+    if (EEL_FULL(fr->eeltype))
+    {
+        bSB = (ir->nwall == 2);
+        if (bSB)
+        {
+            copy_mat(box,boxs);
+            svmul(ir->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
+            box_size[ZZ] *= ir->wall_ewald_zfac;
+        }
+        
+        clear_mat(fr->vir_el_recip);   
+        
+        if (fr->bEwald)
+        {
+            if (fr->n_tpi == 0)
+            {
+                dvdlambda = 0;
+                Vcorr = ewald_LRcorrection(fplog,md->start,md->start+md->homenr,
+                                           cr,fr,
+                                           md->chargeA,
+                                           md->nChargePerturbed ? md->chargeB : NULL,
+                                           excl,x,bSB ? boxs : box,mu_tot,
+                                           ir->ewald_geometry,
+                                           ir->epsilon_surface,
+                                           lambda,&dvdlambda,&vdip,&vcharge);
+                PRINT_SEPDVDL("Ewald excl./charge/dip. corr.",Vcorr,dvdlambda);
+                enerd->dvdl_lin += dvdlambda;
+            }
+            else
+            {
+                if (ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0)
+                {
+                    gmx_fatal(FARGS,"TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions");
+                }
+                /* The TPI molecule does not have exclusions with the rest
+                 * of the system and no intra-molecular PME grid contributions
+                 * will be calculated in gmx_pme_calc_energy.
+                 */
+                Vcorr = 0;
+            }
+        }
+        else
+        {
+            Vcorr = shift_LRcorrection(fplog,md->start,md->homenr,cr,fr,
+                                       md->chargeA,excl,x,TRUE,box,
+                                       fr->vir_el_recip);
+        }
+        
+        dvdlambda = 0;
+        status = 0;
+        switch (fr->eeltype)
+        {
+        case eelPPPM:
+            status = gmx_pppm_do(fplog,fr->pmedata,FALSE,x,fr->f_novirsum,
+                                 md->chargeA,
+                                 box_size,fr->phi,cr,md->start,md->homenr,
+                                 nrnb,ir->pme_order,&Vlr);
+            break;
+        case eelPME:
+        case eelPMESWITCH:
+        case eelPMEUSER:
+        case eelPMEUSERSWITCH:
+            if (cr->duty & DUTY_PME)
+            {
+                if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
+                {
+                    pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE;
+                    if (flags & GMX_FORCE_FORCES)
+                    {
+                        pme_flags |= GMX_PME_CALC_F;
+                    }
+                    if (flags & GMX_FORCE_VIRIAL)
+                    {
+                        pme_flags |= GMX_PME_CALC_ENER_VIR;
+                    }
+                    if (fr->n_tpi > 0)
+                    {
+                        /* We don't calculate f, but we do want the potential */
+                        pme_flags |= GMX_PME_CALC_POT;
+                    }
+                    wallcycle_start(wcycle,ewcPMEMESH);
+                    status = gmx_pme_do(fr->pmedata,
+                                        md->start,md->homenr - fr->n_tpi,
+                                        x,fr->f_novirsum,
+                                        md->chargeA,md->chargeB,
+                                        bSB ? boxs : box,cr,
+                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
+                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
+                                        nrnb,wcycle,
+                                        fr->vir_el_recip,fr->ewaldcoeff,
+                                        &Vlr,lambda,&dvdlambda,
+                                        pme_flags);
+                    *cycles_pme = wallcycle_stop(wcycle,ewcPMEMESH);
+
+                    /* We should try to do as little computation after
+                     * this as possible, because parallel PME synchronizes
+                     * the nodes, so we want all load imbalance of the rest
+                     * of the force calculation to be before the PME call.
+                     * DD load balancing is done on the whole time of
+                     * the force call (without PME).
+                     */
+                }
+                if (fr->n_tpi > 0)
+                {
+                    /* Determine the PME grid energy of the test molecule
+                     * with the PME grid potential of the other charges.
+                     */
+                    gmx_pme_calc_energy(fr->pmedata,fr->n_tpi,
+                                        x + md->homenr - fr->n_tpi,
+                                        md->chargeA + md->homenr - fr->n_tpi,
+                                        &Vlr);
+                }
+                PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda);
+            } 
+            else
+            {
+                /* Energies and virial are obtained later from the PME nodes */
+                /* but values have to be zeroed out here */
+                Vlr=0.0;
+            }
+            break;
+        case eelEWALD:
+            Vlr = do_ewald(fplog,FALSE,ir,x,fr->f_novirsum,
+                           md->chargeA,md->chargeB,
+                           box_size,cr,md->homenr,
+                           fr->vir_el_recip,fr->ewaldcoeff,
+                           lambda,&dvdlambda,fr->ewald_table);
+            PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda);
+            break;
+        default:
+            Vlr = 0;
+            gmx_fatal(FARGS,"No such electrostatics method implemented %s",
+                      eel_names[fr->eeltype]);
+        }
+        if (status != 0)
+        {
+            gmx_fatal(FARGS,"Error %d in long range electrostatics routine %s",
+                      status,EELTYPE(fr->eeltype));
+               }
+        enerd->dvdl_lin += dvdlambda;
+        enerd->term[F_COUL_RECIP] = Vlr + Vcorr;
+        if (debug)
+        {
+            fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
+                    Vlr,Vcorr,enerd->term[F_COUL_RECIP]);
+            pr_rvecs(debug,0,"vir_el_recip after corr",fr->vir_el_recip,DIM);
+            pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS);
+        }
+    }
+    else
+    {
+        if (EEL_RF(fr->eeltype))
+        {
+            dvdlambda = 0;
+            
+            if (fr->eeltype != eelRF_NEC)
+            {
+                enerd->term[F_RF_EXCL] =
+                    RF_excl_correction(fplog,fr,graph,md,excl,x,f,
+                                       fr->fshift,&pbc,lambda,&dvdlambda);
+            }
+            
+            enerd->dvdl_lin += dvdlambda;
+            PRINT_SEPDVDL("RF exclusion correction",
+                          enerd->term[F_RF_EXCL],dvdlambda);
+        }
+    }
+    where();
+    debug_gmx();
+       
+    if (debug)
+    {
+        print_nrnb(debug,nrnb); 
+    }
+    debug_gmx();
+    
+#ifdef GMX_MPI
+    if (TAKETIME)
+    {
+        t2=MPI_Wtime();
+        MPI_Barrier(cr->mpi_comm_mygroup);
+        t3=MPI_Wtime();
+        fr->t_wait += t3-t2;
+        if (fr->timesteps == 11)
+        {
+            fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", 
+                    cr->nodeid, gmx_step_str(fr->timesteps,buf), 
+                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf), 
+                    (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
+        }        
+        fr->timesteps++;
+    }
+#endif
+    
+    if (debug)
+    {
+        pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS);
+    }
+    
+}
+
+void init_enerdata(int ngener,int n_flambda,gmx_enerdata_t *enerd)
+{
+    int i,n2;
+    
+    for(i=0; i<F_NRE; i++)
+    {
+        enerd->term[i] = 0;
+    }
+    
+    n2=ngener*ngener;
+    if (debug)
+    {
+        fprintf(debug,"Creating %d sized group matrix for energies\n",n2);
+    }
+    enerd->grpp.nener = n2;
+    for(i=0; (i<egNR); i++)
+    {
+        snew(enerd->grpp.ener[i],n2);
+    }
+
+    if (n_flambda)
+    {
+        enerd->n_lambda = 1 + n_flambda;
+        snew(enerd->enerpart_lambda,enerd->n_lambda);
+    }
+    else
+    {
+        enerd->n_lambda = 0;
+    }
+}
+
+void destroy_enerdata(gmx_enerdata_t *enerd)
+{
+    int i;
+
+    for(i=0; (i<egNR); i++)
+    {
+        sfree(enerd->grpp.ener[i]);
+    }
+
+    if (enerd->n_lambda)
+    {
+        sfree(enerd->enerpart_lambda);
+    }
+}
+
+static real sum_v(int n,real v[])
+{
+  real t;
+  int  i;
+  
+  t = 0.0;
+  for(i=0; (i<n); i++)
+    t = t + v[i];
+    
+  return t;
+}
+
+void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd)
+{
+  gmx_grppairener_t *grpp;
+  real *epot;
+  int i;
+  
+  grpp = &enerd->grpp;
+  epot = enerd->term;
+
+  /* Accumulate energies */
+  epot[F_COUL_SR]  = sum_v(grpp->nener,grpp->ener[egCOULSR]);
+  epot[F_LJ]       = sum_v(grpp->nener,grpp->ener[egLJSR]);
+  epot[F_LJ14]     = sum_v(grpp->nener,grpp->ener[egLJ14]);
+  epot[F_COUL14]   = sum_v(grpp->nener,grpp->ener[egCOUL14]);
+  epot[F_COUL_LR]  = sum_v(grpp->nener,grpp->ener[egCOULLR]);
+  epot[F_LJ_LR]    = sum_v(grpp->nener,grpp->ener[egLJLR]);
+  /* We have already added 1-2,1-3, and 1-4 terms to F_GBPOL */
+  epot[F_GBPOL]   += sum_v(grpp->nener,grpp->ener[egGB]);
+    
+/* lattice part of LR doesnt belong to any group
+ * and has been added earlier
+ */
+  epot[F_BHAM]     = sum_v(grpp->nener,grpp->ener[egBHAMSR]);
+  epot[F_BHAM_LR]  = sum_v(grpp->nener,grpp->ener[egBHAMLR]);
+
+  epot[F_EPOT] = 0;
+  for(i=0; (i<F_EPOT); i++)
+    if (i != F_DISRESVIOL && i != F_ORIRESDEV && i != F_DIHRESVIOL)
+      epot[F_EPOT] += epot[i];
+}
+
+void sum_dhdl(gmx_enerdata_t *enerd,double lambda,t_inputrec *ir)
+{
+    int i;
+    double dlam,dhdl_lin;
+
+    enerd->term[F_DVDL] = enerd->dvdl_lin + enerd->dvdl_nonlin;
+
+    if (debug)
+    {
+        fprintf(debug,"dvdl: %f, non-linear %f + linear %f\n",
+                enerd->term[F_DVDL],enerd->dvdl_nonlin,enerd->dvdl_lin);
+    }
+
+    /* Notes on the foreign lambda free energy difference evaluation:
+     * Adding the potential and ekin terms that depend linearly on lambda
+     * as delta lam * dvdl to the energy differences is exact.
+     * For the constraint dvdl this is not exact, but we have no other option.
+     * For the non-bonded LR term we assume that the soft-core (if present)
+     * no longer affects the energy beyond the short-range cut-off,
+     * which is a very good approximation (except for exotic settings).
+     */
+    for(i=1; i<enerd->n_lambda; i++)
+    {
+        dlam = (ir->flambda[i-1] - lambda);
+        dhdl_lin =
+            enerd->dvdl_lin + enerd->term[F_DKDL] + enerd->term[F_DHDL_CON];
+        if (debug)
+        {
+            fprintf(debug,"enerdiff lam %g: non-linear %f linear %f*%f\n",
+                    ir->flambda[i-1],
+                    enerd->enerpart_lambda[i] - enerd->enerpart_lambda[0],
+                    dlam,dhdl_lin);
+        }
+        enerd->enerpart_lambda[i] += dlam*dhdl_lin;
+
+    }
+}
+
+void reset_enerdata(t_grpopts *opts,
+                    t_forcerec *fr,gmx_bool bNS,
+                    gmx_enerdata_t *enerd,
+                    gmx_bool bMaster)
+{
+  gmx_bool bKeepLR;
+  int  i,j;
+  
+  /* First reset all energy components, except for the long range terms
+   * on the master at non neighbor search steps, since the long range
+   * terms have already been summed at the last neighbor search step.
+   */
+  bKeepLR = (fr->bTwinRange && !bNS);
+  for(i=0; (i<egNR); i++) {
+    if (!(bKeepLR && bMaster && (i == egCOULLR || i == egLJLR))) {
+      for(j=0; (j<enerd->grpp.nener); j++)
+       enerd->grpp.ener[i][j] = 0.0;
+    }
+  }
+  enerd->dvdl_lin    = 0.0;
+  enerd->dvdl_nonlin = 0.0;
+
+  /* Normal potential energy components */
+  for(i=0; (i<=F_EPOT); i++) {
+    enerd->term[i] = 0.0;
+  }
+  /* Initialize the dVdlambda term with the long range contribution */
+  enerd->term[F_DVDL]     = 0.0;
+  enerd->term[F_DKDL]     = 0.0;
+  enerd->term[F_DHDL_CON] = 0.0;
+  if (enerd->n_lambda > 0)
+  {
+      for(i=0; i<enerd->n_lambda; i++)
+      {
+          enerd->enerpart_lambda[i] = 0.0;
+      }
+  }
+}
similarity index 100%
rename from src/mdlib/ghat.c
rename to src/gromacs/mdlib/ghat.c
diff --git a/src/gromacs/mdlib/gmx_wallcycle.c b/src/gromacs/mdlib/gmx_wallcycle.c
new file mode 100644 (file)
index 0000000..47fbcdc
--- /dev/null
@@ -0,0 +1,474 @@
+/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "gmx_wallcycle.h"
+#include "gmx_cyclecounter.h"
+#include "smalloc.h"
+#include "gmx_fatal.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+typedef struct
+{
+    int          n;
+    gmx_cycles_t c;
+    gmx_cycles_t start;
+    gmx_cycles_t last;
+} wallcc_t;
+
+typedef struct gmx_wallcycle
+{
+    wallcc_t     *wcc;
+    /* variables for testing/debugging */
+    gmx_bool         wc_barrier;
+    wallcc_t     *wcc_all;
+    int          wc_depth;
+    int          ewc_prev;
+    gmx_cycles_t cycle_prev;
+    gmx_large_int_t   reset_counters;
+#ifdef GMX_MPI
+    MPI_Comm     mpi_comm_mygroup;
+#endif
+} gmx_wallcycle_t_t;
+
+/* Each name should not exceed 19 characters */
+static const char *wcn[ewcNR] =
+{ "Run", "Step", "PP during PME", "Domain decomp.", "DD comm. load", "DD comm. bounds", "Vsite constr.", "Send X to PME", "Comm. coord.", "Neighbor search", "Born radii", "Force", "Wait + Comm. F", "PME mesh", "PME redist. X/F", "PME spread/gather", "PME 3D-FFT", "PME solve", "Wait + Comm. X/F", "Wait + Recv. PME F", "Vsite spread", "Write traj.", "Update", "Constraints", "Comm. energies", "Enforced rotation", "Test" };
+
+gmx_bool wallcycle_have_counter(void)
+{
+  return gmx_cycles_have_counter();
+}
+
+gmx_wallcycle_t wallcycle_init(FILE *fplog,int resetstep,t_commrec *cr)
+{
+    gmx_wallcycle_t wc;
+    
+    
+    if (!wallcycle_have_counter())
+    {
+        return NULL;
+    }
+
+    snew(wc,1);
+
+    wc->wc_barrier = FALSE;
+    wc->wcc_all    = NULL;
+    wc->wc_depth   = 0;
+    wc->ewc_prev   = -1;
+    wc->reset_counters = resetstep;
+
+#ifdef GMX_MPI
+    if (PAR(cr) && getenv("GMX_CYCLE_BARRIER") != NULL)
+    {
+        if (fplog) 
+        {
+            fprintf(fplog,"\nWill call MPI_Barrier before each cycle start/stop call\n\n");
+        }
+        wc->wc_barrier = TRUE;
+        wc->mpi_comm_mygroup = cr->mpi_comm_mygroup;
+    }
+#endif
+
+    snew(wc->wcc,ewcNR);
+    if (getenv("GMX_CYCLE_ALL") != NULL)
+    {
+/*#ifndef GMX_THREADS*/
+        if (fplog) 
+        {
+            fprintf(fplog,"\nWill time all the code during the run\n\n");
+        }
+        snew(wc->wcc_all,ewcNR*ewcNR);
+/*#else*/
+        gmx_fatal(FARGS, "GMX_CYCLE_ALL is incompatible with threaded code");
+/*#endif*/
+    }
+    
+    return wc;
+}
+
+void wallcycle_destroy(gmx_wallcycle_t wc)
+{
+    if (wc == NULL)
+    {
+        return;
+    }
+    
+    if (wc->wcc != NULL)
+    {
+        sfree(wc->wcc);
+    }
+    if (wc->wcc_all != NULL)
+    {
+        sfree(wc->wcc_all);
+    }
+    sfree(wc);
+}
+
+static void wallcycle_all_start(gmx_wallcycle_t wc,int ewc,gmx_cycles_t cycle)
+{
+    wc->ewc_prev = ewc;
+    wc->cycle_prev = cycle;
+}
+
+static void wallcycle_all_stop(gmx_wallcycle_t wc,int ewc,gmx_cycles_t cycle)
+{
+    wc->wcc_all[wc->ewc_prev*ewcNR+ewc].n += 1;
+    wc->wcc_all[wc->ewc_prev*ewcNR+ewc].c += cycle - wc->cycle_prev;
+}
+
+void wallcycle_start(gmx_wallcycle_t wc, int ewc)
+{
+    gmx_cycles_t cycle;
+
+    if (wc == NULL)
+    {
+        return;
+    }
+
+#ifdef GMX_MPI
+    if (wc->wc_barrier)
+    {
+        MPI_Barrier(wc->mpi_comm_mygroup);
+    }
+#endif
+
+    cycle = gmx_cycles_read();
+    wc->wcc[ewc].start = cycle;
+    if (wc->wcc_all != NULL)
+    {
+        wc->wc_depth++;
+        if (ewc == ewcRUN)
+        {
+            wallcycle_all_start(wc,ewc,cycle);
+        }
+        else if (wc->wc_depth == 3)
+        {
+            wallcycle_all_stop(wc,ewc,cycle);
+        }
+    }
+}
+
+double wallcycle_stop(gmx_wallcycle_t wc, int ewc)
+{
+    gmx_cycles_t cycle,last;
+    
+    if (wc == NULL)
+    {
+        return 0;
+    }
+    
+#ifdef GMX_MPI
+    if (wc->wc_barrier)
+    {
+        MPI_Barrier(wc->mpi_comm_mygroup);
+    }
+#endif
+    
+    cycle = gmx_cycles_read();
+    last = cycle - wc->wcc[ewc].start;
+    wc->wcc[ewc].c += last;
+    wc->wcc[ewc].n++;
+    if (wc->wcc_all)
+    {
+        wc->wc_depth--;
+        if (ewc == ewcRUN)
+        {
+            wallcycle_all_stop(wc,ewc,cycle);
+        }
+        else if (wc->wc_depth == 2)
+        {
+            wallcycle_all_start(wc,ewc,cycle);
+        }
+    }
+
+    return last;
+}
+
+void wallcycle_reset_all(gmx_wallcycle_t wc)
+{
+    int i;
+
+    if (wc == NULL)
+    {
+        return;
+    }
+
+    for(i=0; i<ewcNR; i++)
+    {
+        wc->wcc[i].n = 0;
+        wc->wcc[i].c = 0;
+        wc->wcc[i].start = 0;
+        wc->wcc[i].last = 0;
+    }
+}
+
+void wallcycle_sum(t_commrec *cr, gmx_wallcycle_t wc,double cycles[])
+{
+    wallcc_t *wcc;
+    double cycles_n[ewcNR],buf[ewcNR],*cyc_all,*buf_all;
+    int    i;
+
+    if (wc == NULL)
+    {
+        return;
+    }
+
+    wcc = wc->wcc;
+
+    if (wcc[ewcDDCOMMLOAD].n > 0)
+    {
+        wcc[ewcDOMDEC].c -= wcc[ewcDDCOMMLOAD].c;
+    }
+    if (wcc[ewcDDCOMMBOUND].n > 0)
+    {
+        wcc[ewcDOMDEC].c -= wcc[ewcDDCOMMBOUND].c;
+    }
+    if (cr->npmenodes == 0)
+    {
+        /* All nodes do PME (or no PME at all) */
+        if (wcc[ewcPMEMESH].n > 0)
+        {
+            wcc[ewcFORCE].c -= wcc[ewcPMEMESH].c;
+        }
+    }
+    else
+    {
+        /* The are PME-only nodes */
+        if (wcc[ewcPMEMESH].n > 0)
+        {
+            /* This must be a PME only node, calculate the Wait + Comm. time */
+            wcc[ewcPMEWAITCOMM].c = wcc[ewcRUN].c - wcc[ewcPMEMESH].c;
+        }
+    }
+    
+    /* Store the cycles in a double buffer for summing */
+    for(i=0; i<ewcNR; i++)
+    {
+        cycles_n[i] = (double)wcc[i].n;
+        cycles[i]   = (double)wcc[i].c;
+    }
+    
+#ifdef GMX_MPI
+    if (cr->nnodes > 1)
+    {
+        MPI_Allreduce(cycles_n,buf,ewcNR,MPI_DOUBLE,MPI_MAX,
+                      cr->mpi_comm_mysim);
+        for(i=0; i<ewcNR; i++)
+        {
+            wcc[i].n = (int)(buf[i] + 0.5);
+        }
+        MPI_Allreduce(cycles,buf,ewcNR,MPI_DOUBLE,MPI_SUM,
+                      cr->mpi_comm_mysim);
+        for(i=0; i<ewcNR; i++)
+        {
+            cycles[i] = buf[i];
+        }
+
+        if (wc->wcc_all != NULL)
+        {
+            snew(cyc_all,ewcNR*ewcNR);
+            snew(buf_all,ewcNR*ewcNR);
+            for(i=0; i<ewcNR*ewcNR; i++)
+            {
+                cyc_all[i] = wc->wcc_all[i].c;
+            }
+            MPI_Allreduce(cyc_all,buf_all,ewcNR*ewcNR,MPI_DOUBLE,MPI_SUM,
+                          cr->mpi_comm_mysim);
+            for(i=0; i<ewcNR*ewcNR; i++)
+            {
+                wc->wcc_all[i].c = buf_all[i];
+            }
+            sfree(buf_all);
+            sfree(cyc_all);
+        }
+    }
+#endif
+}
+
+static void print_cycles(FILE *fplog, double c2t, const char *name, int nnodes,
+                         int n, double c, double tot)
+{
+    char num[11];
+  
+    if (c > 0)
+    {
+        if (n > 0)
+        {
+            sprintf(num,"%10d",n);
+        }
+        else
+        {
+            sprintf(num,"          ");
+        }
+        fprintf(fplog," %-19s %4d %10s %12.3f %10.1f   %5.1f\n",
+                name,nnodes,num,c*1e-9,c*c2t,100*c/tot);
+    }
+}
+
+static gmx_bool subdivision(int ewc)
+{
+    return (ewc >= ewcPME_REDISTXF && ewc <= ewcPME_SOLVE);
+}
+
+void wallcycle_print(FILE *fplog, int nnodes, int npme, double realtime,
+                     gmx_wallcycle_t wc, double cycles[])
+{
+    double c2t,tot,sum;
+    int    i,j,npp;
+    char   buf[STRLEN];
+    const char *myline = "-----------------------------------------------------------------------";
+    
+    if (wc == NULL)
+    {
+        return;
+    }
+
+    if (npme > 0)
+    {
+        npp = nnodes - npme;
+    }
+    else
+    {
+        npp  = nnodes;
+        npme = nnodes;
+    }
+    tot = cycles[ewcRUN];
+    /* Conversion factor from cycles to seconds */
+    if (tot > 0)
+    {
+      c2t = nnodes*realtime/tot;
+    }
+    else
+    {
+      c2t = 0;
+    }
+
+    fprintf(fplog,"\n     R E A L   C Y C L E   A N D   T I M E   A C C O U N T I N G\n\n");
+
+    fprintf(fplog," Computing:         Nodes     Number     G-Cycles    Seconds     %c\n",'%');
+    fprintf(fplog,"%s\n",myline);
+    sum = 0;
+    for(i=ewcPPDURINGPME+1; i<ewcNR; i++)
+    {
+        if (!subdivision(i))
+        {
+            print_cycles(fplog,c2t,wcn[i],
+                         (i==ewcPMEMESH || i==ewcPMEWAITCOMM) ? npme : npp,
+                         wc->wcc[i].n,cycles[i],tot);
+            sum += cycles[i];
+        }
+    }
+    if (wc->wcc_all != NULL)
+    {
+        for(i=0; i<ewcNR; i++)
+        {
+            for(j=0; j<ewcNR; j++)
+            {
+                sprintf(buf,"%-9s",wcn[i]);
+                buf[9] = ' ';
+                sprintf(buf+10,"%-9s",wcn[j]);
+                buf[19] = '\0';
+                print_cycles(fplog,c2t,buf,
+                             (i==ewcPMEMESH || i==ewcPMEWAITCOMM) ? npme : npp,
+                             wc->wcc_all[i*ewcNR+j].n,
+                             wc->wcc_all[i*ewcNR+j].c,
+                             tot);
+            }
+        }
+    }
+    print_cycles(fplog,c2t,"Rest",npp,0,tot-sum,tot);
+    fprintf(fplog,"%s\n",myline);
+    print_cycles(fplog,c2t,"Total",nnodes,0,tot,tot);
+    fprintf(fplog,"%s\n",myline);
+    
+    if (wc->wcc[ewcPMEMESH].n > 0)
+    {
+        fprintf(fplog,"%s\n",myline);
+        for(i=ewcPPDURINGPME+1; i<ewcNR; i++)
+        {
+            if (subdivision(i))
+            {
+                print_cycles(fplog,c2t,wcn[i],
+                             (i>=ewcPMEMESH || i<=ewcPME_SOLVE) ? npme : npp,
+                             wc->wcc[i].n,cycles[i],tot);
+            }
+        }
+        fprintf(fplog,"%s\n",myline);
+    }
+
+    if (cycles[ewcMoveE] > tot*0.05)
+    {
+        sprintf(buf,
+                "NOTE: %d %% of the run time was spent communicating energies,\n"
+                "      you might want to use the -gcom option of mdrun\n",
+                (int)(100*cycles[ewcMoveE]/tot+0.5));
+        if (fplog)
+        {
+            fprintf(fplog,"\n%s\n",buf);
+        }
+        /* Only the sim master calls this function, so always print to stderr */
+        fprintf(stderr,"\n%s\n",buf);
+    }
+}
+
+extern gmx_large_int_t wcycle_get_reset_counters(gmx_wallcycle_t wc)
+{
+    if (wc == NULL)
+    {
+        return -1;
+    }
+    
+    return wc->reset_counters;
+}
+
+extern void wcycle_set_reset_counters(gmx_wallcycle_t wc, gmx_large_int_t reset_counters)
+{
+    if (wc == NULL)
+        return;
+
+    wc->reset_counters = reset_counters;
+}
diff --git a/src/gromacs/mdlib/groupcoord.c b/src/gromacs/mdlib/groupcoord.c
new file mode 100644 (file)
index 0000000..3ee2e40
--- /dev/null
@@ -0,0 +1,386 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 4.5
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "groupcoord.h"
+#include "network.h"
+#include "pbc.h"
+#include "vec.h"
+#include "smalloc.h"
+#include "gmx_ga2la.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+
+
+/* Select the indices of the group's atoms which are local and store them in 
+ * anrs_loc[0..nr_loc]. The indices are saved in coll_ind[] for later reduction
+ * in communicate_group_positions()
+ */
+extern void dd_make_local_group_indices(
+        gmx_ga2la_t   ga2la,
+        const int     nr,          /* IN:  Total number of atoms in the group */
+        int           anrs[],      /* IN:  Global atom numbers of the groups atoms */
+        int           *nr_loc,     /* OUT: Number of group atoms found locally */
+        int           *anrs_loc[], /* OUT: Local atom numbers of the group  */
+        int           *nalloc_loc, /* IN+OUT: Allocation size of anrs_loc */
+        int           coll_ind[])  /* OUT (opt): Where is this position found in the collective array? */
+{
+    int  i,ii;
+    int  localnr;       
+
+    
+    /* Loop over all the atom indices of the group to check
+     * which ones are on the local node */
+    localnr = 0;
+    for(i=0; i<nr; i++)
+    {
+        if (ga2la_get_home(ga2la,anrs[i],&ii))
+        {
+            /* The atom with this index is a home atom */
+            if (localnr >= *nalloc_loc) /* Check whether memory suffices */
+            {
+                *nalloc_loc = over_alloc_dd(localnr+1);
+                /* We never need more memory than the number of atoms in the group */
+                *nalloc_loc = MIN(*nalloc_loc, nr);
+                srenew(*anrs_loc,*nalloc_loc);
+            }
+            /* Save the atoms index in the local atom numbers array */
+            (*anrs_loc)[localnr] = ii;
+
+            if (coll_ind != NULL)
+            {
+                /* Keep track of where this local atom belongs in the collective index array.
+                 * This is needed when reducing the local arrays to a collective/global array
+                 * in communicate_group_positions */
+                coll_ind[localnr] = i;
+            }
+
+            /* add one to the local atom count */
+            localnr++;
+        }
+    }
+    /* Return the number of local atoms that were found */
+    *nr_loc = localnr;
+}
+
+
+static void get_shifts_group(
+        int    npbcdim, 
+        matrix box,
+        rvec   *xcoll,     /* IN:  Collective set of positions [0..nr] */
+        int    nr,         /* IN:  Total number of atoms in the group */
+        rvec   *xcoll_old, /* IN:  Positions from the last time step [0...nr] */
+        ivec   *shifts)    /* OUT: Shifts for xcoll */
+{
+    int  i,m,d;
+    rvec dx;
+
+
+    /* Get the shifts such that each atom is within closest
+     * distance to its position at the last NS time step after shifting.
+     * If we start with a whole group, and always keep track of 
+     * shift changes, the group will stay whole this way */
+    for (i=0; i < nr; i++)
+        clear_ivec(shifts[i]);
+
+    for (i=0; i<nr; i++)
+    {
+        /* The distance this atom moved since the last time step */
+        /* If this is more than just a bit, it has changed its home pbc box */
+        rvec_sub(xcoll[i],xcoll_old[i],dx);
+
+        for(m=npbcdim-1; m>=0; m--)
+        {
+            while (dx[m] < -0.5*box[m][m])
+            {
+                for(d=0; d<DIM; d++)
+                    dx[d] += box[m][d];
+                shifts[i][m]++;
+            }
+            while (dx[m] >= 0.5*box[m][m])
+            {
+                for(d=0; d<DIM; d++)
+                    dx[d] -= box[m][d];
+                shifts[i][m]--;
+            }
+        }
+    }
+}
+
+
+static void shift_positions_group(
+        matrix box, 
+        rvec   x[],      /* The positions [0..nr] */ 
+        ivec   *is,      /* The shifts [0..nr] */ 
+        int    nr)       /* The number of positions and shifts */
+{
+    int      i,tx,ty,tz;
+
+
+    /* Loop over the group's atoms */
+    if(TRICLINIC(box)) 
+    {
+        for (i=0; i < nr; i++)
+        {
+            tx=is[i][XX];
+            ty=is[i][YY];
+            tz=is[i][ZZ];
+
+            x[i][XX]=x[i][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
+            x[i][YY]=x[i][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
+            x[i][ZZ]=x[i][ZZ]+tz*box[ZZ][ZZ];
+        }
+    } else
+    {
+        for (i=0; i < nr; i++)
+        {
+            tx=is[i][XX];
+            ty=is[i][YY];
+            tz=is[i][ZZ];
+
+            x[i][XX]=x[i][XX]+tx*box[XX][XX];
+            x[i][YY]=x[i][YY]+ty*box[YY][YY];
+            x[i][ZZ]=x[i][ZZ]+tz*box[ZZ][ZZ];
+        }
+    }    
+}
+
+
+/* Assemble the positions of the group such that every node has all of them. 
+ * The atom indices are retrieved from anrs_loc[0..nr_loc] 
+ * Note that coll_ind[i] = i is needed in the serial case */
+extern void communicate_group_positions(
+        t_commrec  *cr, 
+        rvec       *xcoll,        /* OUT: Collective array of positions */
+        ivec       *shifts,       /* IN+OUT: Collective array of shifts for xcoll */
+        ivec       *extra_shifts, /* BUF: Extra shifts since last time step */
+        const gmx_bool bNS,           /* IN:  NS step, the shifts have changed */
+        rvec       *x_loc,        /* IN:  Local positions on this node */ 
+        const int  nr,            /* IN:  Total number of atoms in the group */
+        const int  nr_loc,        /* IN:  Local number of atoms in the group */
+        int        *anrs_loc,     /* IN:  Local atom numbers */
+        int        *coll_ind,     /* IN:  Collective index */
+        rvec       *xcoll_old,    /* IN+OUT: Positions from the last time step, used to make group whole */
+        matrix     box)
+{
+    int i;
+
+
+    /* Zero out the groups' global position array */
+    clear_rvecs(nr, xcoll);
+
+    /* Put the local positions that this node has into the right place of 
+     * the collective array. Note that in the serial case, coll_ind[i] = i */
+    for (i=0; i<nr_loc; i++)
+        copy_rvec(x_loc[anrs_loc[i]], xcoll[coll_ind[i]]);
+
+    if (PAR(cr))
+    {
+        /* Add the arrays from all nodes together */
+        gmx_sum(nr*3, xcoll[0], cr);
+
+        /* To make the group whole, start with a whole group and each
+         * step move the assembled positions at closest distance to the positions 
+         * from the last step. First shift the positions with the saved shift 
+         * vectors (these are 0 when this routine is called for the first time!) */
+        shift_positions_group(box, xcoll, shifts, nr);
+        
+        /* Now check if some shifts changed since the last step.
+         * This only needs to be done when the shifts are expected to have changed,
+         * i.e. after neighboursearching */
+        if (bNS) 
+        {
+            get_shifts_group(3, box, xcoll, nr, xcoll_old, extra_shifts);
+            
+            /* Shift with the additional shifts such that we get a whole group now */
+            shift_positions_group(box, xcoll, extra_shifts, nr);
+            
+            /* Add the shift vectors together for the next time step */
+            for (i=0; i<nr; i++)
+            {
+                shifts[i][XX] += extra_shifts[i][XX];
+                shifts[i][YY] += extra_shifts[i][YY];
+                shifts[i][ZZ] += extra_shifts[i][ZZ];
+            }
+            
+            /* Store current correctly-shifted positions for comparison in the next NS time step */
+            for (i=0; i<nr; i++)
+                copy_rvec(xcoll[i],xcoll_old[i]);   
+        }
+    }
+}
+
+
+/* Determine the (weighted) sum vector from positions x */
+extern double get_sum_of_positions(rvec x[], real weight[], const int nat, dvec dsumvec)
+{
+    int i;
+    rvec x_weighted;
+    double weight_sum = 0.0;
+
+
+    /* Zero out the center */
+    clear_dvec(dsumvec);
+
+    /* Loop over all atoms and add their weighted position vectors */
+    if (weight != NULL)
+    {
+        for (i=0; i<nat; i++)
+        {
+            weight_sum += weight[i];
+            svmul(weight[i], x[i], x_weighted);
+            dsumvec[XX] += x_weighted[XX];
+            dsumvec[YY] += x_weighted[YY];
+            dsumvec[ZZ] += x_weighted[ZZ];
+        }
+    }
+    else
+    {
+        for (i=0; i<nat; i++)
+        {
+            dsumvec[XX] += x[i][XX];
+            dsumvec[YY] += x[i][YY];
+            dsumvec[ZZ] += x[i][ZZ];
+        }
+    }
+    return weight_sum;
+}
+
+
+/* Determine center of structure from collective positions x */
+extern void get_center(rvec x[], real weight[], const int nr, rvec rcenter)
+{
+    dvec   dcenter;
+    double weight_sum, denom;
+
+    
+    weight_sum = get_sum_of_positions(x, weight, nr, dcenter);
+    
+    if (weight != NULL)
+        denom = weight_sum; /* Divide by the sum of weight */
+    else
+        denom = nr;        /* Divide by the number of atoms */
+        
+    dsvmul(1.0/denom, dcenter, dcenter);
+    
+    rcenter[XX] = dcenter[XX];
+    rcenter[YY] = dcenter[YY];
+    rcenter[ZZ] = dcenter[ZZ];
+}
+
+
+/* Get the center from local positions that already have the correct
+ * PBC representation */
+extern void get_center_comm(
+        t_commrec *cr,
+        rvec x_loc[],       /* Local positions */
+        real weight_loc[],  /* Local masses or other weights */
+        int nr_loc,         /* Local number of atoms */
+        int nr_group,       /* Total number of atoms of the group */ 
+        rvec center)        /* Weighted center */
+{
+    double weight_sum, denom;
+    dvec   dsumvec;
+    double buf[4];    
+    
+    
+    weight_sum = get_sum_of_positions(x_loc, weight_loc, nr_loc, dsumvec);
+    
+    /* Add the local contributions from all nodes. Put the sum vector and the 
+     * weight in a buffer array so that we get along with a single communication
+     * call. */
+    if (PAR(cr))
+    {
+        buf[0] = dsumvec[XX];
+        buf[1] = dsumvec[YY];
+        buf[2] = dsumvec[ZZ];
+        buf[3] = weight_sum;
+        
+        /* Communicate buffer */
+        gmx_sumd(4, buf, cr);
+        
+        dsumvec[XX] = buf[0];
+        dsumvec[YY] = buf[1];
+        dsumvec[ZZ] = buf[2];
+        weight_sum  = buf[3];
+    }
+    
+    if (weight_loc != NULL)
+        denom = 1.0/weight_sum; /* Divide by the sum of weight to get center of mass e.g. */
+    else
+        denom = 1.0/nr_group;   /* Divide by the number of atoms to get the geometrical center */
+        
+    center[XX] = dsumvec[XX]*denom;
+    center[YY] = dsumvec[YY]*denom;
+    center[ZZ] = dsumvec[ZZ]*denom;
+}
+
+
+/* Translate x with transvec */
+extern void translate_x(rvec x[], const int nr, const rvec transvec)
+{
+    int i;
+    
+    
+    for (i=0; i<nr; i++)
+        rvec_inc(x[i], transvec);
+}
+
+
+extern void rotate_x(rvec x[], const int nr, matrix rmat)
+{
+    int i,j,k;
+    rvec x_old;
+
+    
+    /* Apply the rotation matrix */
+    for (i=0; i<nr; i++)
+    {
+        for (j=0; j<3; j++)
+            x_old[j] = x[i][j];
+        for (j=0; j<3; j++)
+        {
+            x[i][j] = 0;
+            for (k=0; k<3; k++)
+                x[i][j] += rmat[k][j]*x_old[k];
+        }
+    }
+}
+
similarity index 100%
rename from src/mdlib/init.c
rename to src/gromacs/mdlib/init.c
diff --git a/src/gromacs/mdlib/md_support.c b/src/gromacs/mdlib/md_support.c
new file mode 100644 (file)
index 0000000..a03a06b
--- /dev/null
@@ -0,0 +1,746 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+/* _isnan() */
+#include <float.h>
+#endif
+
+#include "typedefs.h"
+#include "string2.h"
+#include "smalloc.h"
+#include "mdrun.h"
+#include "domdec.h"
+#include "mtop_util.h"
+#include "gmx_wallcycle.h"
+#include "vcm.h"
+#include "nrnb.h"
+
+/* Is the signal in one simulation independent of other simulations? */
+gmx_bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
+
+/* check which of the multisim simulations has the shortest number of
+   steps and return that number of nsteps */
+gmx_large_int_t get_multisim_nsteps(const t_commrec *cr,
+                                    gmx_large_int_t nsteps)
+{
+    gmx_large_int_t steps_out;
+
+    if MASTER(cr)
+    {
+        gmx_large_int_t *buf;
+        int s;
+
+        snew(buf,cr->ms->nsim);
+
+        buf[cr->ms->sim] = nsteps;
+        gmx_sumli_sim(cr->ms->nsim, buf, cr->ms);
+
+        steps_out=-1;
+        for(s=0; s<cr->ms->nsim; s++)
+        {
+            /* find the smallest positive number */
+            if (buf[s]>= 0 && ((steps_out < 0) || (buf[s]<steps_out)) )
+            {
+                steps_out=buf[s];
+            }
+        }
+        sfree(buf);
+
+        /* if we're the limiting simulation, don't do anything */
+        if (steps_out>=0 && steps_out<nsteps) 
+        {
+            char strbuf[255];
+            snprintf(strbuf, 255, "Will stop simulation %%d after %s steps (another simulation will end then).\n", gmx_large_int_pfmt);
+            fprintf(stderr, strbuf, cr->ms->sim, steps_out);
+        }
+    }
+    /* broadcast to non-masters */
+    gmx_bcast(sizeof(gmx_large_int_t), &steps_out, cr);
+    return steps_out;
+}
+
+int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
+{
+    int  *buf;
+    gmx_bool bPos,bEqual;
+    int  s,d;
+
+    snew(buf,ms->nsim);
+    buf[ms->sim] = n;
+    gmx_sumi_sim(ms->nsim,buf,ms);
+    bPos   = TRUE;
+    bEqual = TRUE;
+    for(s=0; s<ms->nsim; s++)
+    {
+        bPos   = bPos   && (buf[s] > 0);
+        bEqual = bEqual && (buf[s] == buf[0]);
+    }
+    if (bPos)
+    {
+        if (bEqual)
+        {
+            nmin = min(nmin,buf[0]);
+        }
+        else
+        {
+            /* Find the least common multiple */
+            for(d=2; d<nmin; d++)
+            {
+                s = 0;
+                while (s < ms->nsim && d % buf[s] == 0)
+                {
+                    s++;
+                }
+                if (s == ms->nsim)
+                {
+                    /* We found the LCM and it is less than nmin */
+                    nmin = d;
+                    break;
+                }
+            }
+        }
+    }
+    sfree(buf);
+
+    return nmin;
+}
+
+int multisim_nstsimsync(const t_commrec *cr,
+                        const t_inputrec *ir,int repl_ex_nst)
+{
+    int nmin;
+
+    if (MASTER(cr))
+    {
+        nmin = INT_MAX;
+        nmin = multisim_min(cr->ms,nmin,ir->nstlist);
+        nmin = multisim_min(cr->ms,nmin,ir->nstcalcenergy);
+        nmin = multisim_min(cr->ms,nmin,repl_ex_nst);
+        if (nmin == INT_MAX)
+        {
+            gmx_fatal(FARGS,"Can not find an appropriate interval for inter-simulation communication, since nstlist, nstcalcenergy and -replex are all <= 0");
+        }
+        /* Avoid inter-simulation communication at every (second) step */
+        if (nmin <= 2)
+        {
+            nmin = 10;
+        }
+    }
+
+    gmx_bcast(sizeof(int),&nmin,cr);
+
+    return nmin;
+}
+
+void init_global_signals(globsig_t *gs,const t_commrec *cr,
+                         const t_inputrec *ir,int repl_ex_nst)
+{
+    int i;
+
+    if (MULTISIM(cr))
+    {
+        gs->nstms = multisim_nstsimsync(cr,ir,repl_ex_nst);
+        if (debug)
+        {
+            fprintf(debug,"Syncing simulations for checkpointing and termination every %d steps\n",gs->nstms);
+        }
+    }
+    else
+    {
+        gs->nstms = 1;
+    }
+
+    for(i=0; i<eglsNR; i++)
+    {
+        gs->sig[i] = 0;
+        gs->set[i] = 0;
+    }
+}
+
+void copy_coupling_state(t_state *statea,t_state *stateb, 
+                         gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts) 
+{
+    
+    /* MRS note -- might be able to get rid of some of the arguments.  Look over it when it's all debugged */
+    
+    int i,j,nc;
+
+    /* Make sure we have enough space for x and v */
+    if (statea->nalloc > stateb->nalloc)
+    {
+        stateb->nalloc = statea->nalloc;
+        srenew(stateb->x,stateb->nalloc);
+        srenew(stateb->v,stateb->nalloc);
+    }
+
+    stateb->natoms     = statea->natoms;
+    stateb->ngtc       = statea->ngtc;
+    stateb->nnhpres    = statea->nnhpres;
+    stateb->veta       = statea->veta;
+    if (ekinda) 
+    {
+        copy_mat(ekinda->ekin,ekindb->ekin);
+        for (i=0; i<stateb->ngtc; i++) 
+        {
+            ekindb->tcstat[i].T = ekinda->tcstat[i].T;
+            ekindb->tcstat[i].Th = ekinda->tcstat[i].Th;
+            copy_mat(ekinda->tcstat[i].ekinh,ekindb->tcstat[i].ekinh);
+            copy_mat(ekinda->tcstat[i].ekinf,ekindb->tcstat[i].ekinf);
+            ekindb->tcstat[i].ekinscalef_nhc =  ekinda->tcstat[i].ekinscalef_nhc;
+            ekindb->tcstat[i].ekinscaleh_nhc =  ekinda->tcstat[i].ekinscaleh_nhc;
+            ekindb->tcstat[i].vscale_nhc =  ekinda->tcstat[i].vscale_nhc;
+        }
+    }
+    copy_rvecn(statea->x,stateb->x,0,stateb->natoms);
+    copy_rvecn(statea->v,stateb->v,0,stateb->natoms);
+    copy_mat(statea->box,stateb->box);
+    copy_mat(statea->box_rel,stateb->box_rel);
+    copy_mat(statea->boxv,stateb->boxv);
+
+    for (i = 0; i<stateb->ngtc; i++) 
+    { 
+        nc = i*opts->nhchainlength;
+        for (j=0; j<opts->nhchainlength; j++) 
+        {
+            stateb->nosehoover_xi[nc+j]  = statea->nosehoover_xi[nc+j];
+            stateb->nosehoover_vxi[nc+j] = statea->nosehoover_vxi[nc+j];
+        }
+    }
+    if (stateb->nhpres_xi != NULL)
+    {
+        for (i = 0; i<stateb->nnhpres; i++) 
+        {
+            nc = i*opts->nhchainlength;
+            for (j=0; j<opts->nhchainlength; j++) 
+            {
+                stateb->nhpres_xi[nc+j]  = statea->nhpres_xi[nc+j];
+                stateb->nhpres_vxi[nc+j] = statea->nhpres_vxi[nc+j];
+            }
+        }
+    }
+}
+
+real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state, t_extmass *MassQ)
+{
+    real quantity = 0;
+    switch (ir->etc) 
+    {
+    case etcNO:
+        break;
+    case etcBERENDSEN:
+        break;
+    case etcNOSEHOOVER:
+        quantity = NPT_energy(ir,state,MassQ);                
+        break;
+    case etcVRESCALE:
+        quantity = vrescale_energy(&(ir->opts),state->therm_integral);
+        break;
+    default:
+        break;
+    }
+    return quantity;
+}
+
+void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir, 
+                     t_forcerec *fr, gmx_ekindata_t *ekind, 
+                     t_state *state, t_state *state_global, t_mdatoms *mdatoms, 
+                     t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
+                     gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir, 
+                     tensor pres, rvec mu_tot, gmx_constr_t constr, 
+                     globsig_t *gs,gmx_bool bInterSimGS,
+                     matrix box, gmx_mtop_t *top_global, real *pcurr, 
+                     int natoms, gmx_bool *bSumEkinhOld, int flags)
+{
+    int  i,gsi;
+    real gs_buf[eglsNR];
+    tensor corr_vir,corr_pres,shakeall_vir;
+    gmx_bool bEner,bPres,bTemp, bVV;
+    gmx_bool bRerunMD, bStopCM, bGStat, bIterate, 
+        bFirstIterate,bReadEkin,bEkinAveVel,bScaleEkin, bConstrain;
+    real ekin,temp,prescorr,enercorr,dvdlcorr;
+    
+    /* translate CGLO flags to gmx_booleans */
+    bRerunMD = flags & CGLO_RERUNMD;
+    bStopCM = flags & CGLO_STOPCM;
+    bGStat = flags & CGLO_GSTAT;
+
+    bReadEkin = (flags & CGLO_READEKIN);
+    bScaleEkin = (flags & CGLO_SCALEEKIN);
+    bEner = flags & CGLO_ENERGY;
+    bTemp = flags & CGLO_TEMPERATURE;
+    bPres  = (flags & CGLO_PRESSURE);
+    bConstrain = (flags & CGLO_CONSTRAINT);
+    bIterate = (flags & CGLO_ITERATE);
+    bFirstIterate = (flags & CGLO_FIRSTITERATE);
+
+    /* we calculate a full state kinetic energy either with full-step velocity verlet
+       or half step where we need the pressure */
+    
+    bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && bPres) || bReadEkin);
+    
+    /* in initalization, it sums the shake virial in vv, and to 
+       sums ekinh_old in leapfrog (or if we are calculating ekinh_old) for other reasons */
+
+    /* ########## Kinetic energy  ############## */
+    
+    if (bTemp) 
+    {
+        /* Non-equilibrium MD: this is parallellized, but only does communication
+         * when there really is NEMD.
+         */
+        
+        if (PAR(cr) && (ekind->bNEMD)) 
+        {
+            accumulate_u(cr,&(ir->opts),ekind);
+        }
+        debug_gmx();
+        if (bReadEkin)
+        {
+            restore_ekinstate_from_state(cr,ekind,&state_global->ekinstate);
+        }
+        else 
+        {
+
+            calc_ke_part(state,&(ir->opts),mdatoms,ekind,nrnb,bEkinAveVel,bIterate);
+        }
+        
+        debug_gmx();
+        
+        /* Calculate center of mass velocity if necessary, also parallellized */
+        if (bStopCM && !bRerunMD && bEner) 
+        {
+            calc_vcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms,
+                         state->x,state->v,vcm);
+        }
+    }
+
+    if (bTemp || bPres || bEner || bConstrain) 
+    {
+        if (!bGStat)
+        {
+            /* We will not sum ekinh_old,                                                            
+             * so signal that we still have to do it.                                                
+             */
+            *bSumEkinhOld = TRUE;
+
+        }
+        else
+        {
+            if (gs != NULL)
+            {
+                for(i=0; i<eglsNR; i++)
+                {
+                    gs_buf[i] = gs->sig[i];
+                }
+            }
+            if (PAR(cr)) 
+            {
+                wallcycle_start(wcycle,ewcMoveE);
+                global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
+                            ir,ekind,constr,vcm,
+                            gs != NULL ? eglsNR : 0,gs_buf,
+                            top_global,state,
+                            *bSumEkinhOld,flags);
+                wallcycle_stop(wcycle,ewcMoveE);
+            }
+            if (gs != NULL)
+            {
+                if (MULTISIM(cr) && bInterSimGS)
+                {
+                    if (MASTER(cr))
+                    {
+                        /* Communicate the signals between the simulations */
+                        gmx_sum_sim(eglsNR,gs_buf,cr->ms);
+                    }
+                    /* Communicate the signals form the master to the others */
+                    gmx_bcast(eglsNR*sizeof(gs_buf[0]),gs_buf,cr);
+                }
+                for(i=0; i<eglsNR; i++)
+                {
+                    if (bInterSimGS || gs_simlocal[i])
+                    {
+                        /* Set the communicated signal only when it is non-zero,
+                         * since signals might not be processed at each MD step.
+                         */
+                        gsi = (gs_buf[i] >= 0 ?
+                               (int)(gs_buf[i] + 0.5) :
+                               (int)(gs_buf[i] - 0.5));
+                        if (gsi != 0)
+                        {
+                            gs->set[i] = gsi;
+                        }
+                        /* Turn off the local signal */
+                        gs->sig[i] = 0;
+                    }
+                }
+            }
+            *bSumEkinhOld = FALSE;
+        }
+    }
+    
+    if (!ekind->bNEMD && debug && bTemp && (vcm->nr > 0))
+    {
+        correct_ekin(debug,
+                     mdatoms->start,mdatoms->start+mdatoms->homenr,
+                     state->v,vcm->group_p[0],
+                     mdatoms->massT,mdatoms->tmass,ekind->ekin);
+    }
+    
+    if (bEner) {
+        /* Do center of mass motion removal */
+        if (bStopCM && !bRerunMD) /* is this correct?  Does it get called too often with this logic? */
+        {
+            check_cm_grp(fplog,vcm,ir,1);
+            do_stopcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms->cVCM,
+                          state->x,state->v,vcm);
+            inc_nrnb(nrnb,eNR_STOPCM,mdatoms->homenr);
+        }
+
+        /* Calculate the amplitude of the cosine velocity profile */
+        ekind->cosacc.vcos = ekind->cosacc.mvcos/mdatoms->tmass;
+    }
+
+    if (bTemp) 
+    {
+        /* Sum the kinetic energies of the groups & calc temp */
+        /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
+        /* three maincase:  VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).  
+           Leap with AveVel is not supported; it's not clear that it will actually work.  
+           bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy. 
+           If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
+           bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.  
+           If FALSE, we go ahead and erase over it.
+        */ 
+        enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,&(enerd->term[F_DKDL]),
+                                       bEkinAveVel,bIterate,bScaleEkin);
+        enerd->term[F_EKIN] = trace(ekind->ekin);
+    }
+    
+    /* ##########  Long range energy information ###### */
+    
+    if (bEner || bPres || bConstrain) 
+    {
+        calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda,
+                      corr_pres,corr_vir,&prescorr,&enercorr,&dvdlcorr);
+    }
+    
+    if (bEner && bFirstIterate) 
+    {
+        enerd->term[F_DISPCORR] = enercorr;
+        enerd->term[F_EPOT] += enercorr;
+        enerd->term[F_DVDL] += dvdlcorr;
+        if (fr->efep != efepNO) {
+            enerd->dvdl_lin += dvdlcorr;
+        }
+    }
+    
+    /* ########## Now pressure ############## */
+    if (bPres || bConstrain) 
+    {
+        
+        m_add(force_vir,shake_vir,total_vir);
+        
+        /* Calculate pressure and apply LR correction if PPPM is used.
+         * Use the box from last timestep since we already called update().
+         */
+        
+        enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres,
+                                        (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+        
+        /* Calculate long range corrections to pressure and energy */
+        /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT], 
+           and computes enerd->term[F_DISPCORR].  Also modifies the 
+           total_vir and pres tesors */
+        
+        m_add(total_vir,corr_vir,total_vir);
+        m_add(pres,corr_pres,pres);
+        enerd->term[F_PDISPCORR] = prescorr;
+        enerd->term[F_PRES] += prescorr;
+        *pcurr = enerd->term[F_PRES];
+        /* calculate temperature using virial */
+        enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
+        
+    }    
+}
+
+void check_nst_param(FILE *fplog,t_commrec *cr,
+                     const char *desc_nst,int nst,
+                     const char *desc_p,int *p)
+{
+    char buf[STRLEN];
+
+    if (*p > 0 && *p % nst != 0)
+    {
+        /* Round up to the next multiple of nst */
+        *p = ((*p)/nst + 1)*nst;
+        sprintf(buf,"NOTE: %s changes %s to %d\n",desc_nst,desc_p,*p);
+        md_print_warning(cr,fplog,buf);
+    }
+}
+
+void reset_all_counters(FILE *fplog,t_commrec *cr,
+                        gmx_large_int_t step,
+                        gmx_large_int_t *step_rel,t_inputrec *ir,
+                        gmx_wallcycle_t wcycle,t_nrnb *nrnb,
+                        gmx_runtime_t *runtime)
+{
+    char buf[STRLEN],sbuf[STEPSTRSIZE];
+
+    /* Reset all the counters related to performance over the run */
+    sprintf(buf,"Step %s: resetting all time and cycle counters\n",
+            gmx_step_str(step,sbuf));
+    md_print_warning(cr,fplog,buf);
+
+    wallcycle_stop(wcycle,ewcRUN);
+    wallcycle_reset_all(wcycle);
+    if (DOMAINDECOMP(cr))
+    {
+        reset_dd_statistics_counters(cr->dd);
+    }
+    init_nrnb(nrnb);
+    ir->init_step += *step_rel;
+    ir->nsteps    -= *step_rel;
+    *step_rel = 0;
+    wallcycle_start(wcycle,ewcRUN);
+    runtime_start(runtime);
+    print_date_and_time(fplog,cr->nodeid,"Restarted time",runtime);
+}
+
+void min_zero(int *n,int i)
+{
+    if (i > 0 && (*n == 0 || i < *n))
+    {
+        *n = i;
+    }
+}
+
+int lcd4(int i1,int i2,int i3,int i4)
+{
+    int nst;
+
+    nst = 0;
+    min_zero(&nst,i1);
+    min_zero(&nst,i2);
+    min_zero(&nst,i3);
+    min_zero(&nst,i4);
+    if (nst == 0)
+    {
+        gmx_incons("All 4 inputs for determininig nstglobalcomm are <= 0");
+    }
+    
+    while (nst > 1 && ((i1 > 0 && i1 % nst != 0)  ||
+                       (i2 > 0 && i2 % nst != 0)  ||
+                       (i3 > 0 && i3 % nst != 0)  ||
+                       (i4 > 0 && i4 % nst != 0)))
+    {
+        nst--;
+    }
+
+    return nst;
+}
+
+int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
+                        int nstglobalcomm,t_inputrec *ir)
+{
+    char buf[STRLEN];
+
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        nstglobalcomm = 1;
+    }
+
+    if (nstglobalcomm == -1)
+    {
+        if (!(ir->nstcalcenergy > 0 ||
+              ir->nstlist > 0 ||
+              ir->etc != etcNO ||
+              ir->epc != epcNO))
+        {
+            nstglobalcomm = 10;
+            if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm)
+            {
+                nstglobalcomm = ir->nstenergy;
+            }
+        }
+        else
+        {
+            /* Ensure that we do timely global communication for
+             * (possibly) each of the four following options.
+             */
+            nstglobalcomm = lcd4(ir->nstcalcenergy,
+                                 ir->nstlist,
+                                 ir->etc != etcNO ? ir->nsttcouple : 0,
+                                 ir->epc != epcNO ? ir->nstpcouple : 0);
+        }
+    }
+    else
+    {
+        if (ir->nstlist > 0 &&
+            nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0)
+        {
+            nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist;
+            sprintf(buf,"WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n",nstglobalcomm);
+            md_print_warning(cr,fplog,buf);
+        }
+        if (ir->nstcalcenergy > 0)
+        {
+            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                            "nstcalcenergy",&ir->nstcalcenergy);
+        }
+        if (ir->etc != etcNO && ir->nsttcouple > 0)
+        {
+            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                            "nsttcouple",&ir->nsttcouple);
+        }
+        if (ir->epc != epcNO && ir->nstpcouple > 0)
+        {
+            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                            "nstpcouple",&ir->nstpcouple);
+        }
+
+        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                        "nstenergy",&ir->nstenergy);
+
+        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                        "nstlog",&ir->nstlog);
+    }
+
+    if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm)
+    {
+        sprintf(buf,"WARNING: Changing nstcomm from %d to %d\n",
+                ir->nstcomm,nstglobalcomm);
+        md_print_warning(cr,fplog,buf);
+        ir->nstcomm = nstglobalcomm;
+    }
+
+    return nstglobalcomm;
+}
+
+void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
+                               t_inputrec *ir,gmx_mtop_t *mtop)
+{
+    /* Check required for old tpx files */
+    if (IR_TWINRANGE(*ir) && ir->nstlist > 1 &&
+        ir->nstcalcenergy % ir->nstlist != 0)
+    {
+        md_print_warning(cr,fplog,"Old tpr file with twin-range settings: modifying energy calculation and/or T/P-coupling frequencies");
+
+        if (gmx_mtop_ftype_count(mtop,F_CONSTR) +
+            gmx_mtop_ftype_count(mtop,F_CONSTRNC) > 0 &&
+            ir->eConstrAlg == econtSHAKE)
+        {
+            md_print_warning(cr,fplog,"With twin-range cut-off's and SHAKE the virial and pressure are incorrect");
+            if (ir->epc != epcNO)
+            {
+                gmx_fatal(FARGS,"Can not do pressure coupling with twin-range cut-off's and SHAKE");
+            }
+        }
+        check_nst_param(fplog,cr,"nstlist",ir->nstlist,
+                        "nstcalcenergy",&ir->nstcalcenergy);
+        if (ir->epc != epcNO)
+        {
+            check_nst_param(fplog,cr,"nstlist",ir->nstlist,
+                            "nstpcouple",&ir->nstpcouple);
+        }
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                        "nstenergy",&ir->nstenergy);
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                        "nstlog",&ir->nstlog);
+        if (ir->efep != efepNO)
+        {
+            check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                            "nstdhdl",&ir->nstdhdl);
+        }
+    }
+}
+
+void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
+                         gmx_bool *bNotLastFrame)
+{
+    gmx_bool bAlloc;
+    rvec *xp,*vp;
+
+    bAlloc = (fr->natoms == 0);
+
+    if (MASTER(cr) && !*bNotLastFrame)
+    {
+        fr->natoms = -1;
+    }
+    xp = fr->x;
+    vp = fr->v;
+    gmx_bcast(sizeof(*fr),fr,cr);
+    fr->x = xp;
+    fr->v = vp;
+
+    *bNotLastFrame = (fr->natoms >= 0);
+
+    if (*bNotLastFrame && PARTDECOMP(cr))
+    {
+        /* x and v are the only variable size quantities stored in trr
+         * that are required for rerun (f is not needed).
+         */
+        if (bAlloc)
+        {
+            snew(fr->x,fr->natoms);
+            snew(fr->v,fr->natoms);
+        }
+        if (fr->bX)
+        {
+            gmx_bcast(fr->natoms*sizeof(fr->x[0]),fr->x[0],cr);
+        }
+        if (fr->bV)
+        {
+            gmx_bcast(fr->natoms*sizeof(fr->v[0]),fr->v[0],cr);
+        }
+    }
+}
+
+void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf)
+{
+    if (MASTER(cr))
+    {
+        fprintf(stderr,"\n%s\n",buf);
+    }
+    if (fplog)
+    {
+        fprintf(fplog,"\n%s\n",buf);
+    }
+}
diff --git a/src/gromacs/mdlib/mdebin.c b/src/gromacs/mdlib/mdebin.c
new file mode 100644 (file)
index 0000000..204a130
--- /dev/null
@@ -0,0 +1,1236 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <float.h>
+#include "typedefs.h"
+#include "string2.h"
+#include "mdebin.h"
+#include "smalloc.h"
+#include "physics.h"
+#include "enxio.h"
+#include "vec.h"
+#include "disre.h"
+#include "main.h"
+#include "network.h"
+#include "names.h"
+#include "orires.h"
+#include "constr.h"
+#include "mtop_util.h"
+#include "xvgr.h"
+#include "gmxfio.h"
+
+#include "mdebin_bar.h"
+
+
+static const char *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
+
+static const char *boxs_nm[] = { "Box-X", "Box-Y", "Box-Z" };
+
+static const char *tricl_boxs_nm[] = { 
+    "Box-XX", "Box-YY", "Box-ZZ",
+    "Box-YX", "Box-ZX", "Box-ZY" 
+};
+
+static const char *vol_nm[] = { "Volume" };
+
+static const char *dens_nm[] = {"Density" };
+
+static const char *pv_nm[] = {"pV" };
+
+static const char *enthalpy_nm[] = {"Enthalpy" };
+
+static const char *boxvel_nm[] = {
+    "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
+    "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY"
+};
+
+#define NBOXS asize(boxs_nm)
+#define NTRICLBOXS asize(tricl_boxs_nm)
+
+
+t_mdebin *init_mdebin(ener_file_t fp_ene,
+                      const gmx_mtop_t *mtop,
+                      const t_inputrec *ir,
+                      FILE *fp_dhdl)
+{
+    const char *ener_nm[F_NRE];
+    static const char *vir_nm[] = {
+        "Vir-XX", "Vir-XY", "Vir-XZ",
+        "Vir-YX", "Vir-YY", "Vir-YZ",
+        "Vir-ZX", "Vir-ZY", "Vir-ZZ"
+    };
+    static const char *sv_nm[] = {
+        "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
+        "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
+        "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
+    };
+    static const char *fv_nm[] = {
+        "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
+        "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
+        "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
+    };
+    static const char *pres_nm[] = {
+        "Pres-XX","Pres-XY","Pres-XZ",
+        "Pres-YX","Pres-YY","Pres-YZ",
+        "Pres-ZX","Pres-ZY","Pres-ZZ"
+    };
+    static const char *surft_nm[] = {
+        "#Surf*SurfTen"
+    };
+    static const char *mu_nm[] = {
+        "Mu-X", "Mu-Y", "Mu-Z"
+    };
+    static const char *vcos_nm[] = {
+        "2CosZ*Vel-X"
+    };
+    static const char *visc_nm[] = {
+        "1/Viscosity"
+    };
+    static const char *baro_nm[] = {
+        "Barostat"
+    };
+
+    char     **grpnms;
+    const gmx_groups_t *groups;
+    char     **gnm;
+    char     buf[256];
+    const char     *bufi;
+    t_mdebin *md;
+    int      i,j,ni,nj,n,nh,k,kk,ncon,nset;
+    gmx_bool     bBHAM,bNoseHoover,b14;
+
+    snew(md,1);
+
+    if (EI_DYNAMICS(ir->eI))
+    {
+        md->delta_t = ir->delta_t;
+    }
+    else
+    {
+        md->delta_t = 0;
+    }
+
+    groups = &mtop->groups;
+
+    bBHAM = (mtop->ffparams.functype[0] == F_BHAM);
+    b14   = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 ||
+             gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0);
+
+    ncon = gmx_mtop_ftype_count(mtop,F_CONSTR);
+    nset = gmx_mtop_ftype_count(mtop,F_SETTLE);
+    md->bConstr    = (ncon > 0 || nset > 0);
+    md->bConstrVir = FALSE;
+    if (md->bConstr) {
+        if (ncon > 0 && ir->eConstrAlg == econtLINCS) {
+            if (ir->eI == eiSD2)
+                md->nCrmsd = 2;
+            else
+                md->nCrmsd = 1;
+        }
+        md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL);
+    } else {
+        md->nCrmsd = 0;
+    }
+
+    /* Energy monitoring */
+    for(i=0;i<egNR;i++)
+    {
+        md->bEInd[i]=FALSE;
+    }
+
+#ifndef GMX_OPENMM
+    for(i=0; i<F_NRE; i++)
+    {
+        md->bEner[i] = FALSE;
+        if (i == F_LJ)
+            md->bEner[i] = !bBHAM;
+        else if (i == F_BHAM)
+            md->bEner[i] = bBHAM;
+        else if (i == F_EQM)
+            md->bEner[i] = ir->bQMMM;
+        else if (i == F_COUL_LR)
+            md->bEner[i] = (ir->rcoulomb > ir->rlist);
+        else if (i == F_LJ_LR)
+            md->bEner[i] = (!bBHAM && ir->rvdw > ir->rlist);
+        else if (i == F_BHAM_LR)
+            md->bEner[i] = (bBHAM && ir->rvdw > ir->rlist);
+        else if (i == F_RF_EXCL)
+            md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC);
+        else if (i == F_COUL_RECIP)
+            md->bEner[i] = EEL_FULL(ir->coulombtype);
+        else if (i == F_LJ14)
+            md->bEner[i] = b14;
+        else if (i == F_COUL14)
+            md->bEner[i] = b14;
+        else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
+            md->bEner[i] = FALSE;
+        else if ((i == F_DVDL) || (i == F_DKDL))
+            md->bEner[i] = (ir->efep != efepNO);
+        else if (i == F_DHDL_CON)
+            md->bEner[i] = (ir->efep != efepNO && md->bConstr);
+        else if ((interaction_function[i].flags & IF_VSITE) ||
+                 (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE))
+            md->bEner[i] = FALSE;
+        else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES)  || (i==F_EQM))
+            md->bEner[i] = TRUE;
+        else if ((i == F_GBPOL) && ir->implicit_solvent==eisGBSA)
+            md->bEner[i] = TRUE;
+        else if ((i == F_NPSOLVATION) && ir->implicit_solvent==eisGBSA && (ir->sa_algorithm != esaNO))
+            md->bEner[i] = TRUE;
+        else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14))
+            md->bEner[i] = FALSE;
+        else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
+            md->bEner[i] = EI_DYNAMICS(ir->eI);
+        else if (i==F_VTEMP) 
+            md->bEner[i] =  (EI_DYNAMICS(ir->eI) && getenv("GMX_VIRIAL_TEMPERATURE"));
+        else if (i == F_DISPCORR || i == F_PDISPCORR)
+            md->bEner[i] = (ir->eDispCorr != edispcNO);
+        else if (i == F_DISRESVIOL)
+            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0);
+        else if (i == F_ORIRESDEV)
+            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0);
+        else if (i == F_CONNBONDS)
+            md->bEner[i] = FALSE;
+        else if (i == F_COM_PULL)
+            md->bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F || ir->bRot);
+        else if (i == F_ECONSERVED)
+            md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) &&
+                            (ir->epc == epcNO || ir->epc==epcMTTK));
+        else
+            md->bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0);
+    }
+#else
+    /* OpenMM always produces only the following 4 energy terms */
+    md->bEner[F_EPOT] = TRUE;
+    md->bEner[F_EKIN] = TRUE;
+    md->bEner[F_ETOT] = TRUE;
+    md->bEner[F_TEMP] = TRUE;
+#endif
+
+    md->f_nre=0;
+    for(i=0; i<F_NRE; i++)
+    {
+        if (md->bEner[i])
+        {
+            /* FIXME: The constness should not be cast away */
+            /*ener_nm[f_nre]=(char *)interaction_function[i].longname;*/
+            ener_nm[md->f_nre]=interaction_function[i].longname;
+            md->f_nre++;
+        }
+    }
+
+    md->epc = ir->epc;
+    md->bDiagPres = !TRICLINIC(ir->ref_p);
+    md->ref_p = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM;
+    md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
+    md->bDynBox = DYNAMIC_BOX(*ir);
+    md->etc = ir->etc;
+    md->bNHC_trotter = IR_NVT_TROTTER(ir);
+    md->bMTTK = IR_NPT_TROTTER(ir);
+
+    md->ebin  = mk_ebin();
+    /* Pass NULL for unit to let get_ebin_space determine the units
+     * for interaction_function[i].longname
+     */
+    md->ie    = get_ebin_space(md->ebin,md->f_nre,ener_nm,NULL);
+    if (md->nCrmsd)
+    {
+        /* This should be called directly after the call for md->ie,
+         * such that md->iconrmsd follows directly in the list.
+         */
+        md->iconrmsd = get_ebin_space(md->ebin,md->nCrmsd,conrmsd_nm,"");
+    }
+    if (md->bDynBox)
+    {
+        md->ib    = get_ebin_space(md->ebin, 
+                                   md->bTricl ? NTRICLBOXS : NBOXS, 
+                                   md->bTricl ? tricl_boxs_nm : boxs_nm,
+                                   unit_length);
+        md->ivol  = get_ebin_space(md->ebin, 1, vol_nm,  unit_volume);
+        md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI);
+        if (md->bDiagPres)
+        {
+            md->ipv   = get_ebin_space(md->ebin, 1, pv_nm,   unit_energy);
+            md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm,   unit_energy);
+        }
+    }
+    if (md->bConstrVir)
+    {
+        md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm,unit_energy);
+        md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm,unit_energy);
+    }
+    md->ivir   = get_ebin_space(md->ebin,asize(vir_nm),vir_nm,unit_energy);
+    md->ipres  = get_ebin_space(md->ebin,asize(pres_nm),pres_nm,unit_pres_bar);
+    md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm,
+                                unit_surft_bar);
+    if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
+    {
+        md->ipc = get_ebin_space(md->ebin,md->bTricl ? 6 : 3,
+                                 boxvel_nm,unit_vel);
+    }
+    md->imu    = get_ebin_space(md->ebin,asize(mu_nm),mu_nm,unit_dipole_D);
+    if (ir->cos_accel != 0)
+    {
+        md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm,unit_vel);
+        md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm,
+                                   unit_invvisc_SI);
+    }
+
+    /* Energy monitoring */
+    for(i=0;i<egNR;i++)
+    {
+        md->bEInd[i] = FALSE;
+    }
+    md->bEInd[egCOULSR] = TRUE;
+    md->bEInd[egLJSR  ] = TRUE;
+
+    if (ir->rcoulomb > ir->rlist)
+    {
+        md->bEInd[egCOULLR] = TRUE;
+    }
+    if (!bBHAM)
+    {
+        if (ir->rvdw > ir->rlist)
+        {
+            md->bEInd[egLJLR]   = TRUE;
+        }
+    }
+    else
+    {
+        md->bEInd[egLJSR]   = FALSE;
+        md->bEInd[egBHAMSR] = TRUE;
+        if (ir->rvdw > ir->rlist)
+        {
+            md->bEInd[egBHAMLR]   = TRUE;
+        }
+    }
+    if (b14)
+    {
+        md->bEInd[egLJ14] = TRUE;
+        md->bEInd[egCOUL14] = TRUE;
+    }
+    md->nEc=0;
+    for(i=0; (i<egNR); i++)
+    {
+        if (md->bEInd[i])
+        {
+            md->nEc++;
+        }
+    }
+
+    n=groups->grps[egcENER].nr;
+    md->nEg=n;
+    md->nE=(n*(n+1))/2;
+    snew(md->igrp,md->nE);
+    if (md->nE > 1)
+    {
+        n=0;
+        snew(gnm,md->nEc);
+        for(k=0; (k<md->nEc); k++)
+        {
+            snew(gnm[k],STRLEN);
+        }
+        for(i=0; (i<groups->grps[egcENER].nr); i++)
+        {
+            ni=groups->grps[egcENER].nm_ind[i];
+            for(j=i; (j<groups->grps[egcENER].nr); j++)
+            {
+                nj=groups->grps[egcENER].nm_ind[j];
+                for(k=kk=0; (k<egNR); k++)
+                {
+                    if (md->bEInd[k])
+                    {
+                        sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k],
+                                *(groups->grpname[ni]),*(groups->grpname[nj]));
+                        kk++;
+                    }
+                }
+                md->igrp[n]=get_ebin_space(md->ebin,md->nEc,
+                                           (const char **)gnm,unit_energy);
+                n++;
+            }
+        }
+        for(k=0; (k<md->nEc); k++)
+        {
+            sfree(gnm[k]);
+        }
+        sfree(gnm);
+
+        if (n != md->nE)
+        {
+            gmx_incons("Number of energy terms wrong");
+        }
+    }
+
+    md->nTC=groups->grps[egcTC].nr;
+    md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ 
+    if (md->bMTTK)
+    {
+        md->nTCP = 1;  /* assume only one possible coupling system for barostat 
+                          for now */
+    } 
+    else 
+    {
+        md->nTCP = 0;
+    }
+
+    if (md->etc == etcNOSEHOOVER) {
+        if (md->bNHC_trotter) { 
+            md->mde_n = 2*md->nNHC*md->nTC;
+        }
+        else 
+        {
+            md->mde_n = 2*md->nTC;
+        }
+        if (md->epc == epcMTTK)
+        {
+            md->mdeb_n = 2*md->nNHC*md->nTCP;
+        }
+    } else { 
+        md->mde_n = md->nTC;
+        md->mdeb_n = 0;
+    }
+
+    snew(md->tmp_r,md->mde_n);
+    snew(md->tmp_v,md->mde_n);
+    snew(md->grpnms,md->mde_n);
+    grpnms = md->grpnms;
+
+    for(i=0; (i<md->nTC); i++)
+    {
+        ni=groups->grps[egcTC].nm_ind[i];
+        sprintf(buf,"T-%s",*(groups->grpname[ni]));
+        grpnms[i]=strdup(buf);
+    }
+    md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms,
+                             unit_temp_K);
+
+    bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); /* whether to print Nose-Hoover chains */
+
+    if (md->etc == etcNOSEHOOVER)
+    {
+        if (bNoseHoover) 
+        {
+            if (md->bNHC_trotter) 
+            {
+                for(i=0; (i<md->nTC); i++) 
+                {
+                    ni=groups->grps[egcTC].nm_ind[i];
+                    bufi = *(groups->grpname[ni]);
+                    for(j=0; (j<md->nNHC); j++) 
+                    {
+                        sprintf(buf,"Xi-%d-%s",j,bufi);
+                        grpnms[2*(i*md->nNHC+j)]=strdup(buf);
+                        sprintf(buf,"vXi-%d-%s",j,bufi);
+                        grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
+                    }
+                }
+                md->itc=get_ebin_space(md->ebin,md->mde_n,
+                                       (const char **)grpnms,unit_invtime);
+                if (md->bMTTK) 
+                {
+                    for(i=0; (i<md->nTCP); i++) 
+                    {
+                        bufi = baro_nm[0];  /* All barostat DOF's together for now. */
+                        for(j=0; (j<md->nNHC); j++) 
+                        {
+                            sprintf(buf,"Xi-%d-%s",j,bufi);
+                            grpnms[2*(i*md->nNHC+j)]=strdup(buf);
+                            sprintf(buf,"vXi-%d-%s",j,bufi);
+                            grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
+                        }
+                    }
+                    md->itcb=get_ebin_space(md->ebin,md->mdeb_n,
+                                            (const char **)grpnms,unit_invtime);
+                }
+            } 
+            else
+            {
+                for(i=0; (i<md->nTC); i++) 
+                {
+                    ni=groups->grps[egcTC].nm_ind[i];
+                    bufi = *(groups->grpname[ni]);
+                    sprintf(buf,"Xi-%s",bufi);
+                    grpnms[2*i]=strdup(buf);
+                    sprintf(buf,"vXi-%s",bufi);
+                    grpnms[2*i+1]=strdup(buf);
+                }
+                md->itc=get_ebin_space(md->ebin,md->mde_n,
+                                       (const char **)grpnms,unit_invtime);
+            }
+        }
+    }
+    else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
+             md->etc == etcVRESCALE)
+    {
+        for(i=0; (i<md->nTC); i++)
+        {
+            ni=groups->grps[egcTC].nm_ind[i];
+            sprintf(buf,"Lamb-%s",*(groups->grpname[ni]));
+            grpnms[i]=strdup(buf);
+        }
+        md->itc=get_ebin_space(md->ebin,md->mde_n,(const char **)grpnms,"");
+    }
+
+    sfree(grpnms);
+
+
+    md->nU=groups->grps[egcACC].nr;
+    if (md->nU > 1)
+    {
+        snew(grpnms,3*md->nU);
+        for(i=0; (i<md->nU); i++)
+        {
+            ni=groups->grps[egcACC].nm_ind[i];
+            sprintf(buf,"Ux-%s",*(groups->grpname[ni]));
+            grpnms[3*i+XX]=strdup(buf);
+            sprintf(buf,"Uy-%s",*(groups->grpname[ni]));
+            grpnms[3*i+YY]=strdup(buf);
+            sprintf(buf,"Uz-%s",*(groups->grpname[ni]));
+            grpnms[3*i+ZZ]=strdup(buf);
+        }
+        md->iu=get_ebin_space(md->ebin,3*md->nU,(const char **)grpnms,unit_vel);
+        sfree(grpnms);
+    }
+
+    if ( fp_ene )
+    {
+        do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm);
+    }
+
+    md->print_grpnms=NULL;
+
+    /* check whether we're going to write dh histograms */
+    md->dhc=NULL; 
+    if (ir->separate_dhdl_file == sepdhdlfileNO )
+    {
+        int i;
+        snew(md->dhc, 1);
+
+        mde_delta_h_coll_init(md->dhc, ir);
+        md->fp_dhdl = NULL;
+    }
+    else
+    {
+        md->fp_dhdl = fp_dhdl;
+    }
+    md->dhdl_derivatives = (ir->dhdl_derivatives==dhdlderivativesYES);
+    return md;
+}
+
+FILE *open_dhdl(const char *filename,const t_inputrec *ir,
+                const output_env_t oenv)
+{
+    FILE *fp;
+    const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
+    char title[STRLEN],label_x[STRLEN],label_y[STRLEN];
+    char **setname;
+    char buf[STRLEN];
+
+    sprintf(label_x,"%s (%s)","Time",unit_time);
+    if (ir->n_flambda == 0)
+    {
+        sprintf(title,"%s",dhdl);
+        sprintf(label_y,"%s (%s %s)",
+                dhdl,unit_energy,"[\\lambda]\\S-1\\N");
+    }
+    else
+    {
+        sprintf(title,"%s, %s",dhdl,deltag);
+        sprintf(label_y,"(%s)",unit_energy);
+    }
+    fp = gmx_fio_fopen(filename,"w+");
+    xvgr_header(fp,title,label_x,label_y,exvggtXNY,oenv);
+
+    if (ir->delta_lambda == 0)
+    {
+        sprintf(buf,"T = %g (K), %s = %g",
+                ir->opts.ref_t[0],lambda,ir->init_lambda);
+    }
+    else
+    {
+        sprintf(buf,"T = %g (K)",
+                ir->opts.ref_t[0]);
+    }
+    xvgr_subtitle(fp,buf,oenv);
+
+    if (ir->n_flambda > 0)
+    {
+        int nsets,s,nsi=0;
+        /* g_bar has to determine the lambda values used in this simulation
+         * from this xvg legend.  */
+        nsets = ( (ir->dhdl_derivatives==dhdlderivativesYES) ? 1 : 0) + 
+                  ir->n_flambda;
+        snew(setname,nsets);
+        if (ir->dhdl_derivatives == dhdlderivativesYES)
+        {
+            sprintf(buf,"%s %s %g",dhdl,lambda,ir->init_lambda);
+            setname[nsi++] = gmx_strdup(buf);
+        }
+        for(s=0; s<ir->n_flambda; s++)
+        {
+            sprintf(buf,"%s %s %g",deltag,lambda,ir->flambda[s]);
+            setname[nsi++] = gmx_strdup(buf);
+        }
+        xvgr_legend(fp,nsets,(const char**)setname,oenv);
+
+        for(s=0; s<nsets; s++)
+        {
+            sfree(setname[s]);
+        }
+        sfree(setname);
+    }
+
+    return fp;
+}
+
+static void copy_energy(t_mdebin *md, real e[],real ecpy[])
+{
+    int i,j;
+
+    for(i=j=0; (i<F_NRE); i++)
+        if (md->bEner[i])
+            ecpy[j++] = e[i];
+    if (j != md->f_nre) 
+        gmx_incons("Number of energy terms wrong");
+}
+
+void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
+                gmx_bool bSum,
+                double time,
+                real tmass,
+                gmx_enerdata_t *enerd,
+                t_state *state,
+                matrix  box,
+                tensor svir,
+                tensor fvir,
+                tensor vir,
+                tensor pres,
+                gmx_ekindata_t *ekind,
+                rvec mu_tot,
+                gmx_constr_t constr)
+{
+    int    i,j,k,kk,m,n,gid;
+    real   crmsd[2],tmp6[6];
+    real   bs[NTRICLBOXS],vol,dens,pv,enthalpy;
+    real   eee[egNR];
+    real   ecopy[F_NRE];
+    real   tmp;
+    gmx_bool   bNoseHoover;
+
+    /* Do NOT use the box in the state variable, but the separate box provided
+     * as an argument. This is because we sometimes need to write the box from
+     * the last timestep to match the trajectory frames.
+     */
+    copy_energy(md, enerd->term,ecopy);
+    add_ebin(md->ebin,md->ie,md->f_nre,ecopy,bSum);
+    if (md->nCrmsd)
+    {
+        crmsd[0] = constr_rmsd(constr,FALSE);
+        if (md->nCrmsd > 1)
+        {
+            crmsd[1] = constr_rmsd(constr,TRUE);
+        }
+        add_ebin(md->ebin,md->iconrmsd,md->nCrmsd,crmsd,FALSE);
+    }
+    if (md->bDynBox)
+    {
+        int nboxs;
+        if(md->bTricl)
+        {
+            bs[0] = box[XX][XX];
+            bs[1] = box[YY][YY];
+            bs[2] = box[ZZ][ZZ];
+            bs[3] = box[YY][XX];
+            bs[4] = box[ZZ][XX];
+            bs[5] = box[ZZ][YY];
+            nboxs=NTRICLBOXS;
+        }
+        else
+        {
+            bs[0] = box[XX][XX];
+            bs[1] = box[YY][YY];
+            bs[2] = box[ZZ][ZZ];
+            nboxs=NBOXS;
+        }
+        vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
+        dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
+
+        add_ebin(md->ebin,md->ib   ,nboxs,bs   ,bSum);
+        add_ebin(md->ebin,md->ivol ,1    ,&vol ,bSum);
+        add_ebin(md->ebin,md->idens,1    ,&dens,bSum);
+
+        if (md->bDiagPres)
+        {
+            /* This is pV (in kJ/mol).  The pressure is the reference pressure,
+               not the instantaneous pressure */  
+            pv = vol*md->ref_p/PRESFAC;
+
+            add_ebin(md->ebin,md->ipv  ,1    ,&pv  ,bSum);
+            enthalpy = pv + enerd->term[F_ETOT];
+            add_ebin(md->ebin,md->ienthalpy  ,1    ,&enthalpy  ,bSum);
+        }
+    }
+    if (md->bConstrVir)
+    {
+        add_ebin(md->ebin,md->isvir,9,svir[0],bSum);
+        add_ebin(md->ebin,md->ifvir,9,fvir[0],bSum);
+    }
+    add_ebin(md->ebin,md->ivir,9,vir[0],bSum);
+    add_ebin(md->ebin,md->ipres,9,pres[0],bSum);
+    tmp = (pres[ZZ][ZZ]-(pres[XX][XX]+pres[YY][YY])*0.5)*box[ZZ][ZZ];
+    add_ebin(md->ebin,md->isurft,1,&tmp,bSum);
+    if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
+    {
+        tmp6[0] = state->boxv[XX][XX];
+        tmp6[1] = state->boxv[YY][YY];
+        tmp6[2] = state->boxv[ZZ][ZZ];
+        tmp6[3] = state->boxv[YY][XX];
+        tmp6[4] = state->boxv[ZZ][XX];
+        tmp6[5] = state->boxv[ZZ][YY];
+        add_ebin(md->ebin,md->ipc,md->bTricl ? 6 : 3,tmp6,bSum);
+    }
+    add_ebin(md->ebin,md->imu,3,mu_tot,bSum);
+    if (ekind && ekind->cosacc.cos_accel != 0)
+    {
+        vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
+        dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
+        add_ebin(md->ebin,md->ivcos,1,&(ekind->cosacc.vcos),bSum);
+        /* 1/viscosity, unit 1/(kg m^-1 s^-1) */
+        tmp = 1/(ekind->cosacc.cos_accel/(ekind->cosacc.vcos*PICO)
+                 *dens*vol*sqr(box[ZZ][ZZ]*NANO/(2*M_PI)));
+        add_ebin(md->ebin,md->ivisc,1,&tmp,bSum);    
+    }
+    if (md->nE > 1)
+    {
+        n=0;
+        for(i=0; (i<md->nEg); i++)
+        {
+            for(j=i; (j<md->nEg); j++)
+            {
+                gid=GID(i,j,md->nEg);
+                for(k=kk=0; (k<egNR); k++)
+                {
+                    if (md->bEInd[k])
+                    {
+                        eee[kk++] = enerd->grpp.ener[k][gid];
+                    }
+                }
+                add_ebin(md->ebin,md->igrp[n],md->nEc,eee,bSum);
+                n++;
+            }
+        }
+    }
+
+    if (ekind)
+    {
+        for(i=0; (i<md->nTC); i++)
+        {
+            md->tmp_r[i] = ekind->tcstat[i].T;
+        }
+        add_ebin(md->ebin,md->itemp,md->nTC,md->tmp_r,bSum);
+
+        /* whether to print Nose-Hoover chains: */
+        bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); 
+
+        if (md->etc == etcNOSEHOOVER)
+        {
+            if (bNoseHoover) 
+            {
+                if (md->bNHC_trotter)
+                {
+                    for(i=0; (i<md->nTC); i++) 
+                    {
+                        for (j=0;j<md->nNHC;j++) 
+                        {
+                            k = i*md->nNHC+j;
+                            md->tmp_r[2*k] = state->nosehoover_xi[k];
+                            md->tmp_r[2*k+1] = state->nosehoover_vxi[k];
+                        }
+                    }
+                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);      
+
+                    if (md->bMTTK) {
+                        for(i=0; (i<md->nTCP); i++) 
+                        {
+                            for (j=0;j<md->nNHC;j++) 
+                            {
+                                k = i*md->nNHC+j;
+                                md->tmp_r[2*k] = state->nhpres_xi[k];
+                                md->tmp_r[2*k+1] = state->nhpres_vxi[k];
+                            }
+                        }
+                        add_ebin(md->ebin,md->itcb,md->mdeb_n,md->tmp_r,bSum);      
+                    }
+
+                } 
+                else 
+                {
+                    for(i=0; (i<md->nTC); i++)
+                    {
+                        md->tmp_r[2*i] = state->nosehoover_xi[i];
+                        md->tmp_r[2*i+1] = state->nosehoover_vxi[i];
+                    }
+                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);
+                }
+            }
+        }
+        else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
+                 md->etc == etcVRESCALE)
+        {
+            for(i=0; (i<md->nTC); i++)
+            {
+                md->tmp_r[i] = ekind->tcstat[i].lambda;
+            }
+            add_ebin(md->ebin,md->itc,md->nTC,md->tmp_r,bSum);
+        }
+    }
+
+    if (ekind && md->nU > 1)
+    {
+        for(i=0; (i<md->nU); i++)
+        {
+            copy_rvec(ekind->grpstat[i].u,md->tmp_v[i]);
+        }
+        add_ebin(md->ebin,md->iu,3*md->nU,md->tmp_v[0],bSum);
+    }
+
+    ebin_increase_count(md->ebin,bSum);
+
+    /* BAR + thermodynamic integration values */
+    if (write_dhdl)
+    {
+        if (md->fp_dhdl)
+        {
+            fprintf(md->fp_dhdl,"%.4f", time);
+
+            if (md->dhdl_derivatives)
+            {
+                fprintf(md->fp_dhdl," %g", enerd->term[F_DVDL]+ 
+                                           enerd->term[F_DKDL]+
+                                           enerd->term[F_DHDL_CON]);
+            }
+            for(i=1; i<enerd->n_lambda; i++)
+            {
+                fprintf(md->fp_dhdl," %g",
+                        enerd->enerpart_lambda[i]-enerd->enerpart_lambda[0]);
+            }
+            fprintf(md->fp_dhdl,"\n");
+        }
+        /* and the binary BAR output */
+        if (md->dhc)
+        {
+            mde_delta_h_coll_add_dh(md->dhc, 
+                                    enerd->term[F_DVDL]+ enerd->term[F_DKDL]+
+                                    enerd->term[F_DHDL_CON],
+                                    enerd->enerpart_lambda, time, 
+                                    state->lambda);
+        }
+    }
+}
+
+void upd_mdebin_step(t_mdebin *md)
+{
+    ebin_increase_count(md->ebin,FALSE); 
+}
+
+static void npr(FILE *log,int n,char c)
+{
+    for(; (n>0); n--) fprintf(log,"%c",c);
+}
+
+static void pprint(FILE *log,const char *s,t_mdebin *md)
+{
+    char CHAR='#';
+    int  slen;
+    char buf1[22],buf2[22];
+
+    slen = strlen(s);
+    fprintf(log,"\t<======  ");
+    npr(log,slen,CHAR);
+    fprintf(log,"  ==>\n");
+    fprintf(log,"\t<====  %s  ====>\n",s);
+    fprintf(log,"\t<==  ");
+    npr(log,slen,CHAR);
+    fprintf(log,"  ======>\n\n");
+
+    fprintf(log,"\tStatistics over %s steps using %s frames\n",
+            gmx_step_str(md->ebin->nsteps_sim,buf1),
+            gmx_step_str(md->ebin->nsum_sim,buf2));
+    fprintf(log,"\n");
+}
+
+void print_ebin_header(FILE *log,gmx_large_int_t steps,double time,real lamb)
+{
+    char buf[22];
+
+    fprintf(log,"   %12s   %12s   %12s\n"
+            "   %12s   %12.5f   %12.5f\n\n",
+            "Step","Time","Lambda",gmx_step_str(steps,buf),time,lamb);
+}
+
+void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
+                FILE *log,
+                gmx_large_int_t step,double time,
+                int mode,gmx_bool bCompact,
+                t_mdebin *md,t_fcdata *fcd,
+                gmx_groups_t *groups,t_grpopts *opts)
+{
+    /*static char **grpnms=NULL;*/
+    char        buf[246];
+    int         i,j,n,ni,nj,ndr,nor,b;
+    int         ndisre=0;
+    real        *disre_rm3tav, *disre_rt;
+
+    /* these are for the old-style blocks (1 subblock, only reals), because
+       there can be only one per ID for these */
+    int         nr[enxNR];
+    int         id[enxNR];
+    real        *block[enxNR];
+
+    /* temporary arrays for the lambda values to write out */
+    double      enxlambda_data[2]; 
+
+    t_enxframe  fr;
+
+    switch (mode)
+    {
+        case eprNORMAL:
+            init_enxframe(&fr);
+            fr.t            = time;
+            fr.step         = step;
+            fr.nsteps       = md->ebin->nsteps;
+            fr.dt           = md->delta_t;
+            fr.nsum         = md->ebin->nsum;
+            fr.nre          = (bEne) ? md->ebin->nener : 0;
+            fr.ener         = md->ebin->e;
+            ndisre          = bDR ? fcd->disres.npair : 0;
+            disre_rm3tav    = fcd->disres.rm3tav;
+            disre_rt        = fcd->disres.rt;
+            /* Optional additional old-style (real-only) blocks. */
+            for(i=0; i<enxNR; i++)
+            {
+                nr[i] = 0;
+            }
+            if (fcd->orires.nr > 0 && bOR)
+            {
+                diagonalize_orires_tensors(&(fcd->orires));
+                nr[enxOR]     = fcd->orires.nr;
+                block[enxOR]  = fcd->orires.otav;
+                id[enxOR]     = enxOR;
+                nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ? 
+                          fcd->orires.nr : 0;
+                block[enxORI] = fcd->orires.oinsl;
+                id[enxORI]    = enxORI;
+                nr[enxORT]    = fcd->orires.nex*12;
+                block[enxORT] = fcd->orires.eig;
+                id[enxORT]    = enxORT;
+            }        
+
+            /* whether we are going to wrte anything out: */
+            if (fr.nre || ndisre || nr[enxOR] || nr[enxORI])
+            {
+
+                /* the old-style blocks go first */
+                fr.nblock = 0;
+                for(i=0; i<enxNR; i++)
+                {
+                    if (nr[i] > 0)
+                    {
+                        fr.nblock = i + 1;
+                    }
+                }
+                add_blocks_enxframe(&fr, fr.nblock);
+                for(b=0;b<fr.nblock;b++)
+                {
+                    add_subblocks_enxblock(&(fr.block[b]), 1);
+                    fr.block[b].id=id[b]; 
+                    fr.block[b].sub[0].nr = nr[b];
+#ifndef GMX_DOUBLE
+                    fr.block[b].sub[0].type = xdr_datatype_float;
+                    fr.block[b].sub[0].fval = block[b];
+#else
+                    fr.block[b].sub[0].type = xdr_datatype_double;
+                    fr.block[b].sub[0].dval = block[b];
+#endif
+                }
+
+                /* check for disre block & fill it. */
+                if (ndisre>0)
+                {
+                    int db = fr.nblock;
+                    fr.nblock+=1;
+                    add_blocks_enxframe(&fr, fr.nblock);
+
+                    add_subblocks_enxblock(&(fr.block[db]), 2);
+                    fr.block[db].id=enxDISRE;
+                    fr.block[db].sub[0].nr=ndisre;
+                    fr.block[db].sub[1].nr=ndisre;
+#ifndef GMX_DOUBLE
+                    fr.block[db].sub[0].type=xdr_datatype_float;
+                    fr.block[db].sub[1].type=xdr_datatype_float;
+                    fr.block[db].sub[0].fval=disre_rt;
+                    fr.block[db].sub[1].fval=disre_rm3tav;
+#else
+                    fr.block[db].sub[0].type=xdr_datatype_double;
+                    fr.block[db].sub[1].type=xdr_datatype_double;
+                    fr.block[db].sub[0].dval=disre_rt;
+                    fr.block[db].sub[1].dval=disre_rm3tav;
+#endif
+                }
+                /* here we can put new-style blocks */
+
+                /* Free energy perturbation blocks */
+                if (md->dhc)
+                {
+                    mde_delta_h_coll_handle_block(md->dhc, &fr, fr.nblock);
+                }
+
+                /* do the actual I/O */
+                do_enx(fp_ene,&fr);
+                gmx_fio_check_file_position(enx_file_pointer(fp_ene));
+                if (fr.nre)
+                {
+                    /* We have stored the sums, so reset the sum history */
+                    reset_ebin_sums(md->ebin);
+                }
+
+                /* we can now free & reset the data in the blocks */
+                if (md->dhc)
+                    mde_delta_h_coll_reset(md->dhc);
+            }
+            free_enxframe(&fr);
+            break;
+        case eprAVER:
+            if (log)
+            {
+                pprint(log,"A V E R A G E S",md);
+            }
+            break;
+        case eprRMS:
+            if (log)
+            {
+                pprint(log,"R M S - F L U C T U A T I O N S",md);
+            }
+            break;
+        default:
+            gmx_fatal(FARGS,"Invalid print mode (%d)",mode);
+    }
+
+    if (log)
+    {
+        for(i=0;i<opts->ngtc;i++)
+        {
+            if(opts->annealing[i]!=eannNO)
+            {
+                fprintf(log,"Current ref_t for group %s: %8.1f\n",
+                        *(groups->grpname[groups->grps[egcTC].nm_ind[i]]),
+                        opts->ref_t[i]);
+            }
+        }
+        if (mode==eprNORMAL && fcd->orires.nr>0)
+        {
+            print_orires_log(log,&(fcd->orires));
+        }
+        fprintf(log,"   Energies (%s)\n",unit_energy);
+        pr_ebin(log,md->ebin,md->ie,md->f_nre+md->nCrmsd,5,mode,TRUE);  
+        fprintf(log,"\n");
+
+        if (!bCompact)
+        {
+            if (md->bDynBox)
+            {
+                pr_ebin(log,md->ebin,md->ib, md->bTricl ? NTRICLBOXS : NBOXS,5,
+                        mode,TRUE);      
+                fprintf(log,"\n");
+            }
+            if (md->bConstrVir)
+            {
+                fprintf(log,"   Constraint Virial (%s)\n",unit_energy);
+                pr_ebin(log,md->ebin,md->isvir,9,3,mode,FALSE);  
+                fprintf(log,"\n");
+                fprintf(log,"   Force Virial (%s)\n",unit_energy);
+                pr_ebin(log,md->ebin,md->ifvir,9,3,mode,FALSE);  
+                fprintf(log,"\n");
+            }
+            fprintf(log,"   Total Virial (%s)\n",unit_energy);
+            pr_ebin(log,md->ebin,md->ivir,9,3,mode,FALSE);   
+            fprintf(log,"\n");
+            fprintf(log,"   Pressure (%s)\n",unit_pres_bar);
+            pr_ebin(log,md->ebin,md->ipres,9,3,mode,FALSE);  
+            fprintf(log,"\n");
+            fprintf(log,"   Total Dipole (%s)\n",unit_dipole_D);
+            pr_ebin(log,md->ebin,md->imu,3,3,mode,FALSE);    
+            fprintf(log,"\n");
+
+            if (md->nE > 1)
+            {
+                if (md->print_grpnms==NULL)
+                {
+                    snew(md->print_grpnms,md->nE);
+                    n=0;
+                    for(i=0; (i<md->nEg); i++)
+                    {
+                        ni=groups->grps[egcENER].nm_ind[i];
+                        for(j=i; (j<md->nEg); j++)
+                        {
+                            nj=groups->grps[egcENER].nm_ind[j];
+                            sprintf(buf,"%s-%s",*(groups->grpname[ni]),
+                                    *(groups->grpname[nj]));
+                            md->print_grpnms[n++]=strdup(buf);
+                        }
+                    }
+                }
+                sprintf(buf,"Epot (%s)",unit_energy);
+                fprintf(log,"%15s   ",buf);
+                for(i=0; (i<egNR); i++)
+                {
+                    if (md->bEInd[i])
+                    {
+                        fprintf(log,"%12s   ",egrp_nm[i]);
+                    }
+                }
+                fprintf(log,"\n");
+                for(i=0; (i<md->nE); i++)
+                {
+                    fprintf(log,"%15s",md->print_grpnms[i]);
+                    pr_ebin(log,md->ebin,md->igrp[i],md->nEc,md->nEc,mode,
+                            FALSE);
+                }
+                fprintf(log,"\n");
+            }
+            if (md->nTC > 1)
+            {
+                pr_ebin(log,md->ebin,md->itemp,md->nTC,4,mode,TRUE);
+                fprintf(log,"\n");
+            }
+            if (md->nU > 1)
+            {
+                fprintf(log,"%15s   %12s   %12s   %12s\n",
+                        "Group","Ux","Uy","Uz");
+                for(i=0; (i<md->nU); i++)
+                {
+                    ni=groups->grps[egcACC].nm_ind[i];
+                    fprintf(log,"%15s",*groups->grpname[ni]);
+                    pr_ebin(log,md->ebin,md->iu+3*i,3,3,mode,FALSE);
+                }
+                fprintf(log,"\n");
+            }
+        }
+    }
+
+}
+
+void update_energyhistory(energyhistory_t * enerhist,t_mdebin * mdebin)
+{
+    int i;
+
+    enerhist->nsteps     = mdebin->ebin->nsteps;
+    enerhist->nsum       = mdebin->ebin->nsum;
+    enerhist->nsteps_sim = mdebin->ebin->nsteps_sim;
+    enerhist->nsum_sim   = mdebin->ebin->nsum_sim;
+    enerhist->nener      = mdebin->ebin->nener;
+
+    if (mdebin->ebin->nsum > 0)
+    {
+        /* Check if we need to allocate first */
+        if(enerhist->ener_ave == NULL)
+        {
+            snew(enerhist->ener_ave,enerhist->nener);
+            snew(enerhist->ener_sum,enerhist->nener);
+        }
+
+        for(i=0;i<enerhist->nener;i++)
+        {
+            enerhist->ener_ave[i] = mdebin->ebin->e[i].eav;
+            enerhist->ener_sum[i] = mdebin->ebin->e[i].esum;
+        }
+    }
+
+    if (mdebin->ebin->nsum_sim > 0)
+    {
+        /* Check if we need to allocate first */
+        if(enerhist->ener_sum_sim == NULL)
+        {
+            snew(enerhist->ener_sum_sim,enerhist->nener);
+        }
+
+        for(i=0;i<enerhist->nener;i++)
+        {
+            enerhist->ener_sum_sim[i] = mdebin->ebin->e_sim[i].esum;
+        }
+    }
+    if (mdebin->dhc)
+    {
+        mde_delta_h_coll_update_energyhistory(mdebin->dhc, enerhist);
+    }
+}
+
+void restore_energyhistory_from_state(t_mdebin * mdebin,
+                                      energyhistory_t * enerhist)
+{
+    int i;
+
+    if ((enerhist->nsum > 0 || enerhist->nsum_sim > 0) &&
+        mdebin->ebin->nener != enerhist->nener)
+    {
+        gmx_fatal(FARGS,"Mismatch between number of energies in run input (%d) and checkpoint file (%d).",
+                  mdebin->ebin->nener,enerhist->nener);
+    }
+
+    mdebin->ebin->nsteps     = enerhist->nsteps;
+    mdebin->ebin->nsum       = enerhist->nsum;
+    mdebin->ebin->nsteps_sim = enerhist->nsteps_sim;
+    mdebin->ebin->nsum_sim   = enerhist->nsum_sim;
+
+    for(i=0; i<mdebin->ebin->nener; i++)
+    {
+        mdebin->ebin->e[i].eav  =
+                  (enerhist->nsum > 0 ? enerhist->ener_ave[i] : 0);
+        mdebin->ebin->e[i].esum =
+                  (enerhist->nsum > 0 ? enerhist->ener_sum[i] : 0);
+        mdebin->ebin->e_sim[i].esum =
+                  (enerhist->nsum_sim > 0 ? enerhist->ener_sum_sim[i] : 0);
+    }
+    if (mdebin->dhc)
+    {         
+        mde_delta_h_coll_restore_energyhistory(mdebin->dhc, enerhist);
+    }
+}
diff --git a/src/gromacs/mdlib/minimize.c b/src/gromacs/mdlib/minimize.c
new file mode 100644 (file)
index 0000000..c11481d
--- /dev/null
@@ -0,0 +1,2516 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include "sysstuff.h"
+#include "string2.h"
+#include "network.h"
+#include "confio.h"
+#include "copyrite.h"
+#include "smalloc.h"
+#include "nrnb.h"
+#include "main.h"
+#include "force.h"
+#include "macros.h"
+#include "random.h"
+#include "names.h"
+#include "gmx_fatal.h"
+#include "txtdump.h"
+#include "typedefs.h"
+#include "update.h"
+#include "constr.h"
+#include "vec.h"
+#include "statutil.h"
+#include "tgroup.h"
+#include "mdebin.h"
+#include "vsite.h"
+#include "force.h"
+#include "mdrun.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "trnio.h"
+#include "sparsematrix.h"
+#include "mtxio.h"
+#include "mdatoms.h"
+#include "ns.h"
+#include "gmx_wallcycle.h"
+#include "mtop_util.h"
+#include "gmxfio.h"
+#include "pme.h"
+#include "membed.h"
+
+typedef struct {
+  t_state s;
+  rvec    *f;
+  real    epot;
+  real    fnorm;
+  real    fmax;
+  int     a_fmax;
+} em_state_t;
+
+static em_state_t *init_em_state()
+{
+  em_state_t *ems;
+  
+  snew(ems,1);
+
+  return ems;
+}
+
+static void print_em_start(FILE *fplog,t_commrec *cr,gmx_runtime_t *runtime,
+                           gmx_wallcycle_t wcycle,
+                           const char *name)
+{
+    char buf[STRLEN];
+
+    runtime_start(runtime);
+
+    sprintf(buf,"Started %s",name);
+    print_date_and_time(fplog,cr->nodeid,buf,NULL);
+
+    wallcycle_start(wcycle,ewcRUN);
+}
+static void em_time_end(FILE *fplog,t_commrec *cr,gmx_runtime_t *runtime,
+                        gmx_wallcycle_t wcycle)
+{
+    wallcycle_stop(wcycle,ewcRUN);
+
+    runtime_end(runtime);
+}
+
+static void sp_header(FILE *out,const char *minimizer,real ftol,int nsteps)
+{
+    fprintf(out,"\n");
+    fprintf(out,"%s:\n",minimizer);
+    fprintf(out,"   Tolerance (Fmax)   = %12.5e\n",ftol);
+    fprintf(out,"   Number of steps    = %12d\n",nsteps);
+}
+
+static void warn_step(FILE *fp,real ftol,gmx_bool bLastStep,gmx_bool bConstrain)
+{
+    if (bLastStep)
+    {
+        fprintf(fp,"\nReached the maximum number of steps before reaching Fmax < %g\n",ftol);
+    }
+    else
+    {
+        fprintf(fp,"\nStepsize too small, or no change in energy.\n"
+                "Converged to machine precision,\n"
+                "but not to the requested precision Fmax < %g\n",
+                ftol);
+        if (sizeof(real)<sizeof(double))
+        {
+            fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
+        }
+        if (bConstrain)
+        {
+            fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
+                    "off constraints alltogether (set constraints = none in mdp file)\n");
+        }
+    }
+}
+
+
+
+static void print_converged(FILE *fp,const char *alg,real ftol,
+                           gmx_large_int_t count,gmx_bool bDone,gmx_large_int_t nsteps,
+                           real epot,real fmax, int nfmax, real fnorm)
+{
+  char buf[STEPSTRSIZE];
+
+  if (bDone)
+    fprintf(fp,"\n%s converged to Fmax < %g in %s steps\n",
+           alg,ftol,gmx_step_str(count,buf)); 
+  else if(count<nsteps)
+    fprintf(fp,"\n%s converged to machine precision in %s steps,\n"
+               "but did not reach the requested Fmax < %g.\n",
+           alg,gmx_step_str(count,buf),ftol);
+  else 
+    fprintf(fp,"\n%s did not converge to Fmax < %g in %s steps.\n",
+           alg,ftol,gmx_step_str(count,buf));
+
+#ifdef GMX_DOUBLE
+  fprintf(fp,"Potential Energy  = %21.14e\n",epot); 
+  fprintf(fp,"Maximum force     = %21.14e on atom %d\n",fmax,nfmax+1); 
+  fprintf(fp,"Norm of force     = %21.14e\n",fnorm); 
+#else
+  fprintf(fp,"Potential Energy  = %14.7e\n",epot); 
+  fprintf(fp,"Maximum force     = %14.7e on atom %d\n",fmax,nfmax+1); 
+  fprintf(fp,"Norm of force     = %14.7e\n",fnorm); 
+#endif
+}
+
+static void get_f_norm_max(t_commrec *cr,
+                          t_grpopts *opts,t_mdatoms *mdatoms,rvec *f,
+                          real *fnorm,real *fmax,int *a_fmax)
+{
+  double fnorm2,*sum;
+  real fmax2,fmax2_0,fam;
+  int  la_max,a_max,start,end,i,m,gf;
+
+  /* This routine finds the largest force and returns it.
+   * On parallel machines the global max is taken.
+   */
+  fnorm2 = 0;
+  fmax2 = 0;
+  la_max = -1;
+  gf = 0;
+  start = mdatoms->start;
+  end   = mdatoms->homenr + start;
+  if (mdatoms->cFREEZE) {
+    for(i=start; i<end; i++) {
+      gf = mdatoms->cFREEZE[i];
+      fam = 0;
+      for(m=0; m<DIM; m++)
+       if (!opts->nFreeze[gf][m])
+         fam += sqr(f[i][m]);
+      fnorm2 += fam;
+      if (fam > fmax2) {
+       fmax2  = fam;
+       la_max = i;
+      }
+    }
+  } else {
+    for(i=start; i<end; i++) {
+      fam = norm2(f[i]);
+      fnorm2 += fam;
+      if (fam > fmax2) {
+       fmax2  = fam;
+       la_max = i;
+      }
+    }
+  }
+
+  if (la_max >= 0 && DOMAINDECOMP(cr)) {
+    a_max = cr->dd->gatindex[la_max];
+  } else {
+    a_max = la_max;
+  }
+  if (PAR(cr)) {
+    snew(sum,2*cr->nnodes+1);
+    sum[2*cr->nodeid]   = fmax2;
+    sum[2*cr->nodeid+1] = a_max;
+    sum[2*cr->nnodes]   = fnorm2;
+    gmx_sumd(2*cr->nnodes+1,sum,cr);
+    fnorm2 = sum[2*cr->nnodes];
+    /* Determine the global maximum */
+    for(i=0; i<cr->nnodes; i++) {
+      if (sum[2*i] > fmax2) {
+       fmax2 = sum[2*i];
+       a_max = (int)(sum[2*i+1] + 0.5);
+      }
+    }
+    sfree(sum);
+  }
+
+  if (fnorm)
+    *fnorm = sqrt(fnorm2);
+  if (fmax)
+    *fmax  = sqrt(fmax2);
+  if (a_fmax)
+    *a_fmax = a_max;
+}
+
+static void get_state_f_norm_max(t_commrec *cr,
+                          t_grpopts *opts,t_mdatoms *mdatoms,
+                          em_state_t *ems)
+{
+  get_f_norm_max(cr,opts,mdatoms,ems->f,&ems->fnorm,&ems->fmax,&ems->a_fmax);
+}
+
+void init_em(FILE *fplog,const char *title,
+             t_commrec *cr,t_inputrec *ir,
+             t_state *state_global,gmx_mtop_t *top_global,
+             em_state_t *ems,gmx_localtop_t **top,
+             rvec **f,rvec **f_global,
+             t_nrnb *nrnb,rvec mu_tot,
+             t_forcerec *fr,gmx_enerdata_t **enerd,
+             t_graph **graph,t_mdatoms *mdatoms,gmx_global_stat_t *gstat,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int nfile,const t_filenm fnm[],
+             gmx_mdoutf_t **outf,t_mdebin **mdebin)
+{
+    int  start,homenr,i;
+    real dvdlambda;
+    
+    if (fplog)
+    {
+        fprintf(fplog,"Initiating %s\n",title);
+    }
+    
+    state_global->ngtc = 0;
+    
+    /* Initiate some variables */
+    if (ir->efep != efepNO)
+    {
+        state_global->lambda = ir->init_lambda;
+    }
+    else 
+    {
+        state_global->lambda = 0.0;
+    }
+    
+    init_nrnb(nrnb);
+    
+    if (DOMAINDECOMP(cr))
+    {
+        *top = dd_init_local_top(top_global);
+        
+        dd_init_local_state(cr->dd,state_global,&ems->s);
+
+        *f = NULL;
+        
+        /* Distribute the charge groups over the nodes from the master node */
+        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
+                            state_global,top_global,ir,
+                            &ems->s,&ems->f,mdatoms,*top,
+                            fr,vsite,NULL,constr,
+                            nrnb,NULL,FALSE);
+        dd_store_state(cr->dd,&ems->s);
+        
+        if (ir->nstfout)
+        {
+            snew(*f_global,top_global->natoms);
+        }
+        else
+        {
+            *f_global = NULL;
+        }
+        *graph = NULL;
+    }
+    else
+    {
+        snew(*f,top_global->natoms);
+
+        /* Just copy the state */
+        ems->s = *state_global;
+        snew(ems->s.x,ems->s.nalloc);
+        snew(ems->f,ems->s.nalloc);
+        for(i=0; i<state_global->natoms; i++)
+        {
+            copy_rvec(state_global->x[i],ems->s.x[i]);
+        }
+        copy_mat(state_global->box,ems->s.box);
+        
+        if (PAR(cr) && ir->eI != eiNM)
+        {
+            /* Initialize the particle decomposition and split the topology */
+            *top = split_system(fplog,top_global,ir,cr);
+            
+            pd_cg_range(cr,&fr->cg0,&fr->hcg);
+        }
+        else
+        {
+            *top = gmx_mtop_generate_local_top(top_global,ir);
+        }
+        *f_global = *f;
+        
+        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
+        {
+            *graph = mk_graph(fplog,&((*top)->idef),0,top_global->natoms,FALSE,FALSE);
+        }
+        else
+        {
+            *graph = NULL;
+        }
+
+        if (PARTDECOMP(cr))
+        {
+            pd_at_range(cr,&start,&homenr);
+            homenr -= start;
+        }
+        else
+        {
+            start  = 0;
+            homenr = top_global->natoms;
+        }
+        atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
+        update_mdatoms(mdatoms,state_global->lambda);
+    
+        if (vsite)
+        {
+            set_vsite_top(vsite,*top,mdatoms,cr);
+        }
+    }
+    
+    if (constr)
+    {
+        if (ir->eConstrAlg == econtSHAKE &&
+            gmx_mtop_ftype_count(top_global,F_CONSTR) > 0)
+        {
+            gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
+                      econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+        }
+        
+        if (!DOMAINDECOMP(cr))
+        {
+            set_constraints(constr,*top,ir,mdatoms,cr);
+        }
+
+        if (!ir->bContinuation)
+        {
+            /* Constrain the starting coordinates */
+            dvdlambda=0;
+            constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
+                      ir,NULL,cr,-1,0,mdatoms,
+                      ems->s.x,ems->s.x,NULL,ems->s.box,
+                      ems->s.lambda,&dvdlambda,
+                      NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+        }
+    }
+    
+    if (PAR(cr))
+    {
+        *gstat = global_stat_init(ir);
+    }
+    
+    *outf = init_mdoutf(nfile,fnm,0,cr,ir,NULL);
+
+    snew(*enerd,1);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
+
+    if (mdebin != NULL)
+    {
+        /* Init bin for energy stuff */
+        *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir,NULL); 
+    }
+
+    clear_rvec(mu_tot);
+    calc_shifts(ems->s.box,fr->shift_vec);
+}
+
+static void finish_em(FILE *fplog,t_commrec *cr,gmx_mdoutf_t *outf,
+                      gmx_runtime_t *runtime,gmx_wallcycle_t wcycle)
+{
+  if (!(cr->duty & DUTY_PME)) {
+    /* Tell the PME only node to finish */
+    gmx_pme_finish(cr);
+  }
+
+  done_mdoutf(outf);
+
+  em_time_end(fplog,cr,runtime,wcycle);
+}
+
+static void swap_em_state(em_state_t *ems1,em_state_t *ems2)
+{
+  em_state_t tmp;
+
+  tmp   = *ems1;
+  *ems1 = *ems2;
+  *ems2 = tmp;
+}
+
+static void copy_em_coords_back(em_state_t *ems,t_state *state,rvec *f)
+{
+  int i;
+
+  for(i=0; (i<state->natoms); i++)
+    copy_rvec(ems->s.x[i],state->x[i]);
+  if (f != NULL)
+    copy_rvec(ems->f[i],f[i]);
+}
+
+static void write_em_traj(FILE *fplog,t_commrec *cr,
+                          gmx_mdoutf_t *outf,
+                          gmx_bool bX,gmx_bool bF,const char *confout,
+                          gmx_mtop_t *top_global,
+                          t_inputrec *ir,gmx_large_int_t step,
+                          em_state_t *state,
+                          t_state *state_global,rvec *f_global)
+{
+    int mdof_flags;
+
+    if ((bX || bF || confout != NULL) && !DOMAINDECOMP(cr))
+    {
+        f_global = state->f;
+        copy_em_coords_back(state,state_global,bF ? f_global : NULL);
+    }
+    
+    mdof_flags = 0;
+    if (bX) { mdof_flags |= MDOF_X; }
+    if (bF) { mdof_flags |= MDOF_F; }
+    write_traj(fplog,cr,outf,mdof_flags,
+               top_global,step,(double)step,
+               &state->s,state_global,state->f,f_global,NULL,NULL);
+    
+    if (confout != NULL && MASTER(cr))
+    {
+        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols && DOMAINDECOMP(cr))
+        {
+            /* Make molecules whole only for confout writing */
+            do_pbc_mtop(fplog,ir->ePBC,state_global->box,top_global,
+                        state_global->x);
+        }
+
+        write_sto_conf_mtop(confout,
+                            *top_global->name,top_global,
+                            state_global->x,NULL,ir->ePBC,state_global->box);
+    }
+}
+
+static void do_em_step(t_commrec *cr,t_inputrec *ir,t_mdatoms *md,
+                      em_state_t *ems1,real a,rvec *f,em_state_t *ems2,
+                      gmx_constr_t constr,gmx_localtop_t *top,
+                      t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                      gmx_large_int_t count)
+
+{
+  t_state *s1,*s2;
+  int  start,end,gf,i,m;
+  rvec *x1,*x2;
+  real dvdlambda;
+
+  s1 = &ems1->s;
+  s2 = &ems2->s;
+
+  if (DOMAINDECOMP(cr) && s1->ddp_count != cr->dd->ddp_count)
+    gmx_incons("state mismatch in do_em_step");
+
+  s2->flags = s1->flags;
+
+  if (s2->nalloc != s1->nalloc) {
+    s2->nalloc = s1->nalloc;
+    srenew(s2->x,s1->nalloc);
+    srenew(ems2->f,  s1->nalloc);
+    if (s2->flags & (1<<estCGP))
+      srenew(s2->cg_p,  s1->nalloc);
+  }
+  
+  s2->natoms = s1->natoms;
+  s2->lambda = s1->lambda;
+  copy_mat(s1->box,s2->box);
+
+  start = md->start;
+  end   = md->start + md->homenr;
+
+  x1 = s1->x;
+  x2 = s2->x;
+  gf = 0;
+  for(i=start; i<end; i++) {
+    if (md->cFREEZE)
+      gf = md->cFREEZE[i];
+    for(m=0; m<DIM; m++) {
+      if (ir->opts.nFreeze[gf][m])
+       x2[i][m] = x1[i][m];
+      else
+       x2[i][m] = x1[i][m] + a*f[i][m];
+    }
+  }
+
+  if (s2->flags & (1<<estCGP)) {
+    /* Copy the CG p vector */
+    x1 = s1->cg_p;
+    x2 = s2->cg_p;
+    for(i=start; i<end; i++)
+      copy_rvec(x1[i],x2[i]);
+  }
+
+  if (DOMAINDECOMP(cr)) {
+    s2->ddp_count = s1->ddp_count;
+    if (s2->cg_gl_nalloc < s1->cg_gl_nalloc) {
+      s2->cg_gl_nalloc = s1->cg_gl_nalloc;
+      srenew(s2->cg_gl,s2->cg_gl_nalloc);
+    }
+    s2->ncg_gl = s1->ncg_gl;
+    for(i=0; i<s2->ncg_gl; i++)
+      s2->cg_gl[i] = s1->cg_gl[i];
+    s2->ddp_count_cg_gl = s1->ddp_count_cg_gl;
+  }
+
+  if (constr) {
+    wallcycle_start(wcycle,ewcCONSTR);
+    dvdlambda = 0;
+    constrain(NULL,TRUE,TRUE,constr,&top->idef,        
+              ir,NULL,cr,count,0,md,
+              s1->x,s2->x,NULL,s2->box,s2->lambda,
+              &dvdlambda,NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+    wallcycle_stop(wcycle,ewcCONSTR);
+  }
+}
+
+static void do_x_step(t_commrec *cr,int n,rvec *x1,real a,rvec *f,rvec *x2)
+
+{
+  int  start,end,i,m;
+
+  if (DOMAINDECOMP(cr)) {
+    start = 0;
+    end   = cr->dd->nat_home;
+  } else if (PARTDECOMP(cr)) {
+    pd_at_range(cr,&start,&end);
+  } else {
+    start = 0;
+    end   = n;
+  }
+
+  for(i=start; i<end; i++) {
+    for(m=0; m<DIM; m++) {
+      x2[i][m] = x1[i][m] + a*f[i][m];
+    }
+  }
+}
+
+static void do_x_sub(t_commrec *cr,int n,rvec *x1,rvec *x2,real a,rvec *f)
+
+{
+  int  start,end,i,m;
+
+  if (DOMAINDECOMP(cr)) {
+    start = 0;
+    end   = cr->dd->nat_home;
+  } else if (PARTDECOMP(cr)) {
+    pd_at_range(cr,&start,&end);
+  } else {
+    start = 0;
+    end   = n;
+  }
+
+  for(i=start; i<end; i++) {
+    for(m=0; m<DIM; m++) {
+      f[i][m] = (x1[i][m] - x2[i][m])*a;
+    }
+  }
+}
+
+static void em_dd_partition_system(FILE *fplog,int step,t_commrec *cr,
+                                   gmx_mtop_t *top_global,t_inputrec *ir,
+                                   em_state_t *ems,gmx_localtop_t *top,
+                                   t_mdatoms *mdatoms,t_forcerec *fr,
+                                   gmx_vsite_t *vsite,gmx_constr_t constr,
+                                   t_nrnb *nrnb,gmx_wallcycle_t wcycle)
+{
+    /* Repartition the domain decomposition */
+    wallcycle_start(wcycle,ewcDOMDEC);
+    dd_partition_system(fplog,step,cr,FALSE,1,
+                        NULL,top_global,ir,
+                        &ems->s,&ems->f,
+                        mdatoms,top,fr,vsite,NULL,constr,
+                        nrnb,wcycle,FALSE);
+    dd_store_state(cr->dd,&ems->s);
+    wallcycle_stop(wcycle,ewcDOMDEC);
+}
+    
+static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
+                            t_state *state_global,gmx_mtop_t *top_global,
+                            em_state_t *ems,gmx_localtop_t *top,
+                            t_inputrec *inputrec,
+                            t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                            gmx_global_stat_t gstat,
+                            gmx_vsite_t *vsite,gmx_constr_t constr,
+                            t_fcdata *fcd,
+                            t_graph *graph,t_mdatoms *mdatoms,
+                            t_forcerec *fr,rvec mu_tot,
+                            gmx_enerdata_t *enerd,tensor vir,tensor pres,
+                            gmx_large_int_t count,gmx_bool bFirst)
+{
+  real t;
+  gmx_bool bNS;
+  int  nabnsb;
+  tensor force_vir,shake_vir,ekin;
+  real dvdl,prescorr,enercorr,dvdlcorr;
+  real terminate=0;
+  
+  /* Set the time to the initial time, the time does not change during EM */
+  t = inputrec->init_t;
+
+  if (bFirst ||
+      (DOMAINDECOMP(cr) && ems->s.ddp_count < cr->dd->ddp_count)) {
+    /* This the first state or an old state used before the last ns */
+    bNS = TRUE;
+  } else {
+    bNS = FALSE;
+    if (inputrec->nstlist > 0) {
+      bNS = TRUE;
+    } else if (inputrec->nstlist == -1) {
+      nabnsb = natoms_beyond_ns_buffer(inputrec,fr,&top->cgs,NULL,ems->s.x);
+      if (PAR(cr))
+       gmx_sumi(1,&nabnsb,cr);
+      bNS = (nabnsb > 0);
+    }
+  }
+
+  if (vsite)
+    construct_vsites(fplog,vsite,ems->s.x,nrnb,1,NULL,
+                    top->idef.iparams,top->idef.il,
+                    fr->ePBC,fr->bMolPBC,graph,cr,ems->s.box);
+
+  if (DOMAINDECOMP(cr)) {
+    if (bNS) {
+      /* Repartition the domain decomposition */
+      em_dd_partition_system(fplog,count,cr,top_global,inputrec,
+                            ems,top,mdatoms,fr,vsite,constr,
+                            nrnb,wcycle);
+    }
+  }
+      
+    /* Calc force & energy on new trial position  */
+    /* do_force always puts the charge groups in the box and shifts again
+     * We do not unshift, so molecules are always whole in congrad.c
+     */
+    do_force(fplog,cr,inputrec,
+             count,nrnb,wcycle,top,top_global,&top_global->groups,
+             ems->s.box,ems->s.x,&ems->s.hist,
+             ems->f,force_vir,mdatoms,enerd,fcd,
+             ems->s.lambda,graph,fr,vsite,mu_tot,t,NULL,NULL,TRUE,
+             GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES | GMX_FORCE_VIRIAL |
+             (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0));
+       
+  /* Clear the unused shake virial and pressure */
+  clear_mat(shake_vir);
+  clear_mat(pres);
+
+  /* Calculate long range corrections to pressure and energy */
+  calc_dispcorr(fplog,inputrec,fr,count,top_global->natoms,ems->s.box,ems->s.lambda,
+                pres,force_vir,&prescorr,&enercorr,&dvdlcorr);
+  /* don't think these next 4 lines  can be moved in for now, because we 
+     don't always want to write it -- figure out how to clean this up MRS 8/4/2009 */
+  enerd->term[F_DISPCORR] = enercorr;
+  enerd->term[F_EPOT] += enercorr;
+  enerd->term[F_PRES] += prescorr;
+  enerd->term[F_DVDL] += dvdlcorr;
+
+    /* Communicate stuff when parallel */
+    if (PAR(cr) && inputrec->eI != eiNM)
+    {
+        wallcycle_start(wcycle,ewcMoveE);
+
+        global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
+                    inputrec,NULL,NULL,NULL,1,&terminate,
+                    top_global,&ems->s,FALSE,
+                    CGLO_ENERGY | 
+                    CGLO_PRESSURE | 
+                    CGLO_CONSTRAINT | 
+                    CGLO_FIRSTITERATE);
+
+        wallcycle_stop(wcycle,ewcMoveE);
+    }
+
+  ems->epot = enerd->term[F_EPOT];
+  
+  if (constr) {
+    /* Project out the constraint components of the force */
+    wallcycle_start(wcycle,ewcCONSTR);
+    dvdl = 0;
+    constrain(NULL,FALSE,FALSE,constr,&top->idef,
+              inputrec,NULL,cr,count,0,mdatoms,
+              ems->s.x,ems->f,ems->f,ems->s.box,ems->s.lambda,&dvdl,
+              NULL,&shake_vir,nrnb,econqForceDispl,FALSE,0,0);
+    if (fr->bSepDVDL && fplog)
+      fprintf(fplog,sepdvdlformat,"Constraints",t,dvdl);
+    enerd->term[F_DHDL_CON] += dvdl;
+    m_add(force_vir,shake_vir,vir);
+    wallcycle_stop(wcycle,ewcCONSTR);
+  } else {
+    copy_mat(force_vir,vir);
+  }
+
+  clear_mat(ekin);
+  enerd->term[F_PRES] =
+    calc_pres(fr->ePBC,inputrec->nwall,ems->s.box,ekin,vir,pres,
+             (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+
+  sum_dhdl(enerd,ems->s.lambda,inputrec);
+
+    if (EI_ENERGY_MINIMIZATION(inputrec->eI))
+    {
+        get_state_f_norm_max(cr,&(inputrec->opts),mdatoms,ems);
+    }
+}
+
+static double reorder_partsum(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
+                             gmx_mtop_t *mtop,
+                             em_state_t *s_min,em_state_t *s_b)
+{
+  rvec *fm,*fb,*fmg;
+  t_block *cgs_gl;
+  int ncg,*cg_gl,*index,c,cg,i,a0,a1,a,gf,m;
+  double partsum;
+  unsigned char *grpnrFREEZE;
+
+  if (debug)
+    fprintf(debug,"Doing reorder_partsum\n");
+
+  fm = s_min->f;
+  fb = s_b->f;
+
+  cgs_gl = dd_charge_groups_global(cr->dd);
+  index = cgs_gl->index;
+
+  /* Collect fm in a global vector fmg.
+   * This conflicts with the spirit of domain decomposition,
+   * but to fully optimize this a much more complicated algorithm is required.
+   */
+  snew(fmg,mtop->natoms);
+  
+  ncg   = s_min->s.ncg_gl;
+  cg_gl = s_min->s.cg_gl;
+  i = 0;
+  for(c=0; c<ncg; c++) {
+    cg = cg_gl[c];
+    a0 = index[cg];
+    a1 = index[cg+1];
+    for(a=a0; a<a1; a++) {
+      copy_rvec(fm[i],fmg[a]);
+      i++;
+    }
+  }
+  gmx_sum(mtop->natoms*3,fmg[0],cr);
+
+  /* Now we will determine the part of the sum for the cgs in state s_b */
+  ncg   = s_b->s.ncg_gl;
+  cg_gl = s_b->s.cg_gl;
+  partsum = 0;
+  i = 0;
+  gf = 0;
+  grpnrFREEZE = mtop->groups.grpnr[egcFREEZE];
+  for(c=0; c<ncg; c++) {
+    cg = cg_gl[c];
+    a0 = index[cg];
+    a1 = index[cg+1];
+    for(a=a0; a<a1; a++) {
+      if (mdatoms->cFREEZE && grpnrFREEZE) {
+       gf = grpnrFREEZE[i];
+      }
+      for(m=0; m<DIM; m++) {
+       if (!opts->nFreeze[gf][m]) {
+         partsum += (fb[i][m] - fmg[a][m])*fb[i][m];
+       }
+      }
+      i++;
+    }
+  }
+  
+  sfree(fmg);
+
+  return partsum;
+}
+
+static real pr_beta(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
+                   gmx_mtop_t *mtop,
+                   em_state_t *s_min,em_state_t *s_b)
+{
+  rvec *fm,*fb;
+  double sum;
+  int  gf,i,m;
+
+  /* This is just the classical Polak-Ribiere calculation of beta;
+   * it looks a bit complicated since we take freeze groups into account,
+   * and might have to sum it in parallel runs.
+   */
+  
+  if (!DOMAINDECOMP(cr) ||
+      (s_min->s.ddp_count == cr->dd->ddp_count &&
+       s_b->s.ddp_count   == cr->dd->ddp_count)) {
+    fm = s_min->f;
+    fb = s_b->f;
+    sum = 0;
+    gf = 0;
+    /* This part of code can be incorrect with DD,
+     * since the atom ordering in s_b and s_min might differ.
+     */
+    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
+      if (mdatoms->cFREEZE)
+       gf = mdatoms->cFREEZE[i];
+      for(m=0; m<DIM; m++)
+       if (!opts->nFreeze[gf][m]) {
+         sum += (fb[i][m] - fm[i][m])*fb[i][m];
+       } 
+    }
+  } else {
+    /* We need to reorder cgs while summing */
+    sum = reorder_partsum(cr,opts,mdatoms,mtop,s_min,s_b);
+  }
+  if (PAR(cr))
+    gmx_sumd(1,&sum,cr);
+
+  return sum/sqr(s_min->fnorm);
+}
+
+double do_cg(FILE *fplog,t_commrec *cr,
+             int nfile,const t_filenm fnm[],
+             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+             int nstglobalcomm,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int stepout,
+             t_inputrec *inputrec,
+             gmx_mtop_t *top_global,t_fcdata *fcd,
+             t_state *state_global,
+             t_mdatoms *mdatoms,
+             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+             gmx_edsam_t ed,
+             t_forcerec *fr,
+             int repl_ex_nst,int repl_ex_seed,
+             gmx_membed_t *membed,
+             real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             gmx_runtime_t *runtime)
+{
+  const char *CG="Polak-Ribiere Conjugate Gradients";
+
+  em_state_t *s_min,*s_a,*s_b,*s_c;
+  gmx_localtop_t *top;
+  gmx_enerdata_t *enerd;
+  rvec   *f;
+  gmx_global_stat_t gstat;
+  t_graph    *graph;
+  rvec   *f_global,*p,*sf,*sfm;
+  double gpa,gpb,gpc,tmp,sum[2],minstep;
+  real   fnormn;
+  real   stepsize;     
+  real   a,b,c,beta=0.0;
+  real   epot_repl=0;
+  real   pnorm;
+  t_mdebin   *mdebin;
+  gmx_bool   converged,foundlower;
+  rvec   mu_tot;
+  gmx_bool   do_log=FALSE,do_ene=FALSE,do_x,do_f;
+  tensor vir,pres;
+  int    number_steps,neval=0,nstcg=inputrec->nstcgsteep;
+  gmx_mdoutf_t *outf;
+  int    i,m,gf,step,nminstep;
+  real   terminate=0;  
+
+  step=0;
+
+  s_min = init_em_state();
+  s_a   = init_em_state();
+  s_b   = init_em_state();
+  s_c   = init_em_state();
+
+  /* Init em and store the local state in s_min */
+  init_em(fplog,CG,cr,inputrec,
+          state_global,top_global,s_min,&top,&f,&f_global,
+          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
+          nfile,fnm,&outf,&mdebin);
+  
+  /* Print to log file */
+  print_em_start(fplog,cr,runtime,wcycle,CG);
+  
+  /* Max number of steps */
+  number_steps=inputrec->nsteps;
+
+  if (MASTER(cr))
+    sp_header(stderr,CG,inputrec->em_tol,number_steps);
+  if (fplog)
+    sp_header(fplog,CG,inputrec->em_tol,number_steps);
+
+  /* Call the force routine and some auxiliary (neighboursearching etc.) */
+  /* do_force always puts the charge groups in the box and shifts again
+   * We do not unshift, so molecules are always whole in congrad.c
+   */
+  evaluate_energy(fplog,bVerbose,cr,
+                 state_global,top_global,s_min,top,
+                 inputrec,nrnb,wcycle,gstat,
+                 vsite,constr,fcd,graph,mdatoms,fr,
+                 mu_tot,enerd,vir,pres,-1,TRUE);
+  where();
+
+  if (MASTER(cr)) {
+    /* Copy stuff to the energy bin for easy printing etc. */
+    upd_mdebin(mdebin,FALSE,FALSE,(double)step,
+              mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
+              NULL,NULL,vir,pres,NULL,mu_tot,constr);
+    
+    print_ebin_header(fplog,step,step,s_min->s.lambda);
+    print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
+               TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+  }
+  where();
+
+  /* Estimate/guess the initial stepsize */
+  stepsize = inputrec->em_stepsize/s_min->fnorm;
+  if (MASTER(cr)) {
+    fprintf(stderr,"   F-max             = %12.5e on atom %d\n",
+           s_min->fmax,s_min->a_fmax+1);
+    fprintf(stderr,"   F-Norm            = %12.5e\n",
+           s_min->fnorm/sqrt(state_global->natoms));
+    fprintf(stderr,"\n");
+    /* and copy to the log file too... */
+    fprintf(fplog,"   F-max             = %12.5e on atom %d\n",
+           s_min->fmax,s_min->a_fmax+1);
+    fprintf(fplog,"   F-Norm            = %12.5e\n",
+           s_min->fnorm/sqrt(state_global->natoms));
+    fprintf(fplog,"\n");
+  }  
+  /* Start the loop over CG steps.             
+   * Each successful step is counted, and we continue until
+   * we either converge or reach the max number of steps.
+   */
+  converged = FALSE;
+  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged;step++) {
+    
+    /* start taking steps in a new direction 
+     * First time we enter the routine, beta=0, and the direction is 
+     * simply the negative gradient.
+     */
+
+    /* Calculate the new direction in p, and the gradient in this direction, gpa */
+    p  = s_min->s.cg_p;
+    sf = s_min->f;
+    gpa = 0;
+    gf = 0;
+    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
+      if (mdatoms->cFREEZE) 
+       gf = mdatoms->cFREEZE[i];
+      for(m=0; m<DIM; m++) {
+       if (!inputrec->opts.nFreeze[gf][m]) {
+         p[i][m] = sf[i][m] + beta*p[i][m];
+         gpa -= p[i][m]*sf[i][m];
+         /* f is negative gradient, thus the sign */
+       } else {
+          p[i][m] = 0;
+       }
+      }
+    }
+    
+    /* Sum the gradient along the line across CPUs */
+    if (PAR(cr))
+      gmx_sumd(1,&gpa,cr);
+
+    /* Calculate the norm of the search vector */
+    get_f_norm_max(cr,&(inputrec->opts),mdatoms,p,&pnorm,NULL,NULL);
+    
+    /* Just in case stepsize reaches zero due to numerical precision... */
+    if(stepsize<=0)      
+      stepsize = inputrec->em_stepsize/pnorm;
+    
+    /* 
+     * Double check the value of the derivative in the search direction.
+     * If it is positive it must be due to the old information in the
+     * CG formula, so just remove that and start over with beta=0.
+     * This corresponds to a steepest descent step.
+     */
+    if(gpa>0) {
+      beta = 0;
+      step--; /* Don't count this step since we are restarting */
+      continue; /* Go back to the beginning of the big for-loop */
+    }
+
+    /* Calculate minimum allowed stepsize, before the average (norm)
+     * relative change in coordinate is smaller than precision
+     */
+    minstep=0;
+    for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
+      for(m=0; m<DIM; m++) {
+       tmp = fabs(s_min->s.x[i][m]);
+       if(tmp < 1.0)
+         tmp = 1.0;
+       tmp = p[i][m]/tmp;
+       minstep += tmp*tmp;
+      }
+    }
+    /* Add up from all CPUs */
+    if(PAR(cr))
+      gmx_sumd(1,&minstep,cr);
+
+    minstep = GMX_REAL_EPS/sqrt(minstep/(3*state_global->natoms));
+
+    if(stepsize<minstep) {
+      converged=TRUE;
+      break;
+    }
+    
+    /* Write coordinates if necessary */
+    do_x = do_per_step(step,inputrec->nstxout);
+    do_f = do_per_step(step,inputrec->nstfout);
+    
+    write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
+                  top_global,inputrec,step,
+                  s_min,state_global,f_global);
+    
+    /* Take a step downhill.
+     * In theory, we should minimize the function along this direction.
+     * That is quite possible, but it turns out to take 5-10 function evaluations
+     * for each line. However, we dont really need to find the exact minimum -
+     * it is much better to start a new CG step in a modified direction as soon
+     * as we are close to it. This will save a lot of energy evaluations.
+     *
+     * In practice, we just try to take a single step.
+     * If it worked (i.e. lowered the energy), we increase the stepsize but
+     * the continue straight to the next CG step without trying to find any minimum.
+     * If it didn't work (higher energy), there must be a minimum somewhere between
+     * the old position and the new one.
+     * 
+     * Due to the finite numerical accuracy, it turns out that it is a good idea
+     * to even accept a SMALL increase in energy, if the derivative is still downhill.
+     * This leads to lower final energies in the tests I've done. / Erik 
+     */
+    s_a->epot = s_min->epot;
+    a = 0.0;
+    c = a + stepsize; /* reference position along line is zero */
+    
+    if (DOMAINDECOMP(cr) && s_min->s.ddp_count < cr->dd->ddp_count) {
+      em_dd_partition_system(fplog,step,cr,top_global,inputrec,
+                            s_min,top,mdatoms,fr,vsite,constr,
+                            nrnb,wcycle);
+    }
+
+    /* Take a trial step (new coords in s_c) */
+    do_em_step(cr,inputrec,mdatoms,s_min,c,s_min->s.cg_p,s_c,
+              constr,top,nrnb,wcycle,-1);
+    
+    neval++;
+    /* Calculate energy for the trial step */
+    evaluate_energy(fplog,bVerbose,cr,
+                   state_global,top_global,s_c,top,
+                   inputrec,nrnb,wcycle,gstat,
+                   vsite,constr,fcd,graph,mdatoms,fr,
+                   mu_tot,enerd,vir,pres,-1,FALSE);
+    
+    /* Calc derivative along line */
+    p  = s_c->s.cg_p;
+    sf = s_c->f;
+    gpc=0;
+    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
+      for(m=0; m<DIM; m++) 
+         gpc -= p[i][m]*sf[i][m];  /* f is negative gradient, thus the sign */
+    }
+    /* Sum the gradient along the line across CPUs */
+    if (PAR(cr))
+      gmx_sumd(1,&gpc,cr);
+
+    /* This is the max amount of increase in energy we tolerate */
+    tmp=sqrt(GMX_REAL_EPS)*fabs(s_a->epot);
+
+    /* Accept the step if the energy is lower, or if it is not significantly higher
+     * and the line derivative is still negative.
+     */
+    if (s_c->epot < s_a->epot || (gpc < 0 && s_c->epot < (s_a->epot + tmp))) {
+      foundlower = TRUE;
+      /* Great, we found a better energy. Increase step for next iteration
+       * if we are still going down, decrease it otherwise
+       */
+      if(gpc<0)
+       stepsize *= 1.618034;  /* The golden section */
+      else
+       stepsize *= 0.618034;  /* 1/golden section */
+    } else {
+      /* New energy is the same or higher. We will have to do some work
+       * to find a smaller value in the interval. Take smaller step next time!
+       */
+      foundlower = FALSE;
+      stepsize *= 0.618034;
+    }    
+
+
+
+    
+    /* OK, if we didn't find a lower value we will have to locate one now - there must
+     * be one in the interval [a=0,c].
+     * The same thing is valid here, though: Don't spend dozens of iterations to find
+     * the line minimum. We try to interpolate based on the derivative at the endpoints,
+     * and only continue until we find a lower value. In most cases this means 1-2 iterations.
+     *
+     * I also have a safeguard for potentially really patological functions so we never
+     * take more than 20 steps before we give up ...
+     *
+     * If we already found a lower value we just skip this step and continue to the update.
+     */
+    if (!foundlower) {
+      nminstep=0;
+
+      do {
+       /* Select a new trial point.
+        * If the derivatives at points a & c have different sign we interpolate to zero,
+        * otherwise just do a bisection.
+        */
+       if(gpa<0 && gpc>0)
+         b = a + gpa*(a-c)/(gpc-gpa);
+       else
+         b = 0.5*(a+c);                
+       
+       /* safeguard if interpolation close to machine accuracy causes errors:
+        * never go outside the interval
+        */
+       if(b<=a || b>=c)
+         b = 0.5*(a+c);
+       
+       if (DOMAINDECOMP(cr) && s_min->s.ddp_count != cr->dd->ddp_count) {
+         /* Reload the old state */
+         em_dd_partition_system(fplog,-1,cr,top_global,inputrec,
+                                s_min,top,mdatoms,fr,vsite,constr,
+                                nrnb,wcycle);
+       }
+
+       /* Take a trial step to this new point - new coords in s_b */
+       do_em_step(cr,inputrec,mdatoms,s_min,b,s_min->s.cg_p,s_b,
+                  constr,top,nrnb,wcycle,-1);
+       
+       neval++;
+       /* Calculate energy for the trial step */
+       evaluate_energy(fplog,bVerbose,cr,
+                       state_global,top_global,s_b,top,
+                       inputrec,nrnb,wcycle,gstat,
+                       vsite,constr,fcd,graph,mdatoms,fr,
+                       mu_tot,enerd,vir,pres,-1,FALSE);
+       
+       /* p does not change within a step, but since the domain decomposition
+        * might change, we have to use cg_p of s_b here.
+        */
+       p  = s_b->s.cg_p;
+       sf = s_b->f;
+       gpb=0;
+       for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
+         for(m=0; m<DIM; m++)
+             gpb -= p[i][m]*sf[i][m];   /* f is negative gradient, thus the sign */
+       }
+       /* Sum the gradient along the line across CPUs */
+       if (PAR(cr))
+         gmx_sumd(1,&gpb,cr);
+       
+       if (debug)
+         fprintf(debug,"CGE: EpotA %f EpotB %f EpotC %f gpb %f\n",
+                 s_a->epot,s_b->epot,s_c->epot,gpb);
+
+       epot_repl = s_b->epot;
+       
+       /* Keep one of the intervals based on the value of the derivative at the new point */
+       if (gpb > 0) {
+         /* Replace c endpoint with b */
+         swap_em_state(s_b,s_c);
+         c = b;
+         gpc = gpb;
+       } else {
+         /* Replace a endpoint with b */
+         swap_em_state(s_b,s_a);
+         a = b;
+         gpa = gpb;
+       }
+       
+       /* 
+        * Stop search as soon as we find a value smaller than the endpoints.
+        * Never run more than 20 steps, no matter what.
+        */
+       nminstep++;
+      } while ((epot_repl > s_a->epot || epot_repl > s_c->epot) &&
+              (nminstep < 20));     
+      
+      if (fabs(epot_repl - s_min->epot) < fabs(s_min->epot)*GMX_REAL_EPS ||
+         nminstep >= 20) {
+       /* OK. We couldn't find a significantly lower energy.
+        * If beta==0 this was steepest descent, and then we give up.
+        * If not, set beta=0 and restart with steepest descent before quitting.
+         */
+       if (beta == 0.0) {
+         /* Converged */
+         converged = TRUE;
+         break;
+       } else {
+         /* Reset memory before giving up */
+         beta = 0.0;
+         continue;
+       }
+      }
+      
+      /* Select min energy state of A & C, put the best in B.
+       */
+      if (s_c->epot < s_a->epot) {
+       if (debug)
+         fprintf(debug,"CGE: C (%f) is lower than A (%f), moving C to B\n",
+                 s_c->epot,s_a->epot);
+       swap_em_state(s_b,s_c);
+       gpb = gpc;
+       b = c;
+      } else {
+       if (debug)
+         fprintf(debug,"CGE: A (%f) is lower than C (%f), moving A to B\n",
+                 s_a->epot,s_c->epot);
+       swap_em_state(s_b,s_a);
+       gpb = gpa;
+       b = a;
+      }
+      
+    } else {
+      if (debug)
+       fprintf(debug,"CGE: Found a lower energy %f, moving C to B\n",
+               s_c->epot);
+      swap_em_state(s_b,s_c);
+      gpb = gpc;
+      b = c;
+    }
+    
+    /* new search direction */
+    /* beta = 0 means forget all memory and restart with steepest descents. */
+    if (nstcg && ((step % nstcg)==0)) 
+      beta = 0.0;
+    else {
+      /* s_min->fnorm cannot be zero, because then we would have converged
+       * and broken out.
+       */
+
+      /* Polak-Ribiere update.
+       * Change to fnorm2/fnorm2_old for Fletcher-Reeves
+       */
+      beta = pr_beta(cr,&inputrec->opts,mdatoms,top_global,s_min,s_b);
+    }
+    /* Limit beta to prevent oscillations */
+    if (fabs(beta) > 5.0)
+      beta = 0.0;
+    
+    
+    /* update positions */
+    swap_em_state(s_min,s_b);
+    gpa = gpb;
+    
+    /* Print it if necessary */
+    if (MASTER(cr)) {
+      if(bVerbose)
+       fprintf(stderr,"\rStep %d, Epot=%12.6e, Fnorm=%9.3e, Fmax=%9.3e (atom %d)\n",
+               step,s_min->epot,s_min->fnorm/sqrt(state_global->natoms),
+               s_min->fmax,s_min->a_fmax+1);
+      /* Store the new (lower) energies */
+      upd_mdebin(mdebin,FALSE,FALSE,(double)step,
+                mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
+                NULL,NULL,vir,pres,NULL,mu_tot,constr);
+      do_log = do_per_step(step,inputrec->nstlog);
+      do_ene = do_per_step(step,inputrec->nstenergy);
+      if(do_log)
+       print_ebin_header(fplog,step,step,s_min->s.lambda);
+      print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
+                do_log ? fplog : NULL,step,step,eprNORMAL,
+                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+    }
+    
+    /* Stop when the maximum force lies below tolerance.
+     * If we have reached machine precision, converged is already set to true.
+     */        
+    converged = converged || (s_min->fmax < inputrec->em_tol);
+    
+  } /* End of the loop */
+  
+  if (converged)       
+    step--; /* we never took that last step in this case */
+  
+    if (s_min->fmax > inputrec->em_tol)
+    {
+        if (MASTER(cr))
+        {
+            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+        }
+        converged = FALSE; 
+    }
+  
+  if (MASTER(cr)) {
+    /* If we printed energy and/or logfile last step (which was the last step)
+     * we don't have to do it again, but otherwise print the final values.
+     */
+    if(!do_log) {
+      /* Write final value to log since we didn't do anything the last step */
+      print_ebin_header(fplog,step,step,s_min->s.lambda);
+    }
+    if (!do_ene || !do_log) {
+      /* Write final energy file entries */
+      print_ebin(outf->fp_ene,!do_ene,FALSE,FALSE,
+                !do_log ? fplog : NULL,step,step,eprNORMAL,
+                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+    }
+  }
+
+  /* Print some stuff... */
+  if (MASTER(cr))
+    fprintf(stderr,"\nwriting lowest energy coordinates.\n");
+  
+  /* IMPORTANT!
+   * For accurate normal mode calculation it is imperative that we
+   * store the last conformation into the full precision binary trajectory.
+   *
+   * However, we should only do it if we did NOT already write this step
+   * above (which we did if do_x or do_f was true).
+   */  
+  do_x = !do_per_step(step,inputrec->nstxout);
+  do_f = (inputrec->nstfout > 0 && !do_per_step(step,inputrec->nstfout));
+  
+  write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
+                top_global,inputrec,step,
+                s_min,state_global,f_global);
+  
+  fnormn = s_min->fnorm/sqrt(state_global->natoms);
+  
+  if (MASTER(cr)) {
+    print_converged(stderr,CG,inputrec->em_tol,step,converged,number_steps,
+                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
+    print_converged(fplog,CG,inputrec->em_tol,step,converged,number_steps,
+                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
+    
+    fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
+  }
+  
+  finish_em(fplog,cr,outf,runtime,wcycle);
+  
+  /* To print the actual number of steps we needed somewhere */
+  runtime->nsteps_done = step;
+
+  return 0;
+} /* That's all folks */
+
+
+double do_lbfgs(FILE *fplog,t_commrec *cr,
+                int nfile,const t_filenm fnm[],
+                const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+                int nstglobalcomm,
+                gmx_vsite_t *vsite,gmx_constr_t constr,
+                int stepout,
+                t_inputrec *inputrec,
+                gmx_mtop_t *top_global,t_fcdata *fcd,
+                t_state *state,
+                t_mdatoms *mdatoms,
+                t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                gmx_edsam_t ed,
+                t_forcerec *fr,
+                int repl_ex_nst,int repl_ex_seed,
+                gmx_membed_t *membed,
+                real cpt_period,real max_hours,
+                const char *deviceOptions,
+                unsigned long Flags,
+                gmx_runtime_t *runtime)
+{
+  static const char *LBFGS="Low-Memory BFGS Minimizer";
+  em_state_t ems;
+  gmx_localtop_t *top;
+  gmx_enerdata_t *enerd;
+  rvec   *f;
+  gmx_global_stat_t gstat;
+  t_graph    *graph;
+  rvec   *f_global;
+  int    ncorr,nmaxcorr,point,cp,neval,nminstep;
+  double stepsize,gpa,gpb,gpc,tmp,minstep;
+  real   *rho,*alpha,*ff,*xx,*p,*s,*lastx,*lastf,**dx,**dg;    
+  real   *xa,*xb,*xc,*fa,*fb,*fc,*xtmp,*ftmp;
+  real   a,b,c,maxdelta,delta;
+  real   diag,Epot0,Epot,EpotA,EpotB,EpotC;
+  real   dgdx,dgdg,sq,yr,beta;
+  t_mdebin   *mdebin;
+  gmx_bool   converged,first;
+  rvec   mu_tot;
+  real   fnorm,fmax;
+  gmx_bool   do_log,do_ene,do_x,do_f,foundlower,*frozen;
+  tensor vir,pres;
+  int    start,end,number_steps;
+  gmx_mdoutf_t *outf;
+  int    i,k,m,n,nfmax,gf,step;
+  /* not used */
+  real   terminate;
+
+  if (PAR(cr))
+    gmx_fatal(FARGS,"Cannot do parallel L-BFGS Minimization - yet.\n");
+  
+  n = 3*state->natoms;
+  nmaxcorr = inputrec->nbfgscorr;
+  
+  /* Allocate memory */
+  /* Use pointers to real so we dont have to loop over both atoms and
+   * dimensions all the time...
+   * x/f are allocated as rvec *, so make new x0/f0 pointers-to-real
+   * that point to the same memory.
+   */
+  snew(xa,n);
+  snew(xb,n);
+  snew(xc,n);
+  snew(fa,n);
+  snew(fb,n);
+  snew(fc,n);
+  snew(frozen,n);
+
+  snew(p,n); 
+  snew(lastx,n); 
+  snew(lastf,n); 
+  snew(rho,nmaxcorr);
+  snew(alpha,nmaxcorr);
+  
+  snew(dx,nmaxcorr);
+  for(i=0;i<nmaxcorr;i++)
+    snew(dx[i],n);
+  
+  snew(dg,nmaxcorr);
+  for(i=0;i<nmaxcorr;i++)
+    snew(dg[i],n);
+
+  step = 0;
+  neval = 0; 
+
+  /* Init em */
+  init_em(fplog,LBFGS,cr,inputrec,
+          state,top_global,&ems,&top,&f,&f_global,
+          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
+          nfile,fnm,&outf,&mdebin);
+  /* Do_lbfgs is not completely updated like do_steep and do_cg,
+   * so we free some memory again.
+   */
+  sfree(ems.s.x);
+  sfree(ems.f);
+
+  xx = (real *)state->x;
+  ff = (real *)f;
+
+  start = mdatoms->start;
+  end   = mdatoms->homenr + start;
+    
+  /* Print to log file */
+  print_em_start(fplog,cr,runtime,wcycle,LBFGS);
+  
+  do_log = do_ene = do_x = do_f = TRUE;
+  
+  /* Max number of steps */
+  number_steps=inputrec->nsteps;
+
+  /* Create a 3*natoms index to tell whether each degree of freedom is frozen */
+  gf = 0;
+  for(i=start; i<end; i++) {
+    if (mdatoms->cFREEZE)
+      gf = mdatoms->cFREEZE[i];
+     for(m=0; m<DIM; m++) 
+       frozen[3*i+m]=inputrec->opts.nFreeze[gf][m];  
+  }
+  if (MASTER(cr))
+    sp_header(stderr,LBFGS,inputrec->em_tol,number_steps);
+  if (fplog)
+    sp_header(fplog,LBFGS,inputrec->em_tol,number_steps);
+  
+  if (vsite)
+    construct_vsites(fplog,vsite,state->x,nrnb,1,NULL,
+                    top->idef.iparams,top->idef.il,
+                    fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+  
+  /* Call the force routine and some auxiliary (neighboursearching etc.) */
+  /* do_force always puts the charge groups in the box and shifts again
+   * We do not unshift, so molecules are always whole
+   */
+  neval++;
+  ems.s.x = state->x;
+  ems.f = f;
+  evaluate_energy(fplog,bVerbose,cr,
+                 state,top_global,&ems,top,
+                 inputrec,nrnb,wcycle,gstat,
+                 vsite,constr,fcd,graph,mdatoms,fr,
+                 mu_tot,enerd,vir,pres,-1,TRUE);
+  where();
+       
+  if (MASTER(cr)) {
+    /* Copy stuff to the energy bin for easy printing etc. */
+    upd_mdebin(mdebin,FALSE,FALSE,(double)step,
+              mdatoms->tmass,enerd,state,state->box,
+              NULL,NULL,vir,pres,NULL,mu_tot,constr);
+    
+    print_ebin_header(fplog,step,step,state->lambda);
+    print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
+               TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+  }
+  where();
+  
+  /* This is the starting energy */
+  Epot = enerd->term[F_EPOT];
+  
+  fnorm = ems.fnorm;
+  fmax  = ems.fmax;
+  nfmax = ems.a_fmax;
+  
+  /* Set the initial step.
+   * since it will be multiplied by the non-normalized search direction 
+   * vector (force vector the first time), we scale it by the
+   * norm of the force.
+   */
+  
+  if (MASTER(cr)) {
+    fprintf(stderr,"Using %d BFGS correction steps.\n\n",nmaxcorr);
+    fprintf(stderr,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
+    fprintf(stderr,"   F-Norm            = %12.5e\n",fnorm/sqrt(state->natoms));
+    fprintf(stderr,"\n");
+    /* and copy to the log file too... */
+    fprintf(fplog,"Using %d BFGS correction steps.\n\n",nmaxcorr);
+    fprintf(fplog,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
+    fprintf(fplog,"   F-Norm            = %12.5e\n",fnorm/sqrt(state->natoms));
+    fprintf(fplog,"\n");
+  }   
+  
+  point=0;
+  for(i=0;i<n;i++)
+    if(!frozen[i])
+      dx[point][i] = ff[i];  /* Initial search direction */
+    else
+      dx[point][i] = 0;
+
+  stepsize = 1.0/fnorm;
+  converged = FALSE;
+  
+  /* Start the loop over BFGS steps.           
+   * Each successful step is counted, and we continue until
+   * we either converge or reach the max number of steps.
+   */
+  
+  ncorr=0;
+
+  /* Set the gradient from the force */
+  converged = FALSE;
+  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged; step++) {
+    
+    /* Write coordinates if necessary */
+    do_x = do_per_step(step,inputrec->nstxout);
+    do_f = do_per_step(step,inputrec->nstfout);
+    
+    write_traj(fplog,cr,outf,MDOF_X | MDOF_F,
+               top_global,step,(real)step,state,state,f,f,NULL,NULL);
+
+    /* Do the linesearching in the direction dx[point][0..(n-1)] */
+    
+    /* pointer to current direction - point=0 first time here */
+    s=dx[point];
+    
+    /* calculate line gradient */
+    for(gpa=0,i=0;i<n;i++) 
+       gpa-=s[i]*ff[i];
+
+    /* Calculate minimum allowed stepsize, before the average (norm) 
+     * relative change in coordinate is smaller than precision 
+     */
+    for(minstep=0,i=0;i<n;i++) {
+      tmp=fabs(xx[i]);
+      if(tmp<1.0)
+       tmp=1.0;
+      tmp = s[i]/tmp;
+      minstep += tmp*tmp;
+    }
+    minstep = GMX_REAL_EPS/sqrt(minstep/n);
+    
+    if(stepsize<minstep) {
+      converged=TRUE;
+      break;
+    }
+    
+    /* Store old forces and coordinates */
+    for(i=0;i<n;i++) {
+      lastx[i]=xx[i];
+      lastf[i]=ff[i];
+    }
+    Epot0=Epot;
+    
+    first=TRUE;
+    
+    for(i=0;i<n;i++)
+      xa[i]=xx[i];
+    
+    /* Take a step downhill.
+     * In theory, we should minimize the function along this direction.
+     * That is quite possible, but it turns out to take 5-10 function evaluations
+     * for each line. However, we dont really need to find the exact minimum -
+     * it is much better to start a new BFGS step in a modified direction as soon
+     * as we are close to it. This will save a lot of energy evaluations.
+     *
+     * In practice, we just try to take a single step.
+     * If it worked (i.e. lowered the energy), we increase the stepsize but
+     * the continue straight to the next BFGS step without trying to find any minimum.
+     * If it didn't work (higher energy), there must be a minimum somewhere between
+     * the old position and the new one.
+     * 
+     * Due to the finite numerical accuracy, it turns out that it is a good idea
+     * to even accept a SMALL increase in energy, if the derivative is still downhill.
+     * This leads to lower final energies in the tests I've done. / Erik 
+     */
+    foundlower=FALSE;
+    EpotA = Epot0;
+    a = 0.0;
+    c = a + stepsize; /* reference position along line is zero */
+
+    /* Check stepsize first. We do not allow displacements 
+     * larger than emstep.
+     */
+    do {
+      c = a + stepsize;
+      maxdelta=0;
+      for(i=0;i<n;i++) {
+       delta=c*s[i];
+       if(delta>maxdelta)
+         maxdelta=delta;
+      }
+      if(maxdelta>inputrec->em_stepsize)
+       stepsize*=0.1;
+    } while(maxdelta>inputrec->em_stepsize);
+
+    /* Take a trial step */
+    for (i=0; i<n; i++)
+      xc[i] = lastx[i] + c*s[i];
+    
+    neval++;
+    /* Calculate energy for the trial step */
+    ems.s.x = (rvec *)xc;
+    ems.f   = (rvec *)fc;
+    evaluate_energy(fplog,bVerbose,cr,
+                   state,top_global,&ems,top,
+                   inputrec,nrnb,wcycle,gstat,
+                   vsite,constr,fcd,graph,mdatoms,fr,
+                   mu_tot,enerd,vir,pres,step,FALSE);
+    EpotC = ems.epot;
+    
+    /* Calc derivative along line */
+    for(gpc=0,i=0; i<n; i++) {
+       gpc -= s[i]*fc[i];   /* f is negative gradient, thus the sign */
+    }
+    /* Sum the gradient along the line across CPUs */
+    if (PAR(cr))
+      gmx_sumd(1,&gpc,cr);
+    
+     /* This is the max amount of increase in energy we tolerate */
+   tmp=sqrt(GMX_REAL_EPS)*fabs(EpotA);
+    
+    /* Accept the step if the energy is lower, or if it is not significantly higher
+     * and the line derivative is still negative.
+     */
+    if(EpotC<EpotA || (gpc<0 && EpotC<(EpotA+tmp))) {
+      foundlower = TRUE;
+      /* Great, we found a better energy. Increase step for next iteration
+       * if we are still going down, decrease it otherwise
+       */
+      if(gpc<0)
+       stepsize *= 1.618034;  /* The golden section */
+      else
+       stepsize *= 0.618034;  /* 1/golden section */
+    } else {
+      /* New energy is the same or higher. We will have to do some work
+       * to find a smaller value in the interval. Take smaller step next time!
+       */
+      foundlower = FALSE;
+      stepsize *= 0.618034;
+    }    
+    
+    /* OK, if we didn't find a lower value we will have to locate one now - there must
+     * be one in the interval [a=0,c].
+     * The same thing is valid here, though: Don't spend dozens of iterations to find
+     * the line minimum. We try to interpolate based on the derivative at the endpoints,
+     * and only continue until we find a lower value. In most cases this means 1-2 iterations.
+     *
+     * I also have a safeguard for potentially really patological functions so we never
+     * take more than 20 steps before we give up ...
+     *
+     * If we already found a lower value we just skip this step and continue to the update.
+     */
+
+    if(!foundlower) {
+     
+      nminstep=0;
+      do {
+       /* Select a new trial point.
+        * If the derivatives at points a & c have different sign we interpolate to zero,
+        * otherwise just do a bisection.
+        */
+       
+       if(gpa<0 && gpc>0)
+         b = a + gpa*(a-c)/(gpc-gpa);
+       else
+         b = 0.5*(a+c);                
+       
+       /* safeguard if interpolation close to machine accuracy causes errors:
+        * never go outside the interval
+        */
+       if(b<=a || b>=c)
+         b = 0.5*(a+c);
+       
+       /* Take a trial step */
+       for (i=0; i<n; i++) 
+         xb[i] = lastx[i] + b*s[i];
+       
+       neval++;
+       /* Calculate energy for the trial step */
+       ems.s.x = (rvec *)xb;
+       ems.f   = (rvec *)fb;
+       evaluate_energy(fplog,bVerbose,cr,
+                       state,top_global,&ems,top,
+                       inputrec,nrnb,wcycle,gstat,
+                       vsite,constr,fcd,graph,mdatoms,fr,
+                       mu_tot,enerd,vir,pres,step,FALSE);
+       EpotB = ems.epot;
+       
+       fnorm = ems.fnorm;
+       
+       for(gpb=0,i=0; i<n; i++) 
+         gpb -= s[i]*fb[i];   /* f is negative gradient, thus the sign */
+       
+       /* Sum the gradient along the line across CPUs */
+       if (PAR(cr))
+         gmx_sumd(1,&gpb,cr);
+       
+       /* Keep one of the intervals based on the value of the derivative at the new point */
+       if(gpb>0) {
+         /* Replace c endpoint with b */
+         EpotC = EpotB;
+         c = b;
+         gpc = gpb;
+         /* swap coord pointers b/c */
+         xtmp = xb; 
+         ftmp = fb;
+         xb = xc; 
+         fb = fc;
+         xc = xtmp;
+         fc = ftmp;
+       } else {
+         /* Replace a endpoint with b */
+         EpotA = EpotB;
+         a = b;
+         gpa = gpb;
+         /* swap coord pointers a/b */
+         xtmp = xb; 
+         ftmp = fb;
+         xb = xa; 
+         fb = fa;
+         xa = xtmp; 
+         fa = ftmp;
+       }
+       
+       /* 
+        * Stop search as soon as we find a value smaller than the endpoints,
+        * or if the tolerance is below machine precision.
+        * Never run more than 20 steps, no matter what.
+        */
+       nminstep++; 
+      } while((EpotB>EpotA || EpotB>EpotC) && (nminstep<20));
+
+      if(fabs(EpotB-Epot0)<GMX_REAL_EPS || nminstep>=20) {
+       /* OK. We couldn't find a significantly lower energy.
+        * If ncorr==0 this was steepest descent, and then we give up.
+        * If not, reset memory to restart as steepest descent before quitting.
+         */
+       if(ncorr==0) {
+       /* Converged */
+         converged=TRUE;
+         break;
+       } else {
+         /* Reset memory */
+         ncorr=0;
+         /* Search in gradient direction */
+         for(i=0;i<n;i++)
+           dx[point][i]=ff[i];
+         /* Reset stepsize */
+         stepsize = 1.0/fnorm;
+         continue;
+       }
+      }
+      
+      /* Select min energy state of A & C, put the best in xx/ff/Epot
+       */
+      if(EpotC<EpotA) {
+       Epot = EpotC;
+       /* Use state C */
+       for(i=0;i<n;i++) {
+         xx[i]=xc[i];
+         ff[i]=fc[i];
+       }
+       stepsize=c;
+      } else {
+       Epot = EpotA;
+       /* Use state A */
+       for(i=0;i<n;i++) {
+         xx[i]=xa[i];
+         ff[i]=fa[i];
+       }
+       stepsize=a;
+      }
+      
+    } else {
+      /* found lower */
+      Epot = EpotC;
+      /* Use state C */
+      for(i=0;i<n;i++) {
+       xx[i]=xc[i];
+       ff[i]=fc[i];
+      }
+      stepsize=c;
+    }
+
+    /* Update the memory information, and calculate a new 
+     * approximation of the inverse hessian 
+     */
+    
+    /* Have new data in Epot, xx, ff */        
+    if(ncorr<nmaxcorr)
+      ncorr++;
+
+    for(i=0;i<n;i++) {
+      dg[point][i]=lastf[i]-ff[i];
+      dx[point][i]*=stepsize;
+    }
+    
+    dgdg=0;
+    dgdx=0;    
+    for(i=0;i<n;i++) {
+      dgdg+=dg[point][i]*dg[point][i];
+      dgdx+=dg[point][i]*dx[point][i];
+    }
+    
+    diag=dgdx/dgdg;
+    
+    rho[point]=1.0/dgdx;
+    point++;
+    
+    if(point>=nmaxcorr)
+      point=0;
+    
+    /* Update */
+    for(i=0;i<n;i++)
+      p[i]=ff[i];
+    
+    cp=point;
+    
+    /* Recursive update. First go back over the memory points */
+    for(k=0;k<ncorr;k++) {
+      cp--;
+      if(cp<0) 
+       cp=ncorr-1;
+      
+      sq=0;
+      for(i=0;i<n;i++)
+       sq+=dx[cp][i]*p[i];
+      
+      alpha[cp]=rho[cp]*sq;
+      
+      for(i=0;i<n;i++)
+       p[i] -= alpha[cp]*dg[cp][i];            
+    }
+    
+    for(i=0;i<n;i++)
+      p[i] *= diag;
+    
+    /* And then go forward again */
+    for(k=0;k<ncorr;k++) {
+      yr = 0;
+      for(i=0;i<n;i++)
+       yr += p[i]*dg[cp][i];
+      
+      beta = rho[cp]*yr;           
+      beta = alpha[cp]-beta;
+      
+      for(i=0;i<n;i++)
+       p[i] += beta*dx[cp][i];
+      
+      cp++;    
+      if(cp>=ncorr)
+       cp=0;
+    }
+    
+    for(i=0;i<n;i++)
+      if(!frozen[i])
+       dx[point][i] = p[i];
+      else
+       dx[point][i] = 0;
+
+    stepsize=1.0;
+    
+    /* Test whether the convergence criterion is met */
+    get_f_norm_max(cr,&(inputrec->opts),mdatoms,f,&fnorm,&fmax,&nfmax);
+    
+    /* Print it if necessary */
+    if (MASTER(cr)) {
+      if(bVerbose)
+       fprintf(stderr,"\rStep %d, Epot=%12.6e, Fnorm=%9.3e, Fmax=%9.3e (atom %d)\n",
+               step,Epot,fnorm/sqrt(state->natoms),fmax,nfmax+1);
+      /* Store the new (lower) energies */
+      upd_mdebin(mdebin,FALSE,FALSE,(double)step,
+                mdatoms->tmass,enerd,state,state->box,
+                NULL,NULL,vir,pres,NULL,mu_tot,constr);
+      do_log = do_per_step(step,inputrec->nstlog);
+      do_ene = do_per_step(step,inputrec->nstenergy);
+      if(do_log)
+       print_ebin_header(fplog,step,step,state->lambda);
+      print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
+                do_log ? fplog : NULL,step,step,eprNORMAL,
+                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+    }
+    
+    /* Stop when the maximum force lies below tolerance.
+     * If we have reached machine precision, converged is already set to true.
+     */
+    
+    converged = converged || (fmax < inputrec->em_tol);
+    
+  } /* End of the loop */
+  
+  if(converged)        
+    step--; /* we never took that last step in this case */
+  
+    if(fmax>inputrec->em_tol)
+    {
+        if (MASTER(cr))
+        {
+            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+        }
+        converged = FALSE; 
+    }
+  
+  /* If we printed energy and/or logfile last step (which was the last step)
+   * we don't have to do it again, but otherwise print the final values.
+   */
+  if(!do_log) /* Write final value to log since we didn't do anythin last step */
+    print_ebin_header(fplog,step,step,state->lambda);
+  if(!do_ene || !do_log) /* Write final energy file entries */
+    print_ebin(outf->fp_ene,!do_ene,FALSE,FALSE,
+              !do_log ? fplog : NULL,step,step,eprNORMAL,
+              TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+  
+  /* Print some stuff... */
+  if (MASTER(cr))
+    fprintf(stderr,"\nwriting lowest energy coordinates.\n");
+  
+  /* IMPORTANT!
+   * For accurate normal mode calculation it is imperative that we
+   * store the last conformation into the full precision binary trajectory.
+   *
+   * However, we should only do it if we did NOT already write this step
+   * above (which we did if do_x or do_f was true).
+   */  
+  do_x = !do_per_step(step,inputrec->nstxout);
+  do_f = !do_per_step(step,inputrec->nstfout);
+  write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
+                top_global,inputrec,step,
+                &ems,state,f);
+  
+  if (MASTER(cr)) {
+    print_converged(stderr,LBFGS,inputrec->em_tol,step,converged,
+                   number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
+    print_converged(fplog,LBFGS,inputrec->em_tol,step,converged,
+                   number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
+    
+    fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
+  }
+  
+  finish_em(fplog,cr,outf,runtime,wcycle);
+
+  /* To print the actual number of steps we needed somewhere */
+  runtime->nsteps_done = step;
+
+  return 0;
+} /* That's all folks */
+
+
+double do_steep(FILE *fplog,t_commrec *cr,
+                int nfile, const t_filenm fnm[],
+                const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+                int nstglobalcomm,
+                gmx_vsite_t *vsite,gmx_constr_t constr,
+                int stepout,
+                t_inputrec *inputrec,
+                gmx_mtop_t *top_global,t_fcdata *fcd,
+                t_state *state_global,
+                t_mdatoms *mdatoms,
+                t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                gmx_edsam_t ed,
+                t_forcerec *fr,
+                int repl_ex_nst,int repl_ex_seed,
+                gmx_membed_t *membed,
+                real cpt_period,real max_hours,
+                const char *deviceOptions,
+                unsigned long Flags,
+                gmx_runtime_t *runtime)
+{ 
+  const char *SD="Steepest Descents";
+  em_state_t *s_min,*s_try;
+  rvec       *f_global;
+  gmx_localtop_t *top;
+  gmx_enerdata_t *enerd;
+  rvec   *f;
+  gmx_global_stat_t gstat;
+  t_graph    *graph;
+  real   stepsize,constepsize;
+  real   ustep,dvdlambda,fnormn;
+  gmx_mdoutf_t *outf;
+  t_mdebin   *mdebin; 
+  gmx_bool   bDone,bAbort,do_x,do_f; 
+  tensor vir,pres; 
+  rvec   mu_tot;
+  int    nsteps;
+  int    count=0; 
+  int    steps_accepted=0; 
+  /* not used */
+  real   terminate=0;
+
+  s_min = init_em_state();
+  s_try = init_em_state();
+
+  /* Init em and store the local state in s_try */
+  init_em(fplog,SD,cr,inputrec,
+          state_global,top_global,s_try,&top,&f,&f_global,
+          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
+          nfile,fnm,&outf,&mdebin);
+       
+  /* Print to log file  */
+  print_em_start(fplog,cr,runtime,wcycle,SD);
+    
+  /* Set variables for stepsize (in nm). This is the largest  
+   * step that we are going to make in any direction. 
+   */
+  ustep = inputrec->em_stepsize; 
+  stepsize = 0;
+  
+  /* Max number of steps  */
+  nsteps = inputrec->nsteps; 
+  
+  if (MASTER(cr)) 
+    /* Print to the screen  */
+    sp_header(stderr,SD,inputrec->em_tol,nsteps);
+  if (fplog)
+    sp_header(fplog,SD,inputrec->em_tol,nsteps);
+    
+  /**** HERE STARTS THE LOOP ****
+   * count is the counter for the number of steps 
+   * bDone will be TRUE when the minimization has converged
+   * bAbort will be TRUE when nsteps steps have been performed or when
+   * the stepsize becomes smaller than is reasonable for machine precision
+   */
+  count  = 0;
+  bDone  = FALSE;
+  bAbort = FALSE;
+  while( !bDone && !bAbort ) {
+    bAbort = (nsteps >= 0) && (count == nsteps);
+    
+    /* set new coordinates, except for first step */
+    if (count > 0) {
+      do_em_step(cr,inputrec,mdatoms,s_min,stepsize,s_min->f,s_try,
+                constr,top,nrnb,wcycle,count);
+    }
+    
+    evaluate_energy(fplog,bVerbose,cr,
+                   state_global,top_global,s_try,top,
+                   inputrec,nrnb,wcycle,gstat,
+                   vsite,constr,fcd,graph,mdatoms,fr,
+                   mu_tot,enerd,vir,pres,count,count==0);
+        
+    if (MASTER(cr))
+      print_ebin_header(fplog,count,count,s_try->s.lambda);
+
+    if (count == 0)
+      s_min->epot = s_try->epot + 1;
+    
+    /* Print it if necessary  */
+    if (MASTER(cr)) {
+      if (bVerbose) {
+       fprintf(stderr,"Step=%5d, Dmax= %6.1e nm, Epot= %12.5e Fmax= %11.5e, atom= %d%c",
+               count,ustep,s_try->epot,s_try->fmax,s_try->a_fmax+1,
+               (s_try->epot < s_min->epot) ? '\n' : '\r');
+      }
+      
+      if (s_try->epot < s_min->epot) {
+       /* Store the new (lower) energies  */
+       upd_mdebin(mdebin,FALSE,FALSE,(double)count,
+                  mdatoms->tmass,enerd,&s_try->s,s_try->s.box,
+                  NULL,NULL,vir,pres,NULL,mu_tot,constr);
+       print_ebin(outf->fp_ene,TRUE,
+                  do_per_step(steps_accepted,inputrec->nstdisreout),
+                  do_per_step(steps_accepted,inputrec->nstorireout),
+                  fplog,count,count,eprNORMAL,TRUE,
+                  mdebin,fcd,&(top_global->groups),&(inputrec->opts));
+       fflush(fplog);
+      }
+    } 
+    
+    /* Now if the new energy is smaller than the previous...  
+     * or if this is the first step!
+     * or if we did random steps! 
+     */
+    
+    if ( (count==0) || (s_try->epot < s_min->epot) ) {
+      steps_accepted++; 
+
+      /* Test whether the convergence criterion is met...  */
+      bDone = (s_try->fmax < inputrec->em_tol);
+      
+      /* Copy the arrays for force, positions and energy  */
+      /* The 'Min' array always holds the coords and forces of the minimal 
+        sampled energy  */
+      swap_em_state(s_min,s_try);
+      if (count > 0)
+       ustep *= 1.2;
+
+      /* Write to trn, if necessary */
+      do_x = do_per_step(steps_accepted,inputrec->nstxout);
+      do_f = do_per_step(steps_accepted,inputrec->nstfout);
+      write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
+                    top_global,inputrec,count,
+                    s_min,state_global,f_global);
+    } 
+    else {
+      /* If energy is not smaller make the step smaller...  */
+      ustep *= 0.5;
+
+      if (DOMAINDECOMP(cr) && s_min->s.ddp_count != cr->dd->ddp_count) {
+       /* Reload the old state */
+       em_dd_partition_system(fplog,count,cr,top_global,inputrec,
+                              s_min,top,mdatoms,fr,vsite,constr,
+                              nrnb,wcycle);
+      }
+    }
+    
+    /* Determine new step  */
+    stepsize = ustep/s_min->fmax;
+    
+    /* Check if stepsize is too small, with 1 nm as a characteristic length */
+#ifdef GMX_DOUBLE
+        if (count == nsteps || ustep < 1e-12)
+#else
+        if (count == nsteps || ustep < 1e-6)
+#endif
+        {
+            if (MASTER(cr))
+            {
+                warn_step(stderr,inputrec->em_tol,count==nsteps,constr!=NULL);
+                warn_step(fplog ,inputrec->em_tol,count==nsteps,constr!=NULL);
+            }
+            bAbort=TRUE;
+        }
+    
+    count++;
+  } /* End of the loop  */
+  
+    /* Print some shit...  */
+  if (MASTER(cr)) 
+    fprintf(stderr,"\nwriting lowest energy coordinates.\n"); 
+  write_em_traj(fplog,cr,outf,TRUE,inputrec->nstfout,ftp2fn(efSTO,nfile,fnm),
+               top_global,inputrec,count,
+               s_min,state_global,f_global);
+
+  fnormn = s_min->fnorm/sqrt(state_global->natoms);
+
+  if (MASTER(cr)) {
+    print_converged(stderr,SD,inputrec->em_tol,count,bDone,nsteps,
+                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
+    print_converged(fplog,SD,inputrec->em_tol,count,bDone,nsteps,
+                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
+  }
+
+  finish_em(fplog,cr,outf,runtime,wcycle);
+  
+  /* To print the actual number of steps we needed somewhere */
+  inputrec->nsteps=count;
+
+  runtime->nsteps_done = count;
+  
+  return 0;
+} /* That's all folks */
+
+
+double do_nm(FILE *fplog,t_commrec *cr,
+             int nfile,const t_filenm fnm[],
+             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+             int nstglobalcomm,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int stepout,
+             t_inputrec *inputrec,
+             gmx_mtop_t *top_global,t_fcdata *fcd,
+             t_state *state_global,
+             t_mdatoms *mdatoms,
+             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+             gmx_edsam_t ed,
+             t_forcerec *fr,
+             int repl_ex_nst,int repl_ex_seed,
+             gmx_membed_t *membed,
+             real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             gmx_runtime_t *runtime)
+{
+    const char *NM = "Normal Mode Analysis";
+    gmx_mdoutf_t *outf;
+    int        natoms,atom,d;
+    int        nnodes,node;
+    rvec       *f_global;
+    gmx_localtop_t *top;
+    gmx_enerdata_t *enerd;
+    rvec       *f;
+    gmx_global_stat_t gstat;
+    t_graph    *graph;
+    real       t,lambda;
+    gmx_bool       bNS;
+    tensor     vir,pres;
+    rvec       mu_tot;
+    rvec       *fneg,*dfdx;
+    gmx_bool       bSparse; /* use sparse matrix storage format */
+    size_t     sz;
+    gmx_sparsematrix_t * sparse_matrix = NULL;
+    real *     full_matrix             = NULL;
+    em_state_t *   state_work;
+       
+    /* added with respect to mdrun */
+    int        i,j,k,row,col;
+    real       der_range=10.0*sqrt(GMX_REAL_EPS);
+    real       x_min;
+    real       fnorm,fmax;
+    
+    if (constr != NULL)
+    {
+        gmx_fatal(FARGS,"Constraints present with Normal Mode Analysis, this combination is not supported");
+    }
+
+    state_work = init_em_state();
+    
+    /* Init em and store the local state in state_minimum */
+    init_em(fplog,NM,cr,inputrec,
+            state_global,top_global,state_work,&top,
+            &f,&f_global,
+            nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
+            nfile,fnm,&outf,NULL);
+    
+    natoms = top_global->natoms;
+    snew(fneg,natoms);
+    snew(dfdx,natoms);
+    
+#ifndef GMX_DOUBLE
+    if (MASTER(cr))
+    {
+        fprintf(stderr,
+                "NOTE: This version of Gromacs has been compiled in single precision,\n"
+                "      which MIGHT not be accurate enough for normal mode analysis.\n"
+                "      Gromacs now uses sparse matrix storage, so the memory requirements\n"
+                "      are fairly modest even if you recompile in double precision.\n\n");
+    }
+#endif
+    
+    /* Check if we can/should use sparse storage format.
+     *
+     * Sparse format is only useful when the Hessian itself is sparse, which it
+      * will be when we use a cutoff.    
+      * For small systems (n<1000) it is easier to always use full matrix format, though.
+      */
+    if(EEL_FULL(fr->eeltype) || fr->rlist==0.0)
+    {
+        fprintf(stderr,"Non-cutoff electrostatics used, forcing full Hessian format.\n");
+        bSparse = FALSE;
+    }
+    else if(top_global->natoms < 1000)
+    {
+        fprintf(stderr,"Small system size (N=%d), using full Hessian format.\n",top_global->natoms);
+        bSparse = FALSE;
+    }
+    else
+    {
+        fprintf(stderr,"Using compressed symmetric sparse Hessian format.\n");
+        bSparse = TRUE;
+    }
+    
+    sz = DIM*top_global->natoms;
+    
+    fprintf(stderr,"Allocating Hessian memory...\n\n");
+
+    if(bSparse)
+    {
+        sparse_matrix=gmx_sparsematrix_init(sz);
+        sparse_matrix->compressed_symmetric = TRUE;
+    }
+    else
+    {
+        snew(full_matrix,sz*sz);
+    }
+    
+    /* Initial values */
+    t      = inputrec->init_t;
+    lambda = inputrec->init_lambda;
+    
+    init_nrnb(nrnb);
+    
+    where();
+    
+    /* Write start time and temperature */
+    print_em_start(fplog,cr,runtime,wcycle,NM);
+
+    /* fudge nr of steps to nr of atoms */
+    inputrec->nsteps = natoms*2;
+
+    if (MASTER(cr)) 
+    {
+        fprintf(stderr,"starting normal mode calculation '%s'\n%d steps.\n\n",
+                *(top_global->name),(int)inputrec->nsteps);
+    }
+
+    nnodes = cr->nnodes;
+   
+    /* Make evaluate_energy do a single node force calculation */
+    cr->nnodes = 1;
+    evaluate_energy(fplog,bVerbose,cr,
+                    state_global,top_global,state_work,top,
+                    inputrec,nrnb,wcycle,gstat,
+                    vsite,constr,fcd,graph,mdatoms,fr,
+                    mu_tot,enerd,vir,pres,-1,TRUE);
+    cr->nnodes = nnodes;
+
+    /* if forces are not small, warn user */
+    get_state_f_norm_max(cr,&(inputrec->opts),mdatoms,state_work);
+
+    if (MASTER(cr))
+    {
+        fprintf(stderr,"Maximum force:%12.5e\n",state_work->fmax);
+        if (state_work->fmax > 1.0e-3) 
+        {
+            fprintf(stderr,"Maximum force probably not small enough to");
+            fprintf(stderr," ensure that you are in an \nenergy well. ");
+            fprintf(stderr,"Be aware that negative eigenvalues may occur");
+            fprintf(stderr," when the\nresulting matrix is diagonalized.\n");
+        }
+    }
+    
+    /***********************************************************
+     *
+     *      Loop over all pairs in matrix 
+     * 
+     *      do_force called twice. Once with positive and 
+     *      once with negative displacement 
+     *
+     ************************************************************/
+
+    /* Steps are divided one by one over the nodes */
+    for(atom=cr->nodeid; atom<natoms; atom+=nnodes) 
+    {
+        
+        for (d=0; d<DIM; d++) 
+        {
+            x_min = state_work->s.x[atom][d];
+
+            state_work->s.x[atom][d] = x_min - der_range;
+          
+            /* Make evaluate_energy do a single node force calculation */
+            cr->nnodes = 1;
+            evaluate_energy(fplog,bVerbose,cr,
+                            state_global,top_global,state_work,top,
+                            inputrec,nrnb,wcycle,gstat,
+                            vsite,constr,fcd,graph,mdatoms,fr,
+                            mu_tot,enerd,vir,pres,atom*2,FALSE);
+                       
+            for(i=0; i<natoms; i++)
+            {
+                copy_rvec(state_work->f[i], fneg[i]);
+            }
+            
+            state_work->s.x[atom][d] = x_min + der_range;
+            
+            evaluate_energy(fplog,bVerbose,cr,
+                            state_global,top_global,state_work,top,
+                            inputrec,nrnb,wcycle,gstat,
+                            vsite,constr,fcd,graph,mdatoms,fr,
+                            mu_tot,enerd,vir,pres,atom*2+1,FALSE);
+            cr->nnodes = nnodes;
+
+            /* x is restored to original */
+            state_work->s.x[atom][d] = x_min;
+
+            for(j=0; j<natoms; j++) 
+            {
+                for (k=0; (k<DIM); k++) 
+                {
+                    dfdx[j][k] =
+                        -(state_work->f[j][k] - fneg[j][k])/(2*der_range);
+                }
+            }
+
+            if (!MASTER(cr))
+            {
+#ifdef GMX_MPI
+#ifdef GMX_DOUBLE
+#define mpi_type MPI_DOUBLE
+#else
+#define mpi_type MPI_FLOAT
+#endif
+                MPI_Send(dfdx[0],natoms*DIM,mpi_type,MASTERNODE(cr),cr->nodeid,
+                         cr->mpi_comm_mygroup);
+#endif
+            }
+            else
+            {
+                for(node=0; (node<nnodes && atom+node<natoms); node++)
+                {
+                    if (node > 0)
+                    {
+#ifdef GMX_MPI
+                        MPI_Status stat;
+                        MPI_Recv(dfdx[0],natoms*DIM,mpi_type,node,node,
+                                 cr->mpi_comm_mygroup,&stat);
+#undef mpi_type
+#endif
+                    }
+
+                    row = (atom + node)*DIM + d;
+
+                    for(j=0; j<natoms; j++) 
+                    {
+                        for(k=0; k<DIM; k++) 
+                        {
+                            col = j*DIM + k;
+                            
+                            if (bSparse)
+                            {
+                                if (col >= row && dfdx[j][k] != 0.0)
+                                {
+                                    gmx_sparsematrix_increment_value(sparse_matrix,
+                                                                     row,col,dfdx[j][k]);
+                                }
+                            }
+                            else
+                            {
+                                full_matrix[row*sz+col] = dfdx[j][k];
+                            }
+                        }
+                    }
+                }
+            }
+            
+            if (bVerbose && fplog)
+            {
+                fflush(fplog);            
+            }
+        }
+        /* write progress */
+        if (MASTER(cr) && bVerbose) 
+        {
+            fprintf(stderr,"\rFinished step %d out of %d",
+                    min(atom+nnodes,natoms),natoms); 
+            fflush(stderr);
+        }
+    }
+    
+    if (MASTER(cr)) 
+    {
+        fprintf(stderr,"\n\nWriting Hessian...\n");
+        gmx_mtxio_write(ftp2fn(efMTX,nfile,fnm),sz,sz,full_matrix,sparse_matrix);
+    }
+
+    finish_em(fplog,cr,outf,runtime,wcycle);
+
+    runtime->nsteps_done = natoms*2;
+    
+    return 0;
+}
similarity index 100%
rename from src/mdlib/mvxvf.c
rename to src/gromacs/mdlib/mvxvf.c
diff --git a/src/gromacs/mdlib/ns.c b/src/gromacs/mdlib/ns.c
new file mode 100644 (file)
index 0000000..2c97fdd
--- /dev/null
@@ -0,0 +1,2794 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef GMX_THREAD_SHM_FDECOMP
+#include <pthread.h> 
+#endif
+
+#include <math.h>
+#include <string.h>
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "macros.h"
+#include "maths.h"
+#include "vec.h"
+#include "network.h"
+#include "nsgrid.h"
+#include "force.h"
+#include "nonbonded.h"
+#include "ns.h"
+#include "pbc.h"
+#include "names.h"
+#include "gmx_fatal.h"
+#include "nrnb.h"
+#include "txtdump.h"
+#include "mtop_util.h"
+
+#include "domdec.h"
+
+
+/* 
+ *    E X C L U S I O N   H A N D L I N G
+ */
+
+#ifdef DEBUG
+static void SETEXCL_(t_excl e[],atom_id i,atom_id j)
+{   e[j] = e[j] | (1<<i); }
+static void RMEXCL_(t_excl e[],atom_id i,atom_id j) 
+{ e[j]=e[j] & ~(1<<i); }
+static gmx_bool ISEXCL_(t_excl e[],atom_id i,atom_id j) 
+{ return (gmx_bool)(e[j] & (1<<i)); }
+static gmx_bool NOTEXCL_(t_excl e[],atom_id i,atom_id j)
+{  return !(ISEXCL(e,i,j)); }
+#else
+#define SETEXCL(e,i,j) (e)[((atom_id) (j))] |= (1<<((atom_id) (i)))
+#define RMEXCL(e,i,j)  (e)[((atom_id) (j))] &= (~(1<<((atom_id) (i))))
+#define ISEXCL(e,i,j)  (gmx_bool) ((e)[((atom_id) (j))] & (1<<((atom_id) (i))))
+#define NOTEXCL(e,i,j) !(ISEXCL(e,i,j))
+#endif
+
+/************************************************
+ *
+ *  U T I L I T I E S    F O R    N S
+ *
+ ************************************************/
+
+static void reallocate_nblist(t_nblist *nl)
+{
+    if (gmx_debug_at)
+    {
+        fprintf(debug,"reallocating neigborlist il_code=%d, maxnri=%d\n",
+                nl->il_code,nl->maxnri); 
+    }
+    srenew(nl->iinr,   nl->maxnri);
+    if (nl->enlist == enlistCG_CG)
+    {
+        srenew(nl->iinr_end,nl->maxnri);
+    }
+    srenew(nl->gid,    nl->maxnri);
+    srenew(nl->shift,  nl->maxnri);
+    srenew(nl->jindex, nl->maxnri+1);
+}
+
+/* ivdw/icoul are used to determine the type of interaction, so we
+ * can set an innerloop index here. The obvious choice for this would have
+ * been the vdwtype/coultype values in the forcerecord, but unfortunately 
+ * those types are braindead - for instance both Buckingham and normal 
+ * Lennard-Jones use the same value (evdwCUT), and a separate gmx_boolean variable
+ * to determine which interaction is used. There is further no special value
+ * for 'no interaction'. For backward compatibility with old TPR files we won't
+ * change this in the 3.x series, so when calling this routine you should use:
+ *
+ * icoul=0 no coulomb interaction
+ * icoul=1 cutoff standard coulomb
+ * icoul=2 reaction-field coulomb
+ * icoul=3 tabulated coulomb
+ *
+ * ivdw=0 no vdw interaction
+ * ivdw=1 standard L-J interaction
+ * ivdw=2 Buckingham
+ * ivdw=3 tabulated vdw.
+ *
+ * Kind of ugly, but it works.
+ */
+static void init_nblist(t_nblist *nl_sr,t_nblist *nl_lr,
+                        int maxsr,int maxlr,
+                        int ivdw, int icoul, 
+                        gmx_bool bfree, int enlist)
+{
+    t_nblist *nl;
+    int      homenr;
+    int      i,nn;
+    
+    int inloop[20] =
+    { 
+        eNR_NBKERNEL_NONE,
+        eNR_NBKERNEL010,
+        eNR_NBKERNEL020,
+        eNR_NBKERNEL030,
+        eNR_NBKERNEL100,
+        eNR_NBKERNEL110,
+        eNR_NBKERNEL120,
+        eNR_NBKERNEL130,
+        eNR_NBKERNEL200,
+        eNR_NBKERNEL210,
+        eNR_NBKERNEL220,
+        eNR_NBKERNEL230,
+        eNR_NBKERNEL300,
+        eNR_NBKERNEL310,
+        eNR_NBKERNEL320,
+        eNR_NBKERNEL330,
+        eNR_NBKERNEL400,
+        eNR_NBKERNEL410,
+        eNR_NBKERNEL_NONE,
+        eNR_NBKERNEL430
+    };
+  
+    for(i=0; (i<2); i++)
+    {
+        nl     = (i == 0) ? nl_sr : nl_lr;
+        homenr = (i == 0) ? maxsr : maxlr;
+
+        if (nl == NULL)
+        {
+            continue;
+        }
+        
+        /* Set coul/vdw in neighborlist, and for the normal loops we determine
+         * an index of which one to call.
+         */
+        nl->ivdw  = ivdw;
+        nl->icoul = icoul;
+        nl->free_energy = bfree;
+    
+        if (bfree)
+        {
+            nl->enlist  = enlistATOM_ATOM;
+            nl->il_code = eNR_NBKERNEL_FREE_ENERGY;
+        }
+        else
+        {
+            nl->enlist = enlist;
+
+            nn = inloop[4*icoul + ivdw];
+            
+            /* solvent loops follow directly after the corresponding
+            * ordinary loops, in the order:
+            *
+            * SPC, SPC-SPC, TIP4p, TIP4p-TIP4p
+            *   
+            */
+            switch (enlist) {
+            case enlistATOM_ATOM:
+            case enlistCG_CG:
+                break;
+            case enlistSPC_ATOM:     nn += 1; break;
+            case enlistSPC_SPC:      nn += 2; break;
+            case enlistTIP4P_ATOM:   nn += 3; break;
+            case enlistTIP4P_TIP4P:  nn += 4; break;
+            }
+            
+            nl->il_code = nn;
+        }
+
+        if (debug)
+            fprintf(debug,"Initiating neighbourlist type %d for %s interactions,\nwith %d SR, %d LR atoms.\n",
+                    nl->il_code,ENLISTTYPE(enlist),maxsr,maxlr);
+        
+        /* maxnri is influenced by the number of shifts (maximum is 8)
+         * and the number of energy groups.
+         * If it is not enough, nl memory will be reallocated during the run.
+         * 4 seems to be a reasonable factor, which only causes reallocation
+         * during runs with tiny and many energygroups.
+         */
+        nl->maxnri      = homenr*4;
+        nl->maxnrj      = 0;
+        nl->maxlen      = 0;
+        nl->nri         = -1;
+        nl->nrj         = 0;
+        nl->iinr        = NULL;
+        nl->gid         = NULL;
+        nl->shift       = NULL;
+        nl->jindex      = NULL;
+        reallocate_nblist(nl);
+        nl->jindex[0] = 0;
+#ifdef GMX_THREAD_SHM_FDECOMP
+        nl->counter = 0;
+        snew(nl->mtx,1);
+        pthread_mutex_init(nl->mtx,NULL);
+#endif
+    }
+}
+
+void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
+{
+   /* Make maxlr tunable! (does not seem to be a big difference though) 
+    * This parameter determines the number of i particles in a long range 
+    * neighbourlist. Too few means many function calls, too many means
+    * cache trashing.
+    */
+   int maxsr,maxsr_wat,maxlr,maxlr_wat;
+   int icoul,icoulf,ivdw;
+   int solvent;
+   int enlist_def,enlist_w,enlist_ww;
+   int i;
+   t_nblists *nbl;
+
+   /* maxsr     = homenr-fr->nWatMol*3; */
+   maxsr     = homenr;
+
+   if (maxsr < 0)
+   {
+     gmx_fatal(FARGS,"%s, %d: Negative number of short range atoms.\n"
+                "Call your Gromacs dealer for assistance.",__FILE__,__LINE__);
+   }
+   /* This is just for initial allocation, so we do not reallocate
+    * all the nlist arrays many times in a row.
+    * The numbers seem very accurate, but they are uncritical.
+    */
+   maxsr_wat = min(fr->nWatMol,(homenr+2)/3); 
+   if (fr->bTwinRange) 
+   {
+       maxlr     = 50;
+       maxlr_wat = min(maxsr_wat,maxlr);
+   }
+   else
+   {
+     maxlr = maxlr_wat = 0;
+   }  
+
+   /* Determine the values for icoul/ivdw. */
+   /* Start with GB */
+   if(fr->bGB)
+   {
+       icoul=4;
+   }
+   else if (fr->bcoultab)
+   {
+       icoul = 3;
+   }
+   else if (EEL_RF(fr->eeltype))
+   {
+       icoul = 2;
+   }
+   else 
+   {
+       icoul = 1;
+   }
+   
+   if (fr->bvdwtab)
+   {
+       ivdw = 3;
+   }
+   else if (fr->bBHAM)
+   {
+       ivdw = 2;
+   }
+   else 
+   {
+       ivdw = 1;
+   }
+
+   fr->ns.bCGlist = (getenv("GMX_NBLISTCG") != 0);
+   if (!fr->ns.bCGlist)
+   {
+       enlist_def = enlistATOM_ATOM;
+   }
+   else
+   {
+       enlist_def = enlistCG_CG;
+       if (log != NULL)
+       {
+           fprintf(log,"\nUsing charge-group - charge-group neighbor lists and kernels\n\n");
+       }
+   }
+   
+   if (fr->solvent_opt == esolTIP4P) {
+       enlist_w  = enlistTIP4P_ATOM;
+       enlist_ww = enlistTIP4P_TIP4P;
+   } else {
+       enlist_w  = enlistSPC_ATOM;
+       enlist_ww = enlistSPC_SPC;
+   }
+
+   for(i=0; i<fr->nnblists; i++) 
+   {
+       nbl = &(fr->nblists[i]);
+       init_nblist(&nbl->nlist_sr[eNL_VDWQQ],&nbl->nlist_lr[eNL_VDWQQ],
+                   maxsr,maxlr,ivdw,icoul,FALSE,enlist_def);
+       init_nblist(&nbl->nlist_sr[eNL_VDW],&nbl->nlist_lr[eNL_VDW],
+                   maxsr,maxlr,ivdw,0,FALSE,enlist_def);
+       init_nblist(&nbl->nlist_sr[eNL_QQ],&nbl->nlist_lr[eNL_QQ],
+                   maxsr,maxlr,0,icoul,FALSE,enlist_def);
+       init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATER],&nbl->nlist_lr[eNL_VDWQQ_WATER],
+                   maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_w);
+       init_nblist(&nbl->nlist_sr[eNL_QQ_WATER],&nbl->nlist_lr[eNL_QQ_WATER],
+                   maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_w);
+       init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATERWATER],&nbl->nlist_lr[eNL_VDWQQ_WATERWATER],
+                   maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_ww);
+       init_nblist(&nbl->nlist_sr[eNL_QQ_WATERWATER],&nbl->nlist_lr[eNL_QQ_WATERWATER],
+                   maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_ww);
+       
+       if (fr->efep != efepNO) 
+       {
+           if (fr->bEwald)
+           {
+               icoulf = 5;
+           }
+           else
+           {
+               icoulf = icoul;
+           }
+
+           init_nblist(&nbl->nlist_sr[eNL_VDWQQ_FREE],&nbl->nlist_lr[eNL_VDWQQ_FREE],
+                       maxsr,maxlr,ivdw,icoulf,TRUE,enlistATOM_ATOM);
+           init_nblist(&nbl->nlist_sr[eNL_VDW_FREE],&nbl->nlist_lr[eNL_VDW_FREE],
+                       maxsr,maxlr,ivdw,0,TRUE,enlistATOM_ATOM);
+           init_nblist(&nbl->nlist_sr[eNL_QQ_FREE],&nbl->nlist_lr[eNL_QQ_FREE],
+                       maxsr,maxlr,0,icoulf,TRUE,enlistATOM_ATOM);
+       }  
+   }
+   /* QMMM MM list */
+   if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
+   {
+       init_nblist(&fr->QMMMlist,NULL,
+                   maxsr,maxlr,0,icoul,FALSE,enlistATOM_ATOM);
+   }
+
+   fr->ns.nblist_initialized=TRUE;
+}
+
+static void reset_nblist(t_nblist *nl)
+{
+     nl->nri       = -1;
+     nl->nrj       = 0;
+     nl->maxlen    = 0;
+     if (nl->jindex)
+     {
+         nl->jindex[0] = 0;
+     }
+}
+
+static void reset_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL)
+{
+    int n,i;
+  
+    if (bLR) 
+    {
+        reset_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
+    }
+    else 
+    {
+        for(n=0; n<fr->nnblists; n++)
+        {
+            for(i=0; i<eNL_NR; i++)
+            {
+                reset_nblist(&(fr->nblists[n].nlist_sr[i]));
+            }
+        }
+        if (fr->bQMMM)
+        { 
+            /* only reset the short-range nblist */
+            reset_nblist(&(fr->QMMMlist));
+        }
+    }
+}
+
+
+
+
+static inline void new_i_nblist(t_nblist *nlist,
+                                gmx_bool bLR,atom_id i_atom,int shift,int gid)
+{
+    int    i,k,nri,nshift;
+    
+    nri = nlist->nri;
+    
+    /* Check whether we have to increase the i counter */
+    if ((nri == -1) ||
+        (nlist->iinr[nri]  != i_atom) || 
+        (nlist->shift[nri] != shift) || 
+        (nlist->gid[nri]   != gid))
+    {
+        /* This is something else. Now see if any entries have 
+         * been added in the list of the previous atom.
+         */
+        if ((nri == -1) ||
+            ((nlist->jindex[nri+1] > nlist->jindex[nri]) && 
+             (nlist->gid[nri] != -1)))
+        {
+            /* If so increase the counter */
+            nlist->nri++;
+            nri++;
+            if (nlist->nri >= nlist->maxnri)
+            {
+                nlist->maxnri += over_alloc_large(nlist->nri);
+                reallocate_nblist(nlist);
+            }
+        }
+        /* Set the number of neighbours and the atom number */
+        nlist->jindex[nri+1] = nlist->jindex[nri];
+        nlist->iinr[nri]     = i_atom;
+        nlist->gid[nri]      = gid;
+        nlist->shift[nri]    = shift;
+    }
+}
+
+static inline void close_i_nblist(t_nblist *nlist) 
+{
+    int nri = nlist->nri;
+    int len;
+    
+    if (nri >= 0)
+    {
+        nlist->jindex[nri+1] = nlist->nrj;
+        
+        len=nlist->nrj -  nlist->jindex[nri];
+        
+        /* nlist length for water i molecules is treated statically 
+         * in the innerloops 
+         */
+        if (len > nlist->maxlen)
+        {
+            nlist->maxlen = len;
+        }
+    }
+}
+
+static inline void close_nblist(t_nblist *nlist)
+{
+    /* Only close this nblist when it has been initialized.
+     * Avoid the creation of i-lists with no j-particles.
+     */
+    if (nlist->nrj == 0)
+    {
+        /* Some assembly kernels do not support empty lists,
+         * make sure here that we don't generate any empty lists.
+         * With the current ns code this branch is taken in two cases:
+         * No i-particles at all: nri=-1 here
+         * There are i-particles, but no j-particles; nri=0 here
+         */
+        nlist->nri = 0;
+    }
+    else
+    {
+        /* Close list number nri by incrementing the count */
+        nlist->nri++;
+    }
+}
+
+static inline void close_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL, 
+                                       gmx_bool bMakeQMMMnblist)
+{
+    int n,i;
+    
+    if (bMakeQMMMnblist) {
+        if (!bLR)
+        {
+            close_nblist(&(fr->QMMMlist));
+        }
+    }
+    else 
+    {
+        if (bLR)
+        {
+            close_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
+        }
+        else
+        { 
+            for(n=0; n<fr->nnblists; n++)
+            {
+                for(i=0; (i<eNL_NR); i++)
+                {
+                    close_nblist(&(fr->nblists[n].nlist_sr[i]));
+                }
+            }
+        }
+    }
+}
+
+static inline void add_j_to_nblist(t_nblist *nlist,atom_id j_atom,gmx_bool bLR)
+{
+    int nrj=nlist->nrj;
+    
+    if (nlist->nrj >= nlist->maxnrj)
+    {
+        nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
+        if (gmx_debug_at)
+            fprintf(debug,"Increasing %s nblist %s j size to %d\n",
+                    bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
+        
+        srenew(nlist->jjnr,nlist->maxnrj);
+    }
+
+    nlist->jjnr[nrj] = j_atom;
+    nlist->nrj ++;
+}
+
+static inline void add_j_to_nblist_cg(t_nblist *nlist,
+                                      atom_id j_start,int j_end,
+                                      t_excl *bexcl,gmx_bool i_is_j,
+                                      gmx_bool bLR)
+{
+    int nrj=nlist->nrj;
+    int j;
+
+    if (nlist->nrj >= nlist->maxnrj)
+    {
+        nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
+        if (gmx_debug_at)
+            fprintf(debug,"Increasing %s nblist %s j size to %d\n",
+                    bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
+        
+        srenew(nlist->jjnr    ,nlist->maxnrj);
+        srenew(nlist->jjnr_end,nlist->maxnrj);
+        srenew(nlist->excl    ,nlist->maxnrj*MAX_CGCGSIZE);
+    }
+
+    nlist->jjnr[nrj]     = j_start;
+    nlist->jjnr_end[nrj] = j_end;
+
+    if (j_end - j_start > MAX_CGCGSIZE)
+    {
+        gmx_fatal(FARGS,"The charge-group - charge-group neighborlist do not support charge groups larger than %d, found a charge group of size %d",MAX_CGCGSIZE,j_end-j_start);
+    }
+
+    /* Set the exclusions */
+    for(j=j_start; j<j_end; j++)
+    {
+        nlist->excl[nrj*MAX_CGCGSIZE + j - j_start] = bexcl[j];
+    }
+    if (i_is_j)
+    {
+        /* Avoid double counting of intra-cg interactions */
+        for(j=1; j<j_end-j_start; j++)
+        {
+            nlist->excl[nrj*MAX_CGCGSIZE + j] |= (1<<j) - 1;
+        }
+    }
+
+    nlist->nrj ++;
+}
+
+typedef void
+put_in_list_t(gmx_bool              bHaveVdW[],
+              int               ngid,
+              t_mdatoms *       md,
+              int               icg,
+              int               jgid,
+              int               nj,
+              atom_id           jjcg[],
+              atom_id           index[],
+              t_excl            bExcl[],
+              int               shift,
+              t_forcerec *      fr,
+              gmx_bool              bLR,
+              gmx_bool              bDoVdW,
+              gmx_bool              bDoCoul);
+
+static void 
+put_in_list_at(gmx_bool              bHaveVdW[],
+               int               ngid,
+               t_mdatoms *       md,
+               int               icg,
+               int               jgid,
+               int               nj,
+               atom_id           jjcg[],
+               atom_id           index[],
+               t_excl            bExcl[],
+               int               shift,
+               t_forcerec *      fr,
+               gmx_bool              bLR,
+               gmx_bool              bDoVdW,
+               gmx_bool              bDoCoul)
+{
+    /* The a[] index has been removed,
+     * to put it back in i_atom should be a[i0] and jj should be a[jj].
+     */
+    t_nblist *   vdwc;
+    t_nblist *   vdw;
+    t_nblist *   coul;
+    t_nblist *   vdwc_free  = NULL;
+    t_nblist *   vdw_free   = NULL;
+    t_nblist *   coul_free  = NULL;
+    t_nblist *   vdwc_ww    = NULL;
+    t_nblist *   coul_ww    = NULL;
+    
+    int            i,j,jcg,igid,gid,nbl_ind,ind_ij;
+    atom_id   jj,jj0,jj1,i_atom;
+    int       i0,nicg,len;
+    
+    int       *cginfo;
+    int       *type,*typeB;
+    real      *charge,*chargeB;
+    real      qi,qiB,qq,rlj;
+    gmx_bool      bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
+    gmx_bool      bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
+    int       iwater,jwater;
+    t_nblist  *nlist;
+    
+    /* Copy some pointers */
+    cginfo  = fr->cginfo;
+    charge  = md->chargeA;
+    chargeB = md->chargeB;
+    type    = md->typeA;
+    typeB   = md->typeB;
+    bPert   = md->bPerturbed;
+    
+    /* Get atom range */
+    i0     = index[icg];
+    nicg   = index[icg+1]-i0;
+    
+    /* Get the i charge group info */
+    igid   = GET_CGINFO_GID(cginfo[icg]);
+    iwater = GET_CGINFO_SOLOPT(cginfo[icg]);
+    
+    bFreeEnergy = FALSE;
+    if (md->nPerturbed) 
+    {
+        /* Check if any of the particles involved are perturbed. 
+         * If not we can do the cheaper normal put_in_list
+         * and use more solvent optimization.
+         */
+        for(i=0; i<nicg; i++)
+        {
+            bFreeEnergy |= bPert[i0+i];
+        }
+        /* Loop over the j charge groups */
+        for(j=0; (j<nj && !bFreeEnergy); j++) 
+        {
+            jcg = jjcg[j];
+            jj0 = index[jcg];
+            jj1 = index[jcg+1];
+            /* Finally loop over the atoms in the j-charge group */    
+            for(jj=jj0; jj<jj1; jj++)
+            {
+                bFreeEnergy |= bPert[jj];
+            }
+        }
+    }
+    
+    /* Unpack pointers to neighbourlist structs */
+    if (fr->nnblists == 1)
+    {
+        nbl_ind = 0;
+    }
+    else
+    {
+        nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
+    }
+    if (bLR)
+    {
+        nlist = fr->nblists[nbl_ind].nlist_lr;
+    }
+    else
+    {
+        nlist = fr->nblists[nbl_ind].nlist_sr;
+    }
+    
+    if (iwater != esolNO)
+    {
+        vdwc = &nlist[eNL_VDWQQ_WATER];
+        vdw  = &nlist[eNL_VDW];
+        coul = &nlist[eNL_QQ_WATER];
+#ifndef DISABLE_WATERWATER_NLIST
+        vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
+        coul_ww = &nlist[eNL_QQ_WATERWATER];
+#endif
+    } 
+    else 
+    {
+        vdwc = &nlist[eNL_VDWQQ];
+        vdw  = &nlist[eNL_VDW];
+        coul = &nlist[eNL_QQ];
+    }
+    
+    if (!bFreeEnergy) 
+    {
+        if (iwater != esolNO) 
+        {
+            /* Loop over the atoms in the i charge group */    
+            i_atom  = i0;
+            gid     = GID(igid,jgid,ngid);
+            /* Create new i_atom for each energy group */
+            if (bDoCoul && bDoVdW)
+            {
+                new_i_nblist(vdwc,bLR,i_atom,shift,gid);
+#ifndef DISABLE_WATERWATER_NLIST
+                new_i_nblist(vdwc_ww,bLR,i_atom,shift,gid);
+#endif
+            }
+            if (bDoVdW)
+            {
+                new_i_nblist(vdw,bLR,i_atom,shift,gid);
+            }
+            if (bDoCoul) 
+            {
+                new_i_nblist(coul,bLR,i_atom,shift,gid);
+#ifndef DISABLE_WATERWATER_NLIST
+                new_i_nblist(coul_ww,bLR,i_atom,shift,gid);
+#endif
+            }      
+         /* Loop over the j charge groups */
+            for(j=0; (j<nj); j++) 
+            {
+                jcg=jjcg[j];
+                
+                if (jcg == icg)
+                {
+                    continue;
+                }
+                
+                jj0 = index[jcg];
+                jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
+                
+                if (iwater == esolSPC && jwater == esolSPC)
+                {
+                    /* Interaction between two SPC molecules */
+                    if (!bDoCoul)
+                    {
+                        /* VdW only - only first atoms in each water interact */
+                        add_j_to_nblist(vdw,jj0,bLR);
+                    }
+                    else 
+                    {
+#ifdef DISABLE_WATERWATER_NLIST        
+                        /* Add entries for the three atoms - only do VdW if we need to */
+                        if (!bDoVdW)
+                        {
+                            add_j_to_nblist(coul,jj0,bLR);
+                        }
+                        else
+                        {
+                            add_j_to_nblist(vdwc,jj0,bLR);
+                        }
+                        add_j_to_nblist(coul,jj0+1,bLR);
+                        add_j_to_nblist(coul,jj0+2,bLR);           
+#else
+                        /* One entry for the entire water-water interaction */
+                        if (!bDoVdW)
+                        {
+                            add_j_to_nblist(coul_ww,jj0,bLR);
+                        }
+                        else
+                        {
+                            add_j_to_nblist(vdwc_ww,jj0,bLR);
+                        }
+#endif
+                    }  
+                } 
+                else if (iwater == esolTIP4P && jwater == esolTIP4P) 
+                {
+                    /* Interaction between two TIP4p molecules */
+                    if (!bDoCoul)
+                    {
+                        /* VdW only - only first atoms in each water interact */
+                        add_j_to_nblist(vdw,jj0,bLR);
+                    }
+                    else 
+                    {
+#ifdef DISABLE_WATERWATER_NLIST        
+                        /* Add entries for the four atoms - only do VdW if we need to */
+                        if (bDoVdW)
+                        {
+                            add_j_to_nblist(vdw,jj0,bLR);
+                        }
+                        add_j_to_nblist(coul,jj0+1,bLR);
+                        add_j_to_nblist(coul,jj0+2,bLR);           
+                        add_j_to_nblist(coul,jj0+3,bLR);           
+#else
+                        /* One entry for the entire water-water interaction */
+                        if (!bDoVdW)
+                        {
+                            add_j_to_nblist(coul_ww,jj0,bLR);
+                        }
+                        else
+                        {
+                            add_j_to_nblist(vdwc_ww,jj0,bLR);
+                        }
+#endif
+                    }                                          
+                }
+                else 
+                {
+                    /* j charge group is not water, but i is.
+                     * Add entries to the water-other_atom lists; the geometry of the water
+                     * molecule doesn't matter - that is taken care of in the nonbonded kernel,
+                     * so we don't care if it is SPC or TIP4P...
+                     */
+                    
+                    jj1 = index[jcg+1];
+                    
+                    if (!bDoVdW) 
+                    {
+                        for(jj=jj0; (jj<jj1); jj++) 
+                        {
+                            if (charge[jj] != 0)
+                            {
+                                add_j_to_nblist(coul,jj,bLR);
+                            }
+                        }
+                    }
+                    else if (!bDoCoul)
+                    {
+                        for(jj=jj0; (jj<jj1); jj++)
+                        {
+                            if (bHaveVdW[type[jj]])
+                            {
+                                add_j_to_nblist(vdw,jj,bLR);
+                            }
+                        }
+                    }
+                    else 
+                    {
+                        /* _charge_ _groups_ interact with both coulomb and LJ */
+                        /* Check which atoms we should add to the lists!       */
+                        for(jj=jj0; (jj<jj1); jj++) 
+                        {
+                            if (bHaveVdW[type[jj]]) 
+                            {
+                                if (charge[jj] != 0)
+                                {
+                                    add_j_to_nblist(vdwc,jj,bLR);
+                                }
+                                else
+                                {
+                                    add_j_to_nblist(vdw,jj,bLR);
+                                }
+                            }
+                            else if (charge[jj] != 0)
+                            {
+                                add_j_to_nblist(coul,jj,bLR);
+                            }
+                        }
+                    }
+                }
+            }
+            close_i_nblist(vdw); 
+            close_i_nblist(coul); 
+            close_i_nblist(vdwc);  
+#ifndef DISABLE_WATERWATER_NLIST
+            close_i_nblist(coul_ww);
+            close_i_nblist(vdwc_ww); 
+#endif
+        } 
+        else
+        { 
+            /* no solvent as i charge group */
+            /* Loop over the atoms in the i charge group */    
+            for(i=0; i<nicg; i++) 
+            {
+                i_atom  = i0+i;
+                gid     = GID(igid,jgid,ngid);
+                qi      = charge[i_atom];
+                
+                /* Create new i_atom for each energy group */
+                if (bDoVdW && bDoCoul)
+                {
+                    new_i_nblist(vdwc,bLR,i_atom,shift,gid);
+                }
+                if (bDoVdW)
+                {
+                    new_i_nblist(vdw,bLR,i_atom,shift,gid);
+                }
+                if (bDoCoul)
+                {
+                    new_i_nblist(coul,bLR,i_atom,shift,gid);
+                }
+                bDoVdW_i  = (bDoVdW  && bHaveVdW[type[i_atom]]);
+                bDoCoul_i = (bDoCoul && qi!=0);
+                
+                if (bDoVdW_i || bDoCoul_i) 
+                {
+                    /* Loop over the j charge groups */
+                    for(j=0; (j<nj); j++) 
+                    {
+                        jcg=jjcg[j];
+                        
+                        /* Check for large charge groups */
+                        if (jcg == icg)
+                        {
+                            jj0 = i0 + i + 1;
+                        }
+                        else
+                        {
+                            jj0 = index[jcg];
+                        }
+                        
+                        jj1=index[jcg+1];
+                        /* Finally loop over the atoms in the j-charge group */        
+                        for(jj=jj0; jj<jj1; jj++) 
+                        {
+                            bNotEx = NOTEXCL(bExcl,i,jj);
+                            
+                            if (bNotEx) 
+                            {
+                                if (!bDoVdW_i) 
+                                { 
+                                    if (charge[jj] != 0)
+                                    {
+                                        add_j_to_nblist(coul,jj,bLR);
+                                    }
+                                }
+                                else if (!bDoCoul_i) 
+                                {
+                                    if (bHaveVdW[type[jj]])
+                                    {
+                                        add_j_to_nblist(vdw,jj,bLR);
+                                    }
+                                }
+                                else 
+                                {
+                                    if (bHaveVdW[type[jj]]) 
+                                    {
+                                        if (charge[jj] != 0)
+                                        {
+                                            add_j_to_nblist(vdwc,jj,bLR);
+                                        }
+                                        else
+                                        {
+                                            add_j_to_nblist(vdw,jj,bLR);
+                                        }
+                                    } 
+                                    else if (charge[jj] != 0)
+                                    {
+                                        add_j_to_nblist(coul,jj,bLR);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                close_i_nblist(vdw);
+                close_i_nblist(coul);
+                close_i_nblist(vdwc);
+            }
+        }
+    }
+    else
+    {
+        /* we are doing free energy */
+        vdwc_free = &nlist[eNL_VDWQQ_FREE];
+        vdw_free  = &nlist[eNL_VDW_FREE];
+        coul_free = &nlist[eNL_QQ_FREE];
+        /* Loop over the atoms in the i charge group */    
+        for(i=0; i<nicg; i++) 
+        {
+            i_atom  = i0+i;
+            gid     = GID(igid,jgid,ngid);
+            qi      = charge[i_atom];
+            qiB     = chargeB[i_atom];
+            
+            /* Create new i_atom for each energy group */
+            if (bDoVdW && bDoCoul) 
+                new_i_nblist(vdwc,bLR,i_atom,shift,gid);
+            if (bDoVdW)   
+                new_i_nblist(vdw,bLR,i_atom,shift,gid);
+            if (bDoCoul) 
+                new_i_nblist(coul,bLR,i_atom,shift,gid);
+            
+            new_i_nblist(vdw_free,bLR,i_atom,shift,gid);
+            new_i_nblist(coul_free,bLR,i_atom,shift,gid);
+            new_i_nblist(vdwc_free,bLR,i_atom,shift,gid);
+            
+            bDoVdW_i  = (bDoVdW  &&
+                         (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
+            bDoCoul_i = (bDoCoul && (qi!=0 || qiB!=0));
+            /* For TIP4P the first atom does not have a charge,
+             * but the last three do. So we should still put an atom
+             * without LJ but with charge in the water-atom neighborlist
+             * for a TIP4p i charge group.
+             * For SPC type water the first atom has LJ and charge,
+             * so there is no such problem.
+             */
+            if (iwater == esolNO)
+            {
+                bDoCoul_i_sol = bDoCoul_i;
+            }
+            else
+            {
+                bDoCoul_i_sol = bDoCoul;
+            }
+            
+            if (bDoVdW_i || bDoCoul_i_sol) 
+            {
+                /* Loop over the j charge groups */
+                for(j=0; (j<nj); j++)
+                {
+                    jcg=jjcg[j];
+                    
+                    /* Check for large charge groups */
+                    if (jcg == icg)
+                    {
+                        jj0 = i0 + i + 1;
+                    }
+                    else
+                    {
+                        jj0 = index[jcg];
+                    }
+                    
+                    jj1=index[jcg+1];
+                    /* Finally loop over the atoms in the j-charge group */    
+                    bFree = bPert[i_atom];
+                    for(jj=jj0; (jj<jj1); jj++) 
+                    {
+                        bFreeJ = bFree || bPert[jj];
+                        /* Complicated if, because the water H's should also
+                         * see perturbed j-particles
+                         */
+                        if (iwater==esolNO || i==0 || bFreeJ) 
+                        {
+                            bNotEx = NOTEXCL(bExcl,i,jj);
+                            
+                            if (bNotEx) 
+                            {
+                                if (bFreeJ)
+                                {
+                                    if (!bDoVdW_i) 
+                                    {
+                                        if (charge[jj]!=0 || chargeB[jj]!=0)
+                                        {
+                                            add_j_to_nblist(coul_free,jj,bLR);
+                                        }
+                                    }
+                                    else if (!bDoCoul_i) 
+                                    {
+                                        if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
+                                        {
+                                            add_j_to_nblist(vdw_free,jj,bLR);
+                                        }
+                                    }
+                                    else 
+                                    {
+                                        if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]]) 
+                                        {
+                                            if (charge[jj]!=0 || chargeB[jj]!=0)
+                                            {
+                                                add_j_to_nblist(vdwc_free,jj,bLR);
+                                            }
+                                            else
+                                            {
+                                                add_j_to_nblist(vdw_free,jj,bLR);
+                                            }
+                                        }
+                                        else if (charge[jj]!=0 || chargeB[jj]!=0)
+                                            add_j_to_nblist(coul_free,jj,bLR);
+                                    }
+                                }
+                                else if (!bDoVdW_i) 
+                                { 
+                                    /* This is done whether or not bWater is set */
+                                    if (charge[jj] != 0)
+                                    {
+                                        add_j_to_nblist(coul,jj,bLR);
+                                    }
+                                }
+                                else if (!bDoCoul_i_sol) 
+                                { 
+                                    if (bHaveVdW[type[jj]])
+                                    {
+                                        add_j_to_nblist(vdw,jj,bLR);
+                                    }
+                                }
+                                else 
+                                {
+                                    if (bHaveVdW[type[jj]]) 
+                                    {
+                                        if (charge[jj] != 0)
+                                        {
+                                            add_j_to_nblist(vdwc,jj,bLR);
+                                        }
+                                        else
+                                        {
+                                            add_j_to_nblist(vdw,jj,bLR);
+                                        }
+                                    } 
+                                    else if (charge[jj] != 0)
+                                    {
+                                        add_j_to_nblist(coul,jj,bLR);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            close_i_nblist(vdw);
+            close_i_nblist(coul);
+            close_i_nblist(vdwc);
+            close_i_nblist(vdw_free);
+            close_i_nblist(coul_free);
+            close_i_nblist(vdwc_free);
+        }
+    }
+}
+
+static void 
+put_in_list_qmmm(gmx_bool              bHaveVdW[],
+                 int               ngid,
+                 t_mdatoms *       md,
+                 int               icg,
+                 int               jgid,
+                 int               nj,
+                 atom_id           jjcg[],
+                 atom_id           index[],
+                 t_excl            bExcl[],
+                 int               shift,
+                 t_forcerec *      fr,
+                 gmx_bool              bLR,
+                 gmx_bool              bDoVdW,
+                 gmx_bool              bDoCoul)
+{
+    t_nblist *   coul;
+    int          i,j,jcg,igid,gid;
+    atom_id   jj,jj0,jj1,i_atom;
+    int       i0,nicg;
+    gmx_bool      bNotEx;
+    
+    /* Get atom range */
+    i0     = index[icg];
+    nicg   = index[icg+1]-i0;
+    
+    /* Get the i charge group info */
+    igid   = GET_CGINFO_GID(fr->cginfo[icg]);
+    
+    coul = &fr->QMMMlist;
+    
+    /* Loop over atoms in the ith charge group */
+    for (i=0;i<nicg;i++)
+    {
+        i_atom = i0+i;
+        gid    = GID(igid,jgid,ngid);
+        /* Create new i_atom for each energy group */
+        new_i_nblist(coul,bLR,i_atom,shift,gid);
+        
+        /* Loop over the j charge groups */
+        for (j=0;j<nj;j++)
+        {
+            jcg=jjcg[j];
+            
+            /* Charge groups cannot have QM and MM atoms simultaneously */
+            if (jcg!=icg)
+            {
+                jj0 = index[jcg];
+                jj1 = index[jcg+1];
+                /* Finally loop over the atoms in the j-charge group */
+                for(jj=jj0; jj<jj1; jj++)
+                {
+                    bNotEx = NOTEXCL(bExcl,i,jj);
+                    if(bNotEx)
+                        add_j_to_nblist(coul,jj,bLR);
+                }
+            }
+        }
+        close_i_nblist(coul);
+    }
+}
+
+static void 
+put_in_list_cg(gmx_bool              bHaveVdW[],
+               int               ngid,
+               t_mdatoms *       md,
+               int               icg,
+               int               jgid,
+               int               nj,
+               atom_id           jjcg[],
+               atom_id           index[],
+               t_excl            bExcl[],
+               int               shift,
+               t_forcerec *      fr,
+               gmx_bool              bLR,
+               gmx_bool              bDoVdW,
+               gmx_bool              bDoCoul)
+{
+    int          cginfo;
+    int          igid,gid,nbl_ind;
+    t_nblist *   vdwc;
+    int          j,jcg;
+
+    cginfo = fr->cginfo[icg];
+
+    igid = GET_CGINFO_GID(cginfo);
+    gid  = GID(igid,jgid,ngid);
+
+    /* Unpack pointers to neighbourlist structs */
+    if (fr->nnblists == 1)
+    {
+        nbl_ind = 0;
+    }
+    else
+    {
+        nbl_ind = fr->gid2nblists[gid];
+    }
+    if (bLR)
+    {
+        vdwc = &fr->nblists[nbl_ind].nlist_lr[eNL_VDWQQ];
+    }
+    else
+    {
+        vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
+    }
+
+    /* Make a new neighbor list for charge group icg.
+     * Currently simply one neighbor list is made with LJ and Coulomb.
+     * If required, zero interactions could be removed here
+     * or in the force loop.
+     */
+    new_i_nblist(vdwc,bLR,index[icg],shift,gid);
+    vdwc->iinr_end[vdwc->nri] = index[icg+1];
+
+    for(j=0; (j<nj); j++) 
+    {
+        jcg = jjcg[j];
+        /* Skip the icg-icg pairs if all self interactions are excluded */
+        if (!(jcg == icg && GET_CGINFO_EXCL_INTRA(cginfo)))
+        {
+            /* Here we add the j charge group jcg to the list,
+             * exclusions are also added to the list.
+             */
+            add_j_to_nblist_cg(vdwc,index[jcg],index[jcg+1],bExcl,icg==jcg,bLR);
+        }
+    }
+
+    close_i_nblist(vdwc);  
+}
+
+static void setexcl(atom_id start,atom_id end,t_blocka *excl,gmx_bool b,
+                    t_excl bexcl[])
+{
+    atom_id i,k;
+    
+    if (b)
+    {
+        for(i=start; i<end; i++)
+        {
+            for(k=excl->index[i]; k<excl->index[i+1]; k++)
+            {
+                SETEXCL(bexcl,i-start,excl->a[k]);
+            }
+        }
+    }
+    else
+    {
+        for(i=start; i<end; i++)
+        {
+            for(k=excl->index[i]; k<excl->index[i+1]; k++)
+            {
+                RMEXCL(bexcl,i-start,excl->a[k]);
+            }
+        }
+    }
+}
+
+int calc_naaj(int icg,int cgtot)
+{
+    int naaj;
+    
+    if ((cgtot % 2) == 1)
+    {
+        /* Odd number of charge groups, easy */
+        naaj = 1 + (cgtot/2);
+    }
+    else if ((cgtot % 4) == 0)
+    {
+    /* Multiple of four is hard */
+        if (icg < cgtot/2)
+        {
+            if ((icg % 2) == 0)
+            {
+                naaj=1+(cgtot/2);
+            }
+            else
+            {
+                naaj=cgtot/2;
+            }
+        }
+        else
+        {
+            if ((icg % 2) == 1)
+            {
+                naaj=1+(cgtot/2);
+            }
+            else
+            {
+                naaj=cgtot/2;
+            }
+        }
+    }
+    else
+    {
+        /* cgtot/2 = odd */
+        if ((icg % 2) == 0)
+        {
+            naaj=1+(cgtot/2);
+        }
+        else
+        {
+            naaj=cgtot/2;
+        }
+    }
+#ifdef DEBUG
+    fprintf(log,"naaj=%d\n",naaj);
+#endif
+
+    return naaj;
+}
+
+/************************************************
+ *
+ *  S I M P L E      C O R E     S T U F F
+ *
+ ************************************************/
+
+static real calc_image_tric(rvec xi,rvec xj,matrix box,
+                            rvec b_inv,int *shift)
+{
+    /* This code assumes that the cut-off is smaller than
+     * a half times the smallest diagonal element of the box.
+     */
+    const real h25=2.5;
+    real dx,dy,dz;
+    real r2;
+    int  tx,ty,tz;
+    
+    /* Compute diff vector */
+    dz = xj[ZZ] - xi[ZZ];
+    dy = xj[YY] - xi[YY];
+    dx = xj[XX] - xi[XX];
+    
+  /* Perform NINT operation, using trunc operation, therefore
+   * we first add 2.5 then subtract 2 again
+   */
+    tz = dz*b_inv[ZZ] + h25;
+    tz -= 2;
+    dz -= tz*box[ZZ][ZZ];
+    dy -= tz*box[ZZ][YY];
+    dx -= tz*box[ZZ][XX];
+
+    ty = dy*b_inv[YY] + h25;
+    ty -= 2;
+    dy -= ty*box[YY][YY];
+    dx -= ty*box[YY][XX];
+    
+    tx = dx*b_inv[XX]+h25;
+    tx -= 2;
+    dx -= tx*box[XX][XX];
+  
+    /* Distance squared */
+    r2 = (dx*dx) + (dy*dy) + (dz*dz);
+
+    *shift = XYZ2IS(tx,ty,tz);
+
+    return r2;
+}
+
+static real calc_image_rect(rvec xi,rvec xj,rvec box_size,
+                            rvec b_inv,int *shift)
+{
+    const real h15=1.5;
+    real ddx,ddy,ddz;
+    real dx,dy,dz;
+    real r2;
+    int  tx,ty,tz;
+    
+    /* Compute diff vector */
+    dx = xj[XX] - xi[XX];
+    dy = xj[YY] - xi[YY];
+    dz = xj[ZZ] - xi[ZZ];
+  
+    /* Perform NINT operation, using trunc operation, therefore
+     * we first add 1.5 then subtract 1 again
+     */
+    tx = dx*b_inv[XX] + h15;
+    ty = dy*b_inv[YY] + h15;
+    tz = dz*b_inv[ZZ] + h15;
+    tx--;
+    ty--;
+    tz--;
+    
+    /* Correct diff vector for translation */
+    ddx = tx*box_size[XX] - dx;
+    ddy = ty*box_size[YY] - dy;
+    ddz = tz*box_size[ZZ] - dz;
+    
+    /* Distance squared */
+    r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
+    
+    *shift = XYZ2IS(tx,ty,tz);
+    
+    return r2;
+}
+
+static void add_simple(t_ns_buf *nsbuf,int nrj,atom_id cg_j,
+                       gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
+                       int icg,int jgid,t_block *cgs,t_excl bexcl[],
+                       int shift,t_forcerec *fr,put_in_list_t *put_in_list)
+{
+    if (nsbuf->nj + nrj > MAX_CG)
+    {
+        put_in_list(bHaveVdW,ngid,md,icg,jgid,nsbuf->ncg,nsbuf->jcg,
+                    cgs->index,bexcl,shift,fr,FALSE,TRUE,TRUE);
+        /* Reset buffer contents */
+        nsbuf->ncg = nsbuf->nj = 0;
+    }
+    nsbuf->jcg[nsbuf->ncg++] = cg_j;
+    nsbuf->nj += nrj;
+}
+
+static void ns_inner_tric(rvec x[],int icg,int *i_egp_flags,
+                          int njcg,atom_id jcg[],
+                          matrix box,rvec b_inv,real rcut2,
+                          t_block *cgs,t_ns_buf **ns_buf,
+                          gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
+                          t_excl bexcl[],t_forcerec *fr,
+                          put_in_list_t *put_in_list)
+{
+    int      shift;
+    int      j,nrj,jgid;
+    int      *cginfo=fr->cginfo;
+    atom_id  cg_j,*cgindex;
+    t_ns_buf *nsbuf;
+    
+    cgindex = cgs->index;
+    shift   = CENTRAL;
+    for(j=0; (j<njcg); j++)
+    {
+        cg_j   = jcg[j];
+        nrj    = cgindex[cg_j+1]-cgindex[cg_j];
+        if (calc_image_tric(x[icg],x[cg_j],box,b_inv,&shift) < rcut2)
+        {
+            jgid  = GET_CGINFO_GID(cginfo[cg_j]);
+            if (!(i_egp_flags[jgid] & EGP_EXCL))
+            {
+                add_simple(&ns_buf[jgid][shift],nrj,cg_j,
+                           bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
+                           put_in_list);
+            }
+        }
+    }
+}
+
+static void ns_inner_rect(rvec x[],int icg,int *i_egp_flags,
+                          int njcg,atom_id jcg[],
+                          gmx_bool bBox,rvec box_size,rvec b_inv,real rcut2,
+                          t_block *cgs,t_ns_buf **ns_buf,
+                          gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
+                          t_excl bexcl[],t_forcerec *fr,
+                          put_in_list_t *put_in_list)
+{
+    int      shift;
+    int      j,nrj,jgid;
+    int      *cginfo=fr->cginfo;
+    atom_id  cg_j,*cgindex;
+    t_ns_buf *nsbuf;
+
+    cgindex = cgs->index;
+    if (bBox)
+    {
+        shift = CENTRAL;
+        for(j=0; (j<njcg); j++)
+        {
+            cg_j   = jcg[j];
+            nrj    = cgindex[cg_j+1]-cgindex[cg_j];
+            if (calc_image_rect(x[icg],x[cg_j],box_size,b_inv,&shift) < rcut2)
+            {
+                jgid  = GET_CGINFO_GID(cginfo[cg_j]);
+                if (!(i_egp_flags[jgid] & EGP_EXCL))
+                {
+                    add_simple(&ns_buf[jgid][shift],nrj,cg_j,
+                               bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
+                               put_in_list);
+                }
+            }
+        }
+    } 
+    else
+    {
+        for(j=0; (j<njcg); j++)
+        {
+            cg_j   = jcg[j];
+            nrj    = cgindex[cg_j+1]-cgindex[cg_j];
+            if ((rcut2 == 0) || (distance2(x[icg],x[cg_j]) < rcut2)) {
+                jgid  = GET_CGINFO_GID(cginfo[cg_j]);
+                if (!(i_egp_flags[jgid] & EGP_EXCL))
+                {
+                    add_simple(&ns_buf[jgid][CENTRAL],nrj,cg_j,
+                               bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,CENTRAL,fr,
+                               put_in_list);
+                }
+            }
+        }
+    }
+}
+
+/* ns_simple_core needs to be adapted for QMMM still 2005 */
+
+static int ns_simple_core(t_forcerec *fr,
+                          gmx_localtop_t *top,
+                          t_mdatoms *md,
+                          matrix box,rvec box_size,
+                          t_excl bexcl[],atom_id *aaj,
+                          int ngid,t_ns_buf **ns_buf,
+                          put_in_list_t *put_in_list,gmx_bool bHaveVdW[])
+{
+    int      naaj,k;
+    real     rlist2;
+    int      nsearch,icg,jcg,igid,i0,nri,nn;
+    int      *cginfo;
+    t_ns_buf *nsbuf;
+    /* atom_id  *i_atoms; */
+    t_block  *cgs=&(top->cgs);
+    t_blocka *excl=&(top->excls);
+    rvec     b_inv;
+    int      m;
+    gmx_bool     bBox,bTriclinic;
+    int      *i_egp_flags;
+    
+    rlist2 = sqr(fr->rlist);
+    
+    bBox = (fr->ePBC != epbcNONE);
+    if (bBox)
+    {
+        for(m=0; (m<DIM); m++)
+        {
+            b_inv[m] = divide_err(1.0,box_size[m]);
+        }
+        bTriclinic = TRICLINIC(box);
+    }
+    else
+    {
+        bTriclinic = FALSE;
+    }
+    
+    cginfo = fr->cginfo;
+    
+    nsearch=0;
+    for (icg=fr->cg0; (icg<fr->hcg); icg++)
+    {
+        /*
+          i0        = cgs->index[icg];
+          nri       = cgs->index[icg+1]-i0;
+          i_atoms   = &(cgs->a[i0]);
+          i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
+          setexcl(nri,i_atoms,excl,TRUE,bexcl);
+        */
+        igid = GET_CGINFO_GID(cginfo[icg]);
+        i_egp_flags = fr->egp_flags + ngid*igid;
+        setexcl(cgs->index[icg],cgs->index[icg+1],excl,TRUE,bexcl);
+        
+        naaj=calc_naaj(icg,cgs->nr);
+        if (bTriclinic)
+        {
+            ns_inner_tric(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
+                          box,b_inv,rlist2,cgs,ns_buf,
+                          bHaveVdW,ngid,md,bexcl,fr,put_in_list);
+        }
+        else
+        {
+            ns_inner_rect(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
+                          bBox,box_size,b_inv,rlist2,cgs,ns_buf,
+                          bHaveVdW,ngid,md,bexcl,fr,put_in_list);
+        }
+        nsearch += naaj;
+        
+        for(nn=0; (nn<ngid); nn++)
+        {
+            for(k=0; (k<SHIFTS); k++)
+            {
+                nsbuf = &(ns_buf[nn][k]);
+                if (nsbuf->ncg > 0)
+                {
+                    put_in_list(bHaveVdW,ngid,md,icg,nn,nsbuf->ncg,nsbuf->jcg,
+                                cgs->index,bexcl,k,fr,FALSE,TRUE,TRUE);
+                    nsbuf->ncg=nsbuf->nj=0;
+                }
+            }
+        }
+        /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
+        setexcl(cgs->index[icg],cgs->index[icg+1],excl,FALSE,bexcl);
+    }
+    close_neighbor_list(fr,FALSE,-1,-1,FALSE);
+    
+    return nsearch;
+}
+
+/************************************************
+ *
+ *    N S 5     G R I D     S T U F F
+ *
+ ************************************************/
+
+static inline void get_dx(int Nx,real gridx,real rc2,int xgi,real x,
+                          int *dx0,int *dx1,real *dcx2)
+{
+    real dcx,tmp;
+    int  xgi0,xgi1,i;
+    
+    if (xgi < 0)
+    {
+        *dx0 = 0;
+        xgi0 = -1;
+        *dx1 = -1;
+        xgi1 = 0;
+    }
+    else if (xgi >= Nx)
+    {
+        *dx0 = Nx;
+        xgi0 = Nx-1;
+        *dx1 = Nx-1;
+        xgi1 = Nx;
+    }
+    else
+    {
+        dcx2[xgi] = 0;
+        *dx0 = xgi;
+        xgi0 = xgi-1;
+        *dx1 = xgi;
+        xgi1 = xgi+1;
+    }
+    
+    for(i=xgi0; i>=0; i--)
+    {
+        dcx = (i+1)*gridx-x;
+        tmp = dcx*dcx;
+        if (tmp >= rc2)
+            break;
+        *dx0 = i;
+        dcx2[i] = tmp;
+    }
+    for(i=xgi1; i<Nx; i++)
+    {
+        dcx = i*gridx-x;
+        tmp = dcx*dcx;
+        if (tmp >= rc2)
+        {
+            break;
+        }
+        *dx1 = i;
+        dcx2[i] = tmp;
+    }
+}
+
+static inline void get_dx_dd(int Nx,real gridx,real rc2,int xgi,real x,
+                             int ncpddc,int shift_min,int shift_max,
+                             int *g0,int *g1,real *dcx2)
+{
+    real dcx,tmp;
+    int  g_min,g_max,shift_home;
+    
+    if (xgi < 0)
+    {
+        g_min = 0;
+        g_max = Nx - 1;
+        *g0   = 0;
+        *g1   = -1;
+    }
+    else if (xgi >= Nx)
+    {
+        g_min = 0;
+        g_max = Nx - 1;
+        *g0   = Nx;
+        *g1   = Nx - 1;
+    }
+    else
+    {
+        if (ncpddc == 0)
+        {
+            g_min = 0;
+            g_max = Nx - 1;
+        }
+        else
+        {
+            if (xgi < ncpddc)
+            {
+                shift_home = 0;
+            }
+            else
+            {
+                shift_home = -1;
+            }
+            g_min = (shift_min == shift_home ? 0          : ncpddc);
+            g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
+        }
+        if (shift_min > 0)
+        {
+            *g0 = g_min;
+            *g1 = g_min - 1;
+        }
+        else if (shift_max < 0)
+        {
+            *g0 = g_max + 1;
+            *g1 = g_max;
+        }
+        else
+        {
+            *g0 = xgi;
+            *g1 = xgi;
+            dcx2[xgi] = 0;
+        }
+    }
+    
+    while (*g0 > g_min)
+    {
+        /* Check one grid cell down */
+        dcx = ((*g0 - 1) + 1)*gridx - x;
+        tmp = dcx*dcx;
+        if (tmp >= rc2)
+        {
+            break;
+        }
+        (*g0)--;
+        dcx2[*g0] = tmp;
+    }
+    
+    while (*g1 < g_max)
+    {
+        /* Check one grid cell up */
+        dcx = (*g1 + 1)*gridx - x;
+        tmp = dcx*dcx;
+        if (tmp >= rc2)
+        {
+            break;
+        }
+        (*g1)++;
+        dcx2[*g1] = tmp;
+    }
+}
+
+
+#define sqr(x) ((x)*(x))
+#define calc_dx2(XI,YI,ZI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]) + sqr(ZI-y[ZZ]))
+#define calc_cyl_dx2(XI,YI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]))
+/****************************************************
+ *
+ *    F A S T   N E I G H B O R  S E A R C H I N G
+ *
+ *    Optimized neighboursearching routine using grid 
+ *    at least 1x1x1, see GROMACS manual
+ *
+ ****************************************************/
+
+static void do_longrange(t_commrec *cr,gmx_localtop_t *top,t_forcerec *fr,
+                         int ngid,t_mdatoms *md,int icg,
+                         int jgid,int nlr,
+                         atom_id lr[],t_excl bexcl[],int shift,
+                         rvec x[],rvec box_size,t_nrnb *nrnb,
+                         real lambda,real *dvdlambda,
+                         gmx_grppairener_t *grppener,
+                         gmx_bool bDoVdW,gmx_bool bDoCoul,
+                         gmx_bool bEvaluateNow,put_in_list_t *put_in_list,
+                         gmx_bool bHaveVdW[],
+                         gmx_bool bDoForces,rvec *f)
+{
+    int n,i;
+    t_nblist *nl;
+    
+    for(n=0; n<fr->nnblists; n++)
+    {
+        for(i=0; (i<eNL_NR); i++)
+        {
+            nl = &fr->nblists[n].nlist_lr[i];
+            if ((nl->nri > nl->maxnri-32) || bEvaluateNow)
+            {
+                close_neighbor_list(fr,TRUE,n,i,FALSE);
+                /* Evaluate the energies and forces */
+                do_nonbonded(cr,fr,x,f,md,NULL,
+                             grppener->ener[fr->bBHAM ? egBHAMLR : egLJLR],
+                             grppener->ener[egCOULLR],
+                                                        grppener->ener[egGB],box_size,
+                             nrnb,lambda,dvdlambda,n,i,
+                             GMX_DONB_LR | GMX_DONB_FORCES);
+                
+                reset_neighbor_list(fr,TRUE,n,i);
+            }
+        }
+    }
+    
+    if (!bEvaluateNow)
+    {  
+        /* Put the long range particles in a list */
+        /* do_longrange is never called for QMMM  */
+        put_in_list(bHaveVdW,ngid,md,icg,jgid,nlr,lr,top->cgs.index,
+                    bexcl,shift,fr,TRUE,bDoVdW,bDoCoul);
+    }
+}
+
+static void get_cutoff2(t_forcerec *fr,gmx_bool bDoLongRange,
+                        real *rvdw2,real *rcoul2,
+                        real *rs2,real *rm2,real *rl2)
+{
+    *rs2 = sqr(fr->rlist);
+    if (bDoLongRange && fr->bTwinRange)
+    {
+        /* The VdW and elec. LR cut-off's could be different,
+         * so we can not simply set them to rlistlong.
+         */
+        if (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(fr->vdwtype) &&
+            fr->rvdw > fr->rlist)
+        {
+            *rvdw2  = sqr(fr->rlistlong);
+        }
+        else
+        {
+            *rvdw2  = sqr(fr->rvdw);
+        }
+        if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(fr->eeltype) &&
+            fr->rcoulomb > fr->rlist)
+        {
+            *rcoul2 = sqr(fr->rlistlong);
+        }
+        else
+        {
+            *rcoul2 = sqr(fr->rcoulomb);
+        }
+    }
+    else
+    {
+        /* Workaround for a gcc -O3 or -ffast-math problem */
+        *rvdw2  = *rs2;
+        *rcoul2 = *rs2;
+    }
+    *rm2 = min(*rvdw2,*rcoul2);
+    *rl2 = max(*rvdw2,*rcoul2);
+}
+
+static void init_nsgrid_lists(t_forcerec *fr,int ngid,gmx_ns_t *ns)
+{
+    real rvdw2,rcoul2,rs2,rm2,rl2;
+    int j;
+
+    get_cutoff2(fr,TRUE,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
+
+    /* Short range buffers */
+    snew(ns->nl_sr,ngid);
+    /* Counters */
+    snew(ns->nsr,ngid);
+    snew(ns->nlr_ljc,ngid);
+    snew(ns->nlr_one,ngid);
+    
+    if (rm2 > rs2)
+    {
+            /* Long range VdW and Coul buffers */
+        snew(ns->nl_lr_ljc,ngid);
+    }
+    if (rl2 > rm2)
+    {
+        /* Long range VdW or Coul only buffers */
+        snew(ns->nl_lr_one,ngid);
+    }
+    for(j=0; (j<ngid); j++) {
+        snew(ns->nl_sr[j],MAX_CG);
+        if (rm2 > rs2)
+        {
+            snew(ns->nl_lr_ljc[j],MAX_CG);
+        }
+        if (rl2 > rm2)
+        {
+            snew(ns->nl_lr_one[j],MAX_CG);
+        }
+    }
+    if (debug)
+    {
+        fprintf(debug,
+                "ns5_core: rs2 = %g, rm2 = %g, rl2 = %g (nm^2)\n",
+                rs2,rm2,rl2);
+    }
+}
+
+static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
+                       matrix box,rvec box_size,int ngid,
+                       gmx_localtop_t *top,
+                       t_grid *grid,rvec x[],
+                       t_excl bexcl[],gmx_bool *bExcludeAlleg,
+                       t_nrnb *nrnb,t_mdatoms *md,
+                       real lambda,real *dvdlambda,
+                       gmx_grppairener_t *grppener,
+                       put_in_list_t *put_in_list,
+                       gmx_bool bHaveVdW[],
+                       gmx_bool bDoLongRange,gmx_bool bDoForces,rvec *f,
+                       gmx_bool bMakeQMMMnblist)
+{
+    gmx_ns_t *ns;
+    atom_id **nl_lr_ljc,**nl_lr_one,**nl_sr;
+    int     *nlr_ljc,*nlr_one,*nsr;
+    gmx_domdec_t *dd=NULL;
+    t_block *cgs=&(top->cgs);
+    int     *cginfo=fr->cginfo;
+    /* atom_id *i_atoms,*cgsindex=cgs->index; */
+    ivec    sh0,sh1,shp;
+    int     cell_x,cell_y,cell_z;
+    int     d,tx,ty,tz,dx,dy,dz,cj;
+#ifdef ALLOW_OFFDIAG_LT_HALFDIAG
+    int     zsh_ty,zsh_tx,ysh_tx;
+#endif
+    int     dx0,dx1,dy0,dy1,dz0,dz1;
+    int     Nx,Ny,Nz,shift=-1,j,nrj,nns,nn=-1;
+    real    gridx,gridy,gridz,grid_x,grid_y,grid_z;
+    real    *dcx2,*dcy2,*dcz2;
+    int     zgi,ygi,xgi;
+    int     cg0,cg1,icg=-1,cgsnr,i0,igid,nri,naaj,max_jcg;
+    int     jcg0,jcg1,jjcg,cgj0,jgid;
+    int     *grida,*gridnra,*gridind;
+    gmx_bool    rvdw_lt_rcoul,rcoul_lt_rvdw;
+    rvec    xi,*cgcm,grid_offset;
+    real    r2,rs2,rvdw2,rcoul2,rm2,rl2,XI,YI,ZI,dcx,dcy,dcz,tmp1,tmp2;
+    int     *i_egp_flags;
+    gmx_bool    bDomDec,bTriclinicX,bTriclinicY;
+    ivec    ncpddc;
+    
+    ns = &fr->ns;
+    
+    bDomDec = DOMAINDECOMP(cr);
+    if (bDomDec)
+    {
+        dd = cr->dd;
+    }
+    
+    bTriclinicX = ((YY < grid->npbcdim &&
+                    (!bDomDec || dd->nc[YY]==1) && box[YY][XX] != 0) ||
+                   (ZZ < grid->npbcdim &&
+                    (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][XX] != 0));
+    bTriclinicY =  (ZZ < grid->npbcdim &&
+                    (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][YY] != 0);
+    
+    cgsnr    = cgs->nr;
+
+    get_cutoff2(fr,bDoLongRange,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
+
+    rvdw_lt_rcoul = (rvdw2 >= rcoul2);
+    rcoul_lt_rvdw = (rcoul2 >= rvdw2);
+    
+    if (bMakeQMMMnblist)
+    {
+        rm2 = rl2;
+        rs2 = rl2;
+    }
+
+    nl_sr     = ns->nl_sr;
+    nsr       = ns->nsr;
+    nl_lr_ljc = ns->nl_lr_ljc;
+    nl_lr_one = ns->nl_lr_one;
+    nlr_ljc   = ns->nlr_ljc;
+    nlr_one   = ns->nlr_one;
+    
+    /* Unpack arrays */
+    cgcm    = fr->cg_cm;
+    Nx      = grid->n[XX];
+    Ny      = grid->n[YY];
+    Nz      = grid->n[ZZ];
+    grida   = grid->a;
+    gridind = grid->index;
+    gridnra = grid->nra;
+    nns     = 0;
+    
+    gridx      = grid->cell_size[XX];
+    gridy      = grid->cell_size[YY];
+    gridz      = grid->cell_size[ZZ];
+    grid_x     = 1/gridx;
+    grid_y     = 1/gridy;
+    grid_z     = 1/gridz;
+    copy_rvec(grid->cell_offset,grid_offset);
+    copy_ivec(grid->ncpddc,ncpddc);
+    dcx2       = grid->dcx2;
+    dcy2       = grid->dcy2;
+    dcz2       = grid->dcz2;
+    
+#ifdef ALLOW_OFFDIAG_LT_HALFDIAG
+    zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
+    zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
+    ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
+    if (zsh_tx!=0 && ysh_tx!=0)
+    {
+        /* This could happen due to rounding, when both ratios are 0.5 */
+        ysh_tx = 0;
+    }
+#endif
+    
+    debug_gmx();
+
+    if (fr->n_tpi)
+    {
+        /* We only want a list for the test particle */
+        cg0 = cgsnr - 1;
+    }
+    else
+    {
+        cg0 = grid->icg0;
+    }
+    cg1 = grid->icg1;
+
+    /* Set the shift range */
+    for(d=0; d<DIM; d++)
+    {
+        sh0[d] = -1;
+        sh1[d] = 1;
+        /* Check if we need periodicity shifts.
+         * Without PBC or with domain decomposition we don't need them.
+         */
+        if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
+        {
+            shp[d] = 0;
+        }
+        else
+        {
+            if (d == XX &&
+                box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
+            {
+                shp[d] = 2;
+            }
+            else
+            {
+                shp[d] = 1;
+            }
+        }
+    }
+    
+    /* Loop over charge groups */
+    for(icg=cg0; (icg < cg1); icg++)
+    {
+        igid = GET_CGINFO_GID(cginfo[icg]);
+        /* Skip this charge group if all energy groups are excluded! */
+        if (bExcludeAlleg[igid])
+        {
+            continue;
+        }
+        
+        i0   = cgs->index[icg];
+        
+        if (bMakeQMMMnblist)
+        { 
+            /* Skip this charge group if it is not a QM atom while making a
+             * QM/MM neighbourlist
+             */
+            if (md->bQM[i0]==FALSE)
+            {
+                continue; /* MM particle, go to next particle */ 
+            }
+            
+            /* Compute the number of charge groups that fall within the control
+             * of this one (icg)
+             */
+            naaj    = calc_naaj(icg,cgsnr);
+            jcg0    = icg;
+            jcg1    = icg + naaj;
+            max_jcg = cgsnr;       
+        } 
+        else
+        { 
+            /* make a normal neighbourlist */
+            
+            if (bDomDec)
+            {
+                /* Get the j charge-group and dd cell shift ranges */
+                dd_get_ns_ranges(cr->dd,icg,&jcg0,&jcg1,sh0,sh1);
+                max_jcg = 0;
+            }
+            else
+            {
+                /* Compute the number of charge groups that fall within the control
+                 * of this one (icg)
+                 */
+                naaj = calc_naaj(icg,cgsnr);
+                jcg0 = icg;
+                jcg1 = icg + naaj;
+                
+                if (fr->n_tpi)
+                {
+                    /* The i-particle is awlways the test particle,
+                     * so we want all j-particles
+                     */
+                    max_jcg = cgsnr - 1;
+                }
+                else
+                {
+                    max_jcg  = jcg1 - cgsnr;
+                }
+            }
+        }
+        
+        i_egp_flags = fr->egp_flags + igid*ngid;
+        
+        /* Set the exclusions for the atoms in charge group icg using a bitmask */
+        setexcl(i0,cgs->index[icg+1],&top->excls,TRUE,bexcl);
+        
+        ci2xyz(grid,icg,&cell_x,&cell_y,&cell_z);
+        
+        /* Changed iicg to icg, DvdS 990115 
+         * (but see consistency check above, DvdS 990330) 
+         */
+#ifdef NS5DB
+        fprintf(log,"icg=%5d, naaj=%5d, cell %d %d %d\n",
+                icg,naaj,cell_x,cell_y,cell_z);
+#endif
+        /* Loop over shift vectors in three dimensions */
+        for (tz=-shp[ZZ]; tz<=shp[ZZ]; tz++)
+        {
+            ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
+            /* Calculate range of cells in Z direction that have the shift tz */
+            zgi = cell_z + tz*Nz;
+#define FAST_DD_NS
+#ifndef FAST_DD_NS
+            get_dx(Nz,gridz,rl2,zgi,ZI,&dz0,&dz1,dcz2);
+#else
+            get_dx_dd(Nz,gridz,rl2,zgi,ZI-grid_offset[ZZ],
+                      ncpddc[ZZ],sh0[ZZ],sh1[ZZ],&dz0,&dz1,dcz2);
+#endif
+            if (dz0 > dz1)
+            {
+                continue;
+            }
+            for (ty=-shp[YY]; ty<=shp[YY]; ty++)
+            {
+                YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
+                /* Calculate range of cells in Y direction that have the shift ty */
+                if (bTriclinicY)
+                {
+                    ygi = (int)(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
+                }
+                else
+                {
+                    ygi = cell_y + ty*Ny;
+                }
+#ifndef FAST_DD_NS
+                get_dx(Ny,gridy,rl2,ygi,YI,&dy0,&dy1,dcy2);
+#else
+                get_dx_dd(Ny,gridy,rl2,ygi,YI-grid_offset[YY],
+                          ncpddc[YY],sh0[YY],sh1[YY],&dy0,&dy1,dcy2);
+#endif
+                if (dy0 > dy1)
+                {
+                    continue;
+                }
+                for (tx=-shp[XX]; tx<=shp[XX]; tx++)
+                {
+                    XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
+                    /* Calculate range of cells in X direction that have the shift tx */
+                    if (bTriclinicX)
+                    {
+                        xgi = (int)(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
+                    }
+                    else
+                    {
+                        xgi = cell_x + tx*Nx;
+                    }
+#ifndef FAST_DD_NS
+                    get_dx(Nx,gridx,rl2,xgi*Nx,XI,&dx0,&dx1,dcx2);
+#else
+                    get_dx_dd(Nx,gridx,rl2,xgi,XI-grid_offset[XX],
+                              ncpddc[XX],sh0[XX],sh1[XX],&dx0,&dx1,dcx2);
+#endif
+                    if (dx0 > dx1)
+                    {
+                        continue;
+                    }
+                    /* Get shift vector */       
+                    shift=XYZ2IS(tx,ty,tz);
+#ifdef NS5DB
+                    range_check(shift,0,SHIFTS);
+#endif
+                    for(nn=0; (nn<ngid); nn++)
+                    {
+                        nsr[nn]      = 0;
+                        nlr_ljc[nn]  = 0;
+                        nlr_one[nn] = 0;
+                    }
+#ifdef NS5DB
+                    fprintf(log,"shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
+                            shift,dx0,dx1,dy0,dy1,dz0,dz1);
+                    fprintf(log,"cgcm: %8.3f  %8.3f  %8.3f\n",cgcm[icg][XX],
+                            cgcm[icg][YY],cgcm[icg][ZZ]);
+                    fprintf(log,"xi:   %8.3f  %8.3f  %8.3f\n",XI,YI,ZI);
+#endif
+                    for (dx=dx0; (dx<=dx1); dx++)
+                    {
+                        tmp1 = rl2 - dcx2[dx];
+                        for (dy=dy0; (dy<=dy1); dy++)
+                        {
+                            tmp2 = tmp1 - dcy2[dy];
+                            if (tmp2 > 0)
+                            {
+                                for (dz=dz0; (dz<=dz1); dz++) {
+                                    if (tmp2 > dcz2[dz]) {
+                                        /* Find grid-cell cj in which possible neighbours are */
+                                        cj   = xyz2ci(Ny,Nz,dx,dy,dz);
+                                        
+                                        /* Check out how many cgs (nrj) there in this cell */
+                                        nrj  = gridnra[cj];
+                                        
+                                        /* Find the offset in the cg list */
+                                        cgj0 = gridind[cj];
+                                        
+                                        /* Check if all j's are out of range so we
+                                         * can skip the whole cell.
+                                         * Should save some time, especially with DD.
+                                         */
+                                        if (nrj == 0 ||
+                                            (grida[cgj0] >= max_jcg &&
+                                             (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
+                                        {
+                                            continue;
+                                        }
+                                        
+                                        /* Loop over cgs */
+                                        for (j=0; (j<nrj); j++)
+                                        {
+                                            jjcg = grida[cgj0+j];
+                                            
+                                            /* check whether this guy is in range! */
+                                            if ((jjcg >= jcg0 && jjcg < jcg1) ||
+                                                (jjcg < max_jcg))
+                                            {
+                                                r2=calc_dx2(XI,YI,ZI,cgcm[jjcg]);
+                                                if (r2 < rl2) {
+                                                    /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
+                                                    jgid = GET_CGINFO_GID(cginfo[jjcg]);
+                                                    /* check energy group exclusions */
+                                                    if (!(i_egp_flags[jgid] & EGP_EXCL))
+                                                    {
+                                                        if (r2 < rs2)
+                                                        {
+                                                            if (nsr[jgid] >= MAX_CG)
+                                                            {
+                                                                put_in_list(bHaveVdW,ngid,md,icg,jgid,
+                                                                            nsr[jgid],nl_sr[jgid],
+                                                                            cgs->index,/* cgsatoms, */ bexcl,
+                                                                            shift,fr,FALSE,TRUE,TRUE);
+                                                                nsr[jgid]=0;
+                                                            }
+                                                            nl_sr[jgid][nsr[jgid]++]=jjcg;
+                                                        } 
+                                                        else if (r2 < rm2)
+                                                        {
+                                                            if (nlr_ljc[jgid] >= MAX_CG)
+                                                            {
+                                                                do_longrange(cr,top,fr,ngid,md,icg,jgid,
+                                                                             nlr_ljc[jgid],
+                                                                             nl_lr_ljc[jgid],bexcl,shift,x,
+                                                                             box_size,nrnb,
+                                                                             lambda,dvdlambda,
+                                                                             grppener,
+                                                                             TRUE,TRUE,FALSE,
+                                                                             put_in_list,
+                                                                             bHaveVdW,
+                                                                             bDoForces,f);
+                                                                nlr_ljc[jgid]=0;
+                                                            }
+                                                            nl_lr_ljc[jgid][nlr_ljc[jgid]++]=jjcg;
+                                                        }
+                                                        else
+                                                        {
+                                                            if (nlr_one[jgid] >= MAX_CG) {
+                                                                do_longrange(cr,top,fr,ngid,md,icg,jgid,
+                                                                             nlr_one[jgid],
+                                                                             nl_lr_one[jgid],bexcl,shift,x,
+                                                                             box_size,nrnb,
+                                                                             lambda,dvdlambda,
+                                                                             grppener,
+                                                                             rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
+                                                                             put_in_list,
+                                                                             bHaveVdW,
+                                                                             bDoForces,f);
+                                                                nlr_one[jgid]=0;
+                                                            }
+                                                            nl_lr_one[jgid][nlr_one[jgid]++]=jjcg;
+                                                        }
+                                                    }
+                                                }
+                                                nns++;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    /* CHECK whether there is anything left in the buffers */
+                    for(nn=0; (nn<ngid); nn++)
+                    {
+                        if (nsr[nn] > 0)
+                        {
+                            put_in_list(bHaveVdW,ngid,md,icg,nn,nsr[nn],nl_sr[nn],
+                                        cgs->index, /* cgsatoms, */ bexcl,
+                                        shift,fr,FALSE,TRUE,TRUE);
+                        }
+                        
+                        if (nlr_ljc[nn] > 0)
+                        {
+                            do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_ljc[nn],
+                                         nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
+                                         lambda,dvdlambda,grppener,TRUE,TRUE,FALSE,
+                                         put_in_list,bHaveVdW,bDoForces,f);
+                        }
+                        
+                        if (nlr_one[nn] > 0)
+                        {
+                            do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_one[nn],
+                                         nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
+                                         lambda,dvdlambda,grppener,
+                                         rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
+                                         put_in_list,bHaveVdW,bDoForces,f);
+                        }
+                    }
+                }
+            }
+        }
+        /* setexcl(nri,i_atoms,&top->atoms.excl,FALSE,bexcl); */
+        setexcl(cgs->index[icg],cgs->index[icg+1],&top->excls,FALSE,bexcl);
+    }
+    /* Perform any left over force calculations */
+    for (nn=0; (nn<ngid); nn++)
+    {
+        if (rm2 > rs2)
+        {
+            do_longrange(cr,top,fr,0,md,icg,nn,nlr_ljc[nn],
+                         nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
+                         lambda,dvdlambda,grppener,
+                         TRUE,TRUE,TRUE,put_in_list,bHaveVdW,bDoForces,f);
+        }
+        if (rl2 > rm2) {
+            do_longrange(cr,top,fr,0,md,icg,nn,nlr_one[nn],
+                         nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
+                         lambda,dvdlambda,grppener,
+                         rvdw_lt_rcoul,rcoul_lt_rvdw,
+                         TRUE,put_in_list,bHaveVdW,bDoForces,f);
+        }
+    }
+    debug_gmx();
+    
+    /* Close off short range neighbourlists */
+    close_neighbor_list(fr,FALSE,-1,-1,bMakeQMMMnblist);
+    
+    return nns;
+}
+
+void ns_realloc_natoms(gmx_ns_t *ns,int natoms)
+{
+    int i;
+    
+    if (natoms > ns->nra_alloc)
+    {
+        ns->nra_alloc = over_alloc_dd(natoms);
+        srenew(ns->bexcl,ns->nra_alloc);
+        for(i=0; i<ns->nra_alloc; i++)
+        {
+            ns->bexcl[i] = 0;
+        }
+    }
+}
+
+void init_ns(FILE *fplog,const t_commrec *cr,
+             gmx_ns_t *ns,t_forcerec *fr,
+             const gmx_mtop_t *mtop,
+             matrix box)
+{
+    int  mt,icg,nr_in_cg,maxcg,i,j,jcg,ngid,ncg;
+    t_block *cgs;
+    char *ptr;
+    
+    /* Compute largest charge groups size (# atoms) */
+    nr_in_cg=1;
+    for(mt=0; mt<mtop->nmoltype; mt++) {
+        cgs = &mtop->moltype[mt].cgs;
+        for (icg=0; (icg < cgs->nr); icg++)
+        {
+            nr_in_cg=max(nr_in_cg,(int)(cgs->index[icg+1]-cgs->index[icg]));
+        }
+    }
+
+    /* Verify whether largest charge group is <= max cg.
+     * This is determined by the type of the local exclusion type 
+     * Exclusions are stored in bits. (If the type is not large
+     * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
+     */
+    maxcg = sizeof(t_excl)*8;
+    if (nr_in_cg > maxcg)
+    {
+        gmx_fatal(FARGS,"Max #atoms in a charge group: %d > %d\n",
+                  nr_in_cg,maxcg);
+    }
+    
+    ngid = mtop->groups.grps[egcENER].nr;
+    snew(ns->bExcludeAlleg,ngid);
+    for(i=0; i<ngid; i++) {
+        ns->bExcludeAlleg[i] = TRUE;
+        for(j=0; j<ngid; j++)
+        {
+            if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
+            {
+                ns->bExcludeAlleg[i] = FALSE;
+            }
+        }
+    }
+    
+    if (fr->bGrid) {
+        /* Grid search */
+        ns->grid = init_grid(fplog,fr);
+        init_nsgrid_lists(fr,ngid,ns);
+    }
+    else
+    {
+        /* Simple search */
+        snew(ns->ns_buf,ngid);
+        for(i=0; (i<ngid); i++)
+        {
+            snew(ns->ns_buf[i],SHIFTS);
+        }
+        ncg = ncg_mtop(mtop);
+        snew(ns->simple_aaj,2*ncg);
+        for(jcg=0; (jcg<ncg); jcg++)
+        {
+            ns->simple_aaj[jcg]     = jcg;
+            ns->simple_aaj[jcg+ncg] = jcg;
+        }
+    }
+    
+    /* Create array that determines whether or not atoms have VdW */
+    snew(ns->bHaveVdW,fr->ntype);
+    for(i=0; (i<fr->ntype); i++)
+    {
+        for(j=0; (j<fr->ntype); j++)
+        {
+            ns->bHaveVdW[i] = (ns->bHaveVdW[i] || 
+                               (fr->bBHAM ? 
+                                ((BHAMA(fr->nbfp,fr->ntype,i,j) != 0) ||
+                                 (BHAMB(fr->nbfp,fr->ntype,i,j) != 0) ||
+                                 (BHAMC(fr->nbfp,fr->ntype,i,j) != 0)) :
+                                ((C6(fr->nbfp,fr->ntype,i,j) != 0) ||
+                                 (C12(fr->nbfp,fr->ntype,i,j) != 0))));
+        }
+    }
+    if (debug) 
+        pr_bvec(debug,0,"bHaveVdW",ns->bHaveVdW,fr->ntype,TRUE);
+    
+    ns->nra_alloc = 0;
+    ns->bexcl = NULL;
+    if (!DOMAINDECOMP(cr))
+    {
+        /* This could be reduced with particle decomposition */
+        ns_realloc_natoms(ns,mtop->natoms);
+    }
+
+    ns->nblist_initialized=FALSE;
+
+    /* nbr list debug dump */
+    {
+        char *ptr=getenv("GMX_DUMP_NL");
+        if (ptr)
+        {
+            ns->dump_nl=strtol(ptr,NULL,10);
+            if (fplog)
+            {
+                fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
+            }
+        }
+        else
+        {
+            ns->dump_nl=0;
+        }
+    }
+}
+
+                        
+int search_neighbours(FILE *log,t_forcerec *fr,
+                      rvec x[],matrix box,
+                      gmx_localtop_t *top,
+                      gmx_groups_t *groups,
+                      t_commrec *cr,
+                      t_nrnb *nrnb,t_mdatoms *md,
+                      real lambda,real *dvdlambda,
+                      gmx_grppairener_t *grppener,
+                      gmx_bool bFillGrid,
+                      gmx_bool bDoLongRange,
+                      gmx_bool bDoForces,rvec *f)
+{
+    t_block  *cgs=&(top->cgs);
+    rvec     box_size,grid_x0,grid_x1;
+    int      i,j,m,ngid;
+    real     min_size,grid_dens;
+    int      nsearch;
+    gmx_bool     bGrid;
+    char     *ptr;
+    gmx_bool     *i_egp_flags;
+    int      cg_start,cg_end,start,end;
+    gmx_ns_t *ns;
+    t_grid   *grid;
+    gmx_domdec_zones_t *dd_zones;
+    put_in_list_t *put_in_list;
+       
+    ns = &fr->ns;
+
+    /* Set some local variables */
+    bGrid = fr->bGrid;
+    ngid = groups->grps[egcENER].nr;
+    
+    for(m=0; (m<DIM); m++)
+    {
+        box_size[m] = box[m][m];
+    }
+  
+    if (fr->ePBC != epbcNONE)
+    {
+        if (sqr(fr->rlistlong) >= max_cutoff2(fr->ePBC,box))
+        {
+            gmx_fatal(FARGS,"One of the box vectors has become shorter than twice the cut-off length or box_yy-|box_zy| or box_zz has become smaller than the cut-off.");
+        }
+        if (!bGrid)
+        {
+            min_size = min(box_size[XX],min(box_size[YY],box_size[ZZ]));
+            if (2*fr->rlistlong >= min_size)
+                gmx_fatal(FARGS,"One of the box diagonal elements has become smaller than twice the cut-off length.");
+        }
+    }
+    
+    if (DOMAINDECOMP(cr))
+    {
+        ns_realloc_natoms(ns,cgs->index[cgs->nr]);
+    }
+    debug_gmx();
+    
+    /* Reset the neighbourlists */
+    reset_neighbor_list(fr,FALSE,-1,-1);
+    
+    if (bGrid && bFillGrid)
+    {
+               
+        grid = ns->grid;
+        if (DOMAINDECOMP(cr))
+        {
+            dd_zones = domdec_zones(cr->dd);
+        }
+        else
+        {
+            dd_zones = NULL;
+
+            get_nsgrid_boundaries(grid,NULL,box,NULL,NULL,NULL,
+                                  cgs->nr,fr->cg_cm,grid_x0,grid_x1,&grid_dens);
+
+            grid_first(log,grid,NULL,NULL,fr->ePBC,box,grid_x0,grid_x1,
+                       fr->rlistlong,grid_dens);
+        }
+        debug_gmx();
+        
+        /* Don't know why this all is... (DvdS 3/99) */
+#ifndef SEGV
+        start = 0;
+        end   = cgs->nr;
+#else
+        start = fr->cg0;
+        end   = (cgs->nr+1)/2;
+#endif
+        
+        if (DOMAINDECOMP(cr))
+        {
+            end = cgs->nr;
+            fill_grid(log,dd_zones,grid,end,-1,end,fr->cg_cm);
+            grid->icg0 = 0;
+            grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
+        }
+        else
+        {
+            fill_grid(log,NULL,grid,cgs->nr,fr->cg0,fr->hcg,fr->cg_cm);
+            grid->icg0 = fr->cg0;
+            grid->icg1 = fr->hcg;
+            debug_gmx();
+            
+            if (PARTDECOMP(cr))
+                mv_grid(cr,grid);
+            debug_gmx();
+        }
+        
+        calc_elemnr(log,grid,start,end,cgs->nr);
+        calc_ptrs(grid);
+        grid_last(log,grid,start,end,cgs->nr);
+        
+        if (gmx_debug_at)
+        {
+            check_grid(debug,grid);
+            print_grid(debug,grid);
+        }
+    }
+    else if (fr->n_tpi)
+    {
+        /* Set the grid cell index for the test particle only.
+         * The cell to cg index is not corrected, but that does not matter.
+         */
+        fill_grid(log,NULL,ns->grid,fr->hcg,fr->hcg-1,fr->hcg,fr->cg_cm);
+    }
+    debug_gmx();
+    
+    if (!fr->ns.bCGlist)
+    {
+        put_in_list = put_in_list_at;
+    }
+    else
+    {
+        put_in_list = put_in_list_cg;
+    }
+
+    /* Do the core! */
+    if (bGrid)
+    {
+        grid = ns->grid;
+        nsearch = nsgrid_core(log,cr,fr,box,box_size,ngid,top,
+                              grid,x,ns->bexcl,ns->bExcludeAlleg,
+                              nrnb,md,lambda,dvdlambda,grppener,
+                              put_in_list,ns->bHaveVdW,
+                              bDoLongRange,bDoForces,f,
+                              FALSE);
+        
+        /* neighbour searching withouth QMMM! QM atoms have zero charge in
+         * the classical calculation. The charge-charge interaction
+         * between QM and MM atoms is handled in the QMMM core calculation
+         * (see QMMM.c). The VDW however, we'd like to compute classically
+         * and the QM MM atom pairs have just been put in the
+         * corresponding neighbourlists. in case of QMMM we still need to
+         * fill a special QMMM neighbourlist that contains all neighbours
+         * of the QM atoms. If bQMMM is true, this list will now be made: 
+         */
+        if (fr->bQMMM && fr->qr->QMMMscheme!=eQMMMschemeoniom)
+        {
+            nsearch += nsgrid_core(log,cr,fr,box,box_size,ngid,top,
+                                   grid,x,ns->bexcl,ns->bExcludeAlleg,
+                                   nrnb,md,lambda,dvdlambda,grppener,
+                                   put_in_list_qmmm,ns->bHaveVdW,
+                                   bDoLongRange,bDoForces,f,
+                                   TRUE);
+        }
+    }
+    else 
+    {
+        nsearch = ns_simple_core(fr,top,md,box,box_size,
+                                 ns->bexcl,ns->simple_aaj,
+                                 ngid,ns->ns_buf,put_in_list,ns->bHaveVdW);
+    }
+    debug_gmx();
+    
+#ifdef DEBUG
+    pr_nsblock(log);
+#endif
+    
+    inc_nrnb(nrnb,eNR_NS,nsearch);
+    /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
+    
+    return nsearch;
+}
+
+int natoms_beyond_ns_buffer(t_inputrec *ir,t_forcerec *fr,t_block *cgs,
+                            matrix scale_tot,rvec *x)
+{
+    int  cg0,cg1,cg,a0,a1,a,i,j;
+    real rint,hbuf2,scale;
+    rvec *cg_cm,cgsc;
+    gmx_bool bIsotropic;
+    int  nBeyond;
+    
+    nBeyond = 0;
+    
+    rint = max(ir->rcoulomb,ir->rvdw);
+    if (ir->rlist < rint)
+    {
+        gmx_fatal(FARGS,"The neighbor search buffer has negative size: %f nm",
+                  ir->rlist - rint);
+    }
+    cg_cm = fr->cg_cm;
+    
+    cg0 = fr->cg0;
+    cg1 = fr->hcg;
+    
+    if (!EI_DYNAMICS(ir->eI) || !DYNAMIC_BOX(*ir))
+    {
+        hbuf2 = sqr(0.5*(ir->rlist - rint));
+        for(cg=cg0; cg<cg1; cg++)
+        {
+            a0 = cgs->index[cg];
+            a1 = cgs->index[cg+1];
+            for(a=a0; a<a1; a++)
+            {
+                if (distance2(cg_cm[cg],x[a]) > hbuf2)
+                {
+                    nBeyond++;
+                }
+            }
+        }
+    }
+    else
+    {
+        bIsotropic = TRUE;
+        scale = scale_tot[0][0];
+        for(i=1; i<DIM; i++)
+        {
+            /* With anisotropic scaling, the original spherical ns volumes become
+             * ellipsoids. To avoid costly transformations we use the minimum
+             * eigenvalue of the scaling matrix for determining the buffer size.
+             * Since the lower half is 0, the eigenvalues are the diagonal elements.
+             */
+            scale = min(scale,scale_tot[i][i]);
+            if (scale_tot[i][i] != scale_tot[i-1][i-1])
+            {
+                bIsotropic = FALSE;
+            }
+            for(j=0; j<i; j++)
+            {
+                if (scale_tot[i][j] != 0)
+                {
+                    bIsotropic = FALSE;
+                }
+            }
+        }
+        hbuf2 = sqr(0.5*(scale*ir->rlist - rint));
+        if (bIsotropic)
+        {
+            for(cg=cg0; cg<cg1; cg++)
+            {
+                svmul(scale,cg_cm[cg],cgsc);
+                a0 = cgs->index[cg];
+                a1 = cgs->index[cg+1];
+                for(a=a0; a<a1; a++)
+                {
+                    if (distance2(cgsc,x[a]) > hbuf2)
+                    {                    
+                        nBeyond++;
+                    }
+                }
+            }
+        }
+        else
+        {
+            /* Anistropic scaling */
+            for(cg=cg0; cg<cg1; cg++)
+            {
+                /* Since scale_tot contains the transpose of the scaling matrix,
+                 * we need to multiply with the transpose.
+                 */
+                tmvmul_ur0(scale_tot,cg_cm[cg],cgsc);
+                a0 = cgs->index[cg];
+                a1 = cgs->index[cg+1];
+                for(a=a0; a<a1; a++)
+                {
+                    if (distance2(cgsc,x[a]) > hbuf2)
+                    {
+                        nBeyond++;
+                    }
+                }
+            }
+        }
+    }
+    
+    return nBeyond;
+}
diff --git a/src/gromacs/mdlib/pme.c b/src/gromacs/mdlib/pme.c
new file mode 100644 (file)
index 0000000..add09f6
--- /dev/null
@@ -0,0 +1,2715 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+/* IMPORTANT FOR DEVELOPERS:
+ *
+ * Triclinic pme stuff isn't entirely trivial, and we've experienced
+ * some bugs during development (many of them due to me). To avoid
+ * this in the future, please check the following things if you make
+ * changes in this file:
+ *
+ * 1. You should obtain identical (at least to the PME precision)
+ *    energies, forces, and virial for
+ *    a rectangular box and a triclinic one where the z (or y) axis is
+ *    tilted a whole box side. For instance you could use these boxes:
+ *
+ *    rectangular       triclinic
+ *     2  0  0           2  0  0
+ *     0  2  0           0  2  0
+ *     0  0  6           2  2  6
+ *
+ * 2. You should check the energy conservation in a triclinic box.
+ *
+ * It might seem an overkill, but better safe than sorry.
+ * /Erik 001109
+ */ 
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "typedefs.h"
+#include "txtdump.h"
+#include "vec.h"
+#include "gmxcomplex.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "coulomb.h"
+#include "gmx_fatal.h"
+#include "pme.h"
+#include "network.h"
+#include "physics.h"
+#include "nrnb.h"
+#include "copyrite.h"
+#include "gmx_wallcycle.h"
+#include "gmx_parallel_3dfft.h"
+#include "pdbio.h"
+
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+#include "gmx_sse2_single.h"
+#endif
+
+#define DFT_TOL 1e-7
+/* #define PRT_FORCE */
+/* conditions for on the fly time-measurement */
+/* #define TAKETIME (step > 1 && timesteps < 10) */
+#define TAKETIME FALSE
+
+#ifdef GMX_DOUBLE
+#define mpi_type MPI_DOUBLE
+#else
+#define mpi_type MPI_FLOAT
+#endif
+
+/* Internal datastructures */
+typedef struct {
+    int send_index0;
+    int send_nindex;
+    int recv_index0;
+    int recv_nindex;
+} pme_grid_comm_t;
+
+typedef struct {
+#ifdef GMX_MPI
+    MPI_Comm mpi_comm;
+#endif
+    int  nnodes,nodeid;
+    int  *s2g0;
+    int  *s2g1;
+    int  noverlap_nodes;
+    int  *send_id,*recv_id;
+    pme_grid_comm_t *comm_data;
+} pme_overlap_t;
+
+typedef struct {
+    int  dimind;            /* The index of the dimension, 0=x, 1=y */
+    int  nslab;
+    int  nodeid;
+#ifdef GMX_MPI
+    MPI_Comm mpi_comm;
+#endif
+
+    int  *node_dest;        /* The nodes to send x and q to with DD */
+    int  *node_src;         /* The nodes to receive x and q from with DD */
+    int  *buf_index;        /* Index for commnode into the buffers */
+
+    int  maxshift;
+
+    int  npd;
+    int  pd_nalloc;
+    int  *pd;
+    int  *count;            /* The number of atoms to send to each node */
+    int  *rcount;           /* The number of atoms to receive */
+
+    int  n;
+    int  nalloc;
+    rvec *x;
+    real *q;
+    rvec *f;
+    gmx_bool bSpread;           /* These coordinates are used for spreading */
+    int  pme_order;
+    splinevec theta,dtheta;
+    ivec *idx;
+    rvec *fractx;            /* Fractional coordinate relative to the
+                              * lower cell boundary 
+                              */
+} pme_atomcomm_t;
+
+typedef struct gmx_pme {
+    int  ndecompdim;         /* The number of decomposition dimensions */
+    int  nodeid;             /* Our nodeid in mpi->mpi_comm */
+    int  nodeid_major;
+    int  nodeid_minor;
+    int  nnodes;             /* The number of nodes doing PME */
+    int  nnodes_major;
+    int  nnodes_minor;
+
+    MPI_Comm mpi_comm;
+    MPI_Comm mpi_comm_d[2];  /* Indexed on dimension, 0=x, 1=y */
+#ifdef GMX_MPI
+    MPI_Datatype  rvec_mpi;  /* the pme vector's MPI type */
+#endif
+
+    gmx_bool bPPnode;            /* Node also does particle-particle forces */
+    gmx_bool bFEP;               /* Compute Free energy contribution */
+    int nkx,nky,nkz;         /* Grid dimensions */
+    int pme_order;
+    real epsilon_r;           
+    
+    real *  pmegridA;  /* Grids on which we do spreading/interpolation, includes overlap */
+    real *  pmegridB;
+    int     pmegrid_nx,pmegrid_ny,pmegrid_nz;
+    int     pmegrid_start_ix,pmegrid_start_iy,pmegrid_start_iz;    
+    
+    real *  pmegrid_sendbuf;
+    real *  pmegrid_recvbuf;
+    
+    real *fftgridA;             /* Grids for FFT. With 1D FFT decomposition this can be a pointer */
+    real *fftgridB;             /* inside the interpolation grid, but separate for 2D PME decomp. */
+    int   fftgrid_nx,fftgrid_ny,fftgrid_nz;
+    
+    t_complex *cfftgridA;             /* Grids for complex FFT data */
+    t_complex *cfftgridB;            
+    int   cfftgrid_nx,cfftgrid_ny,cfftgrid_nz;
+    
+    gmx_parallel_3dfft_t  pfft_setupA;
+    gmx_parallel_3dfft_t  pfft_setupB;
+    
+    int  *nnx,*nny,*nnz;
+    real *fshx,*fshy,*fshz;
+    
+    pme_atomcomm_t atc[2];  /* Indexed on decomposition index */
+    matrix    recipbox;
+    splinevec bsp_mod;
+    
+    pme_overlap_t overlap[2]; /* Indexed on dimension, 0=x, 1=y */
+
+
+    pme_atomcomm_t atc_energy; /* Only for gmx_pme_calc_energy */
+    
+    rvec *bufv;             /* Communication buffer */
+    real *bufr;             /* Communication buffer */
+    int  buf_nalloc;        /* The communication buffer size */
+
+    /* work data for solve_pme */
+    int      work_nalloc;
+    real *   work_mhx;
+    real *   work_mhy;
+    real *   work_mhz;
+    real *   work_m2;
+    real *   work_denom;
+    real *   work_tmp1_alloc;
+    real *   work_tmp1;
+    real *   work_m2inv;
+
+    /* Work data for PME_redist */
+    gmx_bool     redist_init;
+    int *    scounts; 
+    int *    rcounts;
+    int *    sdispls;
+    int *    rdispls;
+    int *    sidx;
+    int *    idxa;    
+    real *   redist_buf;
+    int      redist_buf_nalloc;
+    
+    /* Work data for sum_qgrid */
+    real *   sum_qgrid_tmp;
+    real *   sum_qgrid_dd_tmp;
+} t_gmx_pme;
+
+
+static void calc_interpolation_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
+{
+    int  i;
+    int  *idxptr,tix,tiy,tiz;
+    real *xptr,*fptr,tx,ty,tz;
+    real rxx,ryx,ryy,rzx,rzy,rzz;
+    int  nx,ny,nz;
+    int  start_ix,start_iy,start_iz;
+    
+    nx  = pme->nkx;
+    ny  = pme->nky;
+    nz  = pme->nkz;
+    
+    start_ix = pme->pmegrid_start_ix;
+    start_iy = pme->pmegrid_start_iy;
+    start_iz = pme->pmegrid_start_iz;
+    
+    rxx = pme->recipbox[XX][XX];
+    ryx = pme->recipbox[YY][XX];
+    ryy = pme->recipbox[YY][YY];
+    rzx = pme->recipbox[ZZ][XX];
+    rzy = pme->recipbox[ZZ][YY];
+    rzz = pme->recipbox[ZZ][ZZ];
+    
+    for(i=0; (i<atc->n); i++) {
+        xptr   = atc->x[i];
+        idxptr = atc->idx[i];
+        fptr   = atc->fractx[i];
+        
+        /* Fractional coordinates along box vectors, add 2.0 to make 100% sure we are positive for triclinic boxes */
+        tx = nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx + 2.0 );
+        ty = ny * (                  xptr[YY] * ryy + xptr[ZZ] * rzy + 2.0 );
+        tz = nz * (                                   xptr[ZZ] * rzz + 2.0 );
+        
+        tix = (int)(tx);
+        tiy = (int)(ty);
+        tiz = (int)(tz);
+        
+        /* Because decomposition only occurs in x and y,
+         * we never have a fraction correction in z.
+         */
+        fptr[XX] = tx - tix + pme->fshx[tix];
+        fptr[YY] = ty - tiy + pme->fshy[tiy];
+        fptr[ZZ] = tz - tiz;   
+
+        idxptr[XX] = pme->nnx[tix];
+        idxptr[YY] = pme->nny[tiy];
+        idxptr[ZZ] = pme->nnz[tiz];
+
+#ifdef DEBUG
+        range_check(idxptr[XX],0,pme->pmegrid_nx);
+        range_check(idxptr[YY],0,pme->pmegrid_ny);
+        range_check(idxptr[ZZ],0,pme->pmegrid_nz);
+#endif
+  }  
+}
+
+static void pme_calc_pidx(int natoms, matrix recipbox, rvec x[],
+                          pme_atomcomm_t *atc)
+{
+    int  nslab,i;
+    int  si;
+    real *xptr,s;
+    real rxx,ryx,rzx,ryy,rzy;
+    int *pd,*count;
+
+    /* Calculate PME task index (pidx) for each grid index.
+     * Here we always assign equally sized slabs to each node
+     * for load balancing reasons (the PME grid spacing is not used).
+     */
+    
+    nslab = atc->nslab;
+    pd    = atc->pd;
+    count = atc->count;
+
+    /* Reset the count */
+    for(i=0; i<nslab; i++)
+    {
+        count[i] = 0;
+    }
+    
+    if (atc->dimind == 0)
+    {
+        rxx = recipbox[XX][XX];
+        ryx = recipbox[YY][XX];
+        rzx = recipbox[ZZ][XX];
+        /* Calculate the node index in x-dimension */
+        for(i=0; (i<natoms); i++)
+        {
+            xptr   = x[i];
+            /* Fractional coordinates along box vectors */
+            s = nslab*(xptr[XX]*rxx + xptr[YY]*ryx + xptr[ZZ]*rzx);
+            si = (int)(s + 2*nslab) % nslab;
+            pd[i] = si;
+            count[si]++;
+        }
+    }
+    else
+    {
+        ryy = recipbox[YY][YY];
+        rzy = recipbox[ZZ][YY];
+        /* Calculate the node index in y-dimension */
+        for(i=0; (i<natoms); i++)
+        {
+            xptr   = x[i];
+            /* Fractional coordinates along box vectors */
+            s = nslab*(xptr[YY]*ryy + xptr[ZZ]*rzy);
+            si = (int)(s + 2*nslab) % nslab;
+            pd[i] = si;
+            count[si]++;
+        }
+    }
+}
+
+static void pme_realloc_atomcomm_things(pme_atomcomm_t *atc)
+{
+    int nalloc_old,i;
+    
+    /* We have to avoid a NULL pointer for atc->x to avoid
+     * possible fatal errors in MPI routines.
+     */
+    if (atc->n > atc->nalloc || atc->nalloc == 0)
+    {
+        nalloc_old = atc->nalloc;
+        atc->nalloc = over_alloc_dd(max(atc->n,1));
+        
+        if (atc->nslab > 1) {
+            srenew(atc->x,atc->nalloc);
+            srenew(atc->q,atc->nalloc);
+            srenew(atc->f,atc->nalloc);
+            for(i=nalloc_old; i<atc->nalloc; i++)
+            {
+                clear_rvec(atc->f[i]);
+            }
+        }
+        if (atc->bSpread) {
+            for(i=0;i<DIM;i++) {
+                srenew(atc->theta[i] ,atc->pme_order*atc->nalloc); 
+                srenew(atc->dtheta[i],atc->pme_order*atc->nalloc);
+            }
+            srenew(atc->fractx,atc->nalloc); 
+            srenew(atc->idx   ,atc->nalloc);
+        }
+    }
+}
+
+static void pmeredist_pd(gmx_pme_t pme, gmx_bool forw,
+                         int n, gmx_bool bXF, rvec *x_f, real *charge,
+                         pme_atomcomm_t *atc)
+/* Redistribute particle data for PME calculation */
+/* domain decomposition by x coordinate           */
+{
+    int *idxa;
+    int i, ii;
+    
+    if(FALSE == pme->redist_init) {
+        snew(pme->scounts,atc->nslab);
+        snew(pme->rcounts,atc->nslab);
+        snew(pme->sdispls,atc->nslab);
+        snew(pme->rdispls,atc->nslab);
+        snew(pme->sidx,atc->nslab);
+        pme->redist_init = TRUE;
+    }
+    if (n > pme->redist_buf_nalloc) {
+        pme->redist_buf_nalloc = over_alloc_dd(n);
+        srenew(pme->redist_buf,pme->redist_buf_nalloc*DIM);
+    }
+    
+    pme->idxa = atc->pd;
+
+#ifdef GMX_MPI
+    if (forw && bXF) {
+        /* forward, redistribution from pp to pme */ 
+        
+        /* Calculate send counts and exchange them with other nodes */
+        for(i=0; (i<atc->nslab); i++) pme->scounts[i]=0;
+        for(i=0; (i<n); i++) pme->scounts[pme->idxa[i]]++;
+        MPI_Alltoall( pme->scounts, 1, MPI_INT, pme->rcounts, 1, MPI_INT, atc->mpi_comm);
+        
+        /* Calculate send and receive displacements and index into send 
+           buffer */
+        pme->sdispls[0]=0;
+        pme->rdispls[0]=0;
+        pme->sidx[0]=0;
+        for(i=1; i<atc->nslab; i++) {
+            pme->sdispls[i]=pme->sdispls[i-1]+pme->scounts[i-1];
+            pme->rdispls[i]=pme->rdispls[i-1]+pme->rcounts[i-1];
+            pme->sidx[i]=pme->sdispls[i];
+        }
+        /* Total # of particles to be received */
+        atc->n = pme->rdispls[atc->nslab-1] + pme->rcounts[atc->nslab-1];
+        
+        pme_realloc_atomcomm_things(atc);
+        
+        /* Copy particle coordinates into send buffer and exchange*/
+        for(i=0; (i<n); i++) {
+            ii=DIM*pme->sidx[pme->idxa[i]];
+            pme->sidx[pme->idxa[i]]++;
+            pme->redist_buf[ii+XX]=x_f[i][XX];
+            pme->redist_buf[ii+YY]=x_f[i][YY];
+            pme->redist_buf[ii+ZZ]=x_f[i][ZZ];
+        }
+        MPI_Alltoallv(pme->redist_buf, pme->scounts, pme->sdispls, 
+                      pme->rvec_mpi, atc->x, pme->rcounts, pme->rdispls, 
+                      pme->rvec_mpi, atc->mpi_comm);
+    }
+    if (forw) {
+        /* Copy charge into send buffer and exchange*/
+        for(i=0; i<atc->nslab; i++) pme->sidx[i]=pme->sdispls[i];
+        for(i=0; (i<n); i++) {
+            ii=pme->sidx[pme->idxa[i]];
+            pme->sidx[pme->idxa[i]]++;
+            pme->redist_buf[ii]=charge[i];
+        }
+        MPI_Alltoallv(pme->redist_buf, pme->scounts, pme->sdispls, mpi_type,
+                      atc->q, pme->rcounts, pme->rdispls, mpi_type,
+                      atc->mpi_comm);
+    }
+    else { /* backward, redistribution from pme to pp */ 
+        MPI_Alltoallv(atc->f, pme->rcounts, pme->rdispls, pme->rvec_mpi,
+                      pme->redist_buf, pme->scounts, pme->sdispls, 
+                      pme->rvec_mpi, atc->mpi_comm);
+        
+        /* Copy data from receive buffer */
+        for(i=0; i<atc->nslab; i++)
+            pme->sidx[i] = pme->sdispls[i];
+        for(i=0; (i<n); i++) {
+            ii = DIM*pme->sidx[pme->idxa[i]];
+            x_f[i][XX] += pme->redist_buf[ii+XX];
+            x_f[i][YY] += pme->redist_buf[ii+YY];
+            x_f[i][ZZ] += pme->redist_buf[ii+ZZ];
+            pme->sidx[pme->idxa[i]]++;
+        }
+    }
+#endif 
+}
+
+static void pme_dd_sendrecv(pme_atomcomm_t *atc,
+                            gmx_bool bBackward,int shift,
+                            void *buf_s,int nbyte_s,
+                            void *buf_r,int nbyte_r)
+{
+#ifdef GMX_MPI
+    int dest,src;
+    MPI_Status stat;
+    
+    if (bBackward == FALSE) {
+        dest = atc->node_dest[shift];
+        src  = atc->node_src[shift];
+    } else {
+        dest = atc->node_src[shift];
+        src  = atc->node_dest[shift];
+    }
+    
+    if (nbyte_s > 0 && nbyte_r > 0) {
+        MPI_Sendrecv(buf_s,nbyte_s,MPI_BYTE,
+                     dest,shift,
+                     buf_r,nbyte_r,MPI_BYTE,
+                     src,shift,
+                     atc->mpi_comm,&stat);
+    } else if (nbyte_s > 0) {
+        MPI_Send(buf_s,nbyte_s,MPI_BYTE,
+                 dest,shift,
+                 atc->mpi_comm);
+    } else if (nbyte_r > 0) {
+        MPI_Recv(buf_r,nbyte_r,MPI_BYTE,
+                 src,shift,
+                 atc->mpi_comm,&stat);
+    }
+#endif
+}
+
+static void dd_pmeredist_x_q(gmx_pme_t pme, 
+                             int n, gmx_bool bX, rvec *x, real *charge,
+                             pme_atomcomm_t *atc)
+{
+    int *commnode,*buf_index;
+    int nnodes_comm,i,nsend,local_pos,buf_pos,node,scount,rcount;
+    
+    commnode  = atc->node_dest;
+    buf_index = atc->buf_index;
+    
+    nnodes_comm = min(2*atc->maxshift,atc->nslab-1);
+    
+    nsend = 0;
+    for(i=0; i<nnodes_comm; i++) {
+        buf_index[commnode[i]] = nsend;
+        nsend += atc->count[commnode[i]];
+    }
+    if (bX) {
+        if (atc->count[atc->nodeid] + nsend != n)
+            gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n"
+                      "This usually means that your system is not well equilibrated.",
+                      n - (atc->count[atc->nodeid] + nsend),
+                      pme->nodeid,'x'+atc->dimind);
+        
+        if (nsend > pme->buf_nalloc) {
+            pme->buf_nalloc = over_alloc_dd(nsend);
+            srenew(pme->bufv,pme->buf_nalloc);
+            srenew(pme->bufr,pme->buf_nalloc);
+        }
+        
+        atc->n = atc->count[atc->nodeid];
+        for(i=0; i<nnodes_comm; i++) {
+            scount = atc->count[commnode[i]];
+            /* Communicate the count */
+            if (debug)
+                fprintf(debug,"dimind %d PME node %d send to node %d: %d\n",
+                        atc->dimind,atc->nodeid,commnode[i],scount);
+            pme_dd_sendrecv(atc,FALSE,i,
+                            &scount,sizeof(int),
+                            &atc->rcount[i],sizeof(int));
+            atc->n += atc->rcount[i];
+        }
+        
+        pme_realloc_atomcomm_things(atc);
+    }
+    
+    local_pos = 0;
+    for(i=0; i<n; i++) {
+        node = atc->pd[i];
+        if (node == atc->nodeid) {
+            /* Copy direct to the receive buffer */
+            if (bX) {
+                copy_rvec(x[i],atc->x[local_pos]);
+            }
+            atc->q[local_pos] = charge[i];
+            local_pos++;
+        } else {
+            /* Copy to the send buffer */
+            if (bX) {
+                copy_rvec(x[i],pme->bufv[buf_index[node]]);
+            }
+            pme->bufr[buf_index[node]] = charge[i];
+            buf_index[node]++;
+        }
+    }
+    
+    buf_pos = 0;
+    for(i=0; i<nnodes_comm; i++) {
+        scount = atc->count[commnode[i]];
+        rcount = atc->rcount[i];
+        if (scount > 0 || rcount > 0) {
+            if (bX) {
+                /* Communicate the coordinates */
+                pme_dd_sendrecv(atc,FALSE,i,
+                                pme->bufv[buf_pos],scount*sizeof(rvec),
+                                atc->x[local_pos],rcount*sizeof(rvec));
+            }
+            /* Communicate the charges */
+            pme_dd_sendrecv(atc,FALSE,i,
+                            pme->bufr+buf_pos,scount*sizeof(real),
+                            atc->q+local_pos,rcount*sizeof(real));
+            buf_pos   += scount;
+            local_pos += atc->rcount[i];
+        }
+    }
+}
+
+static void dd_pmeredist_f(gmx_pme_t pme, pme_atomcomm_t *atc,
+                           int n, rvec *f,
+                           gmx_bool bAddF)
+{
+  int *commnode,*buf_index;
+  int nnodes_comm,local_pos,buf_pos,i,scount,rcount,node;
+
+  commnode  = atc->node_dest;
+  buf_index = atc->buf_index;
+
+  nnodes_comm = min(2*atc->maxshift,atc->nslab-1);
+
+  local_pos = atc->count[atc->nodeid];
+  buf_pos = 0;
+  for(i=0; i<nnodes_comm; i++) {
+    scount = atc->rcount[i];
+    rcount = atc->count[commnode[i]];
+    if (scount > 0 || rcount > 0) {
+      /* Communicate the forces */
+      pme_dd_sendrecv(atc,TRUE,i,
+                      atc->f[local_pos],scount*sizeof(rvec),
+                      pme->bufv[buf_pos],rcount*sizeof(rvec));
+      local_pos += scount;
+    }
+    buf_index[commnode[i]] = buf_pos;
+    buf_pos   += rcount;
+  }
+
+    local_pos = 0;
+    if (bAddF)
+    {
+        for(i=0; i<n; i++)
+        {
+            node = atc->pd[i];
+            if (node == atc->nodeid)
+            {
+                /* Add from the local force array */
+                rvec_inc(f[i],atc->f[local_pos]);
+                local_pos++;
+            }
+            else
+            {
+                /* Add from the receive buffer */
+                rvec_inc(f[i],pme->bufv[buf_index[node]]);
+                buf_index[node]++;
+            }
+        }
+    }
+    else
+    {
+        for(i=0; i<n; i++)
+        {
+            node = atc->pd[i];
+            if (node == atc->nodeid)
+            {
+                /* Copy from the local force array */
+                copy_rvec(atc->f[local_pos],f[i]);
+                local_pos++;
+            }
+            else
+            {
+                /* Copy from the receive buffer */
+                copy_rvec(pme->bufv[buf_index[node]],f[i]);
+                buf_index[node]++;
+            }
+        }
+    }
+}
+
+#ifdef GMX_MPI
+static void 
+gmx_sum_qgrid_dd(gmx_pme_t pme, real *grid, int direction)
+{
+    pme_overlap_t *overlap;
+    int send_index0,send_nindex;
+    int recv_index0,recv_nindex;
+    MPI_Status stat;
+    int i,j,k,ix,iy,iz,icnt;
+    int ipulse,send_id,recv_id,datasize;
+    real *p;
+    real *sendptr,*recvptr;
+    
+    /* Start with minor-rank communication. This is a bit of a pain since it is not contiguous */
+    overlap = &pme->overlap[1];
+    
+    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+    {
+        /* Since we have already (un)wrapped the overlap in the z-dimension,
+         * we only have to communicate 0 to nkz (not pmegrid_nz).
+         */
+        if (direction==GMX_SUM_QGRID_FORWARD)
+        {
+            send_id = overlap->send_id[ipulse];
+            recv_id = overlap->recv_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].send_index0;
+            send_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recv_index0   = overlap->comm_data[ipulse].recv_index0;
+            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
+        }
+        else
+        {
+            send_id = overlap->recv_id[ipulse];
+            recv_id = overlap->send_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].recv_index0;
+            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
+            recv_index0   = overlap->comm_data[ipulse].send_index0;
+            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
+        }
+
+        /* Copy data to contiguous send buffer */
+        if (debug)
+        {
+            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,send_id,
+                    pme->pmegrid_start_iy,
+                    send_index0-pme->pmegrid_start_iy,
+                    send_index0-pme->pmegrid_start_iy+send_nindex);
+        }
+        icnt = 0;
+        for(i=0;i<pme->pmegrid_nx;i++)
+        {
+            ix = i;
+            for(j=0;j<send_nindex;j++)
+            {
+                iy = j + send_index0 - pme->pmegrid_start_iy;
+                for(k=0;k<pme->nkz;k++)
+                {
+                    iz = k;
+                    pme->pmegrid_sendbuf[icnt++] = grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz];
+                }
+            }
+        }
+            
+        datasize      = pme->pmegrid_nx * pme->nkz;
+        
+        MPI_Sendrecv(pme->pmegrid_sendbuf,send_nindex*datasize,GMX_MPI_REAL,
+                     send_id,ipulse,
+                     pme->pmegrid_recvbuf,recv_nindex*datasize,GMX_MPI_REAL,
+                     recv_id,ipulse,
+                     overlap->mpi_comm,&stat);
+        
+        /* Get data from contiguous recv buffer */
+        if (debug)
+        {
+            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,recv_id,
+                    pme->pmegrid_start_iy,
+                    recv_index0-pme->pmegrid_start_iy,
+                    recv_index0-pme->pmegrid_start_iy+recv_nindex);
+        }
+        icnt = 0;
+        for(i=0;i<pme->pmegrid_nx;i++)
+        {
+            ix = i;
+            for(j=0;j<recv_nindex;j++)
+            {
+                iy = j + recv_index0 - pme->pmegrid_start_iy;
+                for(k=0;k<pme->nkz;k++)
+                {
+                    iz = k;
+                    if(direction==GMX_SUM_QGRID_FORWARD)
+                    {
+                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz] += pme->pmegrid_recvbuf[icnt++];
+                    }
+                    else
+                    {
+                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz]  = pme->pmegrid_recvbuf[icnt++];
+                    }
+                }
+            }
+        }
+    }
+    
+    /* Major dimension is easier, no copying required,
+     * but we might have to sum to separate array.
+     * Since we don't copy, we have to communicate up to pmegrid_nz,
+     * not nkz as for the minor direction.
+     */
+    overlap = &pme->overlap[0];
+    
+    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+    {
+        if(direction==GMX_SUM_QGRID_FORWARD)
+        {
+            send_id = overlap->send_id[ipulse];
+            recv_id = overlap->recv_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].send_index0;
+            send_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recv_index0   = overlap->comm_data[ipulse].recv_index0;
+            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
+            recvptr   = pme->pmegrid_recvbuf;
+        }
+        else
+        {
+            send_id = overlap->recv_id[ipulse];
+            recv_id = overlap->send_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].recv_index0;
+            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
+            recv_index0   = overlap->comm_data[ipulse].send_index0;
+            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recvptr   = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+        }
+                
+        sendptr       = grid + (send_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+        datasize      = pme->pmegrid_ny * pme->pmegrid_nz;
+
+        if (debug)
+        {
+            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,send_id,
+                    pme->pmegrid_start_ix,
+                    send_index0-pme->pmegrid_start_ix,
+                    send_index0-pme->pmegrid_start_ix+send_nindex);
+            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,recv_id,
+                    pme->pmegrid_start_ix,
+                    recv_index0-pme->pmegrid_start_ix,
+                    recv_index0-pme->pmegrid_start_ix+recv_nindex);
+        }
+
+        MPI_Sendrecv(sendptr,send_nindex*datasize,GMX_MPI_REAL,
+                     send_id,ipulse,
+                     recvptr,recv_nindex*datasize,GMX_MPI_REAL,
+                     recv_id,ipulse,
+                     overlap->mpi_comm,&stat);
+        
+        /* ADD data from contiguous recv buffer */
+        if(direction==GMX_SUM_QGRID_FORWARD)
+        {        
+            p = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+            for(i=0;i<recv_nindex*datasize;i++)
+            {
+                p[i] += pme->pmegrid_recvbuf[i];
+            }
+        }
+    }
+}
+#endif
+
+
+static int
+copy_pmegrid_to_fftgrid(gmx_pme_t pme, real *pmegrid, real *fftgrid)
+{
+    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
+    ivec    local_pme_size;
+    int     i,ix,iy,iz;
+    int     pmeidx,fftidx;
+
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+                                   local_fft_ndata,
+                                   local_fft_offset,
+                                   local_fft_size);
+    
+    local_pme_size[0] = pme->pmegrid_nx;
+    local_pme_size[1] = pme->pmegrid_ny;
+    local_pme_size[2] = pme->pmegrid_nz;
+    
+    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
+     the offset is identical, and the PME grid always has more data (due to overlap)
+     */
+    {
+#ifdef DEBUG_PME
+        FILE *fp,*fp2;
+        char fn[STRLEN],format[STRLEN];
+        real val;
+        sprintf(fn,"pmegrid%d.pdb",pme->nodeid);
+        fp = ffopen(fn,"w");
+        sprintf(fn,"pmegrid%d.txt",pme->nodeid);
+        fp2 = ffopen(fn,"w");
+     sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
+#endif
+    for(ix=0;ix<local_fft_ndata[XX];ix++)
+    {
+        for(iy=0;iy<local_fft_ndata[YY];iy++)
+        {
+            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+            {
+                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+                fftgrid[fftidx] = pmegrid[pmeidx];
+#ifdef DEBUG_PME
+                val = 100*pmegrid[pmeidx];
+                if (pmegrid[pmeidx] != 0)
+                fprintf(fp,format,"ATOM",pmeidx,"CA","GLY",' ',pmeidx,' ',
+                        5.0*ix,5.0*iy,5.0*iz,1.0,val);
+                if (pmegrid[pmeidx] != 0)
+                    fprintf(fp2,"%-12s  %5d  %5d  %5d  %12.5e\n",
+                            "qgrid",
+                            pme->pmegrid_start_ix + ix,
+                            pme->pmegrid_start_iy + iy,
+                            pme->pmegrid_start_iz + iz,
+                            pmegrid[pmeidx]);
+#endif
+            }
+        }
+    }
+#ifdef DEBUG_PME
+    fclose(fp);
+    fclose(fp2);
+#endif
+    }
+    return 0;
+}
+
+
+static int
+copy_fftgrid_to_pmegrid(gmx_pme_t pme, real *fftgrid, real *pmegrid)
+{
+    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
+    ivec    local_pme_size;
+    int     i,ix,iy,iz;
+    int     pmeidx,fftidx;
+    
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+                                   local_fft_ndata,
+                                   local_fft_offset,
+                                   local_fft_size);
+
+    local_pme_size[0] = pme->pmegrid_nx;
+    local_pme_size[1] = pme->pmegrid_ny;
+    local_pme_size[2] = pme->pmegrid_nz;
+    
+    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
+     the offset is identical, and the PME grid always has more data (due to overlap)
+     */
+    for(ix=0;ix<local_fft_ndata[XX];ix++)
+    {
+        for(iy=0;iy<local_fft_ndata[YY];iy++)
+        {
+            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+            {
+                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+                pmegrid[pmeidx] = fftgrid[fftidx];
+            }
+        }
+    }   
+    return 0;
+}
+
+
+static void
+wrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+
+    overlap = pme->pme_order - 1;
+
+    /* Add periodic overlap in z */
+    for(ix=0; ix<pnx; ix++)
+    {
+        for(iy=0; iy<pny; iy++)
+        {
+            for(iz=0; iz<overlap; iz++)
+            {
+                pmegrid[(ix*pny+iy)*pnz+iz] +=
+                    pmegrid[(ix*pny+iy)*pnz+nz+iz];
+            }
+        }
+    }
+
+    if (pme->nnodes_minor == 1)
+    {
+       for(ix=0; ix<pnx; ix++)
+       {
+           for(iy=0; iy<overlap; iy++)
+           {
+               for(iz=0; iz<nz; iz++)
+               {
+                   pmegrid[(ix*pny+iy)*pnz+iz] +=
+                       pmegrid[(ix*pny+ny+iy)*pnz+iz];
+               }
+           }
+       }
+    }
+     
+    if (pme->nnodes_major == 1)
+    {
+        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+        for(ix=0; ix<overlap; ix++)
+        {
+            for(iy=0; iy<ny_x; iy++)
+            {
+                for(iz=0; iz<nz; iz++)
+                {
+                    pmegrid[(ix*pny+iy)*pnz+iz] +=
+                        pmegrid[((nx+ix)*pny+iy)*pnz+iz];
+                }
+            }
+        }
+    }
+}
+
+
+static void
+unwrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+
+    overlap = pme->pme_order - 1;
+
+    if (pme->nnodes_major == 1)
+    {
+        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+        for(ix=0; ix<overlap; ix++)
+        {
+            for(iy=0; iy<ny_x; iy++)
+            {
+                for(iz=0; iz<nz; iz++)
+                {
+                    pmegrid[((nx+ix)*pny+iy)*pnz+iz] =
+                        pmegrid[(ix*pny+iy)*pnz+iz];
+                }
+            }
+        }
+    }
+
+    if (pme->nnodes_minor == 1)
+    {
+       for(ix=0; ix<pnx; ix++)
+       {
+           for(iy=0; iy<overlap; iy++)
+           {
+               for(iz=0; iz<nz; iz++)
+               {
+                   pmegrid[(ix*pny+ny+iy)*pnz+iz] =
+                       pmegrid[(ix*pny+iy)*pnz+iz];
+               }
+           }
+       }
+    }
+
+    /* Copy periodic overlap in z */
+    for(ix=0; ix<pnx; ix++)
+    {
+        for(iy=0; iy<pny; iy++)
+        {
+            for(iz=0; iz<overlap; iz++)
+            {
+                pmegrid[(ix*pny+iy)*pnz+nz+iz] =
+                    pmegrid[(ix*pny+iy)*pnz+iz];
+            }
+        }
+    }
+}
+
+
+/* This has to be a macro to enable full compiler optimization with xlC (and probably others too) */
+#define DO_BSPLINE(order)                            \
+for(ithx=0; (ithx<order); ithx++)                    \
+{                                                    \
+    index_x = (i0+ithx)*pny*pnz;                     \
+    valx    = qn*thx[ithx];                          \
+                                                     \
+    for(ithy=0; (ithy<order); ithy++)                \
+    {                                                \
+        valxy    = valx*thy[ithy];                   \
+        index_xy = index_x+(j0+ithy)*pnz;            \
+                                                     \
+        for(ithz=0; (ithz<order); ithz++)            \
+        {                                            \
+            index_xyz        = index_xy+(k0+ithz);   \
+            grid[index_xyz] += valxy*thz[ithz];      \
+        }                                            \
+    }                                                \
+}
+
+
+static void spread_q_bsplines(gmx_pme_t pme, pme_atomcomm_t *atc, 
+                              real *grid)
+{
+
+    /* spread charges from home atoms to local grid */
+    pme_overlap_t *ol;
+    int      b,i,nn,n,ithx,ithy,ithz,i0,j0,k0;
+    int *    idxptr;
+    int      order,norder,index_x,index_xy,index_xyz;
+    real     valx,valxy,qn;
+    real     *thx,*thy,*thz;
+    int      localsize, bndsize;
+  
+    int      pnx,pny,pnz,ndatatot;
+  
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+    ndatatot = pnx*pny*pnz;
+    
+    for(i=0;i<ndatatot;i++)
+    {
+        grid[i] = 0;
+    }
+
+    order = pme->pme_order;
+
+    for(nn=0; (nn<atc->n);nn++) 
+    {
+        n      = nn;
+        qn     = atc->q[n];
+
+        if (qn != 0) 
+        {
+            idxptr = atc->idx[n];
+            norder = n*order;
+            
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            thx = atc->theta[XX] + norder;
+            thy = atc->theta[YY] + norder;
+            thz = atc->theta[ZZ] + norder;
+            
+            switch (order) {
+            case 4:  DO_BSPLINE(4);     break;
+            case 5:  DO_BSPLINE(5);     break;
+            default: DO_BSPLINE(order); break;
+            }
+        }
+    }  
+}
+
+
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+    /* Calculate exponentials through SSE in float precision */
+#define CALC_EXPONENTIALS(start,end,r_aligned)      \
+    {                                               \
+        __m128 tmp_sse;                             \
+        for(kx=0; kx<end; kx+=4)                    \
+        {                                           \
+            tmp_sse = _mm_load_ps(r_aligned+kx);    \
+            tmp_sse = gmx_mm_exp_ps(tmp_sse);       \
+            _mm_store_ps(r_aligned+kx,tmp_sse);     \
+        }                                           \
+    }
+#else
+#define CALC_EXPONENTIALS(start,end,r)          \
+    for(kx=start; kx<end; kx++)                 \
+    {                                           \
+        r[kx] = exp(r[kx]);                     \
+    }
+#endif
+
+
+static int solve_pme_yzx(gmx_pme_t pme,t_complex *grid,
+                         real ewaldcoeff,real vol,
+                         gmx_bool bEnerVir,real *mesh_energy,matrix vir)
+{
+    /* do recip sum over local cells in grid */
+    /* y major, z middle, x minor or continuous */
+    t_complex *p0;
+    int     kx,ky,kz,maxkx,maxky,maxkz;
+    int     nx,ny,nz,iy,iz,kxstart,kxend;
+    real    mx,my,mz;
+    real    factor=M_PI*M_PI/(ewaldcoeff*ewaldcoeff);
+    real    ets2,struct2,vfactor,ets2vf;
+    real    eterm,d1,d2,energy=0;
+    real    by,bz;
+    real    virxx=0,virxy=0,virxz=0,viryy=0,viryz=0,virzz=0;
+    real    rxx,ryx,ryy,rzx,rzy,rzz;
+       real    *mhx,*mhy,*mhz,*m2,*denom,*tmp1,*m2inv;
+    real    mhxk,mhyk,mhzk,m2k;
+    real    corner_fac;
+    ivec    complex_order;
+    ivec    local_ndata,local_offset,local_size;
+    
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+    
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_complex_limits(pme->pfft_setupA,
+                                      complex_order,
+                                      local_ndata,
+                                      local_offset,
+                                      local_size);
+    
+    rxx = pme->recipbox[XX][XX];
+    ryx = pme->recipbox[YY][XX];
+    ryy = pme->recipbox[YY][YY];
+    rzx = pme->recipbox[ZZ][XX];
+    rzy = pme->recipbox[ZZ][YY];
+    rzz = pme->recipbox[ZZ][ZZ];
+    
+    maxkx = (nx+1)/2;
+    maxky = (ny+1)/2;
+    maxkz = nz/2+1;
+       
+       mhx   = pme->work_mhx;
+       mhy   = pme->work_mhy;
+       mhz   = pme->work_mhz;
+       m2    = pme->work_m2;
+       denom = pme->work_denom;
+       tmp1  = pme->work_tmp1;
+       m2inv = pme->work_m2inv;        
+
+    for(iy=0;iy<local_ndata[YY];iy++)
+    {
+        ky = iy + local_offset[YY];
+        
+        if (ky < maxky) 
+        {
+            my = ky;
+        }
+        else 
+        {
+            my = (ky - ny);
+        }
+        
+        by = M_PI*vol*pme->bsp_mod[YY][ky];
+
+        for(iz=0;iz<local_ndata[ZZ];iz++)
+        {
+            kz = iz + local_offset[ZZ];
+            
+            mz = kz;
+
+            bz = pme->bsp_mod[ZZ][kz];
+            
+            /* 0.5 correction for corner points */
+                       corner_fac = 1;
+            if (kz == 0)
+                corner_fac = 0.5;
+            if (kz == (nz+1)/2)
+                corner_fac = 0.5;
+                      
+            p0 = grid + iy*local_size[ZZ]*local_size[XX] + iz*local_size[XX];
+            
+            /* We should skip the k-space point (0,0,0) */
+            if (local_offset[XX] > 0 ||
+                local_offset[YY] > 0 || ky > 0 ||
+                kz > 0)
+            {
+                kxstart = local_offset[XX];
+            }
+            else
+            {
+                kxstart = local_offset[XX] + 1;
+                p0++;
+            }
+            kxend = local_offset[XX] + local_ndata[XX];
+                       
+            if (bEnerVir)
+            {
+                /* More expensive inner loop, especially because of the storage
+                 * of the mh elements in array's.
+                 * Because x is the minor grid index, all mh elements
+                 * depend on kx for triclinic unit cells.
+                 */
+
+                /* Two explicit loops to avoid a conditional inside the loop */
+                for(kx=kxstart; kx<maxkx; kx++)
+                {
+                    mx = kx;
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    mhx[kx]   = mhxk;
+                    mhy[kx]   = mhyk;
+                    mhz[kx]   = mhzk;
+                    m2[kx]    = m2k;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=maxkx; kx<kxend; kx++)
+                {
+                    mx = (kx - nx);
+
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    mhx[kx]   = mhxk;
+                    mhy[kx]   = mhyk;
+                    mhz[kx]   = mhzk;
+                    m2[kx]    = m2k;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    m2inv[kx] = 1.0/m2[kx];
+                }
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    denom[kx] = 1.0/denom[kx];
+                }
+
+                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+
+                for(kx=kxstart; kx<kxend; kx++,p0++)
+                {
+                    d1      = p0->re;
+                    d2      = p0->im;
+                    
+                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+                    
+                    p0->re  = d1*eterm;
+                    p0->im  = d2*eterm;
+                    
+                    struct2 = 2.0*(d1*d1+d2*d2);
+                    
+                    tmp1[kx] = eterm*struct2;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    ets2     = corner_fac*tmp1[kx];
+                    vfactor  = (factor*m2[kx] + 1.0)*2.0*m2inv[kx];
+                    energy  += ets2;
+                    
+                    ets2vf   = ets2*vfactor;
+                    virxx   += ets2vf*mhx[kx]*mhx[kx] - ets2;
+                    virxy   += ets2vf*mhx[kx]*mhy[kx];
+                    virxz   += ets2vf*mhx[kx]*mhz[kx];
+                    viryy   += ets2vf*mhy[kx]*mhy[kx] - ets2;
+                    viryz   += ets2vf*mhy[kx]*mhz[kx];
+                    virzz   += ets2vf*mhz[kx]*mhz[kx] - ets2;
+                }
+            }
+            else
+            {
+                /* We don't need to calculate the energy and the virial.
+                 * In this case the triclinic overhead is small.
+                 */
+
+                /* Two explicit loops to avoid a conditional inside the loop */
+
+                for(kx=kxstart; kx<maxkx; kx++)
+                {
+                    mx = kx;
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=maxkx; kx<kxend; kx++)
+                {
+                    mx = (kx - nx);
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    denom[kx] = 1.0/denom[kx];
+                }
+
+                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+               
+                for(kx=kxstart; kx<kxend; kx++,p0++)
+                {
+                    d1      = p0->re;
+                    d2      = p0->im;
+                    
+                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+                    
+                    p0->re  = d1*eterm;
+                    p0->im  = d2*eterm;
+                }
+            }
+        }
+    }
+    
+    if (bEnerVir)
+    {
+        /* Update virial with local values.
+         * The virial is symmetric by definition.
+         * this virial seems ok for isotropic scaling, but I'm
+         * experiencing problems on semiisotropic membranes.
+         * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
+         */
+        vir[XX][XX] = 0.25*virxx;
+        vir[YY][YY] = 0.25*viryy;
+        vir[ZZ][ZZ] = 0.25*virzz;
+        vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
+        vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
+        vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
+        
+        /* This energy should be corrected for a charged system */
+        *mesh_energy = 0.5*energy;
+    }
+
+    /* Return the loop count */
+    return local_ndata[YY]*local_ndata[ZZ]*local_ndata[XX];
+}
+
+
+#define DO_FSPLINE(order)                      \
+for(ithx=0; (ithx<order); ithx++)              \
+{                                                                         \
+    index_x = (i0+ithx)*pny*pnz;               \
+    tx      = thx[ithx];                       \
+    dx      = dthx[ithx];                      \
+                                               \
+    for(ithy=0; (ithy<order); ithy++)          \
+    {                                                                             \
+        index_xy = index_x+(j0+ithy)*pnz;      \
+        ty       = thy[ithy];                  \
+        dy       = dthy[ithy];                 \
+        fxy1     = fz1 = 0;                    \
+                                               \
+        for(ithz=0; (ithz<order); ithz++)      \
+        {                                                                 \
+            gval  = grid[index_xy+(k0+ithz)];  \
+            fxy1 += thz[ithz]*gval;            \
+            fz1  += dthz[ithz]*gval;           \
+        }                                      \
+        fx += dx*ty*fxy1;                      \
+        fy += tx*dy*fxy1;                      \
+        fz += tx*ty*fz1;                       \
+    }                                          \
+}
+
+
+void gather_f_bsplines(gmx_pme_t pme,real *grid,
+                       gmx_bool bClearF,pme_atomcomm_t *atc,real scale)
+{
+    /* sum forces for local particles */  
+    int     nn,n,ithx,ithy,ithz,i0,j0,k0;
+    int     index_x,index_xy;
+    int     nx,ny,nz,pnx,pny,pnz;
+    int *   idxptr;
+    real    tx,ty,dx,dy,qn;
+    real    fx,fy,fz,gval;
+    real    fxy1,fz1;
+    real    *thx,*thy,*thz,*dthx,*dthy,*dthz;
+    int     norder;
+    real    rxx,ryx,ryy,rzx,rzy,rzz;
+    int     order;
+    
+    order = pme->pme_order;
+    thx   = atc->theta[XX];
+    thy   = atc->theta[YY];
+    thz   = atc->theta[ZZ];
+    dthx  = atc->dtheta[XX];
+    dthy  = atc->dtheta[YY];
+    dthz  = atc->dtheta[ZZ];
+    nx    = pme->nkx;
+    ny    = pme->nky;
+    nz    = pme->nkz;
+    pnx   = pme->pmegrid_nx;
+    pny   = pme->pmegrid_ny;
+    pnz   = pme->pmegrid_nz;
+    
+    rxx   = pme->recipbox[XX][XX];
+    ryx   = pme->recipbox[YY][XX];
+    ryy   = pme->recipbox[YY][YY];
+    rzx   = pme->recipbox[ZZ][XX];
+    rzy   = pme->recipbox[ZZ][YY];
+    rzz   = pme->recipbox[ZZ][ZZ];
+
+    for(nn=0; (nn<atc->n); nn++) 
+    {
+        n = nn;
+        qn      = scale*atc->q[n];
+        
+        if (bClearF) 
+        {
+            atc->f[n][XX] = 0;
+            atc->f[n][YY] = 0;
+            atc->f[n][ZZ] = 0;
+        }
+        if (qn != 0) 
+        {
+            fx     = 0;
+            fy     = 0;
+            fz     = 0;
+            idxptr = atc->idx[n];
+            norder = n*order;
+            
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            
+            /* Pointer arithmetic alert, next six statements */
+            thx  = atc->theta[XX] + norder;
+            thy  = atc->theta[YY] + norder;
+            thz  = atc->theta[ZZ] + norder;
+            dthx = atc->dtheta[XX] + norder;
+            dthy = atc->dtheta[YY] + norder;
+            dthz = atc->dtheta[ZZ] + norder;
+            
+            switch (order) {
+            case 4:  DO_FSPLINE(4);     break;
+            case 5:  DO_FSPLINE(5);     break;
+            default: DO_FSPLINE(order); break;
+            }
+
+            atc->f[n][XX] += -qn*( fx*nx*rxx );
+            atc->f[n][YY] += -qn*( fx*nx*ryx + fy*ny*ryy );
+            atc->f[n][ZZ] += -qn*( fx*nx*rzx + fy*ny*rzy + fz*nz*rzz );
+        }
+    }
+    /* Since the energy and not forces are interpolated
+     * the net force might not be exactly zero.
+     * This can be solved by also interpolating F, but
+     * that comes at a cost.
+     * A better hack is to remove the net force every
+     * step, but that must be done at a higher level
+     * since this routine doesn't see all atoms if running
+     * in parallel. Don't know how important it is?  EL 990726
+     */
+}
+
+static real gather_energy_bsplines(gmx_pme_t pme,real *grid,
+                                   pme_atomcomm_t *atc)
+{
+    int     n,ithx,ithy,ithz,i0,j0,k0;
+    int     index_x,index_xy;
+    int *   idxptr;
+    real    energy,pot,tx,ty,qn,gval;
+    real    *thx,*thy,*thz;
+    int     norder;
+    int     order;
+    
+    
+    order = pme->pme_order;
+    
+    energy = 0;
+    for(n=0; (n<atc->n); n++) {
+        qn      = atc->q[n];
+        
+        if (qn != 0) {
+            idxptr = atc->idx[n];
+            norder = n*order;
+            
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            
+            /* Pointer arithmetic alert, next three statements */
+            thx  = atc->theta[XX] + norder;
+            thy  = atc->theta[YY] + norder;
+            thz  = atc->theta[ZZ] + norder;
+
+            pot = 0;
+            for(ithx=0; (ithx<order); ithx++)
+            {
+                index_x = (i0+ithx)*pme->pmegrid_ny*pme->pmegrid_nz;
+                tx      = thx[ithx];
+
+                for(ithy=0; (ithy<order); ithy++)
+                {
+                    index_xy = index_x+(j0+ithy)*pme->pmegrid_nz;
+                    ty       = thy[ithy];
+
+                    for(ithz=0; (ithz<order); ithz++)
+                    {
+                        gval  = grid[index_xy+(k0+ithz)];
+                        pot  += tx*ty*thz[ithz]*gval;
+                    }
+
+                }
+            }
+
+            energy += pot*qn;
+        }
+    }
+
+    return energy;
+}
+
+void make_bsplines(splinevec theta,splinevec dtheta,int order,
+                   rvec fractx[],int nr,real charge[],
+                   gmx_bool bFreeEnergy)
+{
+    /* construct splines for local atoms */
+    int  i,j,k,l;
+    real dr,div;
+    real *data,*ddata,*xptr;
+    
+    for(i=0; (i<nr); i++) {
+        /* With free energy we do not use the charge check.
+         * In most cases this will be more efficient than calling make_bsplines
+         * twice, since usually more than half the particles have charges.
+         */
+        if (bFreeEnergy || charge[i] != 0.0) {
+            xptr = fractx[i];
+            for(j=0; (j<DIM); j++) {
+                dr  = xptr[j];
+                
+                /* dr is relative offset from lower cell limit */
+                data=&(theta[j][i*order]);
+                data[order-1]=0;
+                data[1]=dr;
+                data[0]=1-dr;
+                
+                for(k=3; (k<order); k++) {
+                    div=1.0/(k-1.0);    
+                    data[k-1]=div*dr*data[k-2];
+                    for(l=1; (l<(k-1)); l++) {
+                        data[k-l-1]=div*((dr+l)*data[k-l-2]+(k-l-dr)*
+                                         data[k-l-1]);
+                    }
+                    data[0]=div*(1-dr)*data[0];
+                }
+                /* differentiate */
+                ddata    = &(dtheta[j][i*order]);
+                ddata[0] = -data[0];
+                for(k=1; (k<order); k++) {
+                    ddata[k]=data[k-1]-data[k];
+                }
+                
+                div=1.0/(order-1);
+                data[order-1]=div*dr*data[order-2];
+                for(l=1; (l<(order-1)); l++) {
+                    data[order-l-1]=div*((dr+l)*data[order-l-2]+
+                                         (order-l-dr)*data[order-l-1]);
+                }
+                data[0]=div*(1-dr)*data[0]; 
+            }
+        }
+    }
+}
+
+
+void make_dft_mod(real *mod,real *data,int ndata)
+{
+  int i,j;
+  real sc,ss,arg;
+    
+  for(i=0;i<ndata;i++) {
+    sc=ss=0;
+    for(j=0;j<ndata;j++) {
+      arg=(2.0*M_PI*i*j)/ndata;
+      sc+=data[j]*cos(arg);
+      ss+=data[j]*sin(arg);
+    }
+    mod[i]=sc*sc+ss*ss;
+  }
+  for(i=0;i<ndata;i++)
+    if(mod[i]<1e-7)
+      mod[i]=(mod[i-1]+mod[i+1])*0.5;
+}
+
+
+
+void make_bspline_moduli(splinevec bsp_mod,int nx,int ny,int nz,int order)
+{
+  int nmax=max(nx,max(ny,nz));
+  real *data,*ddata,*bsp_data;
+  int i,k,l;
+  real div;
+    
+  snew(data,order);
+  snew(ddata,order);
+  snew(bsp_data,nmax);
+
+  data[order-1]=0;
+  data[1]=0;
+  data[0]=1;
+           
+  for(k=3;k<order;k++) {
+    div=1.0/(k-1.0);
+    data[k-1]=0;
+    for(l=1;l<(k-1);l++)
+      data[k-l-1]=div*(l*data[k-l-2]+(k-l)*data[k-l-1]);
+    data[0]=div*data[0];
+  }
+  /* differentiate */
+  ddata[0]=-data[0];
+  for(k=1;k<order;k++)
+    ddata[k]=data[k-1]-data[k];
+  div=1.0/(order-1);
+  data[order-1]=0;
+  for(l=1;l<(order-1);l++)
+    data[order-l-1]=div*(l*data[order-l-2]+(order-l)*data[order-l-1]);
+  data[0]=div*data[0]; 
+
+  for(i=0;i<nmax;i++)
+    bsp_data[i]=0;
+  for(i=1;i<=order;i++)
+    bsp_data[i]=data[i-1];
+    
+  make_dft_mod(bsp_mod[XX],bsp_data,nx);
+  make_dft_mod(bsp_mod[YY],bsp_data,ny);
+  make_dft_mod(bsp_mod[ZZ],bsp_data,nz);
+
+  sfree(data);
+  sfree(ddata);
+  sfree(bsp_data);
+}
+
+static void setup_coordinate_communication(pme_atomcomm_t *atc)
+{
+  int nslab,n,i;
+  int fw,bw;
+
+  nslab = atc->nslab;
+
+  n = 0;
+  for(i=1; i<=nslab/2; i++) {
+    fw = (atc->nodeid + i) % nslab;
+    bw = (atc->nodeid - i + nslab) % nslab;
+    if (n < nslab - 1) {
+      atc->node_dest[n] = fw;
+      atc->node_src[n]  = bw;
+      n++;
+    } 
+    if (n < nslab - 1) {
+      atc->node_dest[n] = bw;
+      atc->node_src[n]  = fw;
+      n++;
+    }
+  }
+}
+
+int gmx_pme_destroy(FILE *log,gmx_pme_t *pmedata)
+{
+    if(NULL != log)
+    {
+        fprintf(log,"Destroying PME data structures.\n");
+    }
+
+    sfree((*pmedata)->nnx);
+    sfree((*pmedata)->nny);
+    sfree((*pmedata)->nnz);
+       
+    sfree((*pmedata)->pmegridA);
+    sfree((*pmedata)->fftgridA);
+    sfree((*pmedata)->cfftgridA);
+    gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupA);
+    
+    if((*pmedata)->pmegridB)
+    {
+        sfree((*pmedata)->pmegridB);
+        sfree((*pmedata)->fftgridB);
+        sfree((*pmedata)->cfftgridB);
+        gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupB);
+    }
+    sfree((*pmedata)->work_mhz);
+    sfree((*pmedata)->work_m2);
+    sfree((*pmedata)->work_denom);
+    sfree((*pmedata)->work_tmp1_alloc);
+    sfree((*pmedata)->work_m2inv);
+       
+    sfree(*pmedata);
+    *pmedata = NULL;
+  
+  return 0;
+}
+
+static int mult_up(int n,int f)
+{
+    return ((n + f - 1)/f)*f;
+}
+
+
+static double pme_load_imbalance(gmx_pme_t pme)
+{
+    int    nma,nmi;
+    double n1,n2,n3;
+
+    nma = pme->nnodes_major;
+    nmi = pme->nnodes_minor;
+
+    n1 = mult_up(pme->nkx,nma)*mult_up(pme->nky,nmi)*pme->nkz;
+    n2 = mult_up(pme->nkx,nma)*mult_up(pme->nkz,nmi)*pme->nky;
+    n3 = mult_up(pme->nky,nma)*mult_up(pme->nkz,nmi)*pme->nkx;
+
+    /* pme_solve is roughly double the cost of an fft */
+
+    return (n1 + n2 + 3*n3)/(double)(6*pme->nkx*pme->nky*pme->nkz);
+}
+
+static void init_atomcomm(gmx_pme_t pme,pme_atomcomm_t *atc, t_commrec *cr,
+                          int dimind,gmx_bool bSpread)
+{
+    int nk,k,s;
+
+    atc->dimind = dimind;
+    atc->nslab  = 1;
+    atc->nodeid = 0;
+    atc->pd_nalloc = 0;
+#ifdef GMX_MPI
+    if (pme->nnodes > 1)
+    {
+        atc->mpi_comm = pme->mpi_comm_d[dimind];
+        MPI_Comm_size(atc->mpi_comm,&atc->nslab);
+        MPI_Comm_rank(atc->mpi_comm,&atc->nodeid);
+    }
+    if (debug)
+    {
+        fprintf(debug,"For PME atom communication in dimind %d: nslab %d rank %d\n",atc->dimind,atc->nslab,atc->nodeid);
+    }
+#endif
+
+    atc->bSpread   = bSpread;
+    atc->pme_order = pme->pme_order;
+
+    if (atc->nslab > 1)
+    {
+        /* These three allocations are not required for particle decomp. */
+        snew(atc->node_dest,atc->nslab);
+        snew(atc->node_src,atc->nslab);
+        setup_coordinate_communication(atc);
+        
+        snew(atc->count,atc->nslab);
+        snew(atc->rcount,atc->nslab);
+        snew(atc->buf_index,atc->nslab);
+    }
+}
+
+static void 
+init_overlap_comm(pme_overlap_t *  ol,
+                  int              norder,
+#ifdef GMX_MPI
+                  MPI_Comm         comm,  
+#endif
+                  int              nnodes, 
+                  int              nodeid,
+                  int              ndata)
+{
+    int lbnd,rbnd,maxlr,b,i;
+    int exten;
+    int nn,nk;
+    pme_grid_comm_t *pgc;
+    gmx_bool bCont;
+    int fft_start,fft_end,send_index1,recv_index1;
+    
+#ifdef GMX_MPI
+    ol->mpi_comm = comm;
+#endif
+    
+    ol->nnodes = nnodes;
+    ol->nodeid = nodeid;
+
+    /* Linear translation of the PME grid wo'nt affect reciprocal space
+     * calculations, so to optimize we only interpolate "upwards",
+     * which also means we only have to consider overlap in one direction.
+     * I.e., particles on this node might also be spread to grid indices
+     * that belong to higher nodes (modulo nnodes)
+     */
+
+    snew(ol->s2g0,ol->nnodes+1);
+    snew(ol->s2g1,ol->nnodes);
+    if (debug) { fprintf(debug,"PME slab boundaries:"); }
+    for(i=0; i<nnodes; i++) 
+    {
+        /* s2g0 the local interpolation grid start.
+         * s2g1 the local interpolation grid end.
+         * Because grid overlap communication only goes forward,
+         * the grid the slabs for fft's should be rounded down.
+         */
+        ol->s2g0[i] = ( i   *ndata + 0       )/nnodes;
+        ol->s2g1[i] = ((i+1)*ndata + nnodes-1)/nnodes + norder - 1;
+
+        if (debug)
+        {
+            fprintf(debug,"  %3d %3d",ol->s2g0[i],ol->s2g1[i]);
+        }
+    }
+    ol->s2g0[nnodes] = ndata;
+    if (debug) { fprintf(debug,"\n"); }
+
+    /* Determine with how many nodes we need to communicate the grid overlap */
+    b = 0;
+    do
+    {
+        b++;
+        bCont = FALSE;
+        for(i=0; i<nnodes; i++)
+        {
+            if ((i+b <  nnodes && ol->s2g1[i] > ol->s2g0[i+b]) ||
+                (i+b >= nnodes && ol->s2g1[i] > ol->s2g0[i+b-nnodes] + ndata))
+            {
+                bCont = TRUE;
+            }
+        }
+    }
+    while (bCont && b < nnodes);
+    ol->noverlap_nodes = b - 1;
+
+    snew(ol->send_id,ol->noverlap_nodes);
+    snew(ol->recv_id,ol->noverlap_nodes);
+    for(b=0; b<ol->noverlap_nodes; b++)
+    {
+        ol->send_id[b] = (ol->nodeid + (b + 1)) % ol->nnodes;
+        ol->recv_id[b] = (ol->nodeid - (b + 1) + ol->nnodes) % ol->nnodes;
+    }
+    snew(ol->comm_data, ol->noverlap_nodes);
+
+    for(b=0; b<ol->noverlap_nodes; b++)
+    {
+        pgc = &ol->comm_data[b];
+        /* Send */
+        fft_start        = ol->s2g0[ol->send_id[b]];
+        fft_end          = ol->s2g0[ol->send_id[b]+1];
+        if (ol->send_id[b] < nodeid)
+        {
+            fft_start += ndata;
+            fft_end   += ndata;
+        }
+        send_index1      = ol->s2g1[nodeid];
+        send_index1      = min(send_index1,fft_end);
+        pgc->send_index0 = fft_start;
+        pgc->send_nindex = max(0,send_index1 - pgc->send_index0);
+
+        /* We always start receiving to the first index of our slab */
+        fft_start        = ol->s2g0[ol->nodeid];
+        fft_end          = ol->s2g0[ol->nodeid+1];
+        recv_index1      = ol->s2g1[ol->recv_id[b]];
+        if (ol->recv_id[b] > nodeid)
+        {
+            recv_index1 -= ndata;
+        }
+        recv_index1      = min(recv_index1,fft_end);
+        pgc->recv_index0 = fft_start;
+        pgc->recv_nindex = max(0,recv_index1 - pgc->recv_index0);
+    }
+}
+
+static void
+make_gridindex5_to_localindex(int n,int local_start,int local_range,
+                              int **global_to_local,
+                              real **fraction_shift)
+{
+    int i;
+    int * gtl;
+    real * fsh;
+
+    snew(gtl,5*n);
+    snew(fsh,5*n);
+    for(i=0; (i<5*n); i++)
+    {
+        /* Determine the global to local grid index */
+        gtl[i] = (i - local_start + n) % n;
+        /* For coordinates that fall within the local grid the fraction
+         * is correct, we don't need to shift it.
+         */
+        fsh[i] = 0;
+        if (local_range < n)
+        {
+            /* Due to rounding issues i could be 1 beyond the lower or
+             * upper boundary of the local grid. Correct the index for this.
+             * If we shift the index, we need to shift the fraction by
+             * the same amount in the other direction to not affect
+             * the weights.
+             * Note that due to this shifting the weights at the end of
+             * the spline might change, but that will only involve values
+             * between zero and values close to the precision of a real,
+             * which is anyhow the accuracy of the whole mesh calculation.
+             */
+            /* With local_range=0 we should not change i=local_start */
+            if (i % n != local_start)
+            {
+                if (gtl[i] == n-1)
+                {
+                    gtl[i] = 0;
+                    fsh[i] = -1; 
+                }
+                else if (gtl[i] == local_range)
+                {
+                    gtl[i] = local_range - 1;
+                    fsh[i] = 1;
+                }
+            }
+        }
+    }
+
+    *global_to_local = gtl;
+    *fraction_shift  = fsh;
+}
+
+static void
+gmx_pme_check_grid_restrictions(FILE *fplog,char dim,int nnodes,int *nk)
+{
+    int nk_new;
+
+    if (*nk % nnodes != 0)
+    {
+        nk_new = nnodes*(*nk/nnodes + 1);
+
+        if (2*nk_new >= 3*(*nk))
+        {
+            gmx_fatal(FARGS,"The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). The grid size would have to be increased by more than 50%% to make the grid divisible. Change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).",
+                      dim,*nk,dim,nnodes,dim);
+        }
+        
+        if (fplog != NULL)
+        {
+            fprintf(fplog,"\nNOTE: The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). Increasing the PME grid size in dim %c to %d. This will increase the accuracy and will not decrease the performance significantly on this number of nodes. For optimal performance change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).\n\n",
+                    dim,*nk,dim,nnodes,dim,nk_new,dim);
+        }
+            
+        *nk = nk_new;
+    }
+}
+
+int gmx_pme_init(gmx_pme_t *         pmedata,
+                 t_commrec *         cr,
+                 int                 nnodes_major,
+                 int                 nnodes_minor,
+                 t_inputrec *        ir,
+                 int                 homenr,
+                 gmx_bool                bFreeEnergy,
+                 gmx_bool                bReproducible)
+{
+    gmx_pme_t pme=NULL;
+    
+    pme_atomcomm_t *atc;
+    int bufsizex,bufsizey,bufsize;
+    ivec ndata;
+    
+    if (debug)
+        fprintf(debug,"Creating PME data structures.\n");
+    snew(pme,1);
+        
+    pme->redist_init         = FALSE;
+    pme->sum_qgrid_tmp       = NULL;
+    pme->sum_qgrid_dd_tmp    = NULL;
+    pme->buf_nalloc          = 0;
+    pme->redist_buf_nalloc   = 0;
+    
+    pme->nnodes              = 1;
+    pme->bPPnode             = TRUE;
+    
+    pme->nnodes_major        = nnodes_major;
+    pme->nnodes_minor        = nnodes_minor;
+
+#ifdef GMX_MPI
+    if (nnodes_major*nnodes_minor > 1 && PAR(cr)) 
+    {
+        pme->mpi_comm        = cr->mpi_comm_mygroup;
+        
+        MPI_Comm_rank(pme->mpi_comm,&pme->nodeid);
+        MPI_Comm_size(pme->mpi_comm,&pme->nnodes);
+        if (pme->nnodes != nnodes_major*nnodes_minor)
+        {
+            gmx_incons("PME node count mismatch");
+        }
+    }
+#endif
+
+    if (pme->nnodes == 1)
+    {
+        pme->ndecompdim = 0;
+        pme->nodeid_major = 0;
+        pme->nodeid_minor = 0;
+    }
+    else
+    {
+        if (nnodes_minor == 1)
+        {
+#ifdef GMX_MPI
+            pme->mpi_comm_d[0] = pme->mpi_comm;
+            pme->mpi_comm_d[1] = NULL;
+#endif
+            pme->ndecompdim = 1;
+            pme->nodeid_major = pme->nodeid;
+            pme->nodeid_minor = 0;
+            
+        }
+        else if (nnodes_major == 1)
+        {
+#ifdef GMX_MPI
+            pme->mpi_comm_d[0] = NULL;
+            pme->mpi_comm_d[1] = pme->mpi_comm;
+#endif
+            pme->ndecompdim = 1;
+            pme->nodeid_major = 0;
+            pme->nodeid_minor = pme->nodeid;
+        }
+        else 
+        {
+            if (pme->nnodes % nnodes_major != 0)
+            {
+                gmx_incons("For 2D PME decomposition, #PME nodes must be divisible by the number of nodes in the major dimension");
+            }
+            pme->ndecompdim = 2;
+            
+#ifdef GMX_MPI
+            MPI_Comm_split(pme->mpi_comm,pme->nodeid % nnodes_minor,
+                           pme->nodeid,&pme->mpi_comm_d[0]);  /* My communicator along major dimension */
+            MPI_Comm_split(pme->mpi_comm,pme->nodeid/nnodes_minor,
+                           pme->nodeid,&pme->mpi_comm_d[1]);  /* My communicator along minor dimension */
+            
+            MPI_Comm_rank(pme->mpi_comm_d[0],&pme->nodeid_major);
+            MPI_Comm_size(pme->mpi_comm_d[0],&pme->nnodes_major);
+            MPI_Comm_rank(pme->mpi_comm_d[1],&pme->nodeid_minor);
+            MPI_Comm_size(pme->mpi_comm_d[1],&pme->nnodes_minor);
+#endif
+        }
+        pme->bPPnode = (cr->duty & DUTY_PP);
+    }
+    
+    if (ir->ePBC == epbcSCREW)
+    {
+        gmx_fatal(FARGS,"pme does not (yet) work with pbc = screw");
+    }
+    
+    pme->bFEP        = ((ir->efep != efepNO) && bFreeEnergy);
+    pme->nkx         = ir->nkx;
+    pme->nky         = ir->nky;
+    pme->nkz         = ir->nkz;
+    pme->pme_order   = ir->pme_order;
+    pme->epsilon_r   = ir->epsilon_r;
+    
+    /* Currently pme.c supports only the fft5d FFT code.
+     * Therefore the grid always needs to be divisible by nnodes.
+     * When the old 1D code is also supported again, change this check.
+     *
+     * This check should be done before calling gmx_pme_init
+     * and fplog should be passed iso stderr.
+     *
+    if (pme->ndecompdim >= 2)
+    */
+    if (pme->ndecompdim >= 1)
+    {
+        /*
+        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+                                        'x',nnodes_major,&pme->nkx);
+        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+                                        'y',nnodes_minor,&pme->nky);
+        */
+    }
+
+    if (pme->nkx <= pme->pme_order*(pme->nnodes_major > 1 ? 2 : 1) ||
+        pme->nky <= pme->pme_order*(pme->nnodes_minor > 1 ? 2 : 1) ||
+        pme->nkz <= pme->pme_order)
+    {
+        gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_order for x and/or y",pme->pme_order);
+    }
+
+    if (pme->nnodes > 1) {
+        double imbal;
+
+#ifdef GMX_MPI
+        MPI_Type_contiguous(DIM, mpi_type, &(pme->rvec_mpi));
+        MPI_Type_commit(&(pme->rvec_mpi));
+#endif
+        
+        /* Note that the charge spreading and force gathering, which usually
+         * takes about the same amount of time as FFT+solve_pme,
+         * is always fully load balanced
+         * (unless the charge distribution is inhomogeneous).
+         */
+        
+        imbal = pme_load_imbalance(pme);
+        if (imbal >= 1.2 && pme->nodeid_major == 0 && pme->nodeid_minor == 0)
+        {
+            fprintf(stderr,
+                    "\n"
+                    "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
+                    "      For optimal PME load balancing\n"
+                    "      PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes_x (%d)\n"
+                    "      and PME grid_y (%d) and grid_z (%d) should be divisible by #PME_nodes_y (%d)\n"
+                    "\n",
+                    (int)((imbal-1)*100 + 0.5),
+                    pme->nkx,pme->nky,pme->nnodes_major,
+                    pme->nky,pme->nkz,pme->nnodes_minor);
+        }
+    }
+
+    init_overlap_comm(&pme->overlap[0],pme->pme_order,
+#ifdef GMX_MPI
+                      pme->mpi_comm_d[0],
+#endif
+                      pme->nnodes_major,pme->nodeid_major,pme->nkx);
+    
+    init_overlap_comm(&pme->overlap[1],pme->pme_order,
+#ifdef GMX_MPI
+                      pme->mpi_comm_d[1],
+#endif
+                      pme->nnodes_minor,pme->nodeid_minor,pme->nky);
+    
+    snew(pme->bsp_mod[XX],pme->nkx);
+    snew(pme->bsp_mod[YY],pme->nky);
+    snew(pme->bsp_mod[ZZ],pme->nkz);
+    
+    /* Allocate data for the interpolation grid, including overlap */
+    pme->pmegrid_nx = pme->overlap[0].s2g1[pme->nodeid_major] -
+                      pme->overlap[0].s2g0[pme->nodeid_major];
+    pme->pmegrid_ny = pme->overlap[1].s2g1[pme->nodeid_minor] - 
+                      pme->overlap[1].s2g0[pme->nodeid_minor];
+    pme->pmegrid_nz = pme->nkz + pme->pme_order - 1;
+    
+    pme->pmegrid_start_ix = pme->overlap[0].s2g0[pme->nodeid_major];
+    pme->pmegrid_start_iy = pme->overlap[1].s2g0[pme->nodeid_minor];
+    pme->pmegrid_start_iz = 0;
+    
+    make_gridindex5_to_localindex(pme->nkx,
+                                  pme->pmegrid_start_ix,
+                                  pme->pmegrid_nx - (pme->pme_order-1),
+                                  &pme->nnx,&pme->fshx);
+    make_gridindex5_to_localindex(pme->nky,
+                                  pme->pmegrid_start_iy,
+                                  pme->pmegrid_ny - (pme->pme_order-1),
+                                  &pme->nny,&pme->fshy);
+    make_gridindex5_to_localindex(pme->nkz,
+                                  pme->pmegrid_start_iz,
+                                  pme->pmegrid_nz - (pme->pme_order-1),
+                                  &pme->nnz,&pme->fshz);
+    
+    snew(pme->pmegridA,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);
+    
+    /* For non-divisible grid we need pme_order iso pme_order-1 */
+    /* x overlap is copied in place: take padding into account.
+     * y is always copied through a buffer: we don't need padding in z,
+     * but we do need the overlap in x because of the communication order.
+     */
+    bufsizex = pme->pme_order*pme->pmegrid_ny*pme->pmegrid_nz;
+    bufsizey = pme->pme_order*pme->pmegrid_nx*pme->nkz;
+    bufsize  = (bufsizex>bufsizey) ? bufsizex : bufsizey;
+    
+    snew(pme->pmegrid_sendbuf,bufsize);
+    snew(pme->pmegrid_recvbuf,bufsize);
+    
+    ndata[0] = pme->nkx;
+    ndata[1] = pme->nky;
+    ndata[2] = pme->nkz;
+    
+    /* This routine will allocate the grid data to fit the FFTs */
+    gmx_parallel_3dfft_init(&pme->pfft_setupA,ndata,
+                            &pme->fftgridA,&pme->cfftgridA,
+                            pme->mpi_comm_d,
+                            pme->overlap[0].s2g0,pme->overlap[1].s2g0,
+                            bReproducible);
+    
+    if (bFreeEnergy)
+    {
+        snew(pme->pmegridB,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);    
+        gmx_parallel_3dfft_init(&pme->pfft_setupB,ndata,
+                                &pme->fftgridB,&pme->cfftgridB,
+                                pme->mpi_comm_d,
+                                pme->overlap[0].s2g0,pme->overlap[1].s2g0,
+                                bReproducible);
+    } else 
+    {
+        pme->pmegridB    = NULL;
+        pme->fftgridB    = NULL;
+        pme->cfftgridB   = NULL;
+    }
+    
+    make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
+    
+    /* Use atc[0] for spreading */
+    init_atomcomm(pme,&pme->atc[0],cr,nnodes_major > 1 ? 0 : 1,TRUE);
+    if (pme->ndecompdim >= 2)
+    {
+        init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
+    }
+    
+    if (pme->nnodes == 1) {
+        pme->atc[0].n = homenr;
+        pme_realloc_atomcomm_things(&pme->atc[0]);
+    }
+    
+    /* Use fft5d, order after FFT is y major, z, x minor */
+    pme->work_nalloc = pme->nkx;
+    snew(pme->work_mhx,pme->work_nalloc);
+    snew(pme->work_mhy,pme->work_nalloc);
+    snew(pme->work_mhz,pme->work_nalloc);
+    snew(pme->work_m2,pme->work_nalloc);
+    snew(pme->work_denom,pme->work_nalloc);
+    /* Allocate an aligned pointer for SSE operations, including 3 extra
+     * elements at the end since SSE operates on 4 elements at a time.
+     */
+    snew(pme->work_tmp1_alloc,pme->work_nalloc+8);
+    pme->work_tmp1 = (real *) (((size_t) pme->work_tmp1_alloc + 16) & (~((size_t) 15)));
+    snew(pme->work_m2inv,pme->work_nalloc);
+
+    *pmedata = pme;
+    
+    return 0;
+}
+
+static void spread_on_grid(gmx_pme_t pme,
+                           pme_atomcomm_t *atc,real *grid,
+                           gmx_bool bCalcSplines,gmx_bool bSpread)
+{    
+    if (bCalcSplines)
+    {
+    
+        /* Compute fftgrid index for all atoms,
+         * with help of some extra variables.
+         */
+        calc_interpolation_idx(pme,atc);
+        
+        /* make local bsplines  */
+        make_bsplines(atc->theta,atc->dtheta,pme->pme_order,
+                      atc->fractx,atc->n,atc->q,pme->bFEP);
+    }    
+    
+    if (bSpread)
+    {
+        /* put local atoms on grid. */
+        spread_q_bsplines(pme,atc,grid);
+    }
+}
+
+void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V)
+{
+    pme_atomcomm_t *atc;
+    real *grid;
+
+    if (pme->nnodes > 1)
+    {
+        gmx_incons("gmx_pme_calc_energy called in parallel");
+    }
+    if (pme->bFEP > 1)
+    {
+        gmx_incons("gmx_pme_calc_energy with free energy");
+    }
+
+    atc = &pme->atc_energy;
+    atc->nslab     = 1;
+    atc->bSpread   = TRUE;
+    atc->pme_order = pme->pme_order;
+    atc->n         = n;
+    pme_realloc_atomcomm_things(atc);
+    atc->x         = x;
+    atc->q         = q;
+    
+    /* We only use the A-charges grid */
+    grid = pme->pmegridA;
+
+    spread_on_grid(pme,atc,NULL,TRUE,FALSE);
+
+    *V = gather_energy_bsplines(pme,grid,atc);
+}
+
+
+static void reset_pmeonly_counters(t_commrec *cr,gmx_wallcycle_t wcycle,
+        t_nrnb *nrnb,t_inputrec *ir, gmx_large_int_t step_rel)
+{
+    /* Reset all the counters related to performance over the run */
+    wallcycle_stop(wcycle,ewcRUN);
+    wallcycle_reset_all(wcycle);
+    init_nrnb(nrnb);
+    ir->init_step += step_rel;
+    ir->nsteps    -= step_rel;
+    wallcycle_start(wcycle,ewcRUN);
+}
+
+
+int gmx_pmeonly(gmx_pme_t pme,
+                t_commrec *cr,    t_nrnb *nrnb,
+                gmx_wallcycle_t wcycle,
+                real ewaldcoeff,  gmx_bool bGatherOnly,
+                t_inputrec *ir)
+{
+    gmx_pme_pp_t pme_pp;
+    int  natoms;
+    matrix box;
+    rvec *x_pp=NULL,*f_pp=NULL;
+    real *chargeA=NULL,*chargeB=NULL;
+    real lambda=0;
+    int  maxshift_x=0,maxshift_y=0;
+    real energy,dvdlambda;
+    matrix vir;
+    float cycles;
+    int  count;
+    gmx_bool bEnerVir;
+    gmx_large_int_t step,step_rel;
+    
+    
+    pme_pp = gmx_pme_pp_init(cr);
+    
+    init_nrnb(nrnb);
+    
+    count = 0;
+    do /****** this is a quasi-loop over time steps! */
+    {
+        /* Domain decomposition */
+        natoms = gmx_pme_recv_q_x(pme_pp,
+                                  &chargeA,&chargeB,box,&x_pp,&f_pp,
+                                  &maxshift_x,&maxshift_y,
+                                  &pme->bFEP,&lambda,
+                                  &bEnerVir,
+                                  &step);
+        
+        if (natoms == -1) {
+            /* We should stop: break out of the loop */
+            break;
+        }
+        
+        step_rel = step - ir->init_step;
+        
+        if (count == 0)
+            wallcycle_start(wcycle,ewcRUN);
+        
+        wallcycle_start(wcycle,ewcPMEMESH);
+        
+        dvdlambda = 0;
+        clear_mat(vir);
+        gmx_pme_do(pme,0,natoms,x_pp,f_pp,chargeA,chargeB,box,
+                   cr,maxshift_x,maxshift_y,nrnb,wcycle,vir,ewaldcoeff,
+                   &energy,lambda,&dvdlambda,
+                   GMX_PME_DO_ALL_F | (bEnerVir ? GMX_PME_CALC_ENER_VIR : 0));
+        
+        cycles = wallcycle_stop(wcycle,ewcPMEMESH);
+        
+        gmx_pme_send_force_vir_ener(pme_pp,
+                                    f_pp,vir,energy,dvdlambda,
+                                    cycles);
+        
+        count++;
+
+        if (step_rel == wcycle_get_reset_counters(wcycle))
+        {
+            /* Reset all the counters related to performance over the run */
+            reset_pmeonly_counters(cr,wcycle,nrnb,ir,step_rel);
+            wcycle_set_reset_counters(wcycle, 0);
+        }
+        
+    } /***** end of quasi-loop, we stop with the break above */
+    while (TRUE);
+    
+    return 0;
+}
+
+int gmx_pme_do(gmx_pme_t pme,
+               int start,       int homenr,
+               rvec x[],        rvec f[],
+               real *chargeA,   real *chargeB,
+               matrix box,     t_commrec *cr,
+               int  maxshift_x, int maxshift_y,
+               t_nrnb *nrnb,    gmx_wallcycle_t wcycle,
+               matrix vir,      real ewaldcoeff,
+               real *energy,    real lambda, 
+               real *dvdlambda, int flags)
+{
+    int     q,d,i,j,ntot,npme;
+    int     nx,ny,nz;
+    int     n_d,local_ny;
+    int     loop_count;
+    pme_atomcomm_t *atc=NULL;
+    real *  grid=NULL;
+    real    *ptr;
+    rvec    *x_d,*f_d;
+    real    *charge=NULL,*q_d,vol;
+    real    energy_AB[2];
+    matrix  vir_AB[2];
+    gmx_bool    bClearF;
+    gmx_parallel_3dfft_t pfft_setup;
+    real *  fftgrid;
+    t_complex * cfftgrid;
+
+    if (pme->nnodes > 1) {
+        atc = &pme->atc[0];
+        atc->npd = homenr;
+        if (atc->npd > atc->pd_nalloc) {
+            atc->pd_nalloc = over_alloc_dd(atc->npd);
+            srenew(atc->pd,atc->pd_nalloc);
+        }
+        atc->maxshift = (atc->dimind==0 ? maxshift_x : maxshift_y);
+    }
+    else
+    {
+        /* This could be necessary for TPI */
+        pme->atc[0].n = homenr;
+    }
+    
+    for(q=0; q<(pme->bFEP ? 2 : 1); q++) {
+        if (q == 0) {
+            grid = pme->pmegridA;
+            fftgrid = pme->fftgridA;
+            cfftgrid = pme->cfftgridA;
+            pfft_setup = pme->pfft_setupA;
+            charge = chargeA+start;
+        } else {
+            grid = pme->pmegridB;
+            fftgrid = pme->fftgridB;
+            cfftgrid = pme->cfftgridB;
+            pfft_setup = pme->pfft_setupB;
+            charge = chargeB+start;
+        }
+        /* Unpack structure */
+        if (debug) {
+            fprintf(debug,"PME: nnodes = %d, nodeid = %d\n",
+                    cr->nnodes,cr->nodeid);
+            fprintf(debug,"Grid = %p\n",(void*)grid);
+            if (grid == NULL)
+                gmx_fatal(FARGS,"No grid!");
+        }
+        where();
+        
+        m_inv_ur0(box,pme->recipbox); 
+
+        if (pme->nnodes == 1) {
+            atc = &pme->atc[0];
+            if (DOMAINDECOMP(cr)) {
+                atc->n = homenr;
+                pme_realloc_atomcomm_things(atc);
+            }
+            atc->x = x;
+            atc->q = charge;
+            atc->f = f;
+        } else {
+            wallcycle_start(wcycle,ewcPME_REDISTXF);
+            for(d=pme->ndecompdim-1; d>=0; d--)
+            {
+                if (d == pme->ndecompdim-1)
+                {
+                    n_d = homenr;
+                    x_d = x + start;
+                    q_d = charge;
+                }
+                else
+                {
+                    n_d = pme->atc[d+1].n;
+                    x_d = atc->x;
+                    q_d = atc->q;
+                }
+                atc = &pme->atc[d];
+                atc->npd = n_d;
+                if (atc->npd > atc->pd_nalloc) {
+                    atc->pd_nalloc = over_alloc_dd(atc->npd);
+                    srenew(atc->pd,atc->pd_nalloc);
+                }
+                atc->maxshift = (atc->dimind==0 ? maxshift_x : maxshift_y);
+                pme_calc_pidx(n_d,pme->recipbox,x_d,atc);
+                where();
+                
+                /* Redistribute x (only once) and qA or qB */
+                if (DOMAINDECOMP(cr)) {
+                    dd_pmeredist_x_q(pme, n_d, q==0, x_d, q_d, atc);
+                } else {
+                    pmeredist_pd(pme, TRUE, n_d, q==0, x_d, q_d, atc);
+                }
+            }
+            where();
+
+            wallcycle_stop(wcycle,ewcPME_REDISTXF);
+        }
+        
+        if (debug)
+            fprintf(debug,"Node= %6d, pme local particles=%6d\n",
+                    cr->nodeid,atc->n);
+
+        if (flags & GMX_PME_SPREAD_Q)
+        {
+            wallcycle_start(wcycle,ewcPME_SPREADGATHER);
+
+            /* Spread the charges on a grid */
+            spread_on_grid(pme,&pme->atc[0],grid,q==0,TRUE);
+
+            if (q == 0)
+            {
+                inc_nrnb(nrnb,eNR_WEIGHTS,DIM*atc->n);
+            }
+            inc_nrnb(nrnb,eNR_SPREADQBSP,
+                     pme->pme_order*pme->pme_order*pme->pme_order*atc->n);
+
+            wrap_periodic_pmegrid(pme,grid);
+
+            /* sum contributions to local grid from other nodes */
+#ifdef GMX_MPI
+            if (pme->nnodes > 1) {
+                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_FORWARD);
+                where();
+            }
+#endif
+            where();
+
+            copy_pmegrid_to_fftgrid(pme,grid,fftgrid);
+
+            wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
+        }
+         
+        if (flags & GMX_PME_SOLVE)
+        {
+            /* do 3d-fft */ 
+            wallcycle_start(wcycle,ewcPME_FFT);
+            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_REAL_TO_COMPLEX,fftgrid,cfftgrid);
+            wallcycle_stop(wcycle,ewcPME_FFT);
+            where();
+            
+            /* solve in k-space for our local cells */
+            vol = det(box);
+            wallcycle_start(wcycle,ewcPME_SOLVE);
+            loop_count =
+                solve_pme_yzx(pme,cfftgrid,ewaldcoeff,vol,
+                              flags & GMX_PME_CALC_ENER_VIR,
+                              &energy_AB[q],vir_AB[q]);
+            wallcycle_stop(wcycle,ewcPME_SOLVE);
+            where();
+            inc_nrnb(nrnb,eNR_SOLVEPME,loop_count);
+        }
+
+        if ((flags & GMX_PME_CALC_F) ||
+            (flags & GMX_PME_CALC_POT))
+        {
+            
+            /* do 3d-invfft */
+            where();
+            wallcycle_start(wcycle,ewcPME_FFT);
+            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_COMPLEX_TO_REAL,cfftgrid,fftgrid);
+            wallcycle_stop(wcycle,ewcPME_FFT);
+
+            where();
+
+            if (pme->nodeid == 0)
+            {
+                ntot = pme->nkx*pme->nky*pme->nkz;
+                npme  = ntot*log((real)ntot)/log(2.0);
+                inc_nrnb(nrnb,eNR_FFT,2*npme);
+            }
+
+            wallcycle_start(wcycle,ewcPME_SPREADGATHER);
+
+            copy_fftgrid_to_pmegrid(pme,fftgrid,grid);
+
+            /* distribute local grid to all nodes */
+#ifdef GMX_MPI
+            if (pme->nnodes > 1) {
+                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_BACKWARD);
+            }
+#endif
+            where();
+
+            unwrap_periodic_pmegrid(pme,grid);
+        }
+
+        if (flags & GMX_PME_CALC_F)
+        {
+            /* interpolate forces for our local atoms */
+
+            where();
+            
+            /* If we are running without parallelization,
+             * atc->f is the actual force array, not a buffer,
+             * therefore we should not clear it.
+             */
+            bClearF = (q == 0 && PAR(cr));
+            gather_f_bsplines(pme,grid,bClearF,&pme->atc[0],
+                              pme->bFEP ? (q==0 ? 1.0-lambda : lambda) : 1.0);
+            where();
+
+            inc_nrnb(nrnb,eNR_GATHERFBSP,
+                     pme->pme_order*pme->pme_order*pme->pme_order*pme->atc[0].n);
+            wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
+       }
+    } /* of q-loop */
+    
+    if ((flags & GMX_PME_CALC_F) && pme->nnodes > 1) {
+        wallcycle_start(wcycle,ewcPME_REDISTXF);
+        for(d=0; d<pme->ndecompdim; d++)
+        {
+            atc = &pme->atc[d];
+            if (d == pme->ndecompdim - 1)
+            {
+                n_d = homenr;
+                f_d = f + start;
+            }
+            else
+            {
+                n_d = pme->atc[d+1].n;
+                f_d = pme->atc[d+1].f;
+            }
+            if (DOMAINDECOMP(cr)) {
+                dd_pmeredist_f(pme,atc,n_d,f_d,
+                               d==pme->ndecompdim-1 && pme->bPPnode);
+            } else {
+                pmeredist_pd(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
+            }
+        }
+
+        wallcycle_stop(wcycle,ewcPME_REDISTXF);
+    }
+    where();
+    
+    if (!pme->bFEP) {
+        *energy = energy_AB[0];
+        m_add(vir,vir_AB[0],vir);
+    } else {
+        *energy = (1.0-lambda)*energy_AB[0] + lambda*energy_AB[1];
+        *dvdlambda += energy_AB[1] - energy_AB[0];
+        for(i=0; i<DIM; i++)
+            for(j=0; j<DIM; j++)
+                vir[i][j] += (1.0-lambda)*vir_AB[0][i][j] + lambda*vir_AB[1][i][j];
+    }
+
+    if (debug)
+        fprintf(debug,"PME mesh energy: %g\n",*energy);
+    
+    return 0;
+}
diff --git a/src/gromacs/mdlib/pme_pp.c b/src/gromacs/mdlib/pme_pp.c
new file mode 100644 (file)
index 0000000..bb4771f
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "gmx_fatal.h"
+#include "vec.h"
+#include "pme.h"
+#include "network.h"
+#include "domdec.h"
+#include "sighandler.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#define PP_PME_CHARGE   (1<<0)
+#define PP_PME_CHARGEB  (1<<1)
+#define PP_PME_COORD    (1<<2)
+#define PP_PME_FEP      (1<<3)
+#define PP_PME_ENER_VIR (1<<4)
+#define PP_PME_FINISH   (1<<5)
+
+#define PME_PP_SIGSTOP     (1<<0)
+#define PME_PP_SIGSTOPNSS     (1<<1)
+
+typedef struct gmx_pme_pp {
+#ifdef GMX_MPI
+  MPI_Comm mpi_comm_mysim;
+#endif
+  int  nnode;        /* The number of PP node to communicate with  */
+  int  *node;        /* The PP node ranks                          */
+  int  node_peer;    /* The peer PP node rank                      */
+  int  *nat;         /* The number of atom for each PP node        */
+  int  flags_charge; /* The flags sent along with the last charges */
+  real *chargeA;
+  real *chargeB;
+  rvec *x;
+  rvec *f;
+  int  nalloc;
+#ifdef GMX_MPI
+  MPI_Request *req;
+  MPI_Status  *stat;
+#endif
+} t_gmx_pme_pp;
+
+typedef struct gmx_pme_comm_n_box {
+  int    natoms;
+  matrix box;
+  int    maxshift_x;
+  int    maxshift_y;
+  real   lambda;
+  int    flags;
+  gmx_large_int_t step;
+} gmx_pme_comm_n_box_t;
+
+typedef struct {
+  matrix vir;
+  real   energy;
+  real   dvdlambda;
+  float  cycles;
+  gmx_stop_cond_t stop_cond;
+} gmx_pme_comm_vir_ene_t;
+
+
+
+
+gmx_pme_pp_t gmx_pme_pp_init(t_commrec *cr)
+{
+  struct gmx_pme_pp *pme_pp;
+  int rank;
+
+  snew(pme_pp,1);
+
+#ifdef GMX_MPI
+  pme_pp->mpi_comm_mysim = cr->mpi_comm_mysim;
+  MPI_Comm_rank(cr->mpi_comm_mygroup,&rank);
+  get_pme_ddnodes(cr,rank,&pme_pp->nnode,&pme_pp->node,&pme_pp->node_peer);
+  snew(pme_pp->nat,pme_pp->nnode);
+  snew(pme_pp->req,2*pme_pp->nnode);
+  snew(pme_pp->stat,2*pme_pp->nnode);
+  pme_pp->nalloc = 0;
+  pme_pp->flags_charge = 0;
+#endif
+
+  return pme_pp;
+}
+
+/* This should be faster with a real non-blocking MPI implementation */
+/* #define GMX_PME_DELAYED_WAIT */
+
+static void gmx_pme_send_q_x_wait(gmx_domdec_t *dd)
+{
+#ifdef GMX_MPI
+  if (dd->nreq_pme) {
+    MPI_Waitall(dd->nreq_pme,dd->req_pme,MPI_STATUSES_IGNORE);
+    dd->nreq_pme = 0;
+  }
+#endif
+}
+
+static void gmx_pme_send_q_x(t_commrec *cr, int flags,
+                            real *chargeA, real *chargeB,
+                            matrix box, rvec *x,
+                            real lambda,
+                            int maxshift_x, int maxshift_y,
+                            gmx_large_int_t step)
+{
+  gmx_domdec_t *dd;
+  gmx_pme_comm_n_box_t *cnb;
+  int  n;
+
+  dd = cr->dd;
+  n = dd->nat_home;
+
+  if (debug)
+    fprintf(debug,"PP node %d sending to PME node %d: %d%s%s\n",
+           cr->sim_nodeid,dd->pme_nodeid,n,
+           flags & PP_PME_CHARGE ? " charges" : "",
+           flags & PP_PME_COORD  ? " coordinates" : "");
+
+#ifdef GMX_PME_DELAYED_WAIT
+  /* When can not use cnb until pending communication has finished */
+  gmx_pme_send_x_q_wait(dd);
+#endif
+
+  if (dd->pme_receive_vir_ener) {
+    /* Peer PP node: communicate all data */
+    if (dd->cnb == NULL)
+      snew(dd->cnb,1);
+    cnb = dd->cnb;
+
+    cnb->flags      = flags;
+    cnb->natoms     = n;
+    cnb->maxshift_x = maxshift_x;
+    cnb->maxshift_y = maxshift_y;
+    cnb->lambda     = lambda;
+    cnb->step       = step;
+    if (flags & PP_PME_COORD)
+      copy_mat(box,cnb->box);
+#ifdef GMX_MPI
+    MPI_Isend(cnb,sizeof(*cnb),MPI_BYTE,
+             dd->pme_nodeid,0,cr->mpi_comm_mysim,
+             &dd->req_pme[dd->nreq_pme++]);
+#endif
+  } else if (flags & PP_PME_CHARGE) {
+#ifdef GMX_MPI
+    /* Communicate only the number of atoms */
+    MPI_Isend(&n,sizeof(n),MPI_BYTE,
+             dd->pme_nodeid,0,cr->mpi_comm_mysim,
+             &dd->req_pme[dd->nreq_pme++]);
+#endif
+  }
+
+#ifdef GMX_MPI
+  if (n > 0) {
+    if (flags & PP_PME_CHARGE) {
+      MPI_Isend(chargeA,n*sizeof(real),MPI_BYTE,
+               dd->pme_nodeid,1,cr->mpi_comm_mysim,
+               &dd->req_pme[dd->nreq_pme++]);
+    }
+    if (flags & PP_PME_CHARGEB) {
+      MPI_Isend(chargeB,n*sizeof(real),MPI_BYTE,
+               dd->pme_nodeid,2,cr->mpi_comm_mysim,
+               &dd->req_pme[dd->nreq_pme++]);
+    }
+    if (flags & PP_PME_COORD) {
+      MPI_Isend(x[0],n*sizeof(rvec),MPI_BYTE,
+               dd->pme_nodeid,3,cr->mpi_comm_mysim,
+               &dd->req_pme[dd->nreq_pme++]);
+    }
+  }
+
+#ifndef GMX_PME_DELAYED_WAIT
+  /* Wait for the data to arrive */
+  /* We can skip this wait as we are sure x and q will not be modified
+   * before the next call to gmx_pme_send_x_q or gmx_pme_receive_f.
+   */
+  gmx_pme_send_q_x_wait(dd);
+#endif
+#endif
+}
+
+void gmx_pme_send_q(t_commrec *cr,
+                   gmx_bool bFreeEnergy, real *chargeA, real *chargeB,
+                   int maxshift_x, int maxshift_y)
+{
+  int flags;
+
+  flags = PP_PME_CHARGE;
+  if (bFreeEnergy)
+    flags |= PP_PME_CHARGEB;
+
+  gmx_pme_send_q_x(cr,flags,
+                  chargeA,chargeB,NULL,NULL,0,maxshift_x,maxshift_y,-1);
+}
+
+void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
+                   gmx_bool bFreeEnergy, real lambda,
+                   gmx_bool bEnerVir,
+                   gmx_large_int_t step)
+{
+  int flags;
+  
+  flags = PP_PME_COORD;
+  if (bFreeEnergy)
+    flags |= PP_PME_FEP;
+  if (bEnerVir)
+    flags |= PP_PME_ENER_VIR;
+
+  gmx_pme_send_q_x(cr,flags,NULL,NULL,box,x,lambda,0,0,step);
+}
+
+void gmx_pme_finish(t_commrec *cr)
+{
+  int flags;
+
+  flags = PP_PME_FINISH;
+
+  gmx_pme_send_q_x(cr,flags,NULL,NULL,NULL,NULL,0,0,0,-1);
+}
+
+int gmx_pme_recv_q_x(struct gmx_pme_pp *pme_pp,
+                     real **chargeA, real **chargeB,
+                     matrix box, rvec **x,rvec **f,
+                     int *maxshift_x, int *maxshift_y,
+                     gmx_bool *bFreeEnergy,real *lambda,
+                    gmx_bool *bEnerVir,
+                     gmx_large_int_t *step)
+{
+    gmx_pme_comm_n_box_t cnb;
+    int  nat=0,q,messages,sender;
+    real *charge_pp;
+
+    messages = 0;
+
+    /* avoid compiler warning about unused variable without MPI support */
+    cnb.flags = 0;     
+#ifdef GMX_MPI
+    do {
+        /* Receive the send count, box and time step from the peer PP node */
+        MPI_Recv(&cnb,sizeof(cnb),MPI_BYTE,
+                 pme_pp->node_peer,0,
+                 pme_pp->mpi_comm_mysim,MPI_STATUS_IGNORE);
+
+        if (debug)
+            fprintf(debug,"PME only node receiving:%s%s%s\n",
+                    (cnb.flags & PP_PME_CHARGE) ? " charges" : "",
+                        (cnb.flags & PP_PME_COORD ) ? " coordinates" : "",
+                            (cnb.flags & PP_PME_FINISH) ? " finish" : "");
+
+        if (cnb.flags & PP_PME_CHARGE) {
+            /* Receive the send counts from the other PP nodes */
+            for(sender=0; sender<pme_pp->nnode; sender++) {
+                if (pme_pp->node[sender] == pme_pp->node_peer) {
+                    pme_pp->nat[sender] = cnb.natoms;
+                } else {
+                    MPI_Irecv(&(pme_pp->nat[sender]),sizeof(pme_pp->nat[0]),
+                              MPI_BYTE,
+                              pme_pp->node[sender],0,
+                              pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
+                }
+            }
+            MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
+            messages = 0;
+
+            nat = 0;
+            for(sender=0; sender<pme_pp->nnode; sender++)
+                nat += pme_pp->nat[sender];
+
+            if (nat > pme_pp->nalloc) {
+                pme_pp->nalloc = over_alloc_dd(nat);
+                srenew(pme_pp->chargeA,pme_pp->nalloc);
+                if (cnb.flags & PP_PME_CHARGEB)
+                    srenew(pme_pp->chargeB,pme_pp->nalloc);
+                srenew(pme_pp->x,pme_pp->nalloc);
+                srenew(pme_pp->f,pme_pp->nalloc);
+            }
+
+            /* maxshift is sent when the charges are sent */
+            *maxshift_x = cnb.maxshift_x;
+            *maxshift_y = cnb.maxshift_y;
+
+            /* Receive the charges in place */
+            for(q=0; q<((cnb.flags & PP_PME_CHARGEB) ? 2 : 1); q++) {
+                if (q == 0)
+                    charge_pp = pme_pp->chargeA;
+                else
+                    charge_pp = pme_pp->chargeB;
+                nat = 0;
+                for(sender=0; sender<pme_pp->nnode; sender++) {
+                    if (pme_pp->nat[sender] > 0) {
+                        MPI_Irecv(charge_pp+nat,
+                                  pme_pp->nat[sender]*sizeof(real),
+                                  MPI_BYTE,
+                                  pme_pp->node[sender],1+q,
+                                  pme_pp->mpi_comm_mysim,
+                                  &pme_pp->req[messages++]);
+                        nat += pme_pp->nat[sender];
+                        if (debug)
+                            fprintf(debug,"Received from PP node %d: %d "
+                                "charges\n",
+                                    pme_pp->node[sender],pme_pp->nat[sender]);
+                    }
+                }
+            }
+
+            pme_pp->flags_charge = cnb.flags;
+        }
+
+        if (cnb.flags & PP_PME_COORD) {
+            if (!(pme_pp->flags_charge & PP_PME_CHARGE))
+                gmx_incons("PME-only node received coordinates before charges"
+                    );
+
+            /* The box, FE flag and lambda are sent along with the coordinates
+             *  */
+            copy_mat(cnb.box,box);
+            *bFreeEnergy = (cnb.flags & PP_PME_FEP);
+            *lambda      = cnb.lambda;
+           *bEnerVir    = (cnb.flags & PP_PME_ENER_VIR);
+
+            if (*bFreeEnergy && !(pme_pp->flags_charge & PP_PME_CHARGEB))
+                gmx_incons("PME-only node received free energy request, but "
+                    "did not receive B-state charges");
+
+            /* Receive the coordinates in place */
+            nat = 0;
+            for(sender=0; sender<pme_pp->nnode; sender++) {
+                if (pme_pp->nat[sender] > 0) {
+                    MPI_Irecv(pme_pp->x[nat],pme_pp->nat[sender]*sizeof(rvec),
+                              MPI_BYTE,
+                              pme_pp->node[sender],3,
+                              pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
+                    nat += pme_pp->nat[sender];
+                    if (debug)
+                        fprintf(debug,"Received from PP node %d: %d "
+                            "coordinates\n",
+                                pme_pp->node[sender],pme_pp->nat[sender]);
+                }
+            }
+        }
+
+        /* Wait for the coordinates and/or charges to arrive */
+        MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
+        messages = 0;
+    } while (!(cnb.flags & (PP_PME_COORD | PP_PME_FINISH)));
+
+    *step = cnb.step;
+#endif
+
+    *chargeA = pme_pp->chargeA;
+    *chargeB = pme_pp->chargeB;
+    *x       = pme_pp->x;
+    *f       = pme_pp->f;
+
+
+    return ((cnb.flags & PP_PME_FINISH) ? -1 : nat);
+}
+
+static void receive_virial_energy(t_commrec *cr,
+                                 matrix vir,real *energy,real *dvdlambda,
+                                 float *pme_cycles) 
+{
+  gmx_pme_comm_vir_ene_t cve;
+
+  if (cr->dd->pme_receive_vir_ener) {
+    if (debug)
+      fprintf(debug,
+             "PP node %d receiving from PME node %d: virial and energy\n",
+             cr->sim_nodeid,cr->dd->pme_nodeid);
+#ifdef GMX_MPI
+    MPI_Recv(&cve,sizeof(cve),MPI_BYTE,cr->dd->pme_nodeid,1,cr->mpi_comm_mysim,
+            MPI_STATUS_IGNORE);
+#else
+    memset(&cve,0,sizeof(cve));
+#endif
+       
+    m_add(vir,cve.vir,vir);
+    *energy = cve.energy;
+    *dvdlambda += cve.dvdlambda;
+    *pme_cycles = cve.cycles;
+
+    if ( cve.stop_cond != gmx_stop_cond_none )
+    {
+        gmx_set_stop_condition(cve.stop_cond);
+    }
+  } else {
+    *energy = 0;
+    *pme_cycles = 0;
+  }
+}
+
+void gmx_pme_receive_f(t_commrec *cr,
+                      rvec f[], matrix vir, 
+                      real *energy, real *dvdlambda,
+                      float *pme_cycles)
+{
+  int natoms,i;
+
+#ifdef GMX_PME_DELAYED_WAIT
+  /* Wait for the x request to finish */
+  gmx_pme_send_q_x_wait(cr->dd);
+#endif
+
+  natoms = cr->dd->nat_home;
+
+  if (natoms > cr->dd->pme_recv_f_alloc)
+  {
+      cr->dd->pme_recv_f_alloc = over_alloc_dd(natoms);
+      srenew(cr->dd->pme_recv_f_buf, cr->dd->pme_recv_f_alloc);
+  }
+
+#ifdef GMX_MPI  
+  MPI_Recv(cr->dd->pme_recv_f_buf[0], 
+           natoms*sizeof(rvec),MPI_BYTE,
+          cr->dd->pme_nodeid,0,cr->mpi_comm_mysim,
+          MPI_STATUS_IGNORE);
+#endif
+
+  for(i=0; i<natoms; i++)
+      rvec_inc(f[i],cr->dd->pme_recv_f_buf[i]);
+
+  
+  receive_virial_energy(cr,vir,energy,dvdlambda,pme_cycles);
+}
+
+void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
+                                rvec *f, matrix vir,
+                                real energy, real dvdlambda,
+                                float cycles)
+{
+  gmx_pme_comm_vir_ene_t cve; 
+  int messages,ind_start,ind_end,receiver;
+
+  cve.cycles = cycles;
+
+  /* Now the evaluated forces have to be transferred to the PP nodes */
+  messages = 0;
+  ind_end = 0;
+  for (receiver=0; receiver<pme_pp->nnode; receiver++) {
+    ind_start = ind_end;
+    ind_end   = ind_start + pme_pp->nat[receiver];
+#ifdef GMX_MPI
+    if (MPI_Isend(f[ind_start],(ind_end-ind_start)*sizeof(rvec),MPI_BYTE,
+                 pme_pp->node[receiver],0,
+                 pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]) != 0)
+      gmx_comm("MPI_Isend failed in do_pmeonly");
+#endif
+    }
+  
+  /* send virial and energy to our last PP node */
+  copy_mat(vir,cve.vir);
+  cve.energy    = energy;
+  cve.dvdlambda = dvdlambda;
+  /* check for the signals to send back to a PP node */
+  cve.stop_cond = gmx_get_stop_condition();
+  cve.cycles = cycles;
+  
+  if (debug)
+    fprintf(debug,"PME node sending to PP node %d: virial and energy\n",
+           pme_pp->node_peer);
+#ifdef GMX_MPI
+  MPI_Isend(&cve,sizeof(cve),MPI_BYTE,
+           pme_pp->node_peer,1,
+           pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
+  
+  /* Wait for the forces to arrive */
+  MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
+#endif
+}
similarity index 100%
rename from src/mdlib/pppm.c
rename to src/gromacs/mdlib/pppm.c
similarity index 100%
rename from src/mdlib/pull.c
rename to src/gromacs/mdlib/pull.c
diff --git a/src/gromacs/mdlib/pull_rotation.c b/src/gromacs/mdlib/pull_rotation.c
new file mode 100644 (file)
index 0000000..fd54812
--- /dev/null
@@ -0,0 +1,3857 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "domdec.h"
+#include "gmx_wallcycle.h"
+#include "trnio.h"
+#include "smalloc.h"
+#include "network.h"
+#include "pbc.h"
+#include "futil.h"
+#include "mdrun.h"
+#include "txtdump.h"
+#include "names.h"
+#include "mtop_util.h"
+#include "names.h"
+#include "nrjac.h"
+#include "vec.h"
+#include "gmx_ga2la.h"
+#include "xvgr.h"
+#include "gmxfio.h"
+#include "groupcoord.h"
+#include "pull_rotation.h"
+#include "gmx_sort.h"
+
+
+static char *RotStr = {"Enforced rotation:"};
+
+
+/* Set the minimum weight for the determination of the slab centers */
+#define WEIGHT_MIN (10*GMX_FLOAT_MIN)
+
+/* Helper structure for sorting positions along rotation vector             */
+typedef struct {
+    real xcproj;            /* Projection of xc on the rotation vector        */
+    int ind;                /* Index of xc                                    */
+    real m;                 /* Mass                                           */
+    rvec x;                 /* Position                                       */
+    rvec x_ref;             /* Reference position                             */
+} sort_along_vec_t;
+
+
+/* Enforced rotation / flexible: determine the angle of each slab             */
+typedef struct gmx_slabdata
+{
+    int  nat;               /* Number of atoms belonging to this slab         */
+    rvec *x;                /* The positions belonging to this slab. In 
+                               general, this should be all positions of the 
+                               whole rotation group, but we leave those away 
+                               that have a small enough weight                */
+    rvec *ref;              /* Same for reference                             */
+    real *weight;           /* The weight for each atom                       */
+} t_gmx_slabdata;
+
+
+/* Helper structure for potential fitting */
+typedef struct gmx_potfit
+{
+    real   *degangle;       /* Set of angles for which the potential is
+                               calculated. The optimum fit is determined as
+                               the angle for with the potential is minimal    */
+    real   *V;              /* Potential for the different angles             */
+    matrix *rotmat;         /* Rotation matrix corresponding to the angles    */
+} t_gmx_potfit;
+
+
+/* Enforced rotation data for all groups                                      */
+typedef struct gmx_enfrot
+{
+    FILE  *out_rot;         /* Output file for rotation data                  */
+    FILE  *out_torque;      /* Output file for torque data                    */
+    FILE  *out_angles;      /* Output file for slab angles for flexible type  */
+    FILE  *out_slabs;       /* Output file for slab centers                   */
+    int   bufsize;          /* Allocation size of buf                         */
+    rvec  *xbuf;            /* Coordinate buffer variable for sorting         */
+    real  *mbuf;            /* Masses buffer variable for sorting             */
+    sort_along_vec_t *data; /* Buffer variable needed for position sorting    */
+    real  *mpi_inbuf;       /* MPI buffer                                     */
+    real  *mpi_outbuf;      /* MPI buffer                                     */
+    int   mpi_bufsize;      /* Allocation size of in & outbuf                 */
+    unsigned long Flags;    /* mdrun flags                                    */
+    gmx_bool bOut;          /* Used to skip first output when appending to 
+                             * avoid duplicate entries in rotation outfiles   */
+} t_gmx_enfrot;
+
+
+/* Global enforced rotation data for a single rotation group                  */
+typedef struct gmx_enfrotgrp
+{
+    real    degangle;       /* Rotation angle in degrees                      */
+    matrix  rotmat;         /* Rotation matrix                                */
+    atom_id *ind_loc;       /* Local rotation indices                         */
+    int     nat_loc;        /* Number of local group atoms                    */
+    int     nalloc_loc;     /* Allocation size for ind_loc and weight_loc     */
+
+    real  V;                /* Rotation potential for this rotation group     */
+    rvec  *f_rot_loc;       /* Array to store the forces on the local atoms
+                               resulting from enforced rotation potential     */
+
+    /* Collective coordinates for the whole rotation group */
+    real  *xc_ref_length;   /* Length of each x_rotref vector after x_rotref 
+                               has been put into origin                       */
+    int   *xc_ref_ind;      /* Position of each local atom in the collective
+                               array                                          */
+    rvec  xc_center;        /* Center of the rotation group positions, may
+                               be mass weighted                               */
+    rvec  xc_ref_center;    /* dito, for the reference positions              */
+    rvec  *xc;              /* Current (collective) positions                 */
+    ivec  *xc_shifts;       /* Current (collective) shifts                    */
+    ivec  *xc_eshifts;      /* Extra shifts since last DD step                */
+    rvec  *xc_old;          /* Old (collective) positions                     */
+    rvec  *xc_norm;         /* Normalized form of the current positions       */
+    rvec  *xc_ref_sorted;   /* Reference positions (sorted in the same order 
+                               as xc when sorted)                             */
+    int   *xc_sortind;      /* Where is a position found after sorting?       */
+    real  *mc;              /* Collective masses                              */
+    real  *mc_sorted;
+    real  invmass;          /* one over the total mass of the rotation group  */
+
+    real  torque_v;         /* Torque in the direction of rotation vector     */
+    real  angle_v;          /* Actual angle of the whole rotation group       */
+    /* Fixed rotation only */
+    real  weight_v;         /* Weights for angle determination                */
+    rvec  *xr_loc;          /* Local reference coords, correctly rotated      */
+    rvec  *x_loc_pbc;       /* Local current coords, correct PBC image        */
+    real  *m_loc;           /* Masses of the current local atoms              */
+
+    /* Flexible rotation only */
+    int   nslabs_alloc;     /* For this many slabs memory is allocated        */
+    int   slab_first;       /* Lowermost slab for that the calculation needs 
+                               to be performed at a given time step           */
+    int   slab_last;        /* Uppermost slab ...                             */
+    int   slab_first_ref;   /* First slab for which ref. center is stored     */
+    int   slab_last_ref;    /* Last ...                                       */
+    int   slab_buffer;      /* Slab buffer region around reference slabs      */
+    int   *firstatom;       /* First relevant atom for a slab                 */
+    int   *lastatom;        /* Last relevant atom for a slab                  */
+    rvec  *slab_center;     /* Gaussian-weighted slab center                  */
+    rvec  *slab_center_ref; /* Gaussian-weighted slab center for the
+                               reference positions                            */
+    real  *slab_weights;    /* Sum of gaussian weights in a slab              */
+    real  *slab_torque_v;   /* Torque T = r x f for each slab.                */
+                            /* torque_v = m.v = angular momentum in the 
+                               direction of v                                 */
+    real  max_beta;         /* min_gaussian from inputrec->rotgrp is the
+                               minimum value the gaussian must have so that 
+                               the force is actually evaluated max_beta is 
+                               just another way to put it                     */
+    real  *gn_atom;         /* Precalculated gaussians for a single atom      */
+    int   *gn_slabind;      /* Tells to which slab each precalculated gaussian 
+                               belongs                                        */
+    rvec  *slab_innersumvec;/* Inner sum of the flexible2 potential per slab;
+                               this is precalculated for optimization reasons */
+    t_gmx_slabdata *slab_data; /* Holds atom positions and gaussian weights 
+                               of atoms belonging to a slab                   */
+
+    /* For potential fits with varying angle: */
+    t_gmx_potfit *PotAngleFit;  /* Used for fit type 'potential'              */
+} t_gmx_enfrotgrp;
+
+
+/* Activate output of forces for correctness checks */
+/* #define PRINT_FORCES */
+#ifdef PRINT_FORCES
+#define PRINT_FORCE_J  fprintf(stderr,"f%d = %15.8f %15.8f %15.8f\n",erg->xc_ref_ind[j],erg->f_rot_loc[j][XX], erg->f_rot_loc[j][YY], erg->f_rot_loc[j][ZZ]);
+#define PRINT_POT_TAU  if (MASTER(cr)) { \
+                           fprintf(stderr,"potential = %15.8f\n" "torque    = %15.8f\n", erg->V, erg->torque_v); \
+                       }
+#else
+#define PRINT_FORCE_J
+#define PRINT_POT_TAU
+#endif
+
+/* Shortcuts for often used queries */
+#define ISFLEX(rg) ( (rg->eType==erotgFLEX) || (rg->eType==erotgFLEXT) || (rg->eType==erotgFLEX2) || (rg->eType==erotgFLEX2T) )
+#define ISCOLL(rg) ( (rg->eType==erotgFLEX) || (rg->eType==erotgFLEXT) || (rg->eType==erotgFLEX2) || (rg->eType==erotgFLEX2T) || (rg->eType==erotgRMPF) || (rg->eType==erotgRM2PF) )
+
+
+/* Does any of the rotation groups use slab decomposition? */
+static gmx_bool HaveFlexibleGroups(t_rot *rot)
+{
+    int g;
+    t_rotgrp *rotg;
+
+
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        if (ISFLEX(rotg))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+/* Is for any group the fit angle determined by finding the minimum of the
+ * rotation potential? */
+static gmx_bool HavePotFitGroups(t_rot *rot)
+{
+    int g;
+    t_rotgrp *rotg;
+
+
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        if (erotgFitPOT == rotg->eFittype)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+
+static double** allocate_square_matrix(int dim)
+{
+    int i;
+    double** mat = NULL; 
+    
+    
+    snew(mat, dim);
+    for(i=0; i<dim; i++)
+        snew(mat[i], dim);
+
+    return mat;
+}
+
+
+static void free_square_matrix(double** mat, int dim)
+{
+    int i;
+    
+    
+    for (i=0; i<dim; i++)
+        sfree(mat[i]);
+    sfree(mat);
+}
+
+
+/* Return the angle for which the potential is minimal */
+static real get_fitangle(t_rotgrp *rotg, gmx_enfrotgrp_t erg)
+{
+    int i;
+    real fitangle = -999.9;
+    real pot_min = GMX_FLOAT_MAX;
+    t_gmx_potfit *fit;
+
+
+    fit = erg->PotAngleFit;
+
+    for (i = 0; i < rotg->PotAngle_nstep; i++)
+    {
+        if (fit->V[i] < pot_min)
+        {
+            pot_min = fit->V[i];
+            fitangle = fit->degangle[i];
+        }
+    }
+
+    return fitangle;
+}
+
+
+/* Reduce potential angle fit data for this group at this time step? */
+static gmx_inline gmx_bool bPotAngle(t_rot *rot, t_rotgrp *rotg, gmx_large_int_t step)
+{
+    return ( (erotgFitPOT==rotg->eFittype) && (do_per_step(step, rot->nstsout) || do_per_step(step, rot->nstrout)) );
+}
+
+/* Reduce slab torqe data for this group at this time step? */
+static gmx_inline gmx_bool bSlabTau(t_rot *rot, t_rotgrp *rotg, gmx_large_int_t step)
+{
+    return ( (ISFLEX(rotg)) && do_per_step(step, rot->nstsout) );
+}
+
+/* Output rotation energy, torques, etc. for each rotation group */
+static void reduce_output(t_commrec *cr, t_rot *rot, real t, gmx_large_int_t step)
+{
+    int      g,i,islab,nslabs=0;
+    int      count;      /* MPI element counter                               */
+    t_rotgrp *rotg;
+    gmx_enfrot_t er;     /* Pointer to the enforced rotation buffer variables */
+    gmx_enfrotgrp_t erg; /* Pointer to enforced rotation group data           */
+    real     fitangle;
+    gmx_bool bFlex;
+
+    
+    er=rot->enfrot;
+    
+    /* Fill the MPI buffer with stuff to reduce. If items are added for reduction
+     * here, the MPI buffer size has to be enlarged also in calc_mpi_bufsize() */
+    if (PAR(cr))
+    {
+        count=0;
+        for (g=0; g < rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            erg = rotg->enfrotgrp;
+            nslabs = erg->slab_last - erg->slab_first + 1;
+            er->mpi_inbuf[count++] = erg->V;
+            er->mpi_inbuf[count++] = erg->torque_v;
+            er->mpi_inbuf[count++] = erg->angle_v;
+            er->mpi_inbuf[count++] = erg->weight_v; /* weights are not needed for flex types, but this is just a single value */
+
+            if (bPotAngle(rot, rotg, step))
+            {
+                for (i = 0; i < rotg->PotAngle_nstep; i++)
+                    er->mpi_inbuf[count++] = erg->PotAngleFit->V[i];
+            }
+            if (bSlabTau(rot, rotg, step))
+            {
+                for (i=0; i<nslabs; i++)
+                    er->mpi_inbuf[count++] = erg->slab_torque_v[i];
+            }
+        }
+        if (count > er->mpi_bufsize)
+            gmx_fatal(FARGS, "%s MPI buffer overflow, please report this error.", RotStr);
+
+#ifdef GMX_MPI
+        MPI_Reduce(er->mpi_inbuf, er->mpi_outbuf, count, GMX_MPI_REAL, MPI_SUM, MASTERRANK(cr), cr->mpi_comm_mygroup);
+#endif
+
+        /* Copy back the reduced data from the buffer on the master */
+        if (MASTER(cr))
+        {
+            count=0;
+            for (g=0; g < rot->ngrp; g++)
+            {
+                rotg = &rot->grp[g];
+                erg = rotg->enfrotgrp;
+                nslabs = erg->slab_last - erg->slab_first + 1;
+                erg->V        = er->mpi_outbuf[count++];
+                erg->torque_v = er->mpi_outbuf[count++];
+                erg->angle_v  = er->mpi_outbuf[count++];
+                erg->weight_v = er->mpi_outbuf[count++];
+
+                if (bPotAngle(rot, rotg, step))
+                {
+                    for (i = 0; i < rotg->PotAngle_nstep; i++)
+                        erg->PotAngleFit->V[i] = er->mpi_outbuf[count++];
+                }
+                if (bSlabTau(rot, rotg, step))
+                {
+                    for (i=0; i<nslabs; i++)
+                        erg->slab_torque_v[i] = er->mpi_outbuf[count++];
+                }
+            }
+        }
+    }
+    
+    /* Output */
+    if (MASTER(cr))
+    {
+        /* Angle and torque for each rotation group */
+        for (g=0; g < rot->ngrp; g++)
+        {
+            rotg=&rot->grp[g];
+            bFlex = ISFLEX(rotg);
+
+            erg=rotg->enfrotgrp;
+            
+            /* Output to main rotation output file: */
+            if ( do_per_step(step, rot->nstrout) )
+            {
+                if (erotgFitPOT == rotg->eFittype)
+                {
+                    fitangle = get_fitangle(rotg, erg);
+                }
+                else
+                {
+                    if (bFlex)
+                        fitangle = erg->angle_v; /* RMSD fit angle */
+                    else
+                        fitangle = (erg->angle_v/erg->weight_v)*180.0*M_1_PI;
+                }
+                fprintf(er->out_rot, "%12.4f", fitangle);
+                fprintf(er->out_rot, "%12.3e", erg->torque_v);
+                fprintf(er->out_rot, "%12.3e", erg->V);
+            }
+
+            if ( do_per_step(step, rot->nstsout) )
+            {
+                /* Output to torque log file: */
+                if (bFlex)
+                {
+                    fprintf(er->out_torque, "%12.3e%6d", t, g);
+                    for (i=erg->slab_first; i<=erg->slab_last; i++)
+                    {
+                        islab = i - erg->slab_first;  /* slab index */
+                        /* Only output if enough weight is in slab */
+                        if (erg->slab_weights[islab] > rotg->min_gaussian)
+                            fprintf(er->out_torque, "%6d%12.3e", i, erg->slab_torque_v[islab]);
+                    }
+                    fprintf(er->out_torque , "\n");
+                }
+
+                /* Output to angles log file: */
+                if (erotgFitPOT == rotg->eFittype)
+                {
+                    fprintf(er->out_angles, "%12.3e%6d%12.4f", t, g, erg->degangle);
+                    /* Output energies at a set of angles around the reference angle */
+                    for (i = 0; i < rotg->PotAngle_nstep; i++)
+                        fprintf(er->out_angles, "%12.3e", erg->PotAngleFit->V[i]);
+                    fprintf(er->out_angles, "\n");
+                }
+            }
+        }
+        if ( do_per_step(step, rot->nstrout) )
+            fprintf(er->out_rot, "\n");
+    }
+}
+
+
+/* Add the forces from enforced rotation potential to the local forces.
+ * Should be called after the SR forces have been evaluated */
+extern real add_rot_forces(t_rot *rot, rvec f[], t_commrec *cr, gmx_large_int_t step, real t)
+{
+    int g,l,ii;
+    t_rotgrp *rotg;
+    gmx_enfrot_t er;     /* Pointer to the enforced rotation buffer variables */
+    gmx_enfrotgrp_t erg; /* Pointer to enforced rotation group data           */
+    real Vrot = 0.0;     /* If more than one rotation group is present, Vrot
+                            assembles the local parts from all groups         */
+
+    
+    er=rot->enfrot;
+    
+    /* Loop over enforced rotation groups (usually 1, though)
+     * Apply the forces from rotation potentials */
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        erg=rotg->enfrotgrp;
+        Vrot += erg->V;  /* add the local parts from the nodes */
+        for (l=0; l<erg->nat_loc; l++)
+        {
+            /* Get the right index of the local force */
+            ii = erg->ind_loc[l];
+            /* Add */
+            rvec_inc(f[ii],erg->f_rot_loc[l]);
+        }
+    }
+
+    /* Reduce energy,torque, angles etc. to get the sum values (per rotation group)
+     * on the master and output these values to file. */
+    if ( (do_per_step(step, rot->nstrout) || do_per_step(step, rot->nstsout)) && er->bOut)
+        reduce_output(cr, rot, t, step);
+
+    /* When appending, er->bOut is FALSE the first time to avoid duplicate entries */
+    er->bOut = TRUE;
+    
+    PRINT_POT_TAU
+
+    return Vrot;
+}
+
+
+/* The Gaussian norm is chosen such that the sum of the gaussian functions
+ * over the slabs is approximately 1.0 everywhere */
+#define GAUSS_NORM   0.569917543430618
+
+
+/* Calculate the maximum beta that leads to a gaussian larger min_gaussian,
+ * also does some checks
+ */
+static double calc_beta_max(real min_gaussian, real slab_dist)
+{
+    double sigma;
+    double arg;
+    
+    
+    /* Actually the next two checks are already made in grompp */
+    if (slab_dist <= 0)
+        gmx_fatal(FARGS, "Slab distance of flexible rotation groups must be >=0 !");
+    if (min_gaussian <= 0)
+        gmx_fatal(FARGS, "Cutoff value for Gaussian must be > 0. (You requested %f)");
+
+    /* Define the sigma value */
+    sigma = 0.7*slab_dist;
+
+    /* Calculate the argument for the logarithm and check that the log() result is negative or 0 */
+    arg = min_gaussian/GAUSS_NORM;
+    if (arg > 1.0)
+        gmx_fatal(FARGS, "min_gaussian of flexible rotation groups must be <%g", GAUSS_NORM);
+    
+    return sqrt(-2.0*sigma*sigma*log(min_gaussian/GAUSS_NORM));
+}
+
+
+static gmx_inline real calc_beta(rvec curr_x, t_rotgrp *rotg, int n)
+{
+    return iprod(curr_x, rotg->vec) - rotg->slab_dist * n;
+}
+
+
+static gmx_inline real gaussian_weight(rvec curr_x, t_rotgrp *rotg, int n)
+{
+    const real norm = GAUSS_NORM;
+    real       sigma;
+
+    
+    /* Define the sigma value */
+    sigma = 0.7*rotg->slab_dist;
+    /* Calculate the Gaussian value of slab n for position curr_x */
+    return norm * exp( -0.5 * sqr( calc_beta(curr_x, rotg, n)/sigma ) );
+}
+
+
+/* Returns the weight in a single slab, also calculates the Gaussian- and mass-
+ * weighted sum of positions for that slab */
+static real get_slab_weight(int j, t_rotgrp *rotg, rvec xc[], real mc[], rvec *x_weighted_sum)
+{
+    rvec curr_x;              /* The position of an atom                      */
+    rvec curr_x_weighted;     /* The gaussian-weighted position               */
+    real gaussian;            /* A single gaussian weight                     */
+    real wgauss;              /* gaussian times current mass                  */
+    real slabweight = 0.0;    /* The sum of weights in the slab               */
+    int i,islab;
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data      */
+
+    
+    erg=rotg->enfrotgrp;
+    clear_rvec(*x_weighted_sum);
+    
+    /* Slab index */
+    islab = j - erg->slab_first;
+    
+    /* Loop over all atoms in the rotation group */
+     for (i=0; i<rotg->nat; i++)
+     {
+         copy_rvec(xc[i], curr_x);
+         gaussian = gaussian_weight(curr_x, rotg, j);
+         wgauss = gaussian * mc[i];
+         svmul(wgauss, curr_x, curr_x_weighted);
+         rvec_add(*x_weighted_sum, curr_x_weighted, *x_weighted_sum);
+         slabweight += wgauss;
+     } /* END of loop over rotation group atoms */
+
+     return slabweight;
+}
+
+
+static void get_slab_centers(
+        t_rotgrp *rotg,       /* The rotation group information               */
+        rvec      *xc,        /* The rotation group positions; will 
+                                 typically be enfrotgrp->xc, but at first call 
+                                 it is enfrotgrp->xc_ref                      */
+        real      *mc,        /* The masses of the rotation group atoms       */
+        t_commrec *cr,        /* Communication record                         */
+        int       g,          /* The number of the rotation group             */
+        real      time,       /* Used for output only                         */
+        FILE      *out_slabs, /* For outputting center per slab information   */
+        gmx_bool  bOutStep,   /* Is this an output step?                      */
+        gmx_bool  bReference) /* If this routine is called from
+                                 init_rot_group we need to store
+                                 the reference slab centers                   */
+{
+    int j,islab;
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+    
+    
+    erg=rotg->enfrotgrp;
+
+    /* Loop over slabs */
+    for (j = erg->slab_first; j <= erg->slab_last; j++)
+    {
+        islab = j - erg->slab_first;
+        erg->slab_weights[islab] = get_slab_weight(j, rotg, xc, mc, &erg->slab_center[islab]);
+        
+        /* We can do the calculations ONLY if there is weight in the slab! */
+        if (erg->slab_weights[islab] > WEIGHT_MIN)
+        {
+            svmul(1.0/erg->slab_weights[islab], erg->slab_center[islab], erg->slab_center[islab]);
+        }
+        else
+        {
+            /* We need to check this here, since we divide through slab_weights
+             * in the flexible low-level routines! */
+            gmx_fatal(FARGS, "Not enough weight in slab %d. Slab center cannot be determined!", j);
+        }
+        
+        /* At first time step: save the centers of the reference structure */
+        if (bReference)
+            copy_rvec(erg->slab_center[islab], erg->slab_center_ref[islab]);
+    } /* END of loop over slabs */
+    
+    /* Output on the master */
+    if (MASTER(cr) && bOutStep)
+    {
+        fprintf(out_slabs, "%12.3e%6d", time, g);
+        for (j = erg->slab_first; j <= erg->slab_last; j++)
+        {
+            islab = j - erg->slab_first;
+            fprintf(out_slabs, "%6d%12.3e%12.3e%12.3e",
+                    j,erg->slab_center[islab][XX],erg->slab_center[islab][YY],erg->slab_center[islab][ZZ]);
+        }
+        fprintf(out_slabs, "\n");
+    }
+}
+
+
+static void calc_rotmat(
+        rvec vec,
+        real degangle,  /* Angle alpha of rotation at time t in degrees       */
+        matrix rotmat)  /* Rotation matrix                                    */
+{
+    real radangle;            /* Rotation angle in radians */
+    real cosa;                /* cosine alpha              */
+    real sina;                /* sine alpha                */
+    real OMcosa;              /* 1 - cos(alpha)            */
+    real dumxy, dumxz, dumyz; /* save computations         */
+    rvec rot_vec;             /* Rotate around rot_vec ... */
+
+
+    radangle = degangle * M_PI/180.0;
+    copy_rvec(vec , rot_vec );
+
+    /* Precompute some variables: */
+    cosa   = cos(radangle);
+    sina   = sin(radangle);
+    OMcosa = 1.0 - cosa;
+    dumxy  = rot_vec[XX]*rot_vec[YY]*OMcosa;
+    dumxz  = rot_vec[XX]*rot_vec[ZZ]*OMcosa;
+    dumyz  = rot_vec[YY]*rot_vec[ZZ]*OMcosa;
+
+    /* Construct the rotation matrix for this rotation group: */
+    /* 1st column: */
+    rotmat[XX][XX] = cosa  + rot_vec[XX]*rot_vec[XX]*OMcosa;
+    rotmat[YY][XX] = dumxy + rot_vec[ZZ]*sina;
+    rotmat[ZZ][XX] = dumxz - rot_vec[YY]*sina;
+    /* 2nd column: */
+    rotmat[XX][YY] = dumxy - rot_vec[ZZ]*sina;
+    rotmat[YY][YY] = cosa  + rot_vec[YY]*rot_vec[YY]*OMcosa;
+    rotmat[ZZ][YY] = dumyz + rot_vec[XX]*sina;
+    /* 3rd column: */
+    rotmat[XX][ZZ] = dumxz + rot_vec[YY]*sina;
+    rotmat[YY][ZZ] = dumyz - rot_vec[XX]*sina;
+    rotmat[ZZ][ZZ] = cosa  + rot_vec[ZZ]*rot_vec[ZZ]*OMcosa;
+
+#ifdef PRINTMATRIX
+    int iii,jjj;
+
+    for (iii=0; iii<3; iii++) {
+        for (jjj=0; jjj<3; jjj++)
+            fprintf(stderr, " %10.8f ",  rotmat[iii][jjj]);
+        fprintf(stderr, "\n");
+    }
+#endif
+}
+
+
+/* Calculates torque on the rotation axis tau = position x force */
+static gmx_inline real torque(
+        rvec rotvec,  /* rotation vector; MUST be normalized!                 */
+        rvec force,   /* force                                                */
+        rvec x,       /* position of atom on which the force acts             */
+        rvec pivot)   /* pivot point of rotation axis                         */
+{
+    rvec vectmp, tau;
+
+    
+    /* Subtract offset */
+    rvec_sub(x,pivot,vectmp);
+    
+    /* position x force */
+    cprod(vectmp, force, tau);
+    
+    /* Return the part of the torque which is parallel to the rotation vector */
+    return iprod(tau, rotvec);
+}
+
+
+/* Right-aligned output of value with standard width */
+static void print_aligned(FILE *fp, char *str)
+{
+    fprintf(fp, "%12s", str);
+}
+
+
+/* Right-aligned output of value with standard short width */
+static void print_aligned_short(FILE *fp, char *str)
+{
+    fprintf(fp, "%6s", str);
+}
+
+
+static FILE *open_output_file(const char *fn, int steps, const char what[])
+{
+    FILE *fp;
+    
+    
+    fp = ffopen(fn, "w");
+
+    fprintf(fp, "# Output of %s is written in intervals of %d time step%s.\n#\n",
+            what,steps, steps>1 ? "s":"");
+    
+    return fp;
+}
+
+
+/* Open output file for slab center data. Call on master only */
+static FILE *open_slab_out(const char *fn, t_rot *rot, const output_env_t oenv)
+{
+    FILE      *fp;
+    int       g,i;
+    t_rotgrp  *rotg;
+
+
+    if (rot->enfrot->Flags & MD_APPENDFILES)
+    {
+        fp = gmx_fio_fopen(fn,"a");
+    }
+    else
+    {
+        fp = open_output_file(fn, rot->nstsout, "gaussian weighted slab centers");
+
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            if (ISFLEX(rotg))
+            {
+                fprintf(fp, "# Rotation group %d (%s), slab distance %f nm, %s.\n",
+                        g, erotg_names[rotg->eType], rotg->slab_dist,
+                        rotg->bMassW? "centers of mass":"geometrical centers");
+            }
+        }
+
+        fprintf(fp, "# Reference centers are listed first (t=-1).\n");
+        fprintf(fp, "# The following columns have the syntax:\n");
+        fprintf(fp, "#     ");
+        print_aligned_short(fp, "t");
+        print_aligned_short(fp, "grp");
+        /* Print legend for the first two entries only ... */
+        for (i=0; i<2; i++)
+        {
+            print_aligned_short(fp, "slab");
+            print_aligned(fp, "X center");
+            print_aligned(fp, "Y center");
+            print_aligned(fp, "Z center");
+        }
+        fprintf(fp, " ...\n");
+        fflush(fp);
+    }
+
+    return fp;
+}
+
+
+/* Adds 'buf' to 'str' */
+static void add_to_string(char **str, char *buf)
+{
+    int len;
+
+
+    len = strlen(*str) + strlen(buf) + 1;
+    srenew(*str, len);
+    strcat(*str, buf);
+}
+
+
+static void add_to_string_aligned(char **str, char *buf)
+{
+    char buf_aligned[STRLEN];
+
+    sprintf(buf_aligned, "%12s", buf);
+    add_to_string(str, buf_aligned);
+}
+
+
+/* Open output file and print some general information about the rotation groups.
+ * Call on master only */
+static FILE *open_rot_out(const char *fn, t_rot *rot, const output_env_t oenv)
+{
+    FILE       *fp;
+    int        g,nsets;
+    t_rotgrp   *rotg;
+    const char **setname;
+    char       buf[50], buf2[75];
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    gmx_bool   bFlex;
+    char       *LegendStr=NULL;
+
+
+    if (rot->enfrot->Flags & MD_APPENDFILES)
+    {
+        fp = gmx_fio_fopen(fn,"a");
+    }
+    else
+    {
+        fp = xvgropen(fn, "Rotation angles and energy", "Time [ps]", "angles [degrees] and energies [kJ/mol]", oenv);
+        fprintf(fp, "# Output of enforced rotation data is written in intervals of %d time step%s.\n#\n", rot->nstrout, rot->nstrout > 1 ? "s":"");
+        fprintf(fp, "# The scalar tau is the torque [kJ/mol] in the direction of the rotation vector v.\n");
+        fprintf(fp, "# To obtain the vectorial torque, multiply tau with the group's rot_vec.\n");
+        fprintf(fp, "# For flexible groups, tau(t,n) from all slabs n have been summed in a single value tau(t) here.\n");
+        fprintf(fp, "# The torques tau(t,n) are found in the rottorque.log (-rt) output file\n");
+        
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            erg=rotg->enfrotgrp;
+            bFlex = ISFLEX(rotg);
+
+            fprintf(fp, "#\n");
+            fprintf(fp, "# ROTATION GROUP %d, potential type '%s':\n"      , g, erotg_names[rotg->eType]);
+            fprintf(fp, "# rot_massw%d          %s\n"                      , g, yesno_names[rotg->bMassW]);
+            fprintf(fp, "# rot_vec%d            %12.5e %12.5e %12.5e\n"    , g, rotg->vec[XX], rotg->vec[YY], rotg->vec[ZZ]);
+            fprintf(fp, "# rot_rate%d           %12.5e degrees/ps\n"       , g, rotg->rate);
+            fprintf(fp, "# rot_k%d              %12.5e kJ/(mol*nm^2)\n"    , g, rotg->k);
+            if ( rotg->eType==erotgISO || rotg->eType==erotgPM || rotg->eType==erotgRM || rotg->eType==erotgRM2)
+                fprintf(fp, "# rot_pivot%d          %12.5e %12.5e %12.5e  nm\n", g, rotg->pivot[XX], rotg->pivot[YY], rotg->pivot[ZZ]);
+
+            if (bFlex)
+            {
+                fprintf(fp, "# rot_slab_distance%d   %f nm\n", g, rotg->slab_dist);
+                fprintf(fp, "# rot_min_gaussian%d   %12.5e\n", g, rotg->min_gaussian);
+            }
+
+            /* Output the centers of the rotation groups for the pivot-free potentials */
+            if ((rotg->eType==erotgISOPF) || (rotg->eType==erotgPMPF) || (rotg->eType==erotgRMPF) || (rotg->eType==erotgRM2PF
+                || (rotg->eType==erotgFLEXT) || (rotg->eType==erotgFLEX2T)) )
+            {
+                fprintf(fp, "# ref. grp. %d center  %12.5e %12.5e %12.5e\n", g,
+                            erg->xc_ref_center[XX], erg->xc_ref_center[YY], erg->xc_ref_center[ZZ]);
+
+                fprintf(fp, "# grp. %d init.center  %12.5e %12.5e %12.5e\n", g,
+                            erg->xc_center[XX], erg->xc_center[YY], erg->xc_center[ZZ]);
+            }
+
+            if ( (rotg->eType == erotgRM2) || (rotg->eType==erotgFLEX2) || (rotg->eType==erotgFLEX2T) )
+            {
+                fprintf(fp, "# rot_eps%d            %12.5e nm^2\n", g, rotg->eps);
+            }
+            if (erotgFitPOT == rotg->eFittype)
+            {
+                fprintf(fp, "#\n");
+                fprintf(fp, "# theta_fit%d is determined by first evaluating the potential for %d angles around theta_ref%d.\n",
+                            g, rotg->PotAngle_nstep, g);
+                fprintf(fp, "# The fit angle is the one with the smallest potential. It is given as the deviation\n");
+                fprintf(fp, "# from the reference angle, i.e. if theta_ref=X and theta_fit=Y, then the angle with\n");
+                fprintf(fp, "# minimal value of the potential is X+Y. Angular resolution is %g degrees.\n", rotg->PotAngle_step);
+            }
+        }
+        
+        /* Print a nice legend */
+        snew(LegendStr, 1);
+        LegendStr[0] = '\0';
+        sprintf(buf, "#     %6s", "time");
+        add_to_string_aligned(&LegendStr, buf);
+
+        nsets = 0;
+        snew(setname, 4*rot->ngrp);
+        
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            sprintf(buf, "theta_ref%d", g);
+            add_to_string_aligned(&LegendStr, buf);
+
+            sprintf(buf2, "%s [degrees]", buf);
+            setname[nsets] = strdup(buf2);
+            nsets++;
+        }
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            bFlex = ISFLEX(rotg);
+
+            /* For flexible axis rotation we use RMSD fitting to determine the
+             * actual angle of the rotation group */
+            if (bFlex || erotgFitPOT == rotg->eFittype)
+                sprintf(buf, "theta_fit%d", g);
+            else
+                sprintf(buf, "theta_av%d", g);
+            add_to_string_aligned(&LegendStr, buf);
+            sprintf(buf2, "%s [degrees]", buf);
+            setname[nsets] = strdup(buf2);
+            nsets++;
+
+            sprintf(buf, "tau%d", g);
+            add_to_string_aligned(&LegendStr, buf);
+            sprintf(buf2, "%s [kJ/mol]", buf);
+            setname[nsets] = strdup(buf2);
+            nsets++;
+
+            sprintf(buf, "energy%d", g);
+            add_to_string_aligned(&LegendStr, buf);
+            sprintf(buf2, "%s [kJ/mol]", buf);
+            setname[nsets] = strdup(buf2);
+            nsets++;
+        }
+        fprintf(fp, "#\n");
+        
+        if (nsets > 1)
+            xvgr_legend(fp, nsets, setname, oenv);
+        sfree(setname);
+
+        fprintf(fp, "#\n# Legend for the following data columns:\n");
+        fprintf(fp, "%s\n", LegendStr);
+        sfree(LegendStr);
+        
+        fflush(fp);
+    }
+    
+    return fp;
+}
+
+
+/* Call on master only */
+static FILE *open_angles_out(const char *fn, t_rot *rot, const output_env_t oenv)
+{
+    int      g,i;
+    FILE     *fp;
+    t_rotgrp *rotg;
+    gmx_enfrotgrp_t erg;        /* Pointer to enforced rotation group data */
+    char     buf[100];
+
+
+    if (rot->enfrot->Flags & MD_APPENDFILES)
+    {
+        fp = gmx_fio_fopen(fn,"a");
+    }
+    else
+    {
+        /* Open output file and write some information about it's structure: */
+        fp = open_output_file(fn, rot->nstsout, "rotation group angles");
+        fprintf(fp, "# All angles given in degrees, time in ps.\n");
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            erg=rotg->enfrotgrp;
+
+            /* Output for this group happens only if potential type is flexible or
+             * if fit type is potential! */
+            if ( ISFLEX(rotg) || (erotgFitPOT == rotg->eFittype) )
+            {
+                if (ISFLEX(rotg))
+                    sprintf(buf, " slab distance %f nm, ", rotg->slab_dist);
+                else
+                    buf[0] = '\0';
+
+                fprintf(fp, "#\n# ROTATION GROUP %d '%s',%s fit type '%s'.\n",
+                        g, erotg_names[rotg->eType], buf, erotg_fitnames[rotg->eFittype]);
+
+                /* Special type of fitting using the potential minimum. This is
+                 * done for the whole group only, not for the individual slabs. */
+                if (erotgFitPOT == rotg->eFittype)
+                {
+                    fprintf(fp, "#    To obtain theta_fit%d, the potential is evaluated for %d angles around theta_ref%d\n", g, rotg->PotAngle_nstep, g);
+                    fprintf(fp, "#    The fit angle in the rotation standard outfile is the one with minimal energy E(theta_fit) [kJ/mol].\n");
+                    fprintf(fp, "#\n");
+                }
+
+                fprintf(fp, "# Legend for the group %d data columns:\n", g);
+                fprintf(fp, "#     ");
+                print_aligned_short(fp, "time");
+                print_aligned_short(fp, "grp");
+                print_aligned(fp, "theta_ref");
+
+                if (erotgFitPOT == rotg->eFittype)
+                {
+                    /* Output the set of angles around the reference angle */
+                    for (i = 0; i < rotg->PotAngle_nstep; i++)
+                    {
+                        sprintf(buf, "E(%g)", erg->PotAngleFit->degangle[i]);
+                        print_aligned(fp, buf);
+                    }
+                }
+                else
+                {
+                    /* Output fit angle for each slab */
+                    print_aligned_short(fp, "slab");
+                    print_aligned_short(fp, "atoms");
+                    print_aligned(fp, "theta_fit");
+                    print_aligned_short(fp, "slab");
+                    print_aligned_short(fp, "atoms");
+                    print_aligned(fp, "theta_fit");
+                    fprintf(fp, " ...");
+                }
+                fprintf(fp, "\n");
+            }
+        }
+        fflush(fp);
+    }
+
+    return fp;
+}
+
+
+/* Open torque output file and write some information about it's structure.
+ * Call on master only */
+static FILE *open_torque_out(const char *fn, t_rot *rot, const output_env_t oenv)
+{
+    FILE      *fp;
+    int       g;
+    t_rotgrp  *rotg;
+
+
+    if (rot->enfrot->Flags & MD_APPENDFILES)
+    {
+        fp = gmx_fio_fopen(fn,"a");
+    }
+    else
+    {
+        fp = open_output_file(fn, rot->nstsout,"torques");
+
+        for (g=0; g<rot->ngrp; g++)
+        {
+            rotg = &rot->grp[g];
+            if (ISFLEX(rotg))
+            {
+                fprintf(fp, "# Rotation group %d (%s), slab distance %f nm.\n", g, erotg_names[rotg->eType], rotg->slab_dist);
+                fprintf(fp, "# The scalar tau is the torque [kJ/mol] in the direction of the rotation vector.\n");
+                fprintf(fp, "# To obtain the vectorial torque, multiply tau with\n");
+                fprintf(fp, "# rot_vec%d            %10.3e %10.3e %10.3e\n", g, rotg->vec[XX], rotg->vec[YY], rotg->vec[ZZ]);
+                fprintf(fp, "#\n");
+            }
+        }
+        fprintf(fp, "# Legend for the following data columns: (tau=torque for that slab):\n");
+        fprintf(fp, "#     ");
+        print_aligned_short(fp, "t");
+        print_aligned_short(fp, "grp");
+        print_aligned_short(fp, "slab");
+        print_aligned(fp, "tau");
+        print_aligned_short(fp, "slab");
+        print_aligned(fp, "tau");
+        fprintf(fp, " ...\n");
+        fflush(fp);
+    }
+
+    return fp;
+}
+
+
+static void swap_val(double* vec, int i, int j)
+{
+    double tmp = vec[j];
+    
+    
+    vec[j]=vec[i];
+    vec[i]=tmp;
+}
+
+
+static void swap_col(double **mat, int i, int j)
+{
+    double tmp[3] = {mat[0][j], mat[1][j], mat[2][j]};
+    
+    
+    mat[0][j]=mat[0][i];
+    mat[1][j]=mat[1][i];
+    mat[2][j]=mat[2][i];
+    
+    mat[0][i]=tmp[0];
+    mat[1][i]=tmp[1];
+    mat[2][i]=tmp[2];
+} 
+
+
+/* Eigenvectors are stored in columns of eigen_vec */
+static void diagonalize_symmetric(
+        double **matrix,
+        double **eigen_vec,
+        double eigenval[3])
+{
+    int n_rot;
+    
+    
+    jacobi(matrix,3,eigenval,eigen_vec,&n_rot);
+    
+    /* sort in ascending order */
+    if (eigenval[0] > eigenval[1])
+    {
+        swap_val(eigenval, 0, 1);
+        swap_col(eigen_vec, 0, 1);
+    } 
+    if (eigenval[1] > eigenval[2])
+    {
+        swap_val(eigenval, 1, 2);
+        swap_col(eigen_vec, 1, 2);
+    }
+    if (eigenval[0] > eigenval[1])
+    {
+        swap_val(eigenval, 0, 1);
+        swap_col(eigen_vec, 0, 1);
+    }
+}
+
+
+static void align_with_z(
+        rvec* s,           /* Structure to align */
+        int natoms,
+        rvec axis)
+{
+    int    i, j, k;
+    rvec   zet = {0.0, 0.0, 1.0};
+    rvec   rot_axis={0.0, 0.0, 0.0};
+    rvec   *rotated_str=NULL;
+    real   ooanorm;
+    real   angle;
+    matrix rotmat;
+    
+    
+    snew(rotated_str, natoms);
+
+    /* Normalize the axis */
+    ooanorm = 1.0/norm(axis);
+    svmul(ooanorm, axis, axis);
+    
+    /* Calculate the angle for the fitting procedure */
+    cprod(axis, zet, rot_axis);
+    angle = acos(axis[2]);
+    if (angle < 0.0)
+        angle += M_PI;
+    
+    /* Calculate the rotation matrix */
+    calc_rotmat(rot_axis, angle*180.0/M_PI, rotmat);
+    
+    /* Apply the rotation matrix to s */
+    for (i=0; i<natoms; i++)
+    {    
+        for(j=0; j<3; j++)
+        {
+            for(k=0; k<3; k++)
+            {
+                rotated_str[i][j] += rotmat[j][k]*s[i][k];
+            }
+        }
+    }
+    
+    /* Rewrite the rotated structure to s */
+    for(i=0; i<natoms; i++)
+    {
+        for(j=0; j<3; j++)
+        {
+            s[i][j]=rotated_str[i][j];
+        }
+    }
+    
+    sfree(rotated_str);
+} 
+
+
+static void calc_correl_matrix(rvec* Xstr, rvec* Ystr, double** Rmat, int natoms)
+{    
+    int i, j, k;
+    
+    for (i=0; i<3; i++)
+        for (j=0; j<3; j++)
+            Rmat[i][j] = 0.0;
+    
+    for (i=0; i<3; i++) 
+        for (j=0; j<3; j++) 
+            for (k=0; k<natoms; k++) 
+                Rmat[i][j] += Ystr[k][i] * Xstr[k][j];
+}
+
+
+static void weigh_coords(rvec* str, real* weight, int natoms)
+{
+    int i, j;
+    
+    
+    for(i=0; i<natoms; i++)
+    {
+        for(j=0; j<3; j++)
+            str[i][j] *= sqrt(weight[i]);
+    }  
+}
+
+
+static real opt_angle_analytic(
+        rvec* ref_s,
+        rvec* act_s,
+        real* weight, 
+        int natoms,
+        rvec ref_com,
+        rvec act_com,
+        rvec axis)
+{    
+    int    i, j, k;
+    rvec   *ref_s_1=NULL;
+    rvec   *act_s_1=NULL;
+    rvec   shift;
+    double **Rmat, **RtR, **eigvec;
+    double eigval[3];
+    double V[3][3], WS[3][3];
+    double rot_matrix[3][3];
+    double opt_angle;
+    
+    
+    /* Do not change the original coordinates */ 
+    snew(ref_s_1, natoms);
+    snew(act_s_1, natoms);
+    for(i=0; i<natoms; i++)
+    {
+        copy_rvec(ref_s[i], ref_s_1[i]);
+        copy_rvec(act_s[i], act_s_1[i]);
+    }
+    
+    /* Translate the structures to the origin */
+    shift[XX] = -ref_com[XX];
+    shift[YY] = -ref_com[YY];
+    shift[ZZ] = -ref_com[ZZ];
+    translate_x(ref_s_1, natoms, shift);
+    
+    shift[XX] = -act_com[XX];
+    shift[YY] = -act_com[YY];
+    shift[ZZ] = -act_com[ZZ];
+    translate_x(act_s_1, natoms, shift);
+    
+    /* Align rotation axis with z */
+    align_with_z(ref_s_1, natoms, axis);
+    align_with_z(act_s_1, natoms, axis);
+    
+    /* Correlation matrix */
+    Rmat = allocate_square_matrix(3);
+    
+    for (i=0; i<natoms; i++)
+    {
+        ref_s_1[i][2]=0.0;
+        act_s_1[i][2]=0.0;
+    }
+    
+    /* Weight positions with sqrt(weight) */
+    if (NULL != weight)
+    {
+        weigh_coords(ref_s_1, weight, natoms);
+        weigh_coords(act_s_1, weight, natoms);
+    }
+    
+    /* Calculate correlation matrices R=YXt (X=ref_s; Y=act_s) */
+    calc_correl_matrix(ref_s_1, act_s_1, Rmat, natoms);
+    
+    /* Calculate RtR */
+    RtR = allocate_square_matrix(3);
+    for (i=0; i<3; i++)
+    {
+        for (j=0; j<3; j++)
+        {
+            for (k=0; k<3; k++)
+            {
+                RtR[i][j] += Rmat[k][i] * Rmat[k][j];
+            }
+        }
+    }
+    /* Diagonalize RtR */
+    snew(eigvec,3);
+    for (i=0; i<3; i++)
+        snew(eigvec[i],3);
+    
+    diagonalize_symmetric(RtR, eigvec, eigval);
+    swap_col(eigvec,0,1);
+    swap_col(eigvec,1,2);
+    swap_val(eigval,0,1);
+    swap_val(eigval,1,2);
+    
+    /* Calculate V */
+    for(i=0; i<3; i++)
+    {
+        for(j=0; j<3; j++)
+        {
+            V[i][j]  = 0.0;
+            WS[i][j] = 0.0;
+        }
+    }
+    
+    for (i=0; i<2; i++)
+        for (j=0; j<2; j++)
+            WS[i][j] = eigvec[i][j] / sqrt(eigval[j]);
+    
+    for (i=0; i<3; i++)
+    {
+        for (j=0; j<3; j++)
+        {
+            for (k=0; k<3; k++)
+            {
+                V[i][j] += Rmat[i][k]*WS[k][j];
+            }
+        }
+    }
+    free_square_matrix(Rmat, 3);
+    
+    /* Calculate optimal rotation matrix */
+    for (i=0; i<3; i++)
+        for (j=0; j<3; j++)
+            rot_matrix[i][j] = 0.0;
+    
+    for (i=0; i<3; i++)
+    {
+        for(j=0; j<3; j++)
+        {
+            for(k=0; k<3; k++){
+                rot_matrix[i][j] += eigvec[i][k]*V[j][k];
+            }
+        }
+    }
+    rot_matrix[2][2] = 1.0;
+        
+    /* In some cases abs(rot_matrix[0][0]) can be slighly larger
+     * than unity due to numerical inacurracies. To be able to calculate
+     * the acos function, we put these values back in range. */
+    if (rot_matrix[0][0] > 1.0)
+    {
+        rot_matrix[0][0] = 1.0;
+    }
+    else if (rot_matrix[0][0] < -1.0)
+    {
+        rot_matrix[0][0] = -1.0;
+    }
+
+    /* Determine the optimal rotation angle: */
+    opt_angle = (-1.0)*acos(rot_matrix[0][0])*180.0/M_PI;
+    if (rot_matrix[0][1] < 0.0)
+        opt_angle = (-1.0)*opt_angle;
+        
+    /* Give back some memory */
+    free_square_matrix(RtR, 3);
+    sfree(ref_s_1);
+    sfree(act_s_1);
+    for (i=0; i<3; i++)
+        sfree(eigvec[i]);
+    sfree(eigvec);
+    
+    return (real) opt_angle;
+}
+
+
+/* Determine angle of the group by RMSD fit to the reference */
+/* Not parallelized, call this routine only on the master */
+static real flex_fit_angle(t_rotgrp *rotg)
+{
+    int         i;
+    rvec        *fitcoords=NULL;
+    rvec        center;         /* Center of positions passed to the fit routine */
+    real        fitangle;       /* Angle of the rotation group derived by fitting */
+    rvec        coord;
+    real        scal;
+    gmx_enfrotgrp_t erg;        /* Pointer to enforced rotation group data */
+
+    
+    erg=rotg->enfrotgrp;
+
+    /* Get the center of the rotation group.
+     * Note, again, erg->xc has been sorted in do_flexible */
+    get_center(erg->xc, erg->mc_sorted, rotg->nat, center);
+
+    /* === Determine the optimal fit angle for the rotation group === */
+    if (rotg->eFittype == erotgFitNORM)
+    {
+        /* Normalize every position to it's reference length */
+        for (i=0; i<rotg->nat; i++)
+        {
+            /* Put the center of the positions into the origin */
+            rvec_sub(erg->xc[i], center, coord);
+            /* Determine the scaling factor for the length: */
+            scal = erg->xc_ref_length[erg->xc_sortind[i]] / norm(coord);
+            /* Get position, multiply with the scaling factor and save  */
+            svmul(scal, coord, erg->xc_norm[i]);
+        }
+        fitcoords = erg->xc_norm;
+    }
+    else
+    {
+        fitcoords = erg->xc;
+    }
+    /* From the point of view of the current positions, the reference has rotated
+     * backwards. Since we output the angle relative to the fixed reference,
+     * we need the minus sign. */
+    fitangle = -opt_angle_analytic(erg->xc_ref_sorted, fitcoords, erg->mc_sorted,
+                                   rotg->nat, erg->xc_ref_center, center, rotg->vec);
+
+    return fitangle;
+}
+
+
+/* Determine actual angle of each slab by RMSD fit to the reference */
+/* Not parallelized, call this routine only on the master */
+static void flex_fit_angle_perslab(
+        int  g,
+        t_rotgrp *rotg,
+        double t,
+        real degangle,
+        FILE *fp)
+{
+    int         i,l,n,islab,ind;
+    rvec        curr_x, ref_x;
+    rvec        act_center;  /* Center of actual positions that are passed to the fit routine */
+    rvec        ref_center;  /* Same for the reference positions */
+    real        fitangle;    /* Angle of a slab derived from an RMSD fit to
+                              * the reference structure at t=0  */
+    t_gmx_slabdata *sd;
+    gmx_enfrotgrp_t erg;     /* Pointer to enforced rotation group data */
+    real        OOm_av;      /* 1/average_mass of a rotation group atom */
+    real        m_rel;       /* Relative mass of a rotation group atom  */
+
+
+    erg=rotg->enfrotgrp;
+
+    /* Average mass of a rotation group atom: */
+    OOm_av = erg->invmass*rotg->nat;
+
+    /**********************************/
+    /* First collect the data we need */
+    /**********************************/
+
+    /* Collect the data for the individual slabs */
+    for (n = erg->slab_first; n <= erg->slab_last; n++)
+    {
+        islab = n - erg->slab_first; /* slab index */
+        sd = &(rotg->enfrotgrp->slab_data[islab]);
+        sd->nat = erg->lastatom[islab]-erg->firstatom[islab]+1;
+        ind = 0;
+
+        /* Loop over the relevant atoms in the slab */
+        for (l=erg->firstatom[islab]; l<=erg->lastatom[islab]; l++)
+        {
+            /* Current position of this atom: x[ii][XX/YY/ZZ] */
+            copy_rvec(erg->xc[l], curr_x);
+
+            /* The (unrotated) reference position of this atom is copied to ref_x.
+             * Beware, the xc coords have been sorted in do_flexible */
+            copy_rvec(erg->xc_ref_sorted[l], ref_x);
+
+            /* Save data for doing angular RMSD fit later */
+            /* Save the current atom position */
+            copy_rvec(curr_x, sd->x[ind]);
+            /* Save the corresponding reference position */
+            copy_rvec(ref_x , sd->ref[ind]);
+
+            /* Maybe also mass-weighting was requested. If yes, additionally
+             * multiply the weights with the relative mass of the atom. If not,
+             * multiply with unity. */
+            m_rel = erg->mc_sorted[l]*OOm_av;
+
+            /* Save the weight for this atom in this slab */
+            sd->weight[ind] = gaussian_weight(curr_x, rotg, n) * m_rel;
+
+            /* Next atom in this slab */
+            ind++;
+        }
+    }
+
+    /******************************/
+    /* Now do the fit calculation */
+    /******************************/
+
+    fprintf(fp, "%12.3e%6d%12.3f", t, g, degangle);
+
+    /* === Now do RMSD fitting for each slab === */
+    /* We require at least SLAB_MIN_ATOMS in a slab, such that the fit makes sense. */
+#define SLAB_MIN_ATOMS 4
+
+    for (n = erg->slab_first; n <= erg->slab_last; n++)
+    {
+        islab = n - erg->slab_first; /* slab index */
+        sd = &(rotg->enfrotgrp->slab_data[islab]);
+        if (sd->nat >= SLAB_MIN_ATOMS)
+        {
+            /* Get the center of the slabs reference and current positions */
+            get_center(sd->ref, sd->weight, sd->nat, ref_center);
+            get_center(sd->x  , sd->weight, sd->nat, act_center);
+            if (rotg->eFittype == erotgFitNORM)
+            {
+                /* Normalize every position to it's reference length
+                 * prior to performing the fit */
+                for (i=0; i<sd->nat;i++) /* Center */
+                {
+                    rvec_dec(sd->ref[i], ref_center);
+                    rvec_dec(sd->x[i]  , act_center);
+                    /* Normalize x_i such that it gets the same length as ref_i */
+                    svmul( norm(sd->ref[i])/norm(sd->x[i]), sd->x[i], sd->x[i] );
+                }
+                /* We already subtracted the centers */
+                clear_rvec(ref_center);
+                clear_rvec(act_center);
+            }
+            fitangle = -opt_angle_analytic(sd->ref, sd->x, sd->weight, sd->nat,
+                                           ref_center, act_center, rotg->vec);
+            fprintf(fp, "%6d%6d%12.3f", n, sd->nat, fitangle);
+        }
+    }
+    fprintf(fp     , "\n");
+
+#undef SLAB_MIN_ATOMS
+}
+
+
+/* Shift x with is */
+static gmx_inline void shift_single_coord(matrix box, rvec x, const ivec is)
+{
+    int tx,ty,tz;
+
+
+    tx=is[XX];
+    ty=is[YY];
+    tz=is[ZZ];
+
+    if(TRICLINIC(box))
+    {
+        x[XX] += tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
+        x[YY] += ty*box[YY][YY]+tz*box[ZZ][YY];
+        x[ZZ] += tz*box[ZZ][ZZ];
+    } else
+    {
+        x[XX] += tx*box[XX][XX];
+        x[YY] += ty*box[YY][YY];
+        x[ZZ] += tz*box[ZZ][ZZ];
+    }
+}
+
+
+/* Determine the 'home' slab of this atom which is the
+ * slab with the highest Gaussian weight of all */
+#define round(a) (int)(a+0.5)
+static gmx_inline int get_homeslab(
+        rvec curr_x,   /* The position for which the home slab shall be determined */ 
+        rvec rotvec,   /* The rotation vector */
+        real slabdist) /* The slab distance */
+{
+    real dist;
+    
+    
+    /* The distance of the atom to the coordinate center (where the
+     * slab with index 0) is */
+    dist = iprod(rotvec, curr_x);
+    
+    return round(dist / slabdist); 
+}
+
+
+/* For a local atom determine the relevant slabs, i.e. slabs in
+ * which the gaussian is larger than min_gaussian
+ */
+static int get_single_atom_gaussians(
+        rvec      curr_x,
+        t_commrec *cr,
+        t_rotgrp  *rotg)
+{
+   int slab, homeslab;
+   real g;
+   int count = 0;
+   gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+
+   
+   erg=rotg->enfrotgrp;
+   
+   /* Determine the 'home' slab of this atom: */
+   homeslab = get_homeslab(curr_x, rotg->vec, rotg->slab_dist);
+
+   /* First determine the weight in the atoms home slab: */
+   g = gaussian_weight(curr_x, rotg, homeslab);
+   
+   erg->gn_atom[count] = g;
+   erg->gn_slabind[count] = homeslab;
+   count++;
+   
+   
+   /* Determine the max slab */
+   slab = homeslab;
+   while (g > rotg->min_gaussian)
+   {
+       slab++;
+       g = gaussian_weight(curr_x, rotg, slab);
+       erg->gn_slabind[count]=slab;
+       erg->gn_atom[count]=g;
+       count++;
+   }
+   count--;
+   
+   /* Determine the max slab */
+   slab = homeslab;
+   do
+   {
+       slab--;
+       g = gaussian_weight(curr_x, rotg, slab);       
+       erg->gn_slabind[count]=slab;
+       erg->gn_atom[count]=g;
+       count++;
+   }
+   while (g > rotg->min_gaussian);
+   count--;
+   
+   return count;
+}
+
+
+static void flex2_precalc_inner_sum(t_rotgrp *rotg, t_commrec *cr)
+{
+    int  i,n,islab;
+    rvec  xi;                /* positions in the i-sum                        */
+    rvec  xcn, ycn;          /* the current and the reference slab centers    */
+    real gaussian_xi;
+    rvec yi0;
+    rvec  rin;               /* Helper variables                              */
+    real  fac,fac2;
+    rvec innersumvec;
+    real OOpsii,OOpsiistar;
+    real sin_rin;          /* s_ii.r_ii */
+    rvec s_in,tmpvec,tmpvec2;
+    real mi,wi;            /* Mass-weighting of the positions                 */
+    real N_M;              /* N/M                                             */
+    gmx_enfrotgrp_t erg;    /* Pointer to enforced rotation group data */
+
+
+    erg=rotg->enfrotgrp;
+    N_M = rotg->nat * erg->invmass;
+
+    /* Loop over all slabs that contain something */
+    for (n=erg->slab_first; n <= erg->slab_last; n++)
+    {
+        islab = n - erg->slab_first; /* slab index */
+
+        /* The current center of this slab is saved in xcn: */
+        copy_rvec(erg->slab_center[islab], xcn);
+        /* ... and the reference center in ycn: */
+        copy_rvec(erg->slab_center_ref[islab+erg->slab_buffer], ycn);
+
+        /*** D. Calculate the whole inner sum used for second and third sum */
+        /* For slab n, we need to loop over all atoms i again. Since we sorted
+         * the atoms with respect to the rotation vector, we know that it is sufficient
+         * to calculate from firstatom to lastatom only. All other contributions will
+         * be very small. */
+        clear_rvec(innersumvec);
+        for (i = erg->firstatom[islab]; i <= erg->lastatom[islab]; i++)
+        {
+            /* Coordinate xi of this atom */
+            copy_rvec(erg->xc[i],xi);
+
+            /* The i-weights */
+            gaussian_xi = gaussian_weight(xi,rotg,n);
+            mi = erg->mc_sorted[i];  /* need the sorted mass here */
+            wi = N_M*mi;
+
+            /* Calculate rin */
+            copy_rvec(erg->xc_ref_sorted[i],yi0); /* Reference position yi0   */
+            rvec_sub(yi0, ycn, tmpvec2);          /* tmpvec2 = yi0 - ycn      */
+            mvmul(erg->rotmat, tmpvec2, rin);     /* rin = Omega.(yi0 - ycn)  */
+
+            /* Calculate psi_i* and sin */
+            rvec_sub(xi, xcn, tmpvec2);           /* tmpvec2 = xi - xcn       */
+            cprod(rotg->vec, tmpvec2, tmpvec);    /* tmpvec = v x (xi - xcn)  */
+            OOpsiistar = norm2(tmpvec)+rotg->eps; /* OOpsii* = 1/psii* = |v x (xi-xcn)|^2 + eps */
+            OOpsii = norm(tmpvec);                /* OOpsii = 1 / psii = |v x (xi - xcn)| */
+
+                                       /*         v x (xi - xcn)          */
+            unitv(tmpvec, s_in);       /*  sin = ----------------         */
+                                       /*        |v x (xi - xcn)|         */
+
+            sin_rin=iprod(s_in,rin);   /* sin_rin = sin . rin             */
+
+            /* Now the whole sum */
+            fac = OOpsii/OOpsiistar;
+            svmul(fac, rin, tmpvec);
+            fac2 = fac*fac*OOpsii;
+            svmul(fac2*sin_rin, s_in, tmpvec2);
+            rvec_dec(tmpvec, tmpvec2);
+
+            svmul(wi*gaussian_xi*sin_rin, tmpvec, tmpvec2);
+
+            rvec_inc(innersumvec,tmpvec2);
+        } /* now we have the inner sum, used both for sum2 and sum3 */
+
+        /* Save it to be used in do_flex2_lowlevel */
+        copy_rvec(innersumvec, erg->slab_innersumvec[islab]);
+    } /* END of loop over slabs */
+}
+
+
+static void flex_precalc_inner_sum(t_rotgrp *rotg, t_commrec *cr)
+{
+    int   i,n,islab;
+    rvec  xi;                /* position                                      */
+    rvec  xcn, ycn;          /* the current and the reference slab centers    */
+    rvec  qin,rin;           /* q_i^n and r_i^n                               */
+    real  bin;
+    rvec  tmpvec;
+    rvec  innersumvec;       /* Inner part of sum_n2                          */
+    real  gaussian_xi;       /* Gaussian weight gn(xi)                        */
+    real  mi,wi;             /* Mass-weighting of the positions               */
+    real  N_M;               /* N/M                                           */
+
+    gmx_enfrotgrp_t erg;    /* Pointer to enforced rotation group data */
+
+
+    erg=rotg->enfrotgrp;
+    N_M = rotg->nat * erg->invmass;
+
+    /* Loop over all slabs that contain something */
+    for (n=erg->slab_first; n <= erg->slab_last; n++)
+    {
+        islab = n - erg->slab_first; /* slab index */
+
+        /* The current center of this slab is saved in xcn: */
+        copy_rvec(erg->slab_center[islab], xcn);
+        /* ... and the reference center in ycn: */
+        copy_rvec(erg->slab_center_ref[islab+erg->slab_buffer], ycn);
+
+        /* For slab n, we need to loop over all atoms i again. Since we sorted
+         * the atoms with respect to the rotation vector, we know that it is sufficient
+         * to calculate from firstatom to lastatom only. All other contributions will
+         * be very small. */
+        clear_rvec(innersumvec);
+        for (i=erg->firstatom[islab]; i<=erg->lastatom[islab]; i++)
+        {
+            /* Coordinate xi of this atom */
+            copy_rvec(erg->xc[i],xi);
+
+            /* The i-weights */
+            gaussian_xi = gaussian_weight(xi,rotg,n);
+            mi = erg->mc_sorted[i];  /* need the sorted mass here */
+            wi = N_M*mi;
+
+            /* Calculate rin and qin */
+            rvec_sub(erg->xc_ref_sorted[i], ycn, tmpvec); /* tmpvec = yi0-ycn */
+            mvmul(erg->rotmat, tmpvec, rin);      /* rin = Omega.(yi0 - ycn)  */
+            cprod(rotg->vec, rin, tmpvec);    /* tmpvec = v x Omega*(yi0-ycn) */
+
+                                             /*        v x Omega*(yi0-ycn)    */
+            unitv(tmpvec, qin);              /* qin = ---------------------   */
+                                             /*       |v x Omega*(yi0-ycn)|   */
+
+            /* Calculate bin */
+            rvec_sub(xi, xcn, tmpvec);            /* tmpvec = xi-xcn          */
+            bin = iprod(qin, tmpvec);             /* bin  = qin*(xi-xcn)      */
+
+            svmul(wi*gaussian_xi*bin, qin, tmpvec);
+
+            /* Add this contribution to the inner sum: */
+            rvec_add(innersumvec, tmpvec, innersumvec);
+        } /* now we have the inner sum vector S^n for this slab */
+        /* Save it to be used in do_flex_lowlevel */
+        copy_rvec(innersumvec, erg->slab_innersumvec[islab]);
+    }
+}
+
+
+static real do_flex2_lowlevel(
+        t_rotgrp  *rotg,
+        real      sigma,    /* The Gaussian width sigma */
+        rvec      x[],
+        gmx_bool  bOutstepRot,
+        gmx_bool  bOutstepSlab,
+        matrix    box,
+        t_commrec *cr)
+{
+    int  count,ic,ii,j,m,n,islab,iigrp,ifit;
+    rvec xj;                 /* position in the i-sum                         */
+    rvec yj0;                /* the reference position in the j-sum           */
+    rvec xcn, ycn;           /* the current and the reference slab centers    */
+    real V;                  /* This node's part of the rotation pot. energy  */
+    real gaussian_xj;        /* Gaussian weight                               */
+    real beta;
+
+    real  numerator,fit_numerator;
+    rvec  rjn,fit_rjn;       /* Helper variables                              */
+    real  fac,fac2;
+
+    real OOpsij,OOpsijstar;
+    real OOsigma2;           /* 1/(sigma^2)                                   */
+    real sjn_rjn;
+    real betasigpsi;
+    rvec sjn,tmpvec,tmpvec2,yj0_ycn;
+    rvec sum1vec_part,sum1vec,sum2vec_part,sum2vec,sum3vec,sum4vec,innersumvec;
+    real sum3,sum4;
+    gmx_enfrotgrp_t erg;     /* Pointer to enforced rotation group data       */
+    real mj,wj;              /* Mass-weighting of the positions               */
+    real N_M;                /* N/M                                           */
+    real Wjn;                /* g_n(x_j) m_j / Mjn                            */
+    gmx_bool bCalcPotFit;
+
+    /* To calculate the torque per slab */
+    rvec slab_force;         /* Single force from slab n on one atom          */
+    rvec slab_sum1vec_part;
+    real slab_sum3part,slab_sum4part;
+    rvec slab_sum1vec, slab_sum2vec, slab_sum3vec, slab_sum4vec;
+
+
+    erg=rotg->enfrotgrp;
+
+    /* Pre-calculate the inner sums, so that we do not have to calculate
+     * them again for every atom */
+    flex2_precalc_inner_sum(rotg, cr);
+
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+    /********************************************************/
+    /* Main loop over all local atoms of the rotation group */
+    /********************************************************/
+    N_M = rotg->nat * erg->invmass;
+    V = 0.0;
+    OOsigma2 = 1.0 / (sigma*sigma);
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        /* Local index of a rotation group atom  */
+        ii = erg->ind_loc[j];
+        /* Position of this atom in the collective array */
+        iigrp = erg->xc_ref_ind[j];
+        /* Mass-weighting */
+        mj = erg->mc[iigrp];  /* need the unsorted mass here */
+        wj = N_M*mj;
+        
+        /* Current position of this atom: x[ii][XX/YY/ZZ]
+         * Note that erg->xc_center contains the center of mass in case the flex2-t
+         * potential was chosen. For the flex2 potential erg->xc_center must be
+         * zero. */
+        rvec_sub(x[ii], erg->xc_center, xj);
+
+        /* Shift this atom such that it is near its reference */
+        shift_single_coord(box, xj, erg->xc_shifts[iigrp]);
+
+        /* Determine the slabs to loop over, i.e. the ones with contributions
+         * larger than min_gaussian */
+        count = get_single_atom_gaussians(xj, cr, rotg);
+        
+        clear_rvec(sum1vec_part);
+        clear_rvec(sum2vec_part);
+        sum3 = 0.0;
+        sum4 = 0.0;
+        /* Loop over the relevant slabs for this atom */
+        for (ic=0; ic < count; ic++)  
+        {
+            n = erg->gn_slabind[ic];
+            
+            /* Get the precomputed Gaussian value of curr_slab for curr_x */
+            gaussian_xj = erg->gn_atom[ic];
+
+            islab = n - erg->slab_first; /* slab index */
+            
+            /* The (unrotated) reference position of this atom is copied to yj0: */
+            copy_rvec(rotg->x_ref[iigrp], yj0);
+
+            beta = calc_beta(xj, rotg,n);
+
+            /* The current center of this slab is saved in xcn: */
+            copy_rvec(erg->slab_center[islab], xcn);
+            /* ... and the reference center in ycn: */
+            copy_rvec(erg->slab_center_ref[islab+erg->slab_buffer], ycn);
+            
+            rvec_sub(yj0, ycn, yj0_ycn);          /* yj0_ycn = yj0 - ycn      */
+
+            /* Rotate: */
+            mvmul(erg->rotmat, yj0_ycn, rjn);     /* rjn = Omega.(yj0 - ycn)  */
+            
+            /* Subtract the slab center from xj */
+            rvec_sub(xj, xcn, tmpvec2);           /* tmpvec2 = xj - xcn       */
+
+            /* Calculate sjn */
+            cprod(rotg->vec, tmpvec2, tmpvec);    /* tmpvec = v x (xj - xcn)  */
+
+            OOpsijstar = norm2(tmpvec)+rotg->eps; /* OOpsij* = 1/psij* = |v x (xj-xcn)|^2 + eps */
+
+            numerator = sqr(iprod(tmpvec, rjn));
+            
+            /*********************************/
+            /* Add to the rotation potential */
+            /*********************************/
+            V += 0.5*rotg->k*wj*gaussian_xj*numerator/OOpsijstar;
+
+            /* If requested, also calculate the potential for a set of angles
+             * near the current reference angle */
+            if (bCalcPotFit)
+            {
+                for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+                {
+                    mvmul(erg->PotAngleFit->rotmat[ifit], yj0_ycn, fit_rjn);
+                    fit_numerator = sqr(iprod(tmpvec, fit_rjn));
+                    erg->PotAngleFit->V[ifit] += 0.5*rotg->k*wj*gaussian_xj*fit_numerator/OOpsijstar;
+                }
+            }
+
+            /*************************************/
+            /* Now calculate the force on atom j */
+            /*************************************/
+
+            OOpsij = norm(tmpvec);    /* OOpsij = 1 / psij = |v x (xj - xcn)| */
+
+                                           /*         v x (xj - xcn)          */
+            unitv(tmpvec, sjn);            /*  sjn = ----------------         */
+                                           /*        |v x (xj - xcn)|         */
+
+            sjn_rjn=iprod(sjn,rjn);        /* sjn_rjn = sjn . rjn             */
+
+
+            /*** A. Calculate the first of the four sum terms: ****************/
+            fac = OOpsij/OOpsijstar;
+            svmul(fac, rjn, tmpvec);
+            fac2 = fac*fac*OOpsij;
+            svmul(fac2*sjn_rjn, sjn, tmpvec2);
+            rvec_dec(tmpvec, tmpvec2);
+            fac2 = wj*gaussian_xj; /* also needed for sum4 */
+            svmul(fac2*sjn_rjn, tmpvec, slab_sum1vec_part);
+            /********************/
+            /*** Add to sum1: ***/
+            /********************/
+            rvec_inc(sum1vec_part, slab_sum1vec_part); /* sum1 still needs to vector multiplied with v */
+
+            /*** B. Calculate the forth of the four sum terms: ****************/
+            betasigpsi = beta*OOsigma2*OOpsij; /* this is also needed for sum3 */
+            /********************/
+            /*** Add to sum4: ***/
+            /********************/
+            slab_sum4part = fac2*betasigpsi*fac*sjn_rjn*sjn_rjn; /* Note that fac is still valid from above */
+            sum4 += slab_sum4part;
+
+            /*** C. Calculate Wjn for second and third sum */
+            /* Note that we can safely divide by slab_weights since we check in
+             * get_slab_centers that it is non-zero. */
+            Wjn = gaussian_xj*mj/erg->slab_weights[islab];
+
+            /* We already have precalculated the inner sum for slab n */
+            copy_rvec(erg->slab_innersumvec[islab], innersumvec);
+
+            /* Weigh the inner sum vector with Wjn */
+            svmul(Wjn, innersumvec, innersumvec);
+
+            /*** E. Calculate the second of the four sum terms: */
+            /********************/
+            /*** Add to sum2: ***/
+            /********************/
+            rvec_inc(sum2vec_part, innersumvec); /* sum2 still needs to be vector crossproduct'ed with v */
+            
+            /*** F. Calculate the third of the four sum terms: */
+            slab_sum3part = betasigpsi * iprod(sjn, innersumvec);
+            sum3 += slab_sum3part; /* still needs to be multiplied with v */
+
+            /*** G. Calculate the torque on the local slab's axis: */
+            if (bOutstepRot)
+            {
+                /* Sum1 */
+                cprod(slab_sum1vec_part, rotg->vec, slab_sum1vec);
+                /* Sum2 */
+                cprod(innersumvec, rotg->vec, slab_sum2vec);
+                /* Sum3 */
+                svmul(slab_sum3part, rotg->vec, slab_sum3vec);
+                /* Sum4 */
+                svmul(slab_sum4part, rotg->vec, slab_sum4vec);
+
+                /* The force on atom ii from slab n only: */
+                for (m=0; m<DIM; m++)
+                    slab_force[m] = rotg->k * (-slab_sum1vec[m] + slab_sum2vec[m] - slab_sum3vec[m] + 0.5*slab_sum4vec[m]);
+
+                erg->slab_torque_v[islab] += torque(rotg->vec, slab_force, xj, xcn);
+            }
+        } /* END of loop over slabs */
+
+        /* Construct the four individual parts of the vector sum: */
+        cprod(sum1vec_part, rotg->vec, sum1vec);      /* sum1vec =   { } x v  */
+        cprod(sum2vec_part, rotg->vec, sum2vec);      /* sum2vec =   { } x v  */
+        svmul(sum3, rotg->vec, sum3vec);              /* sum3vec =   { } . v  */
+        svmul(sum4, rotg->vec, sum4vec);              /* sum4vec =   { } . v  */
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        for (m=0; m<DIM; m++)
+            erg->f_rot_loc[j][m] = rotg->k * (-sum1vec[m] + sum2vec[m] - sum3vec[m] + 0.5*sum4vec[m]);
+
+#ifdef SUM_PARTS
+        fprintf(stderr, "sum1: %15.8f %15.8f %15.8f\n",    -rotg->k*sum1vec[XX],    -rotg->k*sum1vec[YY],    -rotg->k*sum1vec[ZZ]);
+        fprintf(stderr, "sum2: %15.8f %15.8f %15.8f\n",     rotg->k*sum2vec[XX],     rotg->k*sum2vec[YY],     rotg->k*sum2vec[ZZ]);
+        fprintf(stderr, "sum3: %15.8f %15.8f %15.8f\n",    -rotg->k*sum3vec[XX],    -rotg->k*sum3vec[YY],    -rotg->k*sum3vec[ZZ]);
+        fprintf(stderr, "sum4: %15.8f %15.8f %15.8f\n", 0.5*rotg->k*sum4vec[XX], 0.5*rotg->k*sum4vec[YY], 0.5*rotg->k*sum4vec[ZZ]);
+#endif
+
+        PRINT_FORCE_J
+
+    } /* END of loop over local atoms */
+
+    return V;
+}
+
+
+static real do_flex_lowlevel(
+        t_rotgrp *rotg,
+        real      sigma,     /* The Gaussian width sigma                      */
+        rvec      x[],
+        gmx_bool  bOutstepRot,
+        gmx_bool  bOutstepSlab,
+        matrix    box,
+        t_commrec *cr)
+{
+    int   count,ic,ifit,ii,j,m,n,islab,iigrp;
+    rvec  xj,yj0;            /* current and reference position                */
+    rvec  xcn, ycn;          /* the current and the reference slab centers    */
+    rvec  yj0_ycn;           /* yj0 - ycn                                     */
+    rvec  xj_xcn;            /* xj - xcn                                      */
+    rvec  qjn,fit_qjn;       /* q_i^n                                         */
+    rvec  sum_n1,sum_n2;     /* Two contributions to the rotation force       */
+    rvec  innersumvec;       /* Inner part of sum_n2                          */
+    rvec  s_n;
+    rvec  force_n;           /* Single force from slab n on one atom          */
+    rvec  force_n1,force_n2; /* First and second part of force_n              */
+    rvec  tmpvec,tmpvec2,tmp_f;   /* Helper variables                         */
+    real  V;                 /* The rotation potential energy                 */
+    real  OOsigma2;          /* 1/(sigma^2)                                   */
+    real  beta;              /* beta_n(xj)                                    */
+    real  bjn, fit_bjn;      /* b_j^n                                         */
+    real  gaussian_xj;       /* Gaussian weight gn(xj)                        */
+    real  betan_xj_sigma2;
+    real  mj,wj;             /* Mass-weighting of the positions               */
+    real  N_M;               /* N/M                                           */
+    gmx_enfrotgrp_t erg;     /* Pointer to enforced rotation group data       */
+    gmx_bool bCalcPotFit;
+
+    
+    erg=rotg->enfrotgrp;
+
+    /* Pre-calculate the inner sums, so that we do not have to calculate
+     * them again for every atom */
+    flex_precalc_inner_sum(rotg, cr);
+
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+    /********************************************************/
+    /* Main loop over all local atoms of the rotation group */
+    /********************************************************/
+    OOsigma2 = 1.0/(sigma*sigma);
+    N_M = rotg->nat * erg->invmass;
+    V = 0.0;
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        /* Local index of a rotation group atom  */
+        ii = erg->ind_loc[j];
+        /* Position of this atom in the collective array */
+        iigrp = erg->xc_ref_ind[j];
+        /* Mass-weighting */
+        mj = erg->mc[iigrp];  /* need the unsorted mass here */
+        wj = N_M*mj;
+        
+        /* Current position of this atom: x[ii][XX/YY/ZZ]
+         * Note that erg->xc_center contains the center of mass in case the flex-t
+         * potential was chosen. For the flex potential erg->xc_center must be
+         * zero. */
+        rvec_sub(x[ii], erg->xc_center, xj);
+        
+        /* Shift this atom such that it is near its reference */
+        shift_single_coord(box, xj, erg->xc_shifts[iigrp]);
+
+        /* Determine the slabs to loop over, i.e. the ones with contributions
+         * larger than min_gaussian */
+        count = get_single_atom_gaussians(xj, cr, rotg);
+
+        clear_rvec(sum_n1);
+        clear_rvec(sum_n2);
+
+        /* Loop over the relevant slabs for this atom */
+        for (ic=0; ic < count; ic++)  
+        {
+            n = erg->gn_slabind[ic];
+                
+            /* Get the precomputed Gaussian for xj in slab n */
+            gaussian_xj = erg->gn_atom[ic];
+
+            islab = n - erg->slab_first; /* slab index */
+            
+            /* The (unrotated) reference position of this atom is saved in yj0: */
+            copy_rvec(rotg->x_ref[iigrp], yj0);
+
+            beta = calc_beta(xj, rotg, n);
+
+            /* The current center of this slab is saved in xcn: */
+            copy_rvec(erg->slab_center[islab], xcn);
+            /* ... and the reference center in ycn: */
+            copy_rvec(erg->slab_center_ref[islab+erg->slab_buffer], ycn);
+            
+            rvec_sub(yj0, ycn, yj0_ycn); /* yj0_ycn = yj0 - ycn */
+
+            /* Rotate: */
+            mvmul(erg->rotmat, yj0_ycn, tmpvec2); /* tmpvec2= Omega.(yj0-ycn) */
+            
+            /* Subtract the slab center from xj */
+            rvec_sub(xj, xcn, xj_xcn);           /* xj_xcn = xj - xcn         */
+            
+            /* Calculate qjn */
+            cprod(rotg->vec, tmpvec2, tmpvec); /* tmpvec= v x Omega.(yj0-ycn) */
+
+                                 /*         v x Omega.(yj0-ycn)    */
+            unitv(tmpvec,qjn);   /*  qjn = ---------------------   */
+                                 /*        |v x Omega.(yj0-ycn)|   */
+
+            bjn = iprod(qjn, xj_xcn);   /* bjn = qjn * (xj - xcn) */
+            
+            /*********************************/
+            /* Add to the rotation potential */
+            /*********************************/
+            V += 0.5*rotg->k*wj*gaussian_xj*sqr(bjn);
+            
+            /* If requested, also calculate the potential for a set of angles
+             * near the current reference angle */
+            if (bCalcPotFit)
+            {
+                for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+                {
+                    /* As above calculate Omega.(yj0-ycn), now for the other angles */
+                    mvmul(erg->PotAngleFit->rotmat[ifit], yj0_ycn, tmpvec2); /* tmpvec2= Omega.(yj0-ycn) */
+                    /* As above calculate qjn */
+                    cprod(rotg->vec, tmpvec2, tmpvec); /* tmpvec= v x Omega.(yj0-ycn) */
+                                             /*             v x Omega.(yj0-ycn)    */
+                    unitv(tmpvec,fit_qjn);   /*  fit_qjn = ---------------------   */
+                                             /*            |v x Omega.(yj0-ycn)|   */
+                    fit_bjn = iprod(fit_qjn, xj_xcn);   /* fit_bjn = fit_qjn * (xj - xcn) */
+                    /* Add to the rotation potential for this angle */
+                    erg->PotAngleFit->V[ifit] += 0.5*rotg->k*wj*gaussian_xj*sqr(fit_bjn);
+                }
+            }
+
+            /****************************************************************/
+            /* sum_n1 will typically be the main contribution to the force: */
+            /****************************************************************/
+            betan_xj_sigma2 = beta*OOsigma2;  /*  beta_n(xj)/sigma^2  */
+
+            /* The next lines calculate
+             *  qjn - (bjn*beta(xj)/(2sigma^2))v  */
+            svmul(bjn*0.5*betan_xj_sigma2, rotg->vec, tmpvec2);
+            rvec_sub(qjn,tmpvec2,tmpvec);
+
+            /* Multiply with gn(xj)*bjn: */
+            svmul(gaussian_xj*bjn,tmpvec,tmpvec2);
+
+            /* Sum over n: */
+            rvec_inc(sum_n1,tmpvec2);
+            
+            /* We already have precalculated the Sn term for slab n */
+            copy_rvec(erg->slab_innersumvec[islab], s_n);
+                                                                          /*          beta_n(xj)              */
+            svmul(betan_xj_sigma2*iprod(s_n, xj_xcn), rotg->vec, tmpvec); /* tmpvec = ---------- s_n (xj-xcn) */
+                                                                          /*            sigma^2               */
+
+            rvec_sub(s_n, tmpvec, innersumvec);
+            
+            /* We can safely divide by slab_weights since we check in get_slab_centers
+             * that it is non-zero. */
+            svmul(gaussian_xj/erg->slab_weights[islab], innersumvec, innersumvec);
+
+            rvec_add(sum_n2, innersumvec, sum_n2);
+            
+            /* Calculate the torque: */
+            if (bOutstepRot)
+            {
+                /* The force on atom ii from slab n only: */
+                svmul(-rotg->k*wj, tmpvec2    , force_n1); /* part 1 */
+                svmul( rotg->k*mj, innersumvec, force_n2); /* part 2 */
+                rvec_add(force_n1, force_n2, force_n);
+                erg->slab_torque_v[islab] += torque(rotg->vec, force_n, xj, xcn);
+            }
+        } /* END of loop over slabs */
+
+        /* Put both contributions together: */
+        svmul(wj, sum_n1, sum_n1);
+        svmul(mj, sum_n2, sum_n2);
+        rvec_sub(sum_n2,sum_n1,tmp_f); /* F = -grad V */
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        for(m=0; m<DIM; m++)
+            erg->f_rot_loc[j][m] = rotg->k*tmp_f[m];
+
+        PRINT_FORCE_J
+
+    } /* END of loop over local atoms */
+
+    return V;
+}
+
+#ifdef PRINT_COORDS
+static void print_coordinates(t_commrec *cr, t_rotgrp *rotg, rvec x[], matrix box, int step)
+{
+    int i;
+    static FILE *fp;
+    static char buf[STRLEN];
+    static gmx_bool bFirst=1;
+
+
+    if (bFirst)
+    {
+        sprintf(buf, "coords%d.txt", cr->nodeid);
+        fp = fopen(buf, "w");
+        bFirst = 0;
+    }
+
+    fprintf(fp, "\nStep %d\n", step);
+    fprintf(fp, "box: %f %f %f %f %f %f %f %f %f\n",
+            box[XX][XX], box[XX][YY], box[XX][ZZ],
+            box[YY][XX], box[YY][YY], box[YY][ZZ],
+            box[ZZ][XX], box[ZZ][ZZ], box[ZZ][ZZ]);
+    for (i=0; i<rotg->nat; i++)
+    {
+        fprintf(fp, "%4d  %f %f %f\n", i,
+                erg->xc[i][XX], erg->xc[i][YY], erg->xc[i][ZZ]);
+    }
+    fflush(fp);
+
+}
+#endif
+
+
+static int projection_compare(const void *a, const void *b)
+{
+    sort_along_vec_t *xca, *xcb;
+    
+    
+    xca = (sort_along_vec_t *)a;
+    xcb = (sort_along_vec_t *)b;
+    
+    if (xca->xcproj < xcb->xcproj)
+        return -1;
+    else if (xca->xcproj > xcb->xcproj)
+        return 1;
+    else
+        return 0;
+}
+
+
+static void sort_collective_coordinates(
+        t_rotgrp *rotg,         /* Rotation group */
+        sort_along_vec_t *data) /* Buffer for sorting the positions */
+{
+    int i;
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+
+    
+    erg=rotg->enfrotgrp;
+    
+    /* The projection of the position vector on the rotation vector is
+     * the relevant value for sorting. Fill the 'data' structure */
+    for (i=0; i<rotg->nat; i++)
+    {
+        data[i].xcproj = iprod(erg->xc[i], rotg->vec);  /* sort criterium */
+        data[i].m      = erg->mc[i];
+        data[i].ind    = i;
+        copy_rvec(erg->xc[i]    , data[i].x    );
+        copy_rvec(rotg->x_ref[i], data[i].x_ref);
+    }
+    /* Sort the 'data' structure */
+    gmx_qsort(data, rotg->nat, sizeof(sort_along_vec_t), projection_compare);
+    
+    /* Copy back the sorted values */
+    for (i=0; i<rotg->nat; i++)
+    {
+        copy_rvec(data[i].x    , erg->xc[i]           );
+        copy_rvec(data[i].x_ref, erg->xc_ref_sorted[i]);
+        erg->mc_sorted[i]  = data[i].m;
+        erg->xc_sortind[i] = data[i].ind;
+    }
+}
+
+
+/* For each slab, get the first and the last index of the sorted atom
+ * indices */
+static void get_firstlast_atom_per_slab(t_rotgrp *rotg, t_commrec *cr)
+{
+    int i,islab,n;
+    real beta;
+    gmx_enfrotgrp_t erg;     /* Pointer to enforced rotation group data */
+
+    
+    erg=rotg->enfrotgrp;
+
+    /* Find the first atom that needs to enter the calculation for each slab */
+    n = erg->slab_first;  /* slab */
+    i = 0; /* start with the first atom */
+    do
+    {
+        /* Find the first atom that significantly contributes to this slab */
+        do /* move forward in position until a large enough beta is found */
+        {
+            beta = calc_beta(erg->xc[i], rotg, n);
+            i++;
+        } while ((beta < -erg->max_beta) && (i < rotg->nat));
+        i--;
+        islab = n - erg->slab_first;  /* slab index */
+        erg->firstatom[islab] = i;
+        /* Proceed to the next slab */
+        n++;
+    } while (n <= erg->slab_last);
+    
+    /* Find the last atom for each slab */
+     n = erg->slab_last; /* start with last slab */
+     i = rotg->nat-1;  /* start with the last atom */
+     do
+     {
+         do /* move backward in position until a large enough beta is found */
+         {
+             beta = calc_beta(erg->xc[i], rotg, n);
+             i--;
+         } while ((beta > erg->max_beta) && (i > -1));
+         i++;
+         islab = n - erg->slab_first;  /* slab index */
+         erg->lastatom[islab] = i;
+         /* Proceed to the next slab */
+         n--;
+     } while (n >= erg->slab_first);
+}
+
+
+/* Determine the very first and very last slab that needs to be considered 
+ * For the first slab that needs to be considered, we have to find the smallest
+ * n that obeys:
+ * 
+ * x_first * v - n*Delta_x <= beta_max
+ * 
+ * slab index n, slab distance Delta_x, rotation vector v. For the last slab we 
+ * have to find the largest n that obeys
+ * 
+ * x_last * v - n*Delta_x >= -beta_max
+ *  
+ */
+static gmx_inline int get_first_slab(
+        t_rotgrp *rotg,     /* The rotation group (inputrec data) */
+        real     max_beta,  /* The max_beta value, instead of min_gaussian */
+        rvec     firstatom) /* First atom after sorting along the rotation vector v */
+{
+    /* Find the first slab for the first atom */   
+    return ceil((iprod(firstatom, rotg->vec) - max_beta)/rotg->slab_dist);
+}
+
+
+static gmx_inline int get_last_slab(
+        t_rotgrp *rotg,     /* The rotation group (inputrec data) */
+        real     max_beta,  /* The max_beta value, instead of min_gaussian */
+        rvec     lastatom)  /* Last atom along v */
+{
+    /* Find the last slab for the last atom */
+    return floor((iprod(lastatom, rotg->vec) + max_beta)/rotg->slab_dist);    
+}
+
+
+static void get_firstlast_slab_check(
+        t_rotgrp        *rotg,     /* The rotation group (inputrec data) */
+        t_gmx_enfrotgrp *erg,      /* The rotation group (data only accessible in this file) */
+        rvec            firstatom, /* First atom after sorting along the rotation vector v */
+        rvec            lastatom,  /* Last atom along v */
+        int             g,         /* The rotation group number */
+        t_commrec       *cr)
+{
+    erg->slab_first = get_first_slab(rotg, erg->max_beta, firstatom);
+    erg->slab_last  = get_last_slab(rotg, erg->max_beta, lastatom);
+
+    /* Check whether we have reference data to compare against */
+    if (erg->slab_first < erg->slab_first_ref)
+        gmx_fatal(FARGS, "%s No reference data for first slab (n=%d), unable to proceed.",
+                  RotStr, erg->slab_first);
+    
+    /* Check whether we have reference data to compare against */
+    if (erg->slab_last > erg->slab_last_ref)
+        gmx_fatal(FARGS, "%s No reference data for last slab (n=%d), unable to proceed.",
+                  RotStr, erg->slab_last);
+}
+
+
+/* Enforced rotation with a flexible axis */
+static void do_flexible(
+        t_commrec *cr,
+        gmx_enfrot_t enfrot,    /* Other rotation data                        */
+        t_rotgrp  *rotg,        /* The rotation group                         */
+        int       g,            /* Group number                               */
+        rvec      x[],          /* The local positions                        */
+        matrix    box,
+        double    t,            /* Time in picoseconds                        */
+        gmx_large_int_t step,   /* The time step                              */
+        gmx_bool  bOutstepRot,  /* Output to main rotation output file        */
+        gmx_bool  bOutstepSlab) /* Output per-slab data                       */
+{
+    int          l,nslabs;
+    real         sigma;       /* The Gaussian width sigma */
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+
+    
+    erg=rotg->enfrotgrp;
+
+    /* Define the sigma value */
+    sigma = 0.7*rotg->slab_dist;
+    
+    /* Sort the collective coordinates erg->xc along the rotation vector. This is
+     * an optimization for the inner loop. */
+    sort_collective_coordinates(rotg, enfrot->data);
+    
+    /* Determine the first relevant slab for the first atom and the last
+     * relevant slab for the last atom */
+    get_firstlast_slab_check(rotg, erg, erg->xc[0], erg->xc[rotg->nat-1], g, cr);
+    
+    /* Determine for each slab depending on the min_gaussian cutoff criterium,
+     * a first and a last atom index inbetween stuff needs to be calculated */
+    get_firstlast_atom_per_slab(rotg, cr);
+
+    /* Determine the gaussian-weighted center of positions for all slabs */
+    get_slab_centers(rotg,erg->xc,erg->mc_sorted,cr,g,t,enfrot->out_slabs,bOutstepSlab,FALSE);
+        
+    /* Clear the torque per slab from last time step: */
+    nslabs = erg->slab_last - erg->slab_first + 1;
+    for (l=0; l<nslabs; l++)
+        erg->slab_torque_v[l] = 0.0;
+    
+    /* Call the rotational forces kernel */
+    if (rotg->eType == erotgFLEX || rotg->eType == erotgFLEXT)
+        erg->V = do_flex_lowlevel(rotg, sigma, x, bOutstepRot, bOutstepSlab, box, cr);
+    else if (rotg->eType == erotgFLEX2 || rotg->eType == erotgFLEX2T)
+        erg->V = do_flex2_lowlevel(rotg, sigma, x, bOutstepRot, bOutstepSlab, box, cr);
+    else
+        gmx_fatal(FARGS, "Unknown flexible rotation type");
+    
+    /* Determine angle by RMSD fit to the reference - Let's hope this */
+    /* only happens once in a while, since this is not parallelized! */
+    if (MASTER(cr) && (erotgFitPOT != rotg->eFittype) )
+    {
+        if (bOutstepRot)
+        {
+            /* Fit angle of the whole rotation group */
+            erg->angle_v = flex_fit_angle(rotg);
+        }
+        if (bOutstepSlab)
+        {
+            /* Fit angle of each slab */
+            flex_fit_angle_perslab(g, rotg, t, erg->degangle, enfrot->out_angles);
+        }
+    }
+
+    /* Lump together the torques from all slabs: */
+    erg->torque_v = 0.0;
+    for (l=0; l<nslabs; l++)
+         erg->torque_v += erg->slab_torque_v[l];
+}
+
+
+/* Calculate the angle between reference and actual rotation group atom,
+ * both projected into a plane perpendicular to the rotation vector: */
+static void angle(t_rotgrp *rotg,
+        rvec x_act,
+        rvec x_ref,
+        real *alpha,
+        real *weight)  /* atoms near the rotation axis should count less than atoms far away */
+{
+    rvec xp, xrp;  /* current and reference positions projected on a plane perpendicular to pg->vec */
+    rvec dum;
+
+
+    /* Project x_ref and x into a plane through the origin perpendicular to rot_vec: */
+    /* Project x_ref: xrp = x_ref - (vec * x_ref) * vec */
+    svmul(iprod(rotg->vec, x_ref), rotg->vec, dum);
+    rvec_sub(x_ref, dum, xrp);
+    /* Project x_act: */
+    svmul(iprod(rotg->vec, x_act), rotg->vec, dum);
+    rvec_sub(x_act, dum, xp);
+
+    /* Retrieve information about which vector precedes. gmx_angle always
+     * returns a positive angle. */
+    cprod(xp, xrp, dum); /* if reference precedes, this is pointing into the same direction as vec */
+
+    if (iprod(rotg->vec, dum) >= 0)
+        *alpha = -gmx_angle(xrp, xp);
+    else
+        *alpha = +gmx_angle(xrp, xp);
+    
+    /* Also return the weight */
+    *weight = norm(xp);
+}
+
+
+/* Project first vector onto a plane perpendicular to the second vector 
+ * dr = dr - (dr.v)v
+ * Note that v must be of unit length.
+ */
+static gmx_inline void project_onto_plane(rvec dr, const rvec v)
+{
+    rvec tmp;
+    
+    
+    svmul(iprod(dr,v),v,tmp);  /* tmp = (dr.v)v */
+    rvec_dec(dr, tmp);         /* dr = dr - (dr.v)v */
+}
+
+
+/* Fixed rotation: The rotation reference group rotates around the v axis. */
+/* The atoms of the actual rotation group are attached with imaginary  */
+/* springs to the reference atoms.                                     */
+static void do_fixed(
+        t_commrec *cr,
+        t_rotgrp  *rotg,        /* The rotation group                         */
+        rvec      x[],          /* The positions                              */
+        matrix    box,          /* The simulation box                         */
+        double    t,            /* Time in picoseconds                        */
+        gmx_large_int_t step,   /* The time step                              */
+        gmx_bool  bOutstepRot,  /* Output to main rotation output file        */
+        gmx_bool  bOutstepSlab) /* Output per-slab data                       */
+{
+    int       ifit,j,jj,m;
+    rvec      dr;
+    rvec      tmp_f;           /* Force */
+    real      alpha;           /* a single angle between an actual and a reference position */
+    real      weight;          /* single weight for a single angle */
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec      xi_xc;           /* xi - xc */
+    gmx_bool  bCalcPotFit;
+    rvec      fit_xr_loc;
+
+    /* for mass weighting: */
+    real      wi;              /* Mass-weighting of the positions */
+    real      N_M;             /* N/M */
+    real      k_wi;            /* k times wi */
+
+    gmx_bool  bProject;
+
+    
+    erg=rotg->enfrotgrp;
+    bProject = (rotg->eType==erotgPM) || (rotg->eType==erotgPMPF);
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+    N_M = rotg->nat * erg->invmass;
+
+    /* Each process calculates the forces on its local atoms */
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        /* Calculate (x_i-x_c) resp. (x_i-u) */
+        rvec_sub(erg->x_loc_pbc[j], erg->xc_center, xi_xc);
+
+        /* Calculate Omega*(y_i-y_c)-(x_i-x_c) */
+        rvec_sub(erg->xr_loc[j], xi_xc, dr);
+        
+        if (bProject)
+            project_onto_plane(dr, rotg->vec);
+            
+        /* Mass-weighting */
+        wi = N_M*erg->m_loc[j];
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        k_wi = rotg->k*wi;
+        for (m=0; m<DIM; m++)
+        {
+            tmp_f[m]             = k_wi*dr[m];
+            erg->f_rot_loc[j][m] = tmp_f[m];
+            erg->V              += 0.5*k_wi*sqr(dr[m]);
+        }
+        
+        /* If requested, also calculate the potential for a set of angles
+         * near the current reference angle */
+        if (bCalcPotFit)
+        {
+            for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+            {
+                /* Index of this rotation group atom with respect to the whole rotation group */
+                jj = erg->xc_ref_ind[j];
+
+                /* Rotate with the alternative angle. Like rotate_local_reference(),
+                 * just for a single local atom */
+                mvmul(erg->PotAngleFit->rotmat[ifit], rotg->x_ref[jj], fit_xr_loc); /* fit_xr_loc = Omega*(y_i-y_c) */
+
+                /* Calculate Omega*(y_i-y_c)-(x_i-x_c) */
+                rvec_sub(fit_xr_loc, xi_xc, dr);
+
+                if (bProject)
+                    project_onto_plane(dr, rotg->vec);
+
+                /* Add to the rotation potential for this angle: */
+                erg->PotAngleFit->V[ifit] += 0.5*k_wi*norm2(dr);
+            }
+        }
+
+        if (bOutstepRot)
+        {
+            /* Add to the torque of this rotation group */
+            erg->torque_v += torque(rotg->vec, tmp_f, erg->x_loc_pbc[j], erg->xc_center);
+            
+            /* Calculate the angle between reference and actual rotation group atom. */
+            angle(rotg, xi_xc, erg->xr_loc[j], &alpha, &weight);  /* angle in rad, weighted */
+            erg->angle_v  += alpha * weight;
+            erg->weight_v += weight;
+        }
+        /* If you want enforced rotation to contribute to the virial,
+         * activate the following lines:
+            if (MASTER(cr))
+            {
+               Add the rotation contribution to the virial
+              for(j=0; j<DIM; j++)
+                for(m=0;m<DIM;m++)
+                  vir[j][m] += 0.5*f[ii][j]*dr[m];
+            }
+         */
+
+        PRINT_FORCE_J
+
+    } /* end of loop over local rotation group atoms */
+}
+
+
+/* Calculate the radial motion potential and forces */
+static void do_radial_motion(
+        t_commrec *cr,
+        t_rotgrp  *rotg,        /* The rotation group                         */
+        rvec      x[],          /* The positions                              */
+        matrix    box,          /* The simulation box                         */
+        double    t,            /* Time in picoseconds                        */
+        gmx_large_int_t step,   /* The time step                              */
+        gmx_bool  bOutstepRot,  /* Output to main rotation output file        */
+        gmx_bool  bOutstepSlab) /* Output per-slab data                       */
+{
+    int       j,jj,ifit;
+    rvec      tmp_f;           /* Force */
+    real      alpha;           /* a single angle between an actual and a reference position */
+    real      weight;          /* single weight for a single angle */
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec      xj_u;            /* xj - u */
+    rvec      tmpvec,fit_tmpvec;
+    real      fac,fac2,sum=0.0;
+    rvec      pj;
+    gmx_bool  bCalcPotFit;
+
+    /* For mass weighting: */
+    real      wj;              /* Mass-weighting of the positions */
+    real      N_M;             /* N/M */
+
+
+    erg=rotg->enfrotgrp;
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+    N_M = rotg->nat * erg->invmass;
+
+    /* Each process calculates the forces on its local atoms */
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        /* Calculate (xj-u) */
+        rvec_sub(erg->x_loc_pbc[j], erg->xc_center, xj_u);  /* xj_u = xj-u */
+
+        /* Calculate Omega.(yj0-u) */
+        cprod(rotg->vec, erg->xr_loc[j], tmpvec);  /* tmpvec = v x Omega.(yj0-u) */
+
+                              /*         v x Omega.(yj0-u)     */
+        unitv(tmpvec, pj);    /*  pj = ---------------------   */
+                              /*       | v x Omega.(yj0-u) |   */
+
+        fac = iprod(pj, xj_u);  /* fac = pj.(xj-u) */
+        fac2 = fac*fac;
+
+        /* Mass-weighting */
+        wj = N_M*erg->m_loc[j];
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        svmul(-rotg->k*wj*fac, pj, tmp_f);
+        copy_rvec(tmp_f, erg->f_rot_loc[j]);
+        sum += wj*fac2;
+
+        /* If requested, also calculate the potential for a set of angles
+         * near the current reference angle */
+        if (bCalcPotFit)
+        {
+            for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+            {
+                /* Index of this rotation group atom with respect to the whole rotation group */
+                jj = erg->xc_ref_ind[j];
+
+                /* Rotate with the alternative angle. Like rotate_local_reference(),
+                 * just for a single local atom */
+                mvmul(erg->PotAngleFit->rotmat[ifit], rotg->x_ref[jj], fit_tmpvec); /* fit_tmpvec = Omega*(yj0-u) */
+
+                /* Calculate Omega.(yj0-u) */
+                cprod(rotg->vec, fit_tmpvec, tmpvec);  /* tmpvec = v x Omega.(yj0-u) */
+                                      /*         v x Omega.(yj0-u)     */
+                unitv(tmpvec, pj);    /*  pj = ---------------------   */
+                                      /*       | v x Omega.(yj0-u) |   */
+
+                fac = iprod(pj, xj_u);  /* fac = pj.(xj-u) */
+                fac2 = fac*fac;
+
+                /* Add to the rotation potential for this angle: */
+                erg->PotAngleFit->V[ifit] += 0.5*rotg->k*wj*fac2;
+            }
+        }
+
+        if (bOutstepRot)
+        {
+            /* Add to the torque of this rotation group */
+            erg->torque_v += torque(rotg->vec, tmp_f, erg->x_loc_pbc[j], erg->xc_center);
+
+            /* Calculate the angle between reference and actual rotation group atom. */
+            angle(rotg, xj_u, erg->xr_loc[j], &alpha, &weight);  /* angle in rad, weighted */
+            erg->angle_v  += alpha * weight;
+            erg->weight_v += weight;
+        }
+
+        PRINT_FORCE_J
+
+    } /* end of loop over local rotation group atoms */
+    erg->V = 0.5*rotg->k*sum;
+}
+
+
+/* Calculate the radial motion pivot-free potential and forces */
+static void do_radial_motion_pf(
+        t_commrec *cr,
+        t_rotgrp  *rotg,        /* The rotation group                         */
+        rvec      x[],          /* The positions                              */
+        matrix    box,          /* The simulation box                         */
+        double    t,            /* Time in picoseconds                        */
+        gmx_large_int_t step,   /* The time step                              */
+        gmx_bool  bOutstepRot,  /* Output to main rotation output file        */
+        gmx_bool  bOutstepSlab) /* Output per-slab data                       */
+{
+    int       i,ii,iigrp,ifit,j;
+    rvec      xj;              /* Current position */
+    rvec      xj_xc;           /* xj  - xc  */
+    rvec      yj0_yc0;         /* yj0 - yc0 */
+    rvec      tmp_f;           /* Force */
+    real      alpha;           /* a single angle between an actual and a reference position */
+    real      weight;          /* single weight for a single angle */
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec      tmpvec, tmpvec2;
+    rvec      innersumvec;     /* Precalculation of the inner sum */
+    rvec      innersumveckM;
+    real      fac,fac2,V=0.0;
+    rvec      qi,qj;
+    gmx_bool  bCalcPotFit;
+
+    /* For mass weighting: */
+    real      mj,wi,wj;        /* Mass-weighting of the positions */
+    real      N_M;             /* N/M */
+
+
+    erg=rotg->enfrotgrp;
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+    N_M = rotg->nat * erg->invmass;
+
+    /* Get the current center of the rotation group: */
+    get_center(erg->xc, erg->mc, rotg->nat, erg->xc_center);
+
+    /* Precalculate Sum_i [ wi qi.(xi-xc) qi ] which is needed for every single j */
+    clear_rvec(innersumvec);
+    for (i=0; i < rotg->nat; i++)
+    {
+        /* Mass-weighting */
+        wi = N_M*erg->mc[i];
+
+        /* Calculate qi. Note that xc_ref_center has already been subtracted from
+         * x_ref in init_rot_group.*/
+        mvmul(erg->rotmat, rotg->x_ref[i], tmpvec);  /* tmpvec  = Omega.(yi0-yc0) */
+
+        cprod(rotg->vec, tmpvec, tmpvec2);          /* tmpvec2 = v x Omega.(yi0-yc0) */
+
+                              /*         v x Omega.(yi0-yc0)     */
+        unitv(tmpvec2, qi);   /*  qi = -----------------------   */
+                              /*       | v x Omega.(yi0-yc0) |   */
+
+        rvec_sub(erg->xc[i], erg->xc_center, tmpvec);  /* tmpvec = xi-xc */
+
+        svmul(wi*iprod(qi, tmpvec), qi, tmpvec2);
+
+        rvec_inc(innersumvec, tmpvec2);
+    }
+    svmul(rotg->k*erg->invmass, innersumvec, innersumveckM);
+
+    /* Each process calculates the forces on its local atoms */
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        /* Local index of a rotation group atom  */
+        ii = erg->ind_loc[j];
+        /* Position of this atom in the collective array */
+        iigrp = erg->xc_ref_ind[j];
+        /* Mass-weighting */
+        mj = erg->mc[iigrp];  /* need the unsorted mass here */
+        wj = N_M*mj;
+
+        /* Current position of this atom: x[ii][XX/YY/ZZ] */
+        copy_rvec(x[ii], xj);
+
+        /* Shift this atom such that it is near its reference */
+        shift_single_coord(box, xj, erg->xc_shifts[iigrp]);
+
+        /* The (unrotated) reference position is yj0. yc0 has already
+         * been subtracted in init_rot_group */
+        copy_rvec(rotg->x_ref[iigrp], yj0_yc0);   /* yj0_yc0 = yj0 - yc0      */
+
+        /* Calculate Omega.(yj0-yc0) */
+        mvmul(erg->rotmat, yj0_yc0, tmpvec2);     /* tmpvec2 = Omega.(yj0 - yc0)  */
+
+        cprod(rotg->vec, tmpvec2, tmpvec);  /* tmpvec = v x Omega.(yj0-yc0) */
+
+                              /*         v x Omega.(yj0-yc0)     */
+        unitv(tmpvec, qj);    /*  qj = -----------------------   */
+                              /*       | v x Omega.(yj0-yc0) |   */
+
+        /* Calculate (xj-xc) */
+        rvec_sub(xj, erg->xc_center, xj_xc);  /* xj_xc = xj-xc */
+
+        fac = iprod(qj, xj_xc);  /* fac = qj.(xj-xc) */
+        fac2 = fac*fac;
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        svmul(-rotg->k*wj*fac, qj, tmp_f); /* part 1 of force */
+        svmul(mj, innersumveckM, tmpvec);  /* part 2 of force */
+        rvec_inc(tmp_f, tmpvec);
+        copy_rvec(tmp_f, erg->f_rot_loc[j]);
+        V += wj*fac2;
+
+        /* If requested, also calculate the potential for a set of angles
+         * near the current reference angle */
+        if (bCalcPotFit)
+        {
+            for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+            {
+                /* Rotate with the alternative angle. Like rotate_local_reference(),
+                 * just for a single local atom */
+                mvmul(erg->PotAngleFit->rotmat[ifit], yj0_yc0, tmpvec2); /* tmpvec2 = Omega*(yj0-yc0) */
+
+                /* Calculate Omega.(yj0-u) */
+                cprod(rotg->vec, tmpvec2, tmpvec);  /* tmpvec = v x Omega.(yj0-yc0) */
+                                      /*         v x Omega.(yj0-yc0)     */
+                unitv(tmpvec, qj);    /*  qj = -----------------------   */
+                                      /*       | v x Omega.(yj0-yc0) |   */
+
+                fac = iprod(qj, xj_xc);  /* fac = qj.(xj-xc) */
+                fac2 = fac*fac;
+
+                /* Add to the rotation potential for this angle: */
+                erg->PotAngleFit->V[ifit] += 0.5*rotg->k*wj*fac2;
+            }
+        }
+
+        if (bOutstepRot)
+        {
+            /* Add to the torque of this rotation group */
+            erg->torque_v += torque(rotg->vec, tmp_f, xj, erg->xc_center);
+
+            /* Calculate the angle between reference and actual rotation group atom. */
+            angle(rotg, xj_xc, yj0_yc0, &alpha, &weight);  /* angle in rad, weighted */
+            erg->angle_v  += alpha * weight;
+            erg->weight_v += weight;
+        }
+
+        PRINT_FORCE_J
+
+    } /* end of loop over local rotation group atoms */
+    erg->V = 0.5*rotg->k*V;
+}
+
+
+/* Precalculate the inner sum for the radial motion 2 forces */
+static void radial_motion2_precalc_inner_sum(t_rotgrp  *rotg, rvec innersumvec)
+{
+    int       i;
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec      xi_xc;           /* xj - xc */
+    rvec      tmpvec,tmpvec2;
+    real      fac,fac2;
+    rvec      ri,si;
+    real      siri;
+    rvec      v_xi_xc;          /* v x (xj - u) */
+    real      psii,psiistar;
+    real      wi;              /* Mass-weighting of the positions */
+    real      N_M;             /* N/M */
+    rvec      sumvec;
+
+    erg=rotg->enfrotgrp;
+    N_M = rotg->nat * erg->invmass;
+
+    /* Loop over the collective set of positions */
+    clear_rvec(sumvec);
+    for (i=0; i<rotg->nat; i++)
+    {
+        /* Mass-weighting */
+        wi = N_M*erg->mc[i];
+
+        rvec_sub(erg->xc[i], erg->xc_center, xi_xc); /* xi_xc = xi-xc         */
+
+        /* Calculate ri. Note that xc_ref_center has already been subtracted from
+         * x_ref in init_rot_group.*/
+        mvmul(erg->rotmat, rotg->x_ref[i], ri);      /* ri  = Omega.(yi0-yc0) */
+
+        cprod(rotg->vec, xi_xc, v_xi_xc);            /* v_xi_xc = v x (xi-u)  */
+
+        fac = norm2(v_xi_xc);
+                                          /*                      1           */
+        psiistar = 1.0/(fac + rotg->eps); /* psiistar = --------------------- */
+                                          /*            |v x (xi-xc)|^2 + eps */
+
+        psii = gmx_invsqrt(fac);          /*                 1                */
+                                          /*  psii    = -------------         */
+                                          /*            |v x (xi-xc)|         */
+
+        svmul(psii, v_xi_xc, si);          /*  si = psii * (v x (xi-xc) )     */
+
+        fac = iprod(v_xi_xc, ri);                   /* fac = (v x (xi-xc)).ri */
+        fac2 = fac*fac;
+
+        siri = iprod(si, ri);                       /* siri = si.ri           */
+
+        svmul(psiistar/psii, ri, tmpvec);
+        svmul(psiistar*psiistar/(psii*psii*psii) * siri, si, tmpvec2);
+        rvec_dec(tmpvec, tmpvec2);
+        cprod(tmpvec, rotg->vec, tmpvec2);
+
+        svmul(wi*siri, tmpvec2, tmpvec);
+
+        rvec_inc(sumvec, tmpvec);
+    }
+    svmul(rotg->k*erg->invmass, sumvec, innersumvec);
+}
+
+
+/* Calculate the radial motion 2 potential and forces */
+static void do_radial_motion2(
+        t_commrec *cr,
+        t_rotgrp  *rotg,        /* The rotation group                         */
+        rvec      x[],          /* The positions                              */
+        matrix    box,          /* The simulation box                         */
+        double    t,            /* Time in picoseconds                        */
+        gmx_large_int_t step,   /* The time step                              */
+        gmx_bool  bOutstepRot,  /* Output to main rotation output file        */
+        gmx_bool  bOutstepSlab) /* Output per-slab data                       */
+{
+    int       ii,iigrp,ifit,j;
+    rvec      xj;              /* Position */
+    real      alpha;           /* a single angle between an actual and a reference position */
+    real      weight;          /* single weight for a single angle */
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec      xj_u;            /* xj - u */
+    rvec      yj0_yc0;         /* yj0 -yc0 */
+    rvec      tmpvec,tmpvec2;
+    real      fac,fit_fac,fac2,Vpart=0.0;
+    rvec      rj,fit_rj,sj;
+    real      sjrj;
+    rvec      v_xj_u;          /* v x (xj - u) */
+    real      psij,psijstar;
+    real      mj,wj;           /* For mass-weighting of the positions */
+    real      N_M;             /* N/M */
+    gmx_bool  bPF;
+    rvec      innersumvec;
+    gmx_bool  bCalcPotFit;
+
+
+    erg=rotg->enfrotgrp;
+
+    bPF = rotg->eType==erotgRM2PF;
+    bCalcPotFit = (bOutstepRot || bOutstepSlab) && (erotgFitPOT==rotg->eFittype);
+
+
+    clear_rvec(yj0_yc0); /* Make the compiler happy */
+
+    clear_rvec(innersumvec);
+    if (bPF)
+    {
+        /* For the pivot-free variant we have to use the current center of
+         * mass of the rotation group instead of the pivot u */
+        get_center(erg->xc, erg->mc, rotg->nat, erg->xc_center);
+
+        /* Also, we precalculate the second term of the forces that is identical
+         * (up to the weight factor mj) for all forces */
+        radial_motion2_precalc_inner_sum(rotg,innersumvec);
+    }
+
+    N_M = rotg->nat * erg->invmass;
+
+    /* Each process calculates the forces on its local atoms */
+    for (j=0; j<erg->nat_loc; j++)
+    {
+        if (bPF)
+        {
+            /* Local index of a rotation group atom  */
+            ii = erg->ind_loc[j];
+            /* Position of this atom in the collective array */
+            iigrp = erg->xc_ref_ind[j];
+            /* Mass-weighting */
+            mj = erg->mc[iigrp];
+
+            /* Current position of this atom: x[ii] */
+            copy_rvec(x[ii], xj);
+
+            /* Shift this atom such that it is near its reference */
+            shift_single_coord(box, xj, erg->xc_shifts[iigrp]);
+
+            /* The (unrotated) reference position is yj0. yc0 has already
+             * been subtracted in init_rot_group */
+            copy_rvec(rotg->x_ref[iigrp], yj0_yc0);   /* yj0_yc0 = yj0 - yc0  */
+
+            /* Calculate Omega.(yj0-yc0) */
+            mvmul(erg->rotmat, yj0_yc0, rj);         /* rj = Omega.(yj0-yc0)  */
+        }
+        else
+        {
+            mj = erg->m_loc[j];
+            copy_rvec(erg->x_loc_pbc[j], xj);
+            copy_rvec(erg->xr_loc[j], rj);           /* rj = Omega.(yj0-u)    */
+        }
+        /* Mass-weighting */
+        wj = N_M*mj;
+
+        /* Calculate (xj-u) resp. (xj-xc) */
+        rvec_sub(xj, erg->xc_center, xj_u);          /* xj_u = xj-u           */
+
+        cprod(rotg->vec, xj_u, v_xj_u);              /* v_xj_u = v x (xj-u)   */
+
+        fac = norm2(v_xj_u);
+                                          /*                      1           */
+        psijstar = 1.0/(fac + rotg->eps); /*  psistar = --------------------  */
+                                          /*            |v x (xj-u)|^2 + eps  */
+
+        psij = gmx_invsqrt(fac);          /*                 1                */
+                                          /*  psij    = ------------          */
+                                          /*            |v x (xj-u)|          */
+
+        svmul(psij, v_xj_u, sj);          /*  sj = psij * (v x (xj-u) )       */
+
+        fac = iprod(v_xj_u, rj);                     /* fac = (v x (xj-u)).rj */
+        fac2 = fac*fac;
+
+        sjrj = iprod(sj, rj);                        /* sjrj = sj.rj          */
+
+        svmul(psijstar/psij, rj, tmpvec);
+        svmul(psijstar*psijstar/(psij*psij*psij) * sjrj, sj, tmpvec2);
+        rvec_dec(tmpvec, tmpvec2);
+        cprod(tmpvec, rotg->vec, tmpvec2);
+
+        /* Store the additional force so that it can be added to the force
+         * array after the normal forces have been evaluated */
+        svmul(-rotg->k*wj*sjrj, tmpvec2, tmpvec);
+        svmul(mj, innersumvec, tmpvec2);  /* This is != 0 only for the pivot-free variant */
+
+        rvec_add(tmpvec2, tmpvec, erg->f_rot_loc[j]);
+        Vpart += wj*psijstar*fac2;
+
+        /* If requested, also calculate the potential for a set of angles
+         * near the current reference angle */
+        if (bCalcPotFit)
+        {
+            for (ifit = 0; ifit < rotg->PotAngle_nstep; ifit++)
+            {
+                if (bPF)
+                {
+                    mvmul(erg->PotAngleFit->rotmat[ifit], yj0_yc0, fit_rj); /* fit_rj = Omega.(yj0-yc0) */
+                }
+                else
+                {
+                    /* Position of this atom in the collective array */
+                    iigrp = erg->xc_ref_ind[j];
+                    /* Rotate with the alternative angle. Like rotate_local_reference(),
+                     * just for a single local atom */
+                    mvmul(erg->PotAngleFit->rotmat[ifit], rotg->x_ref[iigrp], fit_rj); /* fit_rj = Omega*(yj0-u) */
+                }
+                fit_fac = iprod(v_xj_u, fit_rj); /* fac = (v x (xj-u)).fit_rj */
+                /* Add to the rotation potential for this angle: */
+                erg->PotAngleFit->V[ifit] += 0.5*rotg->k*wj*psijstar*fit_fac*fit_fac;
+            }
+        }
+
+        if (bOutstepRot)
+        {
+            /* Add to the torque of this rotation group */
+            erg->torque_v += torque(rotg->vec, erg->f_rot_loc[j], xj, erg->xc_center);
+
+            /* Calculate the angle between reference and actual rotation group atom. */
+            angle(rotg, xj_u, rj, &alpha, &weight);  /* angle in rad, weighted */
+            erg->angle_v  += alpha * weight;
+            erg->weight_v += weight;
+        }
+
+        PRINT_FORCE_J
+
+    } /* end of loop over local rotation group atoms */
+    erg->V = 0.5*rotg->k*Vpart;
+}
+
+
+/* Determine the smallest and largest position vector (with respect to the 
+ * rotation vector) for the reference group */
+static void get_firstlast_atom_ref(
+        t_rotgrp  *rotg, 
+        int       *firstindex, 
+        int       *lastindex)
+{
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    int i;
+    real xcproj;               /* The projection of a reference position on the 
+                                  rotation vector */
+    real minproj, maxproj;     /* Smallest and largest projection on v */
+    
+
+    
+    erg=rotg->enfrotgrp;
+
+    /* Start with some value */
+    minproj = iprod(rotg->x_ref[0], rotg->vec);
+    maxproj = minproj;
+    
+    /* This is just to ensure that it still works if all the atoms of the 
+     * reference structure are situated in a plane perpendicular to the rotation 
+     * vector */
+    *firstindex = 0;
+    *lastindex  = rotg->nat-1;
+    
+    /* Loop over all atoms of the reference group, 
+     * project them on the rotation vector to find the extremes */
+    for (i=0; i<rotg->nat; i++)
+    {
+        xcproj = iprod(rotg->x_ref[i], rotg->vec);
+        if (xcproj < minproj)
+        {
+            minproj = xcproj;
+            *firstindex = i;
+        }
+        if (xcproj > maxproj)
+        {
+            maxproj = xcproj;
+            *lastindex = i;
+        }
+    }
+}
+
+
+/* Allocate memory for the slabs */
+static void allocate_slabs(
+        t_rotgrp  *rotg, 
+        FILE      *fplog, 
+        int       g, 
+        gmx_bool  bVerbose,
+        t_commrec *cr)
+{
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+    int i, nslabs;
+    
+    
+    erg=rotg->enfrotgrp;
+    
+    /* More slabs than are defined for the reference are never needed */
+    nslabs = erg->slab_last_ref - erg->slab_first_ref + 1;
+    
+    /* Remember how many we allocated */
+    erg->nslabs_alloc = nslabs;
+
+    if (MASTER(cr) && bVerbose)
+        fprintf(fplog, "%s allocating memory to store data for %d slabs (rotation group %d).\n",
+                RotStr, nslabs,g);
+    snew(erg->slab_center     , nslabs);
+    snew(erg->slab_center_ref , nslabs);
+    snew(erg->slab_weights    , nslabs);
+    snew(erg->slab_torque_v   , nslabs);
+    snew(erg->slab_data       , nslabs);
+    snew(erg->gn_atom         , nslabs);
+    snew(erg->gn_slabind      , nslabs);
+    snew(erg->slab_innersumvec, nslabs);
+    for (i=0; i<nslabs; i++)
+    {
+        snew(erg->slab_data[i].x     , rotg->nat);
+        snew(erg->slab_data[i].ref   , rotg->nat);
+        snew(erg->slab_data[i].weight, rotg->nat);
+    }
+    snew(erg->xc_ref_sorted, rotg->nat);
+    snew(erg->xc_sortind   , rotg->nat);
+    snew(erg->firstatom    , nslabs);
+    snew(erg->lastatom     , nslabs);
+}
+
+
+/* From the extreme coordinates of the reference group, determine the first 
+ * and last slab of the reference. We can never have more slabs in the real
+ * simulation than calculated here for the reference.
+ */
+static void get_firstlast_slab_ref(t_rotgrp *rotg, real mc[], int ref_firstindex, int ref_lastindex)
+{
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+    int first,last,firststart;
+    rvec dummy;
+
+    
+    erg=rotg->enfrotgrp;
+    first = get_first_slab(rotg, erg->max_beta, rotg->x_ref[ref_firstindex]);
+    last  = get_last_slab( rotg, erg->max_beta, rotg->x_ref[ref_lastindex ]);
+    firststart = first;
+
+    while (get_slab_weight(first, rotg, rotg->x_ref, mc, &dummy) > WEIGHT_MIN)
+    {
+        first--;
+    }
+    erg->slab_first_ref = first+1;
+    while (get_slab_weight(last, rotg, rotg->x_ref, mc, &dummy) > WEIGHT_MIN)
+    {
+        last++;
+    }
+    erg->slab_last_ref  = last-1;
+    
+    erg->slab_buffer = firststart - erg->slab_first_ref;
+}
+
+
+
+static void init_rot_group(FILE *fplog,t_commrec *cr,int g,t_rotgrp *rotg,
+        rvec *x,gmx_mtop_t *mtop,gmx_bool bVerbose,FILE *out_slabs, gmx_bool bOutputCenters)
+{
+    int i,ii;
+    rvec        coord,*xdum;
+    gmx_bool    bFlex,bColl;
+    t_atom      *atom;
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+    int         ref_firstindex, ref_lastindex;
+    real        mass,totalmass;
+    real        start=0.0;
+    
+
+    /* Do we have a flexible axis? */
+    bFlex = ISFLEX(rotg);
+    /* Do we use a global set of coordinates? */
+    bColl = ISCOLL(rotg);
+
+    erg=rotg->enfrotgrp;
+    
+    /* Allocate space for collective coordinates if needed */
+    if (bColl)
+    {
+        snew(erg->xc        , rotg->nat);
+        snew(erg->xc_shifts , rotg->nat);
+        snew(erg->xc_eshifts, rotg->nat);
+
+        /* Save the original (whole) set of positions such that later the
+         * molecule can always be made whole again */
+        snew(erg->xc_old    , rotg->nat);        
+        if (MASTER(cr))
+        {
+            for (i=0; i<rotg->nat; i++)
+            {
+                ii = rotg->ind[i];
+                copy_rvec(x[ii], erg->xc_old[i]);
+            }
+        }
+#ifdef GMX_MPI
+        if (PAR(cr))
+            gmx_bcast(rotg->nat*sizeof(erg->xc_old[0]),erg->xc_old, cr);
+#endif
+
+        if (rotg->eFittype == erotgFitNORM)
+        {
+            snew(erg->xc_ref_length, rotg->nat); /* in case fit type NORM is chosen */
+            snew(erg->xc_norm      , rotg->nat);
+        }
+    }
+    else
+    {
+        snew(erg->xr_loc   , rotg->nat);
+        snew(erg->x_loc_pbc, rotg->nat);
+    }
+    
+    snew(erg->f_rot_loc , rotg->nat);
+    snew(erg->xc_ref_ind, rotg->nat);
+    
+    /* Make space for the calculation of the potential at other angles (used
+     * for fitting only) */
+    if (erotgFitPOT == rotg->eFittype)
+    {
+        snew(erg->PotAngleFit, 1);
+        snew(erg->PotAngleFit->degangle, rotg->PotAngle_nstep);
+        snew(erg->PotAngleFit->V       , rotg->PotAngle_nstep);
+        snew(erg->PotAngleFit->rotmat  , rotg->PotAngle_nstep);
+
+        /* Get the set of angles around the reference angle */
+        start = -0.5 * (rotg->PotAngle_nstep - 1)*rotg->PotAngle_step;
+        for (i = 0; i < rotg->PotAngle_nstep; i++)
+            erg->PotAngleFit->degangle[i] = start + i*rotg->PotAngle_step;
+    }
+    else
+    {
+        erg->PotAngleFit = NULL;
+    }
+
+    /* xc_ref_ind needs to be set to identity in the serial case */
+    if (!PAR(cr))
+        for (i=0; i<rotg->nat; i++)
+            erg->xc_ref_ind[i] = i;
+
+    /* Copy the masses so that the center can be determined. For all types of
+     * enforced rotation, we store the masses in the erg->mc array. */
+    snew(erg->mc, rotg->nat);
+    if (bFlex)
+        snew(erg->mc_sorted, rotg->nat);
+    if (!bColl)
+        snew(erg->m_loc, rotg->nat);
+    totalmass=0.0;
+    for (i=0; i<rotg->nat; i++)
+    {
+        if (rotg->bMassW)
+        {
+            gmx_mtop_atomnr_to_atom(mtop,rotg->ind[i],&atom);
+            mass=atom->m;
+        }
+        else
+        {
+            mass=1.0;
+        }
+        erg->mc[i] = mass;
+        totalmass += mass;
+    }
+    erg->invmass = 1.0/totalmass;
+    
+    /* Set xc_ref_center for any rotation potential */
+    if ((rotg->eType==erotgISO) || (rotg->eType==erotgPM) || (rotg->eType==erotgRM) || (rotg->eType==erotgRM2))
+    {
+        /* Set the pivot point for the fixed, stationary-axis potentials. This
+         * won't change during the simulation */
+        copy_rvec(rotg->pivot, erg->xc_ref_center);
+        copy_rvec(rotg->pivot, erg->xc_center    );
+    }
+    else
+    {
+        /* Center of the reference positions */
+        get_center(rotg->x_ref, erg->mc, rotg->nat, erg->xc_ref_center);
+
+        /* Center of the actual positions */
+        if (MASTER(cr))
+        {
+            snew(xdum, rotg->nat);
+            for (i=0; i<rotg->nat; i++)
+            {
+                ii = rotg->ind[i];
+                copy_rvec(x[ii], xdum[i]);
+            }
+            get_center(xdum, erg->mc, rotg->nat, erg->xc_center);
+            sfree(xdum);
+        }
+#ifdef GMX_MPI
+        if (PAR(cr))
+            gmx_bcast(sizeof(erg->xc_center), erg->xc_center, cr);
+#endif
+    }
+
+    if ( (rotg->eType != erotgFLEX) && (rotg->eType != erotgFLEX2) )
+    {
+        /* Put the reference positions into origin: */
+        for (i=0; i<rotg->nat; i++)
+            rvec_dec(rotg->x_ref[i], erg->xc_ref_center);
+    }
+
+    /* Enforced rotation with flexible axis */
+    if (bFlex)
+    {
+        /* Calculate maximum beta value from minimum gaussian (performance opt.) */
+        erg->max_beta = calc_beta_max(rotg->min_gaussian, rotg->slab_dist);
+
+        /* Determine the smallest and largest coordinate with respect to the rotation vector */
+        get_firstlast_atom_ref(rotg, &ref_firstindex, &ref_lastindex);
+        
+        /* From the extreme coordinates of the reference group, determine the first 
+         * and last slab of the reference. */
+        get_firstlast_slab_ref(rotg, erg->mc, ref_firstindex, ref_lastindex);
+                
+        /* Allocate memory for the slabs */
+        allocate_slabs(rotg, fplog, g, bVerbose, cr);
+
+        /* Flexible rotation: determine the reference centers for the rest of the simulation */
+        erg->slab_first = erg->slab_first_ref;
+        erg->slab_last = erg->slab_last_ref;
+        get_slab_centers(rotg,rotg->x_ref,erg->mc,cr,g,-1,out_slabs,bOutputCenters,TRUE);
+
+        /* Length of each x_rotref vector from center (needed if fit routine NORM is chosen): */
+        if (rotg->eFittype == erotgFitNORM)
+        {
+            for (i=0; i<rotg->nat; i++)
+            {
+                rvec_sub(rotg->x_ref[i], erg->xc_ref_center, coord);
+                erg->xc_ref_length[i] = norm(coord);
+            }
+        }
+    }
+}
+
+
+extern void dd_make_local_rotation_groups(gmx_domdec_t *dd,t_rot *rot)
+{
+    gmx_ga2la_t ga2la;
+    int g;
+    t_rotgrp *rotg;
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+    
+    ga2la = dd->ga2la;
+
+    for(g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        erg  = rotg->enfrotgrp;
+
+
+        dd_make_local_group_indices(ga2la,rotg->nat,rotg->ind,
+                &erg->nat_loc,&erg->ind_loc,&erg->nalloc_loc,erg->xc_ref_ind);
+    }
+}
+
+
+/* Calculate the size of the MPI buffer needed in reduce_output() */
+static int calc_mpi_bufsize(t_rot *rot)
+{
+    int g;
+    int count_group, count_total;
+    t_rotgrp *rotg;
+    gmx_enfrotgrp_t erg;      /* Pointer to enforced rotation group data */
+
+
+    count_total = 0;
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        erg  = rotg->enfrotgrp;
+
+        /* Count the items that are transferred for this group: */
+        count_group = 4; /* V, torque, angle, weight */
+
+        /* Add the maximum number of slabs for flexible groups */
+        if (ISFLEX(rotg))
+            count_group += erg->slab_last_ref - erg->slab_first_ref + 1;
+
+        /* Add space for the potentials at different angles: */
+        if (erotgFitPOT == rotg->eFittype)
+            count_group += rotg->PotAngle_nstep;
+
+        /* Add to the total number: */
+        count_total += count_group;
+    }
+
+    return count_total;
+}
+
+
+extern void init_rot(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
+        t_commrec *cr, rvec *x, matrix box, gmx_mtop_t *mtop, const output_env_t oenv,
+        gmx_bool bVerbose, unsigned long Flags)
+{
+    t_rot    *rot;
+    t_rotgrp *rotg;
+    int      g;
+    int      nat_max=0;     /* Size of biggest rotation group */
+    gmx_enfrot_t er;        /* Pointer to the enforced rotation buffer variables */    
+    gmx_enfrotgrp_t erg;    /* Pointer to enforced rotation group data */
+    rvec     *x_pbc=NULL;   /* Space for the pbc-correct atom positions */
+
+
+    if ( (PAR(cr)) && !DOMAINDECOMP(cr) )
+        gmx_fatal(FARGS, "Enforced rotation is only implemented for domain decomposition!");
+
+    if ( MASTER(cr) && bVerbose)
+        fprintf(stdout, "%s Initializing ...\n", RotStr);
+
+
+    rot = ir->rot;
+    snew(rot->enfrot, 1);
+    er = rot->enfrot;
+    er->Flags = Flags;
+
+    /* When appending, skip first output to avoid duplicate entries in the data files */
+    if (er->Flags & MD_APPENDFILES)
+        er->bOut = FALSE;
+    else
+        er->bOut = TRUE;
+    
+    /* Output every step for reruns */
+    if (er->Flags & MD_RERUN)
+    {
+        if (fplog)
+            fprintf(fplog, "%s rerun - will write rotation output every available step.\n", RotStr);
+        rot->nstrout = 1;
+        rot->nstsout = 1;
+    }
+
+    er->out_slabs = NULL;
+    if ( MASTER(cr) && HaveFlexibleGroups(rot) )
+        er->out_slabs = open_slab_out(opt2fn("-rs",nfile,fnm), rot, oenv);
+
+    if (MASTER(cr))
+    {
+        /* Remove pbc, make molecule whole.
+         * When ir->bContinuation=TRUE this has already been done, but ok. */
+        snew(x_pbc,mtop->natoms);
+        m_rveccopy(mtop->natoms,x,x_pbc);
+        do_pbc_first_mtop(NULL,ir->ePBC,box,mtop,x_pbc);
+    }
+
+    for (g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+
+        if (fplog)
+            fprintf(fplog,"%s group %d type '%s'\n", RotStr, g, erotg_names[rotg->eType]);
+        
+        if (rotg->nat > 0)
+        {
+            /* Allocate space for the rotation group's data: */
+            snew(rotg->enfrotgrp, 1);
+            erg  = rotg->enfrotgrp;
+
+            nat_max=max(nat_max, rotg->nat);
+            
+            if (PAR(cr))
+            {
+                erg->nat_loc    = 0;
+                erg->nalloc_loc = 0;
+                erg->ind_loc    = NULL;
+            }
+            else
+            {
+                erg->nat_loc = rotg->nat;
+                erg->ind_loc = rotg->ind;
+            }
+            init_rot_group(fplog,cr,g,rotg,x_pbc,mtop,bVerbose,er->out_slabs,
+                           !(er->Flags & MD_APPENDFILES) ); /* Do not output the reference centers
+                                                             * again if we are appending */
+        }
+    }
+    
+    /* Allocate space for enforced rotation buffer variables */
+    er->bufsize = nat_max;
+    snew(er->data, nat_max);
+    snew(er->xbuf, nat_max);
+    snew(er->mbuf, nat_max);
+
+    /* Buffers for MPI reducing torques, angles, weights (for each group), and V */
+    if (PAR(cr))
+    {
+        er->mpi_bufsize = calc_mpi_bufsize(rot) + 100; /* larger to catch errors */
+        snew(er->mpi_inbuf , er->mpi_bufsize);
+        snew(er->mpi_outbuf, er->mpi_bufsize);
+    }
+    else
+    {
+        er->mpi_bufsize = 0;
+        er->mpi_inbuf = NULL;
+        er->mpi_outbuf = NULL;
+    }
+
+    /* Only do I/O on the MASTER */
+    er->out_angles  = NULL;
+    er->out_rot     = NULL;
+    er->out_torque  = NULL;
+    if (MASTER(cr))
+    {
+        er->out_rot = open_rot_out(opt2fn("-ro",nfile,fnm), rot, oenv);
+
+        if (rot->nstsout > 0)
+        {
+            if ( HaveFlexibleGroups(rot) || HavePotFitGroups(rot) )
+                er->out_angles  = open_angles_out(opt2fn("-ra",nfile,fnm), rot, oenv);
+            if ( HaveFlexibleGroups(rot) )
+                er->out_torque  = open_torque_out(opt2fn("-rt",nfile,fnm), rot, oenv);
+        }
+
+        sfree(x_pbc);
+    }
+}
+
+
+extern void finish_rot(FILE *fplog,t_rot *rot)
+{
+    gmx_enfrot_t er;        /* Pointer to the enforced rotation buffer variables */    
+
+    
+    er=rot->enfrot;
+    if (er->out_rot)
+        gmx_fio_fclose(er->out_rot);
+    if (er->out_slabs)
+        gmx_fio_fclose(er->out_slabs);
+    if (er->out_angles)
+        gmx_fio_fclose(er->out_angles);
+    if (er->out_torque)
+        gmx_fio_fclose(er->out_torque);
+}
+
+
+/* Rotate the local reference positions and store them in
+ * erg->xr_loc[0...(nat_loc-1)]
+ *
+ * Note that we already subtracted u or y_c from the reference positions
+ * in init_rot_group().
+ */
+static void rotate_local_reference(t_rotgrp *rotg)
+{
+    gmx_enfrotgrp_t erg;
+    int i,ii;
+
+    
+    erg=rotg->enfrotgrp;
+    
+    for (i=0; i<erg->nat_loc; i++)
+    {
+        /* Index of this rotation group atom with respect to the whole rotation group */
+        ii = erg->xc_ref_ind[i];
+        /* Rotate */
+        mvmul(erg->rotmat, rotg->x_ref[ii], erg->xr_loc[i]);
+    }
+}
+
+
+/* Select the PBC representation for each local x position and store that
+ * for later usage. We assume the right PBC image of an x is the one nearest to
+ * its rotated reference */
+static void choose_pbc_image(rvec x[], t_rotgrp *rotg, matrix box, int npbcdim)
+{
+    int d,i,ii,m;
+    gmx_enfrotgrp_t erg;       /* Pointer to enforced rotation group data */
+    rvec xref,xcurr,dx;
+    ivec shift;
+
+
+    erg=rotg->enfrotgrp;
+    
+    for (i=0; i<erg->nat_loc; i++)
+    {
+        clear_ivec(shift);
+        
+        /* Index of a rotation group atom  */
+        ii = erg->ind_loc[i];
+
+        /* Get the reference position. The pivot was already
+         * subtracted in init_rot_group() from the reference positions. Also,
+         * the reference positions have already been rotated in
+         * rotate_local_reference() */
+        copy_rvec(erg->xr_loc[i], xref);
+        
+        /* Subtract the (old) center from the current positions
+         * (just to determine the shifts!) */
+        rvec_sub(x[ii], erg->xc_center, xcurr);
+        
+        /* Shortest PBC distance between the atom and its reference */
+        rvec_sub(xcurr, xref, dx);
+        
+        /* Determine the shift for this atom */
+        for(m=npbcdim-1; m>=0; m--)
+        {
+            while (dx[m] < -0.5*box[m][m])
+            {
+                for(d=0; d<DIM; d++)
+                    dx[d] += box[m][d];
+                shift[m]++;
+            }
+            while (dx[m] >= 0.5*box[m][m])
+            {
+                for(d=0; d<DIM; d++)
+                    dx[d] -= box[m][d];
+                shift[m]--;
+            }
+        }
+        
+        /* Apply the shift to the current atom */
+        copy_rvec(x[ii], erg->x_loc_pbc[i]);
+        shift_single_coord(box, erg->x_loc_pbc[i], shift); 
+    }
+}
+
+
+extern void do_rotation(
+        t_commrec *cr,
+        t_inputrec *ir,
+        matrix box,
+        rvec x[],
+        real t,
+        gmx_large_int_t step,
+        gmx_wallcycle_t wcycle,
+        gmx_bool bNS)
+{
+    int      g,i,ii;
+    t_rot    *rot;
+    t_rotgrp *rotg;
+    gmx_bool outstep_slab, outstep_rot;
+    gmx_bool bFlex,bColl;
+    double   cycles_rot;
+    gmx_enfrot_t er;     /* Pointer to the enforced rotation buffer variables */
+    gmx_enfrotgrp_t erg; /* Pointer to enforced rotation group data           */
+    rvec     transvec;
+    t_gmx_potfit *fit=NULL;     /* For fit type 'potential' determine the fit
+                                   angle via the potential minimum            */
+#ifdef TAKETIME
+    double t0;
+#endif
+    
+    
+    rot=ir->rot;
+    er=rot->enfrot;
+    
+    /* When to output in main rotation output file */
+    outstep_rot  = do_per_step(step, rot->nstrout) && er->bOut;
+    /* When to output per-slab data */
+    outstep_slab = do_per_step(step, rot->nstsout) && er->bOut;
+
+    /* Output time into rotation output file */
+    if (outstep_rot && MASTER(cr))
+        fprintf(er->out_rot, "%12.3e",t);
+
+    /**************************************************************************/
+    /* First do ALL the communication! */
+    for(g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        erg=rotg->enfrotgrp;
+
+        /* Do we have a flexible axis? */
+        bFlex = ISFLEX(rotg);
+        /* Do we use a collective (global) set of coordinates? */
+        bColl = ISCOLL(rotg);
+
+        /* Calculate the rotation matrix for this angle: */
+        erg->degangle = rotg->rate * t;
+        calc_rotmat(rotg->vec,erg->degangle,erg->rotmat);
+
+        if (bColl)
+        {
+            /* Transfer the rotation group's positions such that every node has
+             * all of them. Every node contributes its local positions x and stores
+             * it in the collective erg->xc array. */
+            communicate_group_positions(cr,erg->xc, erg->xc_shifts, erg->xc_eshifts, bNS,
+                    x, rotg->nat, erg->nat_loc, erg->ind_loc, erg->xc_ref_ind, erg->xc_old, box);
+        }
+        else
+        {
+            /* Fill the local masses array;
+             * this array changes in DD/neighborsearching steps */
+            if (bNS)
+            {
+                for (i=0; i<erg->nat_loc; i++)
+                {
+                    /* Index of local atom w.r.t. the collective rotation group */
+                    ii = erg->xc_ref_ind[i];
+                    erg->m_loc[i] = erg->mc[ii];
+                }
+            }
+
+            /* Calculate Omega*(y_i-y_c) for the local positions */
+            rotate_local_reference(rotg);
+
+            /* Choose the nearest PBC images of the group atoms with respect
+             * to the rotated reference positions */
+            choose_pbc_image(x, rotg, box, 3);
+
+            /* Get the center of the rotation group */
+            if ( (rotg->eType==erotgISOPF) || (rotg->eType==erotgPMPF) )
+                get_center_comm(cr, erg->x_loc_pbc, erg->m_loc, erg->nat_loc, rotg->nat, erg->xc_center);
+        }
+
+    } /* End of loop over rotation groups */
+
+    /**************************************************************************/
+    /* Done communicating, we can start to count cycles now ... */
+    wallcycle_start(wcycle, ewcROT);
+
+#ifdef TAKETIME
+    t0 = MPI_Wtime();
+#endif
+
+    for(g=0; g<rot->ngrp; g++)
+    {
+        rotg = &rot->grp[g];
+        erg=rotg->enfrotgrp;
+
+        bFlex = ISFLEX(rotg);
+        bColl = ISCOLL(rotg);
+
+        if (outstep_rot && MASTER(cr))
+            fprintf(er->out_rot, "%12.4f", erg->degangle);
+
+        /* Calculate angles and rotation matrices for potential fitting: */
+        if ( (outstep_rot || outstep_slab) && (erotgFitPOT == rotg->eFittype) )
+        {
+            fit = erg->PotAngleFit;
+            for (i = 0; i < rotg->PotAngle_nstep; i++)
+            {
+                calc_rotmat(rotg->vec, erg->degangle + fit->degangle[i], fit->rotmat[i]);
+
+                /* Clear value from last step */
+                erg->PotAngleFit->V[i] = 0.0;
+            }
+        }
+
+        /* Clear values from last time step */
+        erg->V        = 0.0;
+        erg->torque_v = 0.0;
+        erg->angle_v  = 0.0;
+        erg->weight_v = 0.0;
+
+        switch(rotg->eType)
+        {
+            case erotgISO:
+            case erotgISOPF:
+            case erotgPM:
+            case erotgPMPF:
+                do_fixed(cr,rotg,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            case erotgRM:
+                do_radial_motion(cr,rotg,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            case erotgRMPF:
+                do_radial_motion_pf(cr,rotg,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            case erotgRM2:
+            case erotgRM2PF:
+                do_radial_motion2(cr,rotg,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            case erotgFLEXT:
+            case erotgFLEX2T:
+                /* Subtract the center of the rotation group from the collective positions array
+                 * Also store the center in erg->xc_center since it needs to be subtracted
+                 * in the low level routines from the local coordinates as well */
+                get_center(erg->xc, erg->mc, rotg->nat, erg->xc_center);
+                svmul(-1.0, erg->xc_center, transvec);
+                translate_x(erg->xc, rotg->nat, transvec);
+                do_flexible(cr,er,rotg,g,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            case erotgFLEX:
+            case erotgFLEX2:
+                /* Do NOT subtract the center of mass in the low level routines! */
+                clear_rvec(erg->xc_center);
+                do_flexible(cr,er,rotg,g,x,box,t,step,outstep_rot,outstep_slab);
+                break;
+            default:
+                gmx_fatal(FARGS, "No such rotation potential.");
+                break;
+        }
+    }
+
+#ifdef TAKETIME
+    if (MASTER(cr))
+        fprintf(stderr, "%s calculation (step %d) took %g seconds.\n", RotStr, step, MPI_Wtime()-t0);
+#endif
+
+    /* Stop the cycle counter and add to the force cycles for load balancing */
+    cycles_rot = wallcycle_stop(wcycle,ewcROT);
+    if (DOMAINDECOMP(cr) && wcycle)
+        dd_cycles_add(cr->dd,cycles_rot,ddCyclF);
+}
similarity index 100%
rename from src/mdlib/qmmm.c
rename to src/gromacs/mdlib/qmmm.c
diff --git a/src/gromacs/mdlib/sim_util.c b/src/gromacs/mdlib/sim_util.c
new file mode 100644 (file)
index 0000000..d0950da
--- /dev/null
@@ -0,0 +1,1540 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef GMX_CRAY_XT3
+#include<catamount/dclock.h>
+#endif
+
+
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <math.h>
+#include "typedefs.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "smalloc.h"
+#include "names.h"
+#include "confio.h"
+#include "mvdata.h"
+#include "txtdump.h"
+#include "pbc.h"
+#include "chargegroup.h"
+#include "vec.h"
+#include "time.h"
+#include "nrnb.h"
+#include "mshift.h"
+#include "mdrun.h"
+#include "update.h"
+#include "physics.h"
+#include "main.h"
+#include "mdatoms.h"
+#include "force.h"
+#include "bondf.h"
+#include "pme.h"
+#include "pppm.h"
+#include "disre.h"
+#include "orires.h"
+#include "network.h"
+#include "calcmu.h"
+#include "constr.h"
+#include "xvgr.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "copyrite.h"
+#include "pull_rotation.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "gmx_wallcycle.h"
+#include "genborn.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#include "qmmm.h"
+
+#if 0
+typedef struct gmx_timeprint {
+    
+} t_gmx_timeprint;
+#endif
+
+/* Portable version of ctime_r implemented in src/gmxlib/string2.c, but we do not want it declared in public installed headers */
+char *
+gmx_ctime_r(const time_t *clock,char *buf, int n);
+
+
+double
+gmx_gettime()
+{
+#ifdef HAVE_GETTIMEOFDAY
+       struct timeval t;
+       double seconds;
+       
+       gettimeofday(&t,NULL);
+       
+       seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
+       
+       return seconds;
+#else
+       double  seconds;
+       
+       seconds = time(NULL);
+       
+       return seconds;
+#endif
+}
+
+
+#define difftime(end,start) ((double)(end)-(double)(start))
+
+void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,   
+                t_inputrec *ir, t_commrec *cr)
+{
+    time_t finish;
+    char   timebuf[STRLEN];
+    double dt;
+    char buf[48];
+    
+#ifndef GMX_THREADS
+    if (!PAR(cr))
+#endif
+    {
+        fprintf(out,"\r");
+    }
+    fprintf(out,"step %s",gmx_step_str(step,buf));
+    if ((step >= ir->nstlist))
+    {
+        if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0))
+        {
+            /* We have done a full cycle let's update time_per_step */
+            runtime->last = gmx_gettime();
+            dt = difftime(runtime->last,runtime->real);
+            runtime->time_per_step = dt/(step - ir->init_step + 1);
+        }
+        dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
+        
+        if (ir->nsteps >= 0)
+        {
+            if (dt >= 300)
+            {    
+                finish = (time_t) (runtime->last + dt);
+                gmx_ctime_r(&finish,timebuf,STRLEN);
+                sprintf(buf,"%s",timebuf);
+                buf[strlen(buf)-1]='\0';
+                fprintf(out,", will finish %s",buf);
+            }
+            else
+                fprintf(out,", remaining runtime: %5d s          ",(int)dt);
+        }
+        else
+        {
+            fprintf(out," performance: %.1f ns/day    ",
+                    ir->delta_t/1000*24*60*60/runtime->time_per_step);
+        }
+    }
+#ifndef GMX_THREADS
+    if (PAR(cr))
+    {
+        fprintf(out,"\n");
+    }
+#endif
+
+    fflush(out);
+}
+
+#ifdef NO_CLOCK 
+#define clock() -1
+#endif
+
+static double set_proctime(gmx_runtime_t *runtime)
+{
+    double diff;
+#ifdef GMX_CRAY_XT3
+    double prev;
+
+    prev = runtime->proc;
+    runtime->proc = dclock();
+    
+    diff = runtime->proc - prev;
+#else
+    clock_t prev;
+
+    prev = runtime->proc;
+    runtime->proc = clock();
+
+    diff = (double)(runtime->proc - prev)/(double)CLOCKS_PER_SEC;
+#endif
+    if (diff < 0)
+    {
+        /* The counter has probably looped, ignore this data */
+        diff = 0;
+    }
+
+    return diff;
+}
+
+void runtime_start(gmx_runtime_t *runtime)
+{
+    runtime->real = gmx_gettime();
+    runtime->proc          = 0;
+    set_proctime(runtime);
+    runtime->realtime      = 0;
+    runtime->proctime      = 0;
+    runtime->last          = 0;
+    runtime->time_per_step = 0;
+}
+
+void runtime_end(gmx_runtime_t *runtime)
+{
+    double now;
+    
+    now = gmx_gettime();
+    
+    runtime->proctime += set_proctime(runtime);
+    runtime->realtime  = now - runtime->real;
+    runtime->real      = now;
+}
+
+void runtime_upd_proc(gmx_runtime_t *runtime)
+{
+    runtime->proctime += set_proctime(runtime);
+}
+
+void print_date_and_time(FILE *fplog,int nodeid,const char *title,
+                         const gmx_runtime_t *runtime)
+{
+    int i;
+    char timebuf[STRLEN];
+    char time_string[STRLEN];
+    time_t tmptime;
+
+    if (fplog)
+    {
+        if (runtime != NULL)
+        {
+            tmptime = (time_t) runtime->real;
+            gmx_ctime_r(&tmptime,timebuf,STRLEN);
+        }
+        else
+        {
+            tmptime = (time_t) gmx_gettime();
+            gmx_ctime_r(&tmptime,timebuf,STRLEN);
+        }
+        for(i=0; timebuf[i]>=' '; i++)
+        {
+            time_string[i]=timebuf[i];
+        }
+        time_string[i]='\0';
+
+        fprintf(fplog,"%s on node %d %s\n",title,nodeid,time_string);
+    }
+}
+
+static void sum_forces(int start,int end,rvec f[],rvec flr[])
+{
+  int i;
+  
+  if (gmx_debug_at) {
+    pr_rvecs(debug,0,"fsr",f+start,end-start);
+    pr_rvecs(debug,0,"flr",flr+start,end-start);
+  }
+  for(i=start; (i<end); i++)
+    rvec_inc(f[i],flr[i]);
+}
+
+/* 
+ * calc_f_el calculates forces due to an electric field.
+ *
+ * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e 
+ *
+ * Et[] contains the parameters for the time dependent 
+ * part of the field (not yet used). 
+ * Ex[] contains the parameters for
+ * the spatial dependent part of the field. You can have cool periodic
+ * fields in principle, but only a constant field is supported
+ * now. 
+ * The function should return the energy due to the electric field
+ * (if any) but for now returns 0.
+ *
+ * WARNING:
+ * There can be problems with the virial.
+ * Since the field is not self-consistent this is unavoidable.
+ * For neutral molecules the virial is correct within this approximation.
+ * For neutral systems with many charged molecules the error is small.
+ * But for systems with a net charge or a few charged molecules
+ * the error can be significant when the field is high.
+ * Solution: implement a self-consitent electric field into PME.
+ */
+static void calc_f_el(FILE *fp,int  start,int homenr,
+                      real charge[],rvec x[],rvec f[],
+                      t_cosines Ex[],t_cosines Et[],double t)
+{
+    rvec Ext;
+    real t0;
+    int  i,m;
+    
+    for(m=0; (m<DIM); m++)
+    {
+        if (Et[m].n > 0)
+        {
+            if (Et[m].n == 3)
+            {
+                t0 = Et[m].a[1];
+                Ext[m] = cos(Et[m].a[0]*(t-t0))*exp(-sqr(t-t0)/(2.0*sqr(Et[m].a[2])));
+            }
+            else
+            {
+                Ext[m] = cos(Et[m].a[0]*t);
+            }
+        }
+        else
+        {
+            Ext[m] = 1.0;
+        }
+        if (Ex[m].n > 0)
+        {
+            /* Convert the field strength from V/nm to MD-units */
+            Ext[m] *= Ex[m].a[0]*FIELDFAC;
+            for(i=start; (i<start+homenr); i++)
+                f[i][m] += charge[i]*Ext[m];
+        }
+        else
+        {
+            Ext[m] = 0;
+        }
+    }
+    if (fp != NULL)
+    {
+        fprintf(fp,"%10g  %10g  %10g  %10g #FIELD\n",t,
+                Ext[XX]/FIELDFAC,Ext[YY]/FIELDFAC,Ext[ZZ]/FIELDFAC);
+    }
+}
+
+static void calc_virial(FILE *fplog,int start,int homenr,rvec x[],rvec f[],
+                       tensor vir_part,t_graph *graph,matrix box,
+                       t_nrnb *nrnb,const t_forcerec *fr,int ePBC)
+{
+  int i,j;
+  tensor virtest;
+
+  /* The short-range virial from surrounding boxes */
+  clear_mat(vir_part);
+  calc_vir(fplog,SHIFTS,fr->shift_vec,fr->fshift,vir_part,ePBC==epbcSCREW,box);
+  inc_nrnb(nrnb,eNR_VIRIAL,SHIFTS);
+  
+  /* Calculate partial virial, for local atoms only, based on short range. 
+   * Total virial is computed in global_stat, called from do_md 
+   */
+  f_calc_vir(fplog,start,start+homenr,x,f,vir_part,graph,box);
+  inc_nrnb(nrnb,eNR_VIRIAL,homenr);
+
+  /* Add position restraint contribution */
+  for(i=0; i<DIM; i++) {
+    vir_part[i][i] += fr->vir_diag_posres[i];
+  }
+
+  /* Add wall contribution */
+  for(i=0; i<DIM; i++) {
+    vir_part[i][ZZ] += fr->vir_wall_z[i];
+  }
+
+  if (debug)
+    pr_rvecs(debug,0,"vir_part",vir_part,DIM);
+}
+
+static void print_large_forces(FILE *fp,t_mdatoms *md,t_commrec *cr,
+                              gmx_large_int_t step,real pforce,rvec *x,rvec *f)
+{
+  int  i;
+  real pf2,fn2;
+  char buf[STEPSTRSIZE];
+
+  pf2 = sqr(pforce);
+  for(i=md->start; i<md->start+md->homenr; i++) {
+    fn2 = norm2(f[i]);
+    /* We also catch NAN, if the compiler does not optimize this away. */
+    if (fn2 >= pf2 || fn2 != fn2) {
+      fprintf(fp,"step %s  atom %6d  x %8.3f %8.3f %8.3f  force %12.5e\n",
+             gmx_step_str(step,buf),
+             ddglatnr(cr->dd,i),x[i][XX],x[i][YY],x[i][ZZ],sqrt(fn2));
+    }
+  }
+}
+
+void do_force(FILE *fplog,t_commrec *cr,
+              t_inputrec *inputrec,
+              gmx_large_int_t step,t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+              gmx_localtop_t *top,
+              gmx_mtop_t *mtop,
+              gmx_groups_t *groups,
+              matrix box,rvec x[],history_t *hist,
+              rvec f[],
+              tensor vir_force,
+              t_mdatoms *mdatoms,
+              gmx_enerdata_t *enerd,t_fcdata *fcd,
+              real lambda,t_graph *graph,
+              t_forcerec *fr,gmx_vsite_t *vsite,rvec mu_tot,
+              double t,FILE *field,gmx_edsam_t ed,
+              gmx_bool bBornRadii,
+              int flags)
+{
+    int    cg0,cg1,i,j;
+    int    start,homenr;
+    double mu[2*DIM]; 
+    gmx_bool   bSepDVDL,bStateChanged,bNS,bFillGrid,bCalcCGCM,bBS;
+    gmx_bool   bDoLongRange,bDoForces,bSepLRF;
+    matrix boxs;
+    real   e,v,dvdl;
+    t_pbc  pbc;
+    float  cycles_ppdpme,cycles_pme,cycles_seppme,cycles_force;
+  
+    start  = mdatoms->start;
+    homenr = mdatoms->homenr;
+
+    bSepDVDL = (fr->bSepDVDL && do_per_step(step,inputrec->nstlog));
+
+    clear_mat(vir_force);
+
+    if (PARTDECOMP(cr))
+    {
+        pd_cg_range(cr,&cg0,&cg1);
+    }
+    else
+    {
+        cg0 = 0;
+        if (DOMAINDECOMP(cr))
+        {
+            cg1 = cr->dd->ncg_tot;
+        }
+        else
+        {
+            cg1 = top->cgs.nr;
+        }
+        if (fr->n_tpi > 0)
+        {
+            cg1--;
+        }
+    }
+
+    bStateChanged = (flags & GMX_FORCE_STATECHANGED);
+    bNS           = (flags & GMX_FORCE_NS) && (fr->bAllvsAll==FALSE); 
+    bFillGrid     = (bNS && bStateChanged);
+    bCalcCGCM     = (bFillGrid && !DOMAINDECOMP(cr));
+    bDoLongRange  = (fr->bTwinRange && bNS && (flags & GMX_FORCE_DOLR));
+    bDoForces     = (flags & GMX_FORCE_FORCES);
+    bSepLRF       = (bDoLongRange && bDoForces && (flags & GMX_FORCE_SEPLRF));
+
+    if (bStateChanged)
+    {
+        update_forcerec(fplog,fr,box);
+        
+        /* Calculate total (local) dipole moment in a temporary common array. 
+         * This makes it possible to sum them over nodes faster.
+         */
+        calc_mu(start,homenr,
+                x,mdatoms->chargeA,mdatoms->chargeB,mdatoms->nChargePerturbed,
+                mu,mu+DIM);
+    }
+  
+  if (fr->ePBC != epbcNONE) { 
+    /* Compute shift vectors every step,
+     * because of pressure coupling or box deformation!
+     */
+    if ((flags & GMX_FORCE_DYNAMICBOX) && bStateChanged)
+      calc_shifts(box,fr->shift_vec);
+    
+    if (bCalcCGCM) { 
+      put_charge_groups_in_box(fplog,cg0,cg1,fr->ePBC,box,
+                              &(top->cgs),x,fr->cg_cm);
+      inc_nrnb(nrnb,eNR_CGCM,homenr);
+      inc_nrnb(nrnb,eNR_RESETX,cg1-cg0);
+    } 
+    else if (EI_ENERGY_MINIMIZATION(inputrec->eI) && graph) {
+      unshift_self(graph,box,x);
+    }
+  } 
+  else if (bCalcCGCM) {
+    calc_cgcm(fplog,cg0,cg1,&(top->cgs),x,fr->cg_cm);
+    inc_nrnb(nrnb,eNR_CGCM,homenr);
+  }
+  
+  if (bCalcCGCM) {
+    if (PAR(cr)) {
+      move_cgcm(fplog,cr,fr->cg_cm);
+    }
+    if (gmx_debug_at)
+      pr_rvecs(debug,0,"cgcm",fr->cg_cm,top->cgs.nr);
+  }
+
+#ifdef GMX_MPI
+  if (!(cr->duty & DUTY_PME)) {
+    /* Send particle coordinates to the pme nodes.
+     * Since this is only implemented for domain decomposition
+     * and domain decomposition does not use the graph,
+     * we do not need to worry about shifting.
+     */    
+
+    wallcycle_start(wcycle,ewcPP_PMESENDX);
+
+    bBS = (inputrec->nwall == 2);
+    if (bBS) {
+      copy_mat(box,boxs);
+      svmul(inputrec->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
+    }
+
+    gmx_pme_send_x(cr,bBS ? boxs : box,x,
+                   mdatoms->nChargePerturbed,lambda,
+                   ( flags & GMX_FORCE_VIRIAL),step);
+
+    wallcycle_stop(wcycle,ewcPP_PMESENDX);
+  }
+#endif /* GMX_MPI */
+
+    /* Communicate coordinates and sum dipole if necessary */
+    if (PAR(cr))
+    {
+        wallcycle_start(wcycle,ewcMOVEX);
+        if (DOMAINDECOMP(cr))
+        {
+            dd_move_x(cr->dd,box,x);
+        }
+        else
+        {
+            move_x(fplog,cr,GMX_LEFT,GMX_RIGHT,x,nrnb);
+        }
+        /* When we don't need the total dipole we sum it in global_stat */
+        if (bStateChanged && NEED_MUTOT(*inputrec))
+        {
+            gmx_sumd(2*DIM,mu,cr);
+        }
+        wallcycle_stop(wcycle,ewcMOVEX);
+    }
+    if (bStateChanged)
+    {
+        for(i=0; i<2; i++)
+        {
+            for(j=0;j<DIM;j++)
+            {
+                fr->mu_tot[i][j] = mu[i*DIM + j];
+            }
+        }
+    }
+    if (fr->efep == efepNO)
+    {
+        copy_rvec(fr->mu_tot[0],mu_tot);
+    }
+    else
+    {
+        for(j=0; j<DIM; j++)
+        {
+            mu_tot[j] =
+                (1.0 - lambda)*fr->mu_tot[0][j] + lambda*fr->mu_tot[1][j];
+        }
+    }
+
+    /* Reset energies */
+    reset_enerdata(&(inputrec->opts),fr,bNS,enerd,MASTER(cr));
+    clear_rvecs(SHIFTS,fr->fshift);
+
+    if (bNS)
+    {
+        wallcycle_start(wcycle,ewcNS);
+        
+        if (graph && bStateChanged)
+        {
+            /* Calculate intramolecular shift vectors to make molecules whole */
+            mk_mshift(fplog,graph,fr->ePBC,box,x);
+        }
+
+        /* Reset long range forces if necessary */
+        if (fr->bTwinRange)
+        {
+            /* Reset the (long-range) forces if necessary */
+            clear_rvecs(fr->natoms_force_constr,bSepLRF ? fr->f_twin : f);
+        }
+
+        /* Do the actual neighbour searching and if twin range electrostatics
+         * also do the calculation of long range forces and energies.
+         */
+        dvdl = 0; 
+        ns(fplog,fr,x,box,
+           groups,&(inputrec->opts),top,mdatoms,
+           cr,nrnb,lambda,&dvdl,&enerd->grpp,bFillGrid,
+           bDoLongRange,bDoForces,bSepLRF ? fr->f_twin : f);
+        if (bSepDVDL)
+        {
+            fprintf(fplog,sepdvdlformat,"LR non-bonded",0.0,dvdl);
+        }
+        enerd->dvdl_lin += dvdl;
+        
+        wallcycle_stop(wcycle,ewcNS);
+    }
+       
+    if (inputrec->implicit_solvent && bNS) 
+    {
+        make_gb_nblist(cr,inputrec->gb_algorithm,inputrec->rlist,
+                       x,box,fr,&top->idef,graph,fr->born);
+    }
+       
+    if (DOMAINDECOMP(cr))
+    {
+        if (!(cr->duty & DUTY_PME))
+        {
+            wallcycle_start(wcycle,ewcPPDURINGPME);
+            dd_force_flop_start(cr->dd,nrnb);
+        }
+    }
+    
+    if (inputrec->bRot)
+    {
+        /* Enforced rotation has its own cycle counter that starts after the collective
+         * coordinates have been communicated. It is added to ddCyclF */
+        do_rotation(cr,inputrec,box,x,t,step,wcycle,bNS);
+    }
+
+    /* Start the force cycle counter.
+     * This counter is stopped in do_forcelow_level.
+     * No parallel communication should occur while this counter is running,
+     * since that will interfere with the dynamic load balancing.
+     */
+    wallcycle_start(wcycle,ewcFORCE);
+
+    if (bDoForces)
+    {
+        /* Reset forces for which the virial is calculated separately:
+         * PME/Ewald forces if necessary */
+        if (fr->bF_NoVirSum) 
+        {
+            if (flags & GMX_FORCE_VIRIAL)
+            {
+                fr->f_novirsum = fr->f_novirsum_alloc;
+                if (fr->bDomDec)
+                {
+                    clear_rvecs(fr->f_novirsum_n,fr->f_novirsum);
+                }
+                else
+                {
+                    clear_rvecs(homenr,fr->f_novirsum+start);
+                }
+            }
+            else
+            {
+                /* We are not calculating the pressure so we do not need
+                 * a separate array for forces that do not contribute
+                 * to the pressure.
+                 */
+                fr->f_novirsum = f;
+            }
+        }
+
+        if (bSepLRF)
+        {
+            /* Add the long range forces to the short range forces */
+            for(i=0; i<fr->natoms_force_constr; i++)
+            {
+                copy_rvec(fr->f_twin[i],f[i]);
+            }
+        }
+        else if (!(fr->bTwinRange && bNS))
+        {
+            /* Clear the short-range forces */
+            clear_rvecs(fr->natoms_force_constr,f);
+        }
+
+        clear_rvec(fr->vir_diag_posres);
+    }
+    if (inputrec->ePull == epullCONSTRAINT)
+    {
+        clear_pull_forces(inputrec->pull);
+    }
+
+    /* update QMMMrec, if necessary */
+    if(fr->bQMMM)
+    {
+        update_QMMMrec(cr,fr,x,mdatoms,box,top);
+    }
+
+    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
+    {
+        /* Position restraints always require full pbc */
+        set_pbc(&pbc,inputrec->ePBC,box);
+        v = posres(top->idef.il[F_POSRES].nr,top->idef.il[F_POSRES].iatoms,
+                   top->idef.iparams_posres,
+                   (const rvec*)x,fr->f_novirsum,fr->vir_diag_posres,
+                   inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda,&dvdl,
+                   fr->rc_scaling,fr->ePBC,fr->posres_com,fr->posres_comB);
+        if (bSepDVDL)
+        {
+            fprintf(fplog,sepdvdlformat,
+                    interaction_function[F_POSRES].longname,v,dvdl);
+        }
+        enerd->term[F_POSRES] += v;
+        /* This linear lambda dependence assumption is only correct
+         * when only k depends on lambda,
+         * not when the reference position depends on lambda.
+         * grompp checks for this.
+         */
+        enerd->dvdl_lin += dvdl;
+        inc_nrnb(nrnb,eNR_POSRES,top->idef.il[F_POSRES].nr/2);
+    }
+
+    /* Compute the bonded and non-bonded energies and optionally forces */    
+    do_force_lowlevel(fplog,step,fr,inputrec,&(top->idef),
+                      cr,nrnb,wcycle,mdatoms,&(inputrec->opts),
+                      x,hist,f,enerd,fcd,mtop,top,fr->born,
+                      &(top->atomtypes),bBornRadii,box,
+                      lambda,graph,&(top->excls),fr->mu_tot,
+                      flags,&cycles_pme);
+    
+    cycles_force = wallcycle_stop(wcycle,ewcFORCE);
+    
+    if (ed)
+    {
+        do_flood(fplog,cr,x,f,ed,box,step);
+    }
+       
+    if (DOMAINDECOMP(cr))
+    {
+        dd_force_flop_stop(cr->dd,nrnb);
+        if (wcycle)
+        {
+            dd_cycles_add(cr->dd,cycles_force-cycles_pme,ddCyclF);
+        }
+    }
+    
+    if (bDoForces)
+    {
+        if (IR_ELEC_FIELD(*inputrec))
+        {
+            /* Compute forces due to electric field */
+            calc_f_el(MASTER(cr) ? field : NULL,
+                      start,homenr,mdatoms->chargeA,x,fr->f_novirsum,
+                      inputrec->ex,inputrec->et,t);
+        }
+        
+        /* Communicate the forces */
+        if (PAR(cr))
+        {
+            wallcycle_start(wcycle,ewcMOVEF);
+            if (DOMAINDECOMP(cr))
+            {
+                dd_move_f(cr->dd,f,fr->fshift);
+                /* Do we need to communicate the separate force array
+                 * for terms that do not contribute to the single sum virial?
+                 * Position restraints and electric fields do not introduce
+                 * inter-cg forces, only full electrostatics methods do.
+                 * When we do not calculate the virial, fr->f_novirsum = f,
+                 * so we have already communicated these forces.
+                 */
+                if (EEL_FULL(fr->eeltype) && cr->dd->n_intercg_excl &&
+                    (flags & GMX_FORCE_VIRIAL))
+                {
+                    dd_move_f(cr->dd,fr->f_novirsum,NULL);
+                }
+                if (bSepLRF)
+                {
+                    /* We should not update the shift forces here,
+                     * since f_twin is already included in f.
+                     */
+                    dd_move_f(cr->dd,fr->f_twin,NULL);
+                }
+            }
+            else
+            {
+                pd_move_f(cr,f,nrnb);
+                if (bSepLRF)
+                {
+                    pd_move_f(cr,fr->f_twin,nrnb);
+                }
+            }
+            wallcycle_stop(wcycle,ewcMOVEF);
+        }
+
+        /* If we have NoVirSum forces, but we do not calculate the virial,
+         * we sum fr->f_novirum=f later.
+         */
+        if (vsite && !(fr->bF_NoVirSum && !(flags & GMX_FORCE_VIRIAL)))
+        {
+            wallcycle_start(wcycle,ewcVSITESPREAD);
+            spread_vsite_f(fplog,vsite,x,f,fr->fshift,nrnb,
+                           &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
+            wallcycle_stop(wcycle,ewcVSITESPREAD);
+
+            if (bSepLRF)
+            {
+                wallcycle_start(wcycle,ewcVSITESPREAD);
+                spread_vsite_f(fplog,vsite,x,fr->f_twin,NULL,
+                               nrnb,
+                               &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
+                wallcycle_stop(wcycle,ewcVSITESPREAD);
+            }
+        }
+        
+        if (flags & GMX_FORCE_VIRIAL)
+        {
+            /* Calculation of the virial must be done after vsites! */
+            calc_virial(fplog,mdatoms->start,mdatoms->homenr,x,f,
+                        vir_force,graph,box,nrnb,fr,inputrec->ePBC);
+        }
+    }
+
+    if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F)
+    {
+        /* Calculate the center of mass forces, this requires communication,
+         * which is why pull_potential is called close to other communication.
+         * The virial contribution is calculated directly,
+         * which is why we call pull_potential after calc_virial.
+         */
+        set_pbc(&pbc,inputrec->ePBC,box);
+        dvdl = 0; 
+        enerd->term[F_COM_PULL] =
+            pull_potential(inputrec->ePull,inputrec->pull,mdatoms,&pbc,
+                           cr,t,lambda,x,f,vir_force,&dvdl);
+        if (bSepDVDL)
+        {
+            fprintf(fplog,sepdvdlformat,"Com pull",enerd->term[F_COM_PULL],dvdl);
+        }
+        enerd->dvdl_lin += dvdl;
+    }
+    else
+        enerd->term[F_COM_PULL] = 0.0;
+    
+    /* Add the forces from enforced rotation potentials (if any) */
+    if (inputrec->bRot)
+        enerd->term[F_COM_PULL] += add_rot_forces(inputrec->rot, f, cr, step, t);
+    
+
+    if (PAR(cr) && !(cr->duty & DUTY_PME))
+    {
+        cycles_ppdpme = wallcycle_stop(wcycle,ewcPPDURINGPME);
+        dd_cycles_add(cr->dd,cycles_ppdpme,ddCyclPPduringPME);
+
+        /* In case of node-splitting, the PP nodes receive the long-range 
+         * forces, virial and energy from the PME nodes here.
+         */    
+        wallcycle_start(wcycle,ewcPP_PMEWAITRECVF);
+        dvdl = 0;
+        gmx_pme_receive_f(cr,fr->f_novirsum,fr->vir_el_recip,&e,&dvdl,
+                          &cycles_seppme);
+        if (bSepDVDL)
+        {
+            fprintf(fplog,sepdvdlformat,"PME mesh",e,dvdl);
+        }
+        enerd->term[F_COUL_RECIP] += e;
+        enerd->dvdl_lin += dvdl;
+        if (wcycle)
+        {
+            dd_cycles_add(cr->dd,cycles_seppme,ddCyclPME);
+        }
+        wallcycle_stop(wcycle,ewcPP_PMEWAITRECVF);
+    }
+
+    if (bDoForces && fr->bF_NoVirSum)
+    {
+        if (vsite)
+        {
+            /* Spread the mesh force on virtual sites to the other particles... 
+             * This is parallellized. MPI communication is performed
+             * if the constructing atoms aren't local.
+             */
+            wallcycle_start(wcycle,ewcVSITESPREAD);
+            spread_vsite_f(fplog,vsite,x,fr->f_novirsum,NULL,nrnb,
+                           &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
+            wallcycle_stop(wcycle,ewcVSITESPREAD);
+        }
+        if (flags & GMX_FORCE_VIRIAL)
+        {
+            /* Now add the forces, this is local */
+            if (fr->bDomDec)
+            {
+                sum_forces(0,fr->f_novirsum_n,f,fr->f_novirsum);
+            }
+            else
+            {
+                sum_forces(start,start+homenr,f,fr->f_novirsum);
+            }
+            if (EEL_FULL(fr->eeltype))
+            {
+                /* Add the mesh contribution to the virial */
+                m_add(vir_force,fr->vir_el_recip,vir_force);
+            }
+            if (debug)
+            {
+                pr_rvecs(debug,0,"vir_force",vir_force,DIM);
+            }
+        }
+    }
+    
+    /* Sum the potential energy terms from group contributions */
+    sum_epot(&(inputrec->opts),enerd);
+    
+    if (fr->print_force >= 0 && bDoForces)
+    {
+        print_large_forces(stderr,mdatoms,cr,step,fr->print_force,x,f);
+    }
+}
+
+void do_constrain_first(FILE *fplog,gmx_constr_t constr,
+                        t_inputrec *ir,t_mdatoms *md,
+                        t_state *state,rvec *f,
+                        t_graph *graph,t_commrec *cr,t_nrnb *nrnb,
+                        t_forcerec *fr, gmx_localtop_t *top, tensor shake_vir)
+{
+    int    i,m,start,end;
+    gmx_large_int_t step;
+    double mass,tmass,vcm[4];
+    real   dt=ir->delta_t;
+    real   dvdlambda;
+    rvec   *savex;
+    
+    snew(savex,state->natoms);
+
+    start = md->start;
+    end   = md->homenr + start;
+    
+    if (debug)
+        fprintf(debug,"vcm: start=%d, homenr=%d, end=%d\n",
+                start,md->homenr,end);
+    /* Do a first constrain to reset particles... */
+    step = ir->init_step;
+    if (fplog)
+    {
+        char buf[STEPSTRSIZE];
+        fprintf(fplog,"\nConstraining the starting coordinates (step %s)\n",
+                gmx_step_str(step,buf));
+    }
+    dvdlambda = 0;
+    
+    /* constrain the current position */
+    constrain(NULL,TRUE,FALSE,constr,&(top->idef),
+              ir,NULL,cr,step,0,md,
+              state->x,state->x,NULL,
+              state->box,state->lambda,&dvdlambda,
+              NULL,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
+    if (EI_VV(ir->eI)) 
+    {
+        /* constrain the inital velocity, and save it */
+        /* also may be useful if we need the ekin from the halfstep for velocity verlet */
+        /* might not yet treat veta correctly */
+        constrain(NULL,TRUE,FALSE,constr,&(top->idef),
+                  ir,NULL,cr,step,0,md,
+                  state->x,state->v,state->v,
+                  state->box,state->lambda,&dvdlambda,
+                  NULL,NULL,nrnb,econqVeloc,ir->epc==epcMTTK,state->veta,state->veta);
+    }
+    /* constrain the inital velocities at t-dt/2 */
+    if (EI_STATE_VELOCITY(ir->eI) && ir->eI!=eiVV)
+    {
+        for(i=start; (i<end); i++) 
+        {
+            for(m=0; (m<DIM); m++) 
+            {
+                /* Reverse the velocity */
+                state->v[i][m] = -state->v[i][m];
+                /* Store the position at t-dt in buf */
+                savex[i][m] = state->x[i][m] + dt*state->v[i][m];
+            }
+        }
+    /* Shake the positions at t=-dt with the positions at t=0                        
+     * as reference coordinates.                                                     
+         */
+        if (fplog)
+        {
+            char buf[STEPSTRSIZE];
+            fprintf(fplog,"\nConstraining the coordinates at t0-dt (step %s)\n",
+                    gmx_step_str(step,buf));
+        }
+        dvdlambda = 0;
+        constrain(NULL,TRUE,FALSE,constr,&(top->idef),
+                  ir,NULL,cr,step,-1,md,
+                  state->x,savex,NULL,
+                  state->box,state->lambda,&dvdlambda,
+                  state->v,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
+        
+        for(i=start; i<end; i++) {
+            for(m=0; m<DIM; m++) {
+                /* Re-reverse the velocities */
+                state->v[i][m] = -state->v[i][m];
+            }
+        }
+    }
+    
+    for(m=0; (m<4); m++)
+        vcm[m] = 0;
+    for(i=start; i<end; i++) {
+        mass = md->massT[i];
+        for(m=0; m<DIM; m++) {
+            vcm[m] += state->v[i][m]*mass;
+        }
+        vcm[3] += mass;
+    }
+    
+    if (ir->nstcomm != 0 || debug) {
+        /* Compute the global sum of vcm */
+        if (debug)
+            fprintf(debug,"vcm: %8.3f  %8.3f  %8.3f,"
+                    " total mass = %12.5e\n",vcm[XX],vcm[YY],vcm[ZZ],vcm[3]);
+        if (PAR(cr))
+            gmx_sumd(4,vcm,cr);
+        tmass = vcm[3];
+        for(m=0; (m<DIM); m++)
+            vcm[m] /= tmass;
+        if (debug) 
+            fprintf(debug,"vcm: %8.3f  %8.3f  %8.3f,"
+                    " total mass = %12.5e\n",vcm[XX],vcm[YY],vcm[ZZ],tmass);
+        if (ir->nstcomm != 0) {
+            /* Now we have the velocity of center of mass, let's remove it */
+            for(i=start; (i<end); i++) {
+                for(m=0; (m<DIM); m++)
+                    state->v[i][m] -= vcm[m];
+            }
+
+        }
+    }
+    sfree(savex);
+}
+
+void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
+{
+  double eners[2],virs[2],enersum,virsum,y0,f,g,h;
+  double r0,r1,r,rc3,rc9,ea,eb,ec,pa,pb,pc,pd;
+  double invscale,invscale2,invscale3;
+  int    ri0,ri1,ri,i,offstart,offset;
+  real   scale,*vdwtab; 
+
+  fr->enershiftsix = 0;
+  fr->enershifttwelve = 0;
+  fr->enerdiffsix = 0;
+  fr->enerdifftwelve = 0;
+  fr->virdiffsix = 0;
+  fr->virdifftwelve = 0;
+
+  if (eDispCorr != edispcNO) {
+    for(i=0; i<2; i++) {
+      eners[i] = 0;
+      virs[i]  = 0;
+    }
+    if ((fr->vdwtype == evdwSWITCH) || (fr->vdwtype == evdwSHIFT)) {
+      if (fr->rvdw_switch == 0)
+       gmx_fatal(FARGS,
+                 "With dispersion correction rvdw-switch can not be zero "
+                 "for vdw-type = %s",evdw_names[fr->vdwtype]);
+
+      scale  = fr->nblists[0].tab.scale;
+      vdwtab = fr->nblists[0].vdwtab;
+
+      /* Round the cut-offs to exact table values for precision */
+      ri0 = floor(fr->rvdw_switch*scale);
+      ri1 = ceil(fr->rvdw*scale);
+      r0  = ri0/scale;
+      r1  = ri1/scale;
+      rc3 = r0*r0*r0;
+      rc9  = rc3*rc3*rc3;
+
+      if (fr->vdwtype == evdwSHIFT) {
+       /* Determine the constant energy shift below rvdw_switch */
+       fr->enershiftsix    = (real)(-1.0/(rc3*rc3)) - vdwtab[8*ri0];
+       fr->enershifttwelve = (real)( 1.0/(rc9*rc3)) - vdwtab[8*ri0 + 4];
+      }
+      /* Add the constant part from 0 to rvdw_switch.
+       * This integration from 0 to rvdw_switch overcounts the number
+       * of interactions by 1, as it also counts the self interaction.
+       * We will correct for this later.
+       */
+      eners[0] += 4.0*M_PI*fr->enershiftsix*rc3/3.0;
+      eners[1] += 4.0*M_PI*fr->enershifttwelve*rc3/3.0;
+      
+      invscale = 1.0/(scale);  
+      invscale2 = invscale*invscale;
+      invscale3 = invscale*invscale2;
+
+      /* following summation derived from cubic spline definition,
+       Numerical Recipies in C, second edition, p. 113-116.  Exact
+       for the cubic spline.  We first calculate the negative of
+       the energy from rvdw to rvdw_switch, assuming that g(r)=1,
+       and then add the more standard, abrupt cutoff correction to
+       that result, yielding the long-range correction for a
+       switched function.  We perform both the pressure and energy
+       loops at the same time for simplicity, as the computational
+       cost is low. */
+      
+      for (i=0;i<2;i++) {
+        enersum = 0.0; virsum = 0.0;
+        if (i==0)
+         offstart = 0;
+       else
+         offstart = 4;
+       for (ri=ri0; ri<ri1; ri++) {
+          r = ri*invscale;
+          ea = invscale3;
+          eb = 2.0*invscale2*r;
+          ec = invscale*r*r;
+          
+          pa = invscale3;
+          pb = 3.0*invscale2*r;
+          pc = 3.0*invscale*r*r;
+          pd = r*r*r;
+          
+          /* this "8" is from the packing in the vdwtab array - perhaps
+           should be #define'ed? */
+          offset = 8*ri + offstart;
+          y0 = vdwtab[offset];
+          f = vdwtab[offset+1];
+          g = vdwtab[offset+2];
+          h = vdwtab[offset+3];
+         
+          enersum += y0*(ea/3 + eb/2 + ec) + f*(ea/4 + eb/3 + ec/2)+
+            g*(ea/5 + eb/4 + ec/3) + h*(ea/6 + eb/5 + ec/4);  
+          virsum  +=  f*(pa/4 + pb/3 + pc/2 + pd) + 
+            2*g*(pa/5 + pb/4 + pc/3 + pd/2) + 3*h*(pa/6 + pb/5 + pc/4 + pd/3);
+         
+        }
+        enersum *= 4.0*M_PI;
+        virsum  *= 4.0*M_PI; 
+        eners[i] -= enersum;
+        virs[i]  -= virsum;
+      }
+
+      /* now add the correction for rvdw_switch to infinity */
+      eners[0] += -4.0*M_PI/(3.0*rc3);
+      eners[1] +=  4.0*M_PI/(9.0*rc9);
+      virs[0]  +=  8.0*M_PI/rc3;
+      virs[1]  += -16.0*M_PI/(3.0*rc9);
+    } 
+    else if ((fr->vdwtype == evdwCUT) || (fr->vdwtype == evdwUSER)) {
+      if (fr->vdwtype == evdwUSER && fplog)
+       fprintf(fplog,
+               "WARNING: using dispersion correction with user tables\n");
+      rc3  = fr->rvdw*fr->rvdw*fr->rvdw;
+      rc9  = rc3*rc3*rc3;
+      eners[0] += -4.0*M_PI/(3.0*rc3);
+      eners[1] +=  4.0*M_PI/(9.0*rc9);
+      virs[0]  +=  8.0*M_PI/rc3;
+      virs[1]  += -16.0*M_PI/(3.0*rc9);
+    } else {
+      gmx_fatal(FARGS,
+               "Dispersion correction is not implemented for vdw-type = %s",
+               evdw_names[fr->vdwtype]);
+    }
+    fr->enerdiffsix    = eners[0];
+    fr->enerdifftwelve = eners[1];
+    /* The 0.5 is due to the Gromacs definition of the virial */
+    fr->virdiffsix     = 0.5*virs[0];
+    fr->virdifftwelve  = 0.5*virs[1];
+  }
+}
+
+void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
+                   gmx_large_int_t step,int natoms,
+                   matrix box,real lambda,tensor pres,tensor virial,
+                   real *prescorr, real *enercorr, real *dvdlcorr)
+{
+    gmx_bool bCorrAll,bCorrPres;
+    real dvdlambda,invvol,dens,ninter,avcsix,avctwelve,enerdiff,svir=0,spres=0;
+    int  m;
+    
+    *prescorr = 0;
+    *enercorr = 0;
+    *dvdlcorr = 0;
+    
+    clear_mat(virial);
+    clear_mat(pres);
+    
+    if (ir->eDispCorr != edispcNO) {
+        bCorrAll  = (ir->eDispCorr == edispcAllEner ||
+                     ir->eDispCorr == edispcAllEnerPres);
+        bCorrPres = (ir->eDispCorr == edispcEnerPres ||
+                     ir->eDispCorr == edispcAllEnerPres);
+        
+        invvol = 1/det(box);
+        if (fr->n_tpi) 
+        {
+            /* Only correct for the interactions with the inserted molecule */
+            dens = (natoms - fr->n_tpi)*invvol;
+            ninter = fr->n_tpi;
+        } 
+        else 
+        {
+            dens = natoms*invvol;
+            ninter = 0.5*natoms;
+        }
+        
+        if (ir->efep == efepNO) 
+        {
+            avcsix    = fr->avcsix[0];
+            avctwelve = fr->avctwelve[0];
+        } 
+        else 
+        {
+            avcsix    = (1 - lambda)*fr->avcsix[0]    + lambda*fr->avcsix[1];
+            avctwelve = (1 - lambda)*fr->avctwelve[0] + lambda*fr->avctwelve[1];
+        }
+        
+        enerdiff = ninter*(dens*fr->enerdiffsix - fr->enershiftsix);
+        *enercorr += avcsix*enerdiff;
+        dvdlambda = 0.0;
+        if (ir->efep != efepNO) 
+        {
+            dvdlambda += (fr->avcsix[1] - fr->avcsix[0])*enerdiff;
+        }
+        if (bCorrAll) 
+        {
+            enerdiff = ninter*(dens*fr->enerdifftwelve - fr->enershifttwelve);
+            *enercorr += avctwelve*enerdiff;
+            if (fr->efep != efepNO) 
+            {
+                dvdlambda += (fr->avctwelve[1] - fr->avctwelve[0])*enerdiff;
+            }
+        }
+        
+        if (bCorrPres) 
+        {
+            svir = ninter*dens*avcsix*fr->virdiffsix/3.0;
+            if (ir->eDispCorr == edispcAllEnerPres)
+            {
+                svir += ninter*dens*avctwelve*fr->virdifftwelve/3.0;
+            }
+            /* The factor 2 is because of the Gromacs virial definition */
+            spres = -2.0*invvol*svir*PRESFAC;
+            
+            for(m=0; m<DIM; m++) {
+                virial[m][m] += svir;
+                pres[m][m] += spres;
+            }
+            *prescorr += spres;
+        }
+        
+        /* Can't currently control when it prints, for now, just print when degugging */
+        if (debug)
+        {
+            if (bCorrAll) {
+                fprintf(debug,"Long Range LJ corr.: <C6> %10.4e, <C12> %10.4e\n",
+                        avcsix,avctwelve);
+            }
+            if (bCorrPres) 
+            {
+                fprintf(debug,
+                        "Long Range LJ corr.: Epot %10g, Pres: %10g, Vir: %10g\n",
+                        *enercorr,spres,svir);
+            }
+            else
+            {
+                fprintf(debug,"Long Range LJ corr.: Epot %10g\n",*enercorr);
+            }
+        }
+        
+        if (fr->bSepDVDL && do_per_step(step,ir->nstlog))
+        {
+            fprintf(fplog,sepdvdlformat,"Dispersion correction",
+                    *enercorr,dvdlambda);
+        }
+        if (fr->efep != efepNO) 
+        {
+            *dvdlcorr += dvdlambda;
+        }
+    }
+}
+
+void do_pbc_first(FILE *fplog,matrix box,t_forcerec *fr,
+                 t_graph *graph,rvec x[])
+{
+  if (fplog)
+    fprintf(fplog,"Removing pbc first time\n");
+  calc_shifts(box,fr->shift_vec);
+  if (graph) {
+    mk_mshift(fplog,graph,fr->ePBC,box,x);
+    if (gmx_debug_at)
+      p_graph(debug,"do_pbc_first 1",graph);
+    shift_self(graph,box,x);
+    /* By doing an extra mk_mshift the molecules that are broken
+     * because they were e.g. imported from another software
+     * will be made whole again. Such are the healing powers
+     * of GROMACS.
+     */
+    mk_mshift(fplog,graph,fr->ePBC,box,x);
+    if (gmx_debug_at)
+      p_graph(debug,"do_pbc_first 2",graph);
+  }
+  if (fplog)
+    fprintf(fplog,"Done rmpbc\n");
+}
+
+static void low_do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
+                           gmx_mtop_t *mtop,rvec x[],
+                           gmx_bool bFirst)
+{
+  t_graph *graph;
+  int mb,as,mol;
+  gmx_molblock_t *molb;
+
+  if (bFirst && fplog)
+    fprintf(fplog,"Removing pbc first time\n");
+
+  snew(graph,1);
+  as = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    molb = &mtop->molblock[mb];
+    if (molb->natoms_mol == 1 || 
+       (!bFirst && mtop->moltype[molb->type].cgs.nr == 1)) {
+      /* Just one atom or charge group in the molecule, no PBC required */
+      as += molb->nmol*molb->natoms_mol;
+    } else {
+      /* Pass NULL iso fplog to avoid graph prints for each molecule type */
+      mk_graph_ilist(NULL,mtop->moltype[molb->type].ilist,
+                    0,molb->natoms_mol,FALSE,FALSE,graph);
+      
+      for(mol=0; mol<molb->nmol; mol++) {
+       mk_mshift(fplog,graph,ePBC,box,x+as);
+       
+       shift_self(graph,box,x+as);
+       /* The molecule is whole now.
+        * We don't need the second mk_mshift call as in do_pbc_first,
+        * since we no longer need this graph.
+        */
+       
+       as += molb->natoms_mol;
+      }
+      done_graph(graph);
+    }
+  }
+  sfree(graph);
+}
+
+void do_pbc_first_mtop(FILE *fplog,int ePBC,matrix box,
+                      gmx_mtop_t *mtop,rvec x[])
+{
+  low_do_pbc_mtop(fplog,ePBC,box,mtop,x,TRUE);
+}
+
+void do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
+                gmx_mtop_t *mtop,rvec x[])
+{
+  low_do_pbc_mtop(fplog,ePBC,box,mtop,x,FALSE);
+}
+
+void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
+                t_inputrec *inputrec,
+                t_nrnb nrnb[],gmx_wallcycle_t wcycle,
+                gmx_runtime_t *runtime,
+                gmx_bool bWriteStat)
+{
+  int    i,j;
+  t_nrnb *nrnb_tot=NULL;
+  real   delta_t;
+  double nbfs,mflop;
+  double cycles[ewcNR];
+
+  wallcycle_sum(cr,wcycle,cycles);
+
+  if (cr->nnodes > 1) {
+    if (SIMMASTER(cr))
+      snew(nrnb_tot,1);
+#ifdef GMX_MPI
+    MPI_Reduce(nrnb->n,nrnb_tot->n,eNRNB,MPI_DOUBLE,MPI_SUM,
+               MASTERRANK(cr),cr->mpi_comm_mysim);
+#endif  
+  } else {
+    nrnb_tot = nrnb;
+  }
+    
+  if (SIMMASTER(cr)) {
+    print_flop(fplog,nrnb_tot,&nbfs,&mflop);
+    if (cr->nnodes > 1) {
+      sfree(nrnb_tot);
+    }
+  }
+
+  if ((cr->duty & DUTY_PP) && DOMAINDECOMP(cr)) {
+    print_dd_statistics(cr,inputrec,fplog);
+  }
+
+#ifdef GMX_MPI
+    if (PARTDECOMP(cr))
+    {
+        if (MASTER(cr))
+        {
+            t_nrnb     *nrnb_all;
+            int        s;
+            MPI_Status stat;
+
+            snew(nrnb_all,cr->nnodes);
+            nrnb_all[0] = *nrnb;
+            for(s=1; s<cr->nnodes; s++)
+            {
+                MPI_Recv(nrnb_all[s].n,eNRNB,MPI_DOUBLE,s,0,
+                         cr->mpi_comm_mysim,&stat);
+            }
+            pr_load(fplog,cr,nrnb_all);
+            sfree(nrnb_all);
+        }
+        else
+        {
+            MPI_Send(nrnb->n,eNRNB,MPI_DOUBLE,MASTERRANK(cr),0,
+                     cr->mpi_comm_mysim);
+        }
+    }
+#endif  
+
+  if (SIMMASTER(cr)) {
+    wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
+                    wcycle,cycles);
+
+    if (EI_DYNAMICS(inputrec->eI)) {
+      delta_t = inputrec->delta_t;
+    } else {
+      delta_t = 0;
+    }
+    
+    if (fplog) {
+        print_perf(fplog,runtime->proctime,runtime->realtime,
+                   cr->nnodes-cr->npmenodes,
+                   runtime->nsteps_done,delta_t,nbfs,mflop);
+    }
+    if (bWriteStat) {
+        print_perf(stderr,runtime->proctime,runtime->realtime,
+                   cr->nnodes-cr->npmenodes,
+                   runtime->nsteps_done,delta_t,nbfs,mflop);
+    }
+
+    /*
+    runtime=inputrec->nsteps*inputrec->delta_t;
+    if (bWriteStat) {
+      if (cr->nnodes == 1)
+       fprintf(stderr,"\n\n");
+      print_perf(stderr,nodetime,realtime,runtime,&ntot,
+                cr->nnodes-cr->npmenodes,FALSE);
+    }
+    wallcycle_print(fplog,cr->nnodes,cr->npmenodes,realtime,wcycle,cycles);
+    print_perf(fplog,nodetime,realtime,runtime,&ntot,cr->nnodes-cr->npmenodes,
+              TRUE);
+    if (PARTDECOMP(cr))
+      pr_load(fplog,cr,nrnb_all);
+    if (cr->nnodes > 1)
+      sfree(nrnb_all);
+    */
+  }
+}
+
+void init_md(FILE *fplog,
+             t_commrec *cr,t_inputrec *ir,const output_env_t oenv,
+             double *t,double *t0,
+             real *lambda,double *lam0,
+             t_nrnb *nrnb,gmx_mtop_t *mtop,
+             gmx_update_t *upd,
+             int nfile,const t_filenm fnm[],
+             gmx_mdoutf_t **outf,t_mdebin **mdebin,
+             tensor force_vir,tensor shake_vir,rvec mu_tot,
+             gmx_bool *bSimAnn,t_vcm **vcm, t_state *state, unsigned long Flags)
+{
+    int  i,j,n;
+    real tmpt,mod;
+       
+    /* Initial values */
+    *t = *t0       = ir->init_t;
+    if (ir->efep != efepNO)
+    {
+        *lam0 = ir->init_lambda;
+        *lambda = *lam0 + ir->init_step*ir->delta_lambda;
+    }
+    else
+    {
+        *lambda = *lam0   = 0.0;
+    } 
+
+    *bSimAnn=FALSE;
+    for(i=0;i<ir->opts.ngtc;i++)
+    {
+        /* set bSimAnn if any group is being annealed */
+        if(ir->opts.annealing[i]!=eannNO)
+        {
+            *bSimAnn = TRUE;
+        }
+    }
+    if (*bSimAnn)
+    {
+        update_annealing_target_temp(&(ir->opts),ir->init_t);
+    }
+    
+    if (upd)
+    {
+        *upd = init_update(fplog,ir);
+    }
+    
+    if (vcm != NULL)
+    {
+        *vcm = init_vcm(fplog,&mtop->groups,ir);
+    }
+    
+    if (EI_DYNAMICS(ir->eI) && !(Flags & MD_APPENDFILES))
+    {
+        if (ir->etc == etcBERENDSEN)
+        {
+            please_cite(fplog,"Berendsen84a");
+        }
+        if (ir->etc == etcVRESCALE)
+        {
+            please_cite(fplog,"Bussi2007a");
+        }
+    }
+    
+    init_nrnb(nrnb);
+    
+    if (nfile != -1)
+    {
+        *outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
+
+        *mdebin = init_mdebin((Flags & MD_APPENDFILES) ? NULL : (*outf)->fp_ene,
+                              mtop,ir, (*outf)->fp_dhdl);
+    }
+    
+    /* Initiate variables */  
+    clear_mat(force_vir);
+    clear_mat(shake_vir);
+    clear_rvec(mu_tot);
+    
+    debug_gmx();
+}
+
similarity index 100%
rename from src/mdlib/stat.c
rename to src/gromacs/mdlib/stat.c
diff --git a/src/gromacs/mdlib/tpi.c b/src/gromacs/mdlib/tpi.c
new file mode 100644 (file)
index 0000000..2a5ae3d
--- /dev/null
@@ -0,0 +1,795 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROwing Monsters And Cloning Shrimps
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include "sysstuff.h"
+#include "string2.h"
+#include "network.h"
+#include "confio.h"
+#include "copyrite.h"
+#include "smalloc.h"
+#include "nrnb.h"
+#include "main.h"
+#include "chargegroup.h"
+#include "force.h"
+#include "macros.h"
+#include "random.h"
+#include "names.h"
+#include "gmx_fatal.h"
+#include "txtdump.h"
+#include "typedefs.h"
+#include "update.h"
+#include "random.h"
+#include "constr.h"
+#include "vec.h"
+#include "statutil.h"
+#include "tgroup.h"
+#include "mdebin.h"
+#include "vsite.h"
+#include "force.h"
+#include "mdrun.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "gmx_random.h"
+#include "physics.h"
+#include "xvgr.h"
+#include "mdatoms.h"
+#include "ns.h"
+#include "gmx_wallcycle.h"
+#include "mtop_util.h"
+#include "gmxfio.h"
+#include "pme.h"
+#include "gbutil.h"
+
+#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
+#if defined(GMX_DOUBLE)
+#include "gmx_sse2_double.h"
+#else
+#include "gmx_sse2_single.h"
+#endif
+#endif
+
+
+static void global_max(t_commrec *cr,int *n)
+{
+  int *sum,i;
+
+  snew(sum,cr->nnodes);
+  sum[cr->nodeid] = *n;
+  gmx_sumi(cr->nnodes,sum,cr);
+  for(i=0; i<cr->nnodes; i++)
+    *n = max(*n,sum[i]);
+  
+  sfree(sum);
+}
+
+static void realloc_bins(double **bin,int *nbin,int nbin_new)
+{
+  int i;
+
+  if (nbin_new != *nbin) {
+    srenew(*bin,nbin_new);
+    for(i=*nbin; i<nbin_new; i++)
+      (*bin)[i] = 0;
+    *nbin = nbin_new;
+  }
+}
+
+double do_tpi(FILE *fplog,t_commrec *cr,
+              int nfile, const t_filenm fnm[],
+              const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+              int nstglobalcomm,
+              gmx_vsite_t *vsite,gmx_constr_t constr,
+              int stepout,
+              t_inputrec *inputrec,
+              gmx_mtop_t *top_global,t_fcdata *fcd,
+              t_state *state,
+              t_mdatoms *mdatoms,
+              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+              gmx_edsam_t ed,
+              t_forcerec *fr,
+              int repl_ex_nst,int repl_ex_seed,
+              gmx_membed_t *membed,
+              real cpt_period,real max_hours,
+              const char *deviceOptions,
+              unsigned long Flags,
+              gmx_runtime_t *runtime)
+{
+  const char *TPI="Test Particle Insertion"; 
+  gmx_localtop_t *top;
+  gmx_groups_t *groups;
+  gmx_enerdata_t *enerd;
+  rvec   *f;
+  real   lambda,t,temp,beta,drmax,epot;
+  double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
+  t_trxstatus   *status;
+  t_trxframe rerun_fr;
+  gmx_bool   bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
+  tensor force_vir,shake_vir,vir,pres;
+  int    cg_tp,a_tp0,a_tp1,ngid,gid_tp,nener,e;
+  rvec   *x_mol;
+  rvec   mu_tot,x_init,dx,x_tp;
+  int    nnodes,frame,nsteps,step;
+  int    i,start,end;
+  gmx_rng_t tpi_rand;
+  FILE   *fp_tpi=NULL;
+  char   *ptr,*dump_pdb,**leg,str[STRLEN],str2[STRLEN];
+  double dbl,dump_ener;
+  gmx_bool   bCavity;
+  int    nat_cavity=0,d;
+  real   *mass_cavity=NULL,mass_tot;
+  int    nbin;
+  double invbinw,*bin,refvolshift,logV,bUlogV;
+  real dvdl,prescorr,enercorr,dvdlcorr;
+  gmx_bool bEnergyOutOfBounds;
+  const char *tpid_leg[2]={"direct","reweighted"};
+
+  /* Since there is no upper limit to the insertion energies,
+   * we need to set an upper limit for the distribution output.
+   */
+  real bU_bin_limit      = 50;
+  real bU_logV_bin_limit = bU_bin_limit + 10;
+
+  nnodes = cr->nnodes;
+
+  top = gmx_mtop_generate_local_top(top_global,inputrec);
+
+  groups = &top_global->groups;
+
+  bCavity = (inputrec->eI == eiTPIC);
+  if (bCavity) {
+    ptr = getenv("GMX_TPIC_MASSES");
+    if (ptr == NULL) {
+      nat_cavity = 1;
+    } else {
+      /* Read (multiple) masses from env var GMX_TPIC_MASSES,
+       * The center of mass of the last atoms is then used for TPIC.
+       */
+      nat_cavity = 0;
+      while (sscanf(ptr,"%lf%n",&dbl,&i) > 0) {
+       srenew(mass_cavity,nat_cavity+1);
+       mass_cavity[nat_cavity] = dbl;
+       fprintf(fplog,"mass[%d] = %f\n",
+               nat_cavity+1,mass_cavity[nat_cavity]);
+       nat_cavity++;
+       ptr += i;
+      }
+      if (nat_cavity == 0)
+       gmx_fatal(FARGS,"Found %d masses in GMX_TPIC_MASSES",nat_cavity);
+    }
+  }
+
+  /*
+  init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
+  state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
+  /* We never need full pbc for TPI */
+  fr->ePBC = epbcXYZ;
+  /* Determine the temperature for the Boltzmann weighting */
+  temp = inputrec->opts.ref_t[0];
+  if (fplog) {
+    for(i=1; (i<inputrec->opts.ngtc); i++) {
+      if (inputrec->opts.ref_t[i] != temp) {
+       fprintf(fplog,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
+       fprintf(stderr,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
+      }
+    }
+    fprintf(fplog,
+           "\n  The temperature for test particle insertion is %.3f K\n\n",
+           temp);
+  }
+  beta = 1.0/(BOLTZ*temp);
+
+  /* Number of insertions per frame */
+  nsteps = inputrec->nsteps; 
+
+  /* Use the same neighborlist with more insertions points
+   * in a sphere of radius drmax around the initial point
+   */
+  /* This should be a proper mdp parameter */
+  drmax = inputrec->rtpi;
+
+  /* An environment variable can be set to dump all configurations
+   * to pdb with an insertion energy <= this value.
+   */
+  dump_pdb = getenv("GMX_TPI_DUMP");
+  dump_ener = 0;
+  if (dump_pdb)
+    sscanf(dump_pdb,"%lf",&dump_ener);
+
+  atoms2md(top_global,inputrec,0,NULL,0,top_global->natoms,mdatoms);
+  update_mdatoms(mdatoms,inputrec->init_lambda);
+
+  snew(enerd,1);
+  init_enerdata(groups->grps[egcENER].nr,inputrec->n_flambda,enerd);
+  snew(f,top_global->natoms);
+
+  /* Print to log file  */
+  runtime_start(runtime);
+  print_date_and_time(fplog,cr->nodeid,
+                      "Started Test Particle Insertion",runtime); 
+  wallcycle_start(wcycle,ewcRUN);
+
+  /* The last charge group is the group to be inserted */
+  cg_tp = top->cgs.nr - 1;
+  a_tp0 = top->cgs.index[cg_tp];
+  a_tp1 = top->cgs.index[cg_tp+1];
+  if (debug)
+    fprintf(debug,"TPI cg %d, atoms %d-%d\n",cg_tp,a_tp0,a_tp1);
+  if (a_tp1 - a_tp0 > 1 &&
+      (inputrec->rlist < inputrec->rcoulomb ||
+       inputrec->rlist < inputrec->rvdw))
+    gmx_fatal(FARGS,"Can not do TPI for multi-atom molecule with a twin-range cut-off");
+  snew(x_mol,a_tp1-a_tp0);
+
+  bDispCorr = (inputrec->eDispCorr != edispcNO);
+  bCharge = FALSE;
+  for(i=a_tp0; i<a_tp1; i++) {
+    /* Copy the coordinates of the molecule to be insterted */
+    copy_rvec(state->x[i],x_mol[i-a_tp0]);
+    /* Check if we need to print electrostatic energies */
+    bCharge |= (mdatoms->chargeA[i] != 0 ||
+               (mdatoms->chargeB && mdatoms->chargeB[i] != 0));
+  }
+  bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype!=eelRF_NEC);
+
+  calc_cgcm(fplog,cg_tp,cg_tp+1,&(top->cgs),state->x,fr->cg_cm);
+  if (bCavity) {
+    if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog) {
+      fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
+      fprintf(stderr,"WARNING: Your TPI molecule is not centered at 0,0,0\n");
+    }
+  } else {
+    /* Center the molecule to be inserted at zero */
+     for(i=0; i<a_tp1-a_tp0; i++)
+      rvec_dec(x_mol[i],fr->cg_cm[cg_tp]);
+  }
+
+  if (fplog) {
+    fprintf(fplog,"\nWill insert %d atoms %s partial charges\n",
+           a_tp1-a_tp0,bCharge ? "with" : "without");
+    
+    fprintf(fplog,"\nWill insert %d times in each frame of %s\n",
+           nsteps,opt2fn("-rerun",nfile,fnm));
+  }
+  
+    if (!bCavity)
+    {
+        if (inputrec->nstlist > 1)
+        {
+            if (drmax==0 && a_tp1-a_tp0==1)
+            {
+                gmx_fatal(FARGS,"Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense",inputrec->nstlist,drmax);
+            }
+            if (fplog)
+            {
+                fprintf(fplog,"Will use the same neighborlist for %d insertions in a sphere of radius %f\n",inputrec->nstlist,drmax);
+            }
+        }
+    }
+    else
+    {
+        if (fplog)
+        {
+            fprintf(fplog,"Will insert randomly in a sphere of radius %f around the center of the cavity\n",drmax);
+        }
+    }
+
+  ngid = groups->grps[egcENER].nr;
+  gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
+  nener = 1 + ngid;
+  if (bDispCorr)
+    nener += 1;
+  if (bCharge) {
+    nener += ngid;
+    if (bRFExcl)
+      nener += 1;
+    if (EEL_FULL(fr->eeltype))
+      nener += 1;
+  }
+  snew(sum_UgembU,nener);
+
+  /* Initialize random generator */
+  tpi_rand = gmx_rng_init(inputrec->ld_seed);
+
+  if (MASTER(cr)) {
+    fp_tpi = xvgropen(opt2fn("-tpi",nfile,fnm),
+                     "TPI energies","Time (ps)",
+                     "(kJ mol\\S-1\\N) / (nm\\S3\\N)",oenv);
+    xvgr_subtitle(fp_tpi,"f. are averages over one frame",oenv);
+    snew(leg,4+nener);
+    e = 0;
+    sprintf(str,"-kT log(<Ve\\S-\\betaU\\N>/<V>)");
+    leg[e++] = strdup(str);
+    sprintf(str,"f. -kT log<e\\S-\\betaU\\N>");
+    leg[e++] = strdup(str);
+    sprintf(str,"f. <e\\S-\\betaU\\N>");
+    leg[e++] = strdup(str);
+    sprintf(str,"f. V");
+    leg[e++] = strdup(str);
+    sprintf(str,"f. <Ue\\S-\\betaU\\N>");
+    leg[e++] = strdup(str);
+    for(i=0; i<ngid; i++) {
+      sprintf(str,"f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
+             *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
+      leg[e++] = strdup(str);
+    }
+    if (bDispCorr) {
+      sprintf(str,"f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
+      leg[e++] = strdup(str);
+    }
+    if (bCharge) {
+      for(i=0; i<ngid; i++) {
+       sprintf(str,"f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
+               *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
+       leg[e++] = strdup(str);
+      }
+      if (bRFExcl) {
+       sprintf(str,"f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
+       leg[e++] = strdup(str);
+      }
+      if (EEL_FULL(fr->eeltype)) {
+       sprintf(str,"f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
+       leg[e++] = strdup(str);
+      }
+    }
+    xvgr_legend(fp_tpi,4+nener,(const char**)leg,oenv);
+    for(i=0; i<4+nener; i++)
+      sfree(leg[i]);
+    sfree(leg);
+  }
+  clear_rvec(x_init);
+  V_all = 0;
+  VembU_all = 0;
+
+  invbinw = 10;
+  nbin = 10;
+  snew(bin,nbin);
+
+  bNotLastFrame = read_first_frame(oenv,&status,opt2fn("-rerun",nfile,fnm),
+                                  &rerun_fr,TRX_NEED_X);
+  frame = 0;
+
+  if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
+      mdatoms->nr - (a_tp1 - a_tp0))
+    gmx_fatal(FARGS,"Number of atoms in trajectory (%d)%s "
+             "is not equal the number in the run input file (%d) "
+             "minus the number of atoms to insert (%d)\n",
+             rerun_fr.natoms,bCavity ? " minus one" : "",
+             mdatoms->nr,a_tp1-a_tp0);
+
+  refvolshift = log(det(rerun_fr.box));
+
+#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
+    /* Make sure we don't detect SSE overflow generated before this point */
+    gmx_mm_check_and_reset_overflow();
+#endif
+
+    while (bNotLastFrame)
+    {
+        lambda = rerun_fr.lambda;
+        t = rerun_fr.time;
+        
+        sum_embU = 0;
+        for(e=0; e<nener; e++)
+        {
+            sum_UgembU[e] = 0;
+        }
+        
+        /* Copy the coordinates from the input trajectory */
+        for(i=0; i<rerun_fr.natoms; i++)
+        {
+            copy_rvec(rerun_fr.x[i],state->x[i]);
+        }
+        
+        V = det(rerun_fr.box);
+        logV = log(V);
+        
+        bStateChanged = TRUE;
+        bNS = TRUE;
+        for(step=0; step<nsteps; step++)
+        {
+            /* In parallel all nodes generate all random configurations.
+             * In that way the result is identical to a single cpu tpi run.
+             */
+            if (!bCavity)
+            {
+                /* Random insertion in the whole volume */
+                bNS = (step % inputrec->nstlist == 0);
+                if (bNS)
+                {
+                    /* Generate a random position in the box */
+                    x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX];
+                    x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY];
+                    x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ];
+                }
+                if (inputrec->nstlist == 1)
+                {
+                    copy_rvec(x_init,x_tp);
+                }
+                else
+                {
+                    /* Generate coordinates within |dx|=drmax of x_init */
+                    do
+                    {
+                        dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                        dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                        dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                    }
+                    while (norm2(dx) > drmax*drmax);
+                    rvec_add(x_init,dx,x_tp);
+                }
+            }
+            else
+            {
+                /* Random insertion around a cavity location
+                 * given by the last coordinate of the trajectory.
+                 */
+                if (step == 0)
+                {
+                    if (nat_cavity == 1)
+                    {
+                        /* Copy the location of the cavity */
+                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1],x_init);
+                    }
+                    else
+                    {
+                        /* Determine the center of mass of the last molecule */
+                        clear_rvec(x_init);
+                        mass_tot = 0;
+                        for(i=0; i<nat_cavity; i++)
+                        {
+                            for(d=0; d<DIM; d++)
+                            {
+                                x_init[d] +=
+                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
+                            }
+                            mass_tot += mass_cavity[i];
+                        }
+                        for(d=0; d<DIM; d++)
+                        {
+                            x_init[d] /= mass_tot;
+                        }
+                    }
+                }
+                /* Generate coordinates within |dx|=drmax of x_init */
+                do
+                {
+                    dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                    dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                    dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
+                }
+                while (norm2(dx) > drmax*drmax);
+                rvec_add(x_init,dx,x_tp);
+            }
+            
+            if (a_tp1 - a_tp0 == 1)
+            {
+                /* Insert a single atom, just copy the insertion location */
+       copy_rvec(x_tp,state->x[a_tp0]);
+            }
+            else
+            {
+                /* Copy the coordinates from the top file */
+                for(i=a_tp0; i<a_tp1; i++)
+                {
+                    copy_rvec(x_mol[i-a_tp0],state->x[i]);
+                }
+                /* Rotate the molecule randomly */
+                rotate_conf(a_tp1-a_tp0,state->x+a_tp0,NULL,
+                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
+                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
+                            2*M_PI*gmx_rng_uniform_real(tpi_rand));
+                /* Shift to the insertion location */
+                for(i=a_tp0; i<a_tp1; i++)
+                {
+                    rvec_inc(state->x[i],x_tp);
+                }
+            }
+            
+            /* Check if this insertion belongs to this node */
+            bOurStep = TRUE;
+            if (PAR(cr))
+            {
+                switch (inputrec->eI)
+                {
+                case eiTPI:
+                    bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid);
+                    break;
+                case eiTPIC:
+                    bOurStep = (step % nnodes == cr->nodeid);
+                    break;
+                default:
+                    gmx_fatal(FARGS,"Unknown integrator %s",ei_names[inputrec->eI]);
+                }
+            }
+            if (bOurStep)
+            {
+                /* Clear some matrix variables  */
+                clear_mat(force_vir); 
+                clear_mat(shake_vir);
+                clear_mat(vir);
+                clear_mat(pres);
+                
+                /* Set the charge group center of mass of the test particle */
+                copy_rvec(x_init,fr->cg_cm[top->cgs.nr-1]);
+                
+                /* Calc energy (no forces) on new positions.
+                 * Since we only need the intermolecular energy
+                 * and the RF exclusion terms of the inserted molecule occur
+                 * within a single charge group we can pass NULL for the graph.
+                 * This also avoids shifts that would move charge groups
+                 * out of the box.
+                 *
+                 * Some checks above ensure than we can not have
+                 * twin-range interactions together with nstlist > 1,
+                 * therefore we do not need to remember the LR energies.
+                 */
+                /* Make do_force do a single node force calculation */
+                cr->nnodes = 1;
+                do_force(fplog,cr,inputrec,
+                         step,nrnb,wcycle,top,top_global,&top_global->groups,
+                         rerun_fr.box,state->x,&state->hist,
+                         f,force_vir,mdatoms,enerd,fcd,
+                         lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
+                         GMX_FORCE_NONBONDED |
+                         (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) |
+                         (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); 
+                cr->nnodes = nnodes;
+                bStateChanged = FALSE;
+                bNS = FALSE;
+                
+                /* Calculate long range corrections to pressure and energy */
+                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box,
+                              lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr);
+                /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
+                enerd->term[F_DISPCORR] = enercorr;
+                enerd->term[F_EPOT] += enercorr;
+                enerd->term[F_PRES] += prescorr;
+                enerd->term[F_DVDL] += dvdlcorr;
+
+                epot = enerd->term[F_EPOT];
+                bEnergyOutOfBounds = FALSE;
+#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
+                /* With SSE the energy can overflow, check for this */
+                if (gmx_mm_check_and_reset_overflow())
+                {
+                    if (debug)
+                    {
+                        fprintf(debug,"Found an SSE overflow, assuming the energy is out of bounds\n");
+                    }
+                    bEnergyOutOfBounds = TRUE;
+                }
+#endif
+                /* If the compiler doesn't optimize this check away
+                 * we catch the NAN energies.
+                 * The epot>GMX_REAL_MAX check catches inf values,
+                 * which should nicely result in embU=0 through the exp below,
+                 * but it does not hurt to check anyhow.
+                 */
+                /* Non-bonded Interaction usually diverge at r=0.
+                 * With tabulated interaction functions the first few entries
+                 * should be capped in a consistent fashion between
+                 * repulsion, dispersion and Coulomb to avoid accidental
+                 * negative values in the total energy.
+                 * The table generation code in tables.c does this.
+                 * With user tbales the user should take care of this.
+                 */
+                if (epot != epot || epot > GMX_REAL_MAX)
+                {
+                    bEnergyOutOfBounds = TRUE;
+                }
+                if (bEnergyOutOfBounds)
+                {
+                    if (debug)
+                    {
+                        fprintf(debug,"\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n",t,step,epot);
+                    }
+                    embU = 0;
+                }
+                else
+                {
+                    embU = exp(-beta*epot);
+                    sum_embU += embU;
+                    /* Determine the weighted energy contributions of each energy group */
+                    e = 0;
+                    sum_UgembU[e++] += epot*embU;
+                    if (fr->bBHAM)
+                    {
+                        for(i=0; i<ngid; i++)
+                        {
+                            sum_UgembU[e++] +=
+                                (enerd->grpp.ener[egBHAMSR][GID(i,gid_tp,ngid)] +
+                                 enerd->grpp.ener[egBHAMLR][GID(i,gid_tp,ngid)])*embU;
+                        }
+                    }
+                    else
+                    {
+                        for(i=0; i<ngid; i++)
+                        {
+                            sum_UgembU[e++] +=
+                                (enerd->grpp.ener[egLJSR][GID(i,gid_tp,ngid)] +
+                                 enerd->grpp.ener[egLJLR][GID(i,gid_tp,ngid)])*embU;
+                        }
+                    }
+                    if (bDispCorr)
+                    {
+                        sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
+                    }
+                    if (bCharge)
+                    {
+                        for(i=0; i<ngid; i++)
+                        {
+                            sum_UgembU[e++] +=
+                                (enerd->grpp.ener[egCOULSR][GID(i,gid_tp,ngid)] +
+                                 enerd->grpp.ener[egCOULLR][GID(i,gid_tp,ngid)])*embU;
+                        }
+                        if (bRFExcl)
+                        {
+                            sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
+                        }
+                        if (EEL_FULL(fr->eeltype))
+                        {
+                            sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
+                        }
+                    }
+                }
+                
+                if (embU == 0 || beta*epot > bU_bin_limit)
+                {
+                    bin[0]++;
+                }
+                else
+                {
+                    i = (int)((bU_logV_bin_limit
+                               - (beta*epot - logV + refvolshift))*invbinw
+                              + 0.5);
+                    if (i < 0)
+                    {
+                        i = 0;
+                    }
+                    if (i >= nbin)
+                    {
+                        realloc_bins(&bin,&nbin,i+10);
+                    }
+                    bin[i]++;
+                }
+                
+                if (debug)
+                {
+                    fprintf(debug,"TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
+                            step,epot,x_tp[XX],x_tp[YY],x_tp[ZZ]);
+                }
+
+                if (dump_pdb && epot <= dump_ener)
+                {
+                    sprintf(str,"t%g_step%d.pdb",t,step);
+                    sprintf(str2,"t: %f step %d ener: %f",t,step,epot);
+                    write_sto_conf_mtop(str,str2,top_global,state->x,state->v,
+                                        inputrec->ePBC,state->box);
+                }
+            }
+        }
+        
+        if (PAR(cr))
+        {
+            /* When running in parallel sum the energies over the processes */
+            gmx_sumd(1,    &sum_embU, cr);
+            gmx_sumd(nener,sum_UgembU,cr);
+        }
+
+        frame++;
+        V_all += V;
+        VembU_all += V*sum_embU/nsteps;
+        
+        if (fp_tpi)
+        {
+            if (bVerbose || frame%10==0 || frame<10)
+            {
+                fprintf(stderr,"mu %10.3e <mu> %10.3e\n",
+                        -log(sum_embU/nsteps)/beta,-log(VembU_all/V_all)/beta);
+            }
+            
+            fprintf(fp_tpi,"%10.3f %12.5e %12.5e %12.5e %12.5e",
+                    t,
+                    VembU_all==0 ? 20/beta : -log(VembU_all/V_all)/beta,
+                    sum_embU==0  ? 20/beta : -log(sum_embU/nsteps)/beta,
+                    sum_embU/nsteps,V);
+            for(e=0; e<nener; e++)
+            {
+                fprintf(fp_tpi," %12.5e",sum_UgembU[e]/nsteps);
+            }
+            fprintf(fp_tpi,"\n");
+            fflush(fp_tpi);
+        }
+        
+        bNotLastFrame = read_next_frame(oenv, status,&rerun_fr);
+    } /* End of the loop  */
+    runtime_end(runtime);
+
+    close_trj(status);
+
+    if (fp_tpi != NULL)
+    {
+        gmx_fio_fclose(fp_tpi);
+    }
+
+    if (fplog != NULL)
+    {
+        fprintf(fplog,"\n");
+        fprintf(fplog,"  <V>  = %12.5e nm^3\n",V_all/frame);
+        fprintf(fplog,"  <mu> = %12.5e kJ/mol\n",-log(VembU_all/V_all)/beta);
+    }
+  
+    /* Write the Boltzmann factor histogram */
+    if (PAR(cr))
+    {
+        /* When running in parallel sum the bins over the processes */
+        i = nbin;
+        global_max(cr,&i);
+        realloc_bins(&bin,&nbin,i);
+        gmx_sumd(nbin,bin,cr);
+    }
+    if (MASTER(cr))
+    {
+        fp_tpi = xvgropen(opt2fn("-tpid",nfile,fnm),
+                          "TPI energy distribution",
+                          "\\betaU - log(V/<V>)","count",oenv);
+        sprintf(str,"number \\betaU > %g: %9.3e",bU_bin_limit,bin[0]);
+        xvgr_subtitle(fp_tpi,str,oenv);
+        xvgr_legend(fp_tpi,2,(const char **)tpid_leg,oenv);
+        for(i=nbin-1; i>0; i--)
+        {
+            bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
+            fprintf(fp_tpi,"%6.2f %10d %12.5e\n",
+                    bUlogV,
+                    (int)(bin[i]+0.5),
+                    bin[i]*exp(-bUlogV)*V_all/VembU_all);
+        }
+        gmx_fio_fclose(fp_tpi);
+    }
+    sfree(bin);
+
+    sfree(sum_UgembU);
+
+    runtime->nsteps_done = frame*inputrec->nsteps;
+
+    return 0;
+}
similarity index 100%
rename from src/mdlib/vcm.c
rename to src/gromacs/mdlib/vcm.c
similarity index 100%
rename from src/mdlib/vsite.c
rename to src/gromacs/mdlib/vsite.c
similarity index 100%
rename from src/mdlib/wall.c
rename to src/gromacs/mdlib/wall.c
diff --git a/src/gromacs/options.h b/src/gromacs/options.h
new file mode 100644 (file)
index 0000000..4efc84d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \defgroup module_options Extensible Handling of Options
+ * \ingroup group_utilitymodules
+ * \brief
+ * Provides functionality for handling options.
+ *
+ * <H3>Basic Use</H3>
+ *
+ * Basic interface for providing options is implemented by the Options class
+ * and classes defined in basicoptions.h for specifying individual options.
+ * Only these are needed if a class wants to provide a set of standard options.
+ *
+ * Values for options can be set using option parsers.
+ * Currently, only one is defined: CommandLineParser.
+ * As the name suggests, this parser gets values from command-line arguments.
+ * Multiple parsers can be used in sequence to provide option values from
+ * multiple sources; in such cases, if an option is provided in multiple
+ * sources, new values overwrite any values from previous sources.
+ *
+ * In most cases, it is desirable to be able to provide a help describing the
+ * available options.  When creating an Options object and adding options, it
+ * is possible to add descriptions for individual options as well as for the
+ * whole set of options.  These can then be used to write out a help using one
+ * of the provided help writers.
+ * Currently, only one is defined: AsciiHelpWriter
+ * (implementation is not yet complete).
+ *
+ * \if libapi
+ * <H3>Advanced Use (in library API)</H3>
+ *
+ * It is possible to extend the module with new option types and/or parsers for
+ * option values.
+ *
+ * To implement new option types, it is necessary to subclass the templates
+ * OptionTemplate and OptionStorageTemplate with the type of the values that
+ * the option should provide as the template argument.  After this is done, it
+ * is possible to add options of this new type using Options::addOption().
+ *
+ * There is limited support for options that need to share information across
+ * instances, e.g., to store values in a shared external data structure or to
+ * provide a global option to set a common setting for all such options,
+ * provided by the OptionsGlobalProperties class.  This mechanism is not
+ * generic, meaning that it is required to change the options module to add
+ * data to this structure.
+ *
+ * To implement new parsers, one can use OptionsAssigner, which provides an
+ * interface to set values in an Options object.
+ *
+ * There is also an interface to iterate over all options in an Options object.
+ * One should implement the OptionsVisitor interface, and then use
+ * OptionsIterator to apply this visitor to the Options object.
+ * \endif
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \file
+ * \brief
+ * Public API convenience header for handling of options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_H
+#define GMX_OPTIONS_H
+
+#include "options/basicoptions.h"
+#include "options/options.h"
+
+#endif
diff --git a/src/gromacs/options/CMakeLists.txt b/src/gromacs/options/CMakeLists.txt
new file mode 100644 (file)
index 0000000..eef1671
--- /dev/null
@@ -0,0 +1,16 @@
+file(GLOB OPTIONS_SOURCES *.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${OPTIONS_SOURCES} PARENT_SCOPE)
+
+set(OPTIONS_PUBLIC_HEADERS
+    abstractoption.h
+    basicoptions.h
+    optionfiletype.h
+    optionflags.h
+    options.h)
+install(FILES ${OPTIONS_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/options
+        COMPONENT development)
+
+if (BUILD_TESTING)
+    add_subdirectory(tests)
+endif (BUILD_TESTING)
diff --git a/src/gromacs/options/abstractoption.cpp b/src/gromacs/options/abstractoption.cpp
new file mode 100644 (file)
index 0000000..bf897e8
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in abstractoption.h and abstractoptionstorage.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/abstractoption.h"
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/optionflags.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AbstractOptionStorage
+ */
+
+AbstractOptionStorage::AbstractOptionStorage(const AbstractOption &settings,
+                                             Options *options,
+                                             OptionFlags staticFlags)
+    : _flags(settings._flags | staticFlags),
+      _minValueCount(settings._minValueCount),
+      _maxValueCount(settings._maxValueCount),
+      _inSet(false),
+      _options(options)
+{
+    // If the maximum number of values is not known, storage to
+    // caller-allocated memory is unsafe.
+    if ((_maxValueCount < 0 || hasFlag(efMulti)) && hasFlag(efExternalStore))
+    {
+        GMX_THROW(APIError("Cannot set user-allocated storage for arbitrary number of values"));
+    }
+    // Check that user has not provided incorrect values for vectors.
+    if (hasFlag(efVector) && (_minValueCount > 1 || _maxValueCount < 1))
+    {
+        GMX_THROW(APIError("Inconsistent value counts for vector values"));
+    }
+
+    if (settings._name != NULL)
+    {
+        _name  = settings._name;
+    }
+    _descr = settings.createDescription();
+}
+
+AbstractOptionStorage::~AbstractOptionStorage()
+{
+}
+
+void AbstractOptionStorage::startSource()
+{
+    setFlag(efHasDefaultValue);
+}
+
+void AbstractOptionStorage::startSet()
+{
+    GMX_RELEASE_ASSERT(!_inSet, "finishSet() not called");
+    // The last condition takes care of the situation where multiple
+    // sources are used, and a later source should be able to reassign
+    // the value even though the option is already set.
+    if (isSet() && !hasFlag(efMulti) && !hasFlag(efHasDefaultValue))
+    {
+        GMX_THROW(InvalidInputError("Option specified multiple times"));
+    }
+    clearSet();
+    _inSet = true;
+}
+
+void AbstractOptionStorage::appendValue(const std::string &value)
+{
+    GMX_RELEASE_ASSERT(_inSet, "startSet() not called");
+    convertValue(value);
+}
+
+void AbstractOptionStorage::finishSet()
+{
+    GMX_RELEASE_ASSERT(_inSet, "startSet() not called");
+    _inSet = false;
+    // TODO: Should this be done only when processSet() does not throw?
+    setFlag(efSet);
+    processSet();
+}
+
+void AbstractOptionStorage::finish()
+{
+    GMX_RELEASE_ASSERT(!_inSet, "finishSet() not called");
+    processAll();
+    if (hasFlag(efRequired) && !isSet())
+    {
+        GMX_THROW(InvalidInputError("Option is required, but not set"));
+    }
+}
+
+void AbstractOptionStorage::setMinValueCount(int count)
+{
+    GMX_RELEASE_ASSERT(!hasFlag(efMulti),
+                       "setMinValueCount() not supported with efMulti");
+    GMX_RELEASE_ASSERT(count >= 0, "Invalid value count");
+    _minValueCount = count;
+    if (isSet()
+        && !hasFlag(efDontCheckMinimumCount) && valueCount() < _minValueCount)
+    {
+        GMX_THROW(InvalidInputError("Too few values"));
+    }
+}
+
+void AbstractOptionStorage::setMaxValueCount(int count)
+{
+    GMX_RELEASE_ASSERT(!hasFlag(efMulti),
+                       "setMaxValueCount() not supported with efMulti");
+    GMX_RELEASE_ASSERT(count >= -1, "Invalid value count");
+    _maxValueCount = count;
+    if (isSet() && _maxValueCount >= 0 && valueCount() > _maxValueCount)
+    {
+        GMX_THROW(InvalidInputError("Too many values"));
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/abstractoption.h b/src/gromacs/options/abstractoption.h
new file mode 100644 (file)
index 0000000..89c273b
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Defines gmx::AbstractOption and a related template.
+ *
+ * This header defines base classes for option settings that are used with
+ * Options::addOption().  These classes implement the "named parameter"
+ * idiom for specifying option properties.
+ *
+ * These classes also take care of creating and setting up the actual option
+ * objects.
+ *
+ * This header is needed directly only when implementing new option types,
+ * but methods of OptionTemplate are visible even to the normal user through
+ * its subclasses.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_ABSTRACTOPTION_H
+#define GMX_OPTIONS_ABSTRACTOPTION_H
+
+#include <string>
+#include <vector>
+
+#include "optionflags.h"
+
+namespace gmx
+{
+
+class AbstractOptionStorage;
+template <typename T> class OptionStorageTemplate;
+class Options;
+
+/*! \brief
+ * Abstract base class for specifying option properties.
+ *
+ * Concrete classes should normally not derive directly from this class,
+ * but from OptionTemplate instead.  Classes derived from this class
+ * are mainly designed to implement the "named parameter" idiom.  For
+ * efficiency and clarity, these classes should only store values provided to
+ * them.  All error checking and memory management should be postponed to the
+ * point when the actual option is created.
+ *
+ * Subclasses should override createDefaultStorage() to create the correct type
+ * of storage object.
+ *
+ * \ingroup module_options
+ */
+class AbstractOption
+{
+    public:
+        // Virtual only for completeness, in normal use should not be needed.
+        virtual ~AbstractOption() { }
+
+    protected:
+        /*! \cond libapi */
+        //! Initializes the name and default values for an option.
+        explicit AbstractOption(const char *name)
+            : _minValueCount(1), _maxValueCount(1),
+              _name(name), _descr(NULL)
+        { }
+
+        /*! \brief
+         * Creates a default storage object for the option.
+         *
+         * \param[in]  options  Option collection object.
+         * \returns The created storage object.
+         * \throws  APIError if invalid option settings have been provided.
+         *
+         * This method is called by when creating an option object
+         * The \p options object is used to implement global properties.
+         *
+         * Derived classes should implement the method to create an actual
+         * storage object and populate it with correct values.
+         * They should also throw APIError if they detect problems.
+         *
+         * Should only be called by Options::addOption().
+         */
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const = 0;
+
+        /*! \brief
+         * Creates the description string for the option.
+         *
+         * \returns Description string for the option.
+         *
+         * This function is virtual to allow derived classes to customize the
+         * description programmatically, e.g., by adding the list of allowed
+         * values.
+         * The default implementation simply returns the user-provided
+         * description.
+         */
+        virtual std::string createDescription() const
+        { return _descr ? _descr : ""; }
+
+        //! Sets the description for the option.
+        void setDescription(const char *descr) { _descr = descr; }
+        //! Sets a flag for the option.
+        void setFlag(OptionFlag flag) { _flags.set(flag); }
+        //! Clears a flag for the option.
+        void clearFlag(OptionFlag flag) { _flags.clear(flag); }
+        //! Sets or clears a flag for the option.
+        void setFlag(OptionFlag flag, bool bSet) { _flags.set(flag, bSet); }
+        //! Returns true if the option is vector-valued.
+        bool isVector() const { return hasFlag(efVector); }
+        //! Sets the option to be vector-valued.
+        void setVector()
+        {
+            setFlag(efVector);
+            _minValueCount = 1;
+            if (_maxValueCount == 1)
+            {
+                _maxValueCount = 3;
+            }
+        }
+        //! Sets the required number of values for the option.
+        void setValueCount(int count)
+        {
+            if (!hasFlag(efVector))
+            {
+                _minValueCount = count;
+            }
+            _maxValueCount = count;
+        }
+
+        //! Minimum number of values required for the option.
+        int                     _minValueCount;
+        //! Maximum number of values allowed for the option.
+        int                     _maxValueCount;
+        //! \endcond
+
+    private:
+        //! Returns true if a flag has been set.
+        bool hasFlag(OptionFlag flag) const { return _flags.test(flag); }
+
+        const char             *_name;
+        //! Pointer to description of the option.
+        const char             *_descr;
+        OptionFlags             _flags;
+
+        /*! \brief
+         * Needed to initialize an AbstractOptionStorage object from this class
+         * without otherwise unnecessary accessors.
+         */
+        friend class AbstractOptionStorage;
+        /*! \brief
+         * Needed to be able to call createDefaultStorage().
+         */
+        friend class Options;
+};
+
+/*! \brief
+ * Templated base class for constructing concrete option settings classes.
+ *
+ * \tparam T Assignable type that stores a single option value.
+ * \tparam U Type of the derived class.
+ *
+ * This template is used as a base class like this:
+ * \code
+class ConcreteOption : public OptionTemplate<int, ConcreteOption>
+{
+ * \endcode
+ *
+ * All public functions in this class return \c *this casted to a reference to
+ * \p U.  They do not throw.
+ *
+ * For examples of how to use classes derived from this class, see the class
+ * documentation for Options.
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+template <typename T, class U>
+class OptionTemplate : public AbstractOption
+{
+    public:
+        //! Type that stores a single option value.
+        typedef T ValueType;
+        //! Alias for the derived class type.
+        typedef U MyClass;
+
+        /*! \brief
+         * Sets a description for the option.
+         *
+         * \param[in] descr Description to set.
+         *
+         * String in \p descr is copied when the option is created.
+         */
+        MyClass &description(const char *descr)
+        { setDescription(descr); return me(); }
+        //! Hides the option from normal help output.
+        MyClass &hidden(bool bHidden = true)
+        { setFlag(efHidden, bHidden); return me(); }
+        //! Requires the option to be specified explicitly.
+        MyClass &required(bool bRequired = true)
+        { setFlag(efRequired, bRequired); return me(); }
+        //! Allows the option to be specified multiple times.
+        MyClass &allowMultiple(bool bMulti = true)
+        { setFlag(efMulti, bMulti); return me(); }
+        //! Requires exactly \p count values for the option.
+        MyClass &valueCount(int count) { setValueCount(count); return me(); }
+        //! Allows any number of values for the option.
+        MyClass &multiValue() { _maxValueCount = -1; return me(); }
+
+        /*! \brief
+         * Sets a default value for the option.
+         *
+         * \param[in] defaultValue Default value.
+         *
+         * If the option is never set, the default value is copied to the
+         * assigned storage.  Note that if the option is not set and there
+         * is no default value, the storage is not altered, which can also be
+         * used to provide a default value.  The latter method has to be used
+         * if the option can take multiple values.
+         * If required() is specified, only affects the default value shown in
+         * help output.
+         *
+         * \p defaultValue is copied when the option is created.
+         */
+        MyClass &defaultValue(const T &defaultValue)
+        { _defaultValue = &defaultValue; return me(); }
+        /*! \brief
+         * Sets a default value for the option when it is set.
+         *
+         * \param[in] defaultValue Default value.
+         *
+         * This value is used if the option is set, but no value is provided.
+         * If the option is never set, the value set with defaultValue() is
+         * used.  Can only be used for options that accept a single value.
+         *
+         * \p defaultValue is copied when the option is created.
+         */
+        MyClass &defaultValueIfSet(const T &defaultValue)
+        { _defaultValueIfSet = &defaultValue; return me(); }
+        /*! \brief
+         * Stores value(s) in memory pointed by \p store.
+         *
+         * \param[in] store  Storage for option value(s).
+         *
+         * The caller is responsible for allocating enough memory such that
+         * the any allowed number of values fits into the array pointed by
+         * \p store.  If there is no maximum allowed number or if the maximum
+         * is inconveniently large, storeVector() should be used.
+         *
+         * For information on when values are available in the storage, see
+         * storeVector().
+         *
+         * The pointer provided should remain valid as long as the associated
+         * Options object exists.
+         */
+        MyClass &store(T *store)
+        { setFlag(efExternalStore); _store = store; return me(); }
+        /*! \brief
+         * Stores number of values in the value pointed by \p countptr.
+         *
+         * \param[in] countptr Storage for the number of values.
+         *
+         * For information on when values are available in the storage, see
+         * storeVector().
+         *
+         * The pointers provided should remain valid as long as the associated
+         * Options object exists.
+         */
+        MyClass &storeCount(int *countptr)
+        { _countptr = countptr; return me(); }
+        /*! \brief
+         * Stores option values in the provided vector.
+         *
+         * \param[in] store  Vector to store option values in.
+         *
+         * Values are added to the vector after each successful set of values
+         * is parsed.  Note that for some options, the value may be changed
+         * later, and is only guaranteed to be correct after Options::finish()
+         * has been called (see, e.g., DoubleOption::timeValue()).
+         *
+         * The pointer provided should remain valid as long as the associated
+         * Options object exists.
+         */
+        MyClass &storeVector(std::vector<T> *store)
+        { setFlag(efExternalValueVector); _storeVector = store; return me(); }
+
+    protected:
+        /*! \cond libapi */
+        //! Alias for the template class for use in base classes.
+        typedef OptionTemplate<T, U> MyBase;
+
+        //! Initializes the name and default values for an option.
+        explicit OptionTemplate(const char *name)
+            : AbstractOption(name),
+              _defaultValue(NULL), _defaultValueIfSet(NULL), _store(NULL),
+              _countptr(NULL), _storeVector(NULL)
+        { }
+
+        /*! \brief
+         * Returns a pointer to user-specified default value, or NULL if there
+         * is none.
+         */
+        const T *defaultValue() const { return _defaultValue; }
+        /*! \brief
+         * Returns a pointer to user-specified default value, or NULL if there
+         * is none.
+         */
+        const T *defaultValueIfSet() const { return _defaultValueIfSet; }
+        //! Returns \p *this casted into MyClass to reduce typing.
+        MyClass &me() { return static_cast<MyClass &>(*this); }
+        //! \endcond
+
+    private:
+        const T                *_defaultValue;
+        const T                *_defaultValueIfSet;
+        T                      *_store;
+        int                    *_countptr;
+        std::vector<T>         *_storeVector;
+
+        /*! \brief
+         * Needed to initialize storage from this class without otherwise
+         * unnecessary accessors.
+         */
+        friend class OptionStorageTemplate<T>;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/abstractoptionstorage.h b/src/gromacs/options/abstractoptionstorage.h
new file mode 100644 (file)
index 0000000..749972a
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::AbstractOptionStorage.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_ABSTRACTOPTIONSTORAGE_H
+#define GMX_OPTIONS_ABSTRACTOPTIONSTORAGE_H
+
+#include <string>
+
+#include "optionflags.h"
+
+namespace gmx
+{
+
+class AbstractOption;
+class Options;
+
+/*! \libinternal \brief
+ * Abstract base class for converting, validating, and storing option values.
+ *
+ * This class should normally not be subclassed directly, but the
+ * OptionStorageTemplate should be used instead.  The templated class provides
+ * basic functionality for most of the pure virtual methods, and also
+ * integrates well with option setting objects derived from OptionTemplate.
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ *
+ * \internal
+ * This class really consists of two parts: the public interface that is
+ * used by the internal implementation of the options module, and the
+ * interface that derived classes use to provide type-dependent functionality.
+ * The latter consists of a few pure virtual methods, of which a few simple
+ * query methods are also part of the module-internal interface, others are
+ * protected and called by the non-virtual methods when needed.
+ * The reason why these two roles are in one class is twofold:
+ *  -# Both the derived classes and the internal module implementation may need
+ *     access to the same information like the allowed number of values and the
+ *     name of the option.
+ *  -# Having only one class is consistent with the structure used for options
+ *     settings objects: there is very direct correspondence between
+ *     AbstractOption and AbstractOptionStorage and between OptionTemplate and
+ *     OptionStorageTemplate.
+ */
+class AbstractOptionStorage
+{
+    public:
+        virtual ~AbstractOptionStorage();
+
+        //! Returns true if the option has been set.
+        bool isSet() const { return hasFlag(efSet); }
+        //! Returns true if the option is a boolean option.
+        bool isBoolean() const { return hasFlag(efBoolean); }
+        //! Returns true if the option is a file option.
+        bool isFile() const { return hasFlag(efFile); }
+        //! Returns true if the option is a hidden option.
+        bool isHidden() const { return hasFlag(efHidden); }
+        //! Returns the name of the option.
+        const std::string &name() const { return _name; }
+        //! Returns the description of the option.
+        const std::string &description() const { return _descr; }
+        /*! \brief
+         * Returns a short string describing the type of the option.
+         *
+         * The caller is free to discard the returned string.
+         */
+        virtual const char *typeString() const = 0;
+        /*! \brief
+         * Returns the number of option values added so far.
+         */
+        virtual int valueCount() const = 0;
+        /*! \brief
+         * Returns the i'th value formatted as a string.
+         */
+        virtual std::string formatValue(int i) const = 0;
+
+        /*! \brief
+         * Starts adding values from a new source for the option.
+         *
+         * This marks the vurrent value of the option as a default value,
+         * causing next call to startSet() to clear it.  This allows values
+         * from the new source to overwrite old values.
+         *
+         * This method does not throw.
+         */
+        void startSource();
+        /*! \brief
+         * Starts adding a new set of values for the option.
+         *
+         * \throws  InvalidInputError if option is specified multiple times,
+         *      but is not specified to accept it.
+         *
+         * If the parameter is specified multiple times, startSet() should be
+         * called before the values for each instance.
+         *
+         * Strong exception safety guarantee.
+         */
+        void startSet();
+        /*! \brief
+         * Adds a new value for the option, converting it from a string.
+         *
+         * \param[in] value  String value to convert.
+         * \throws  InvalidInputError if value cannot be converted, or
+         *      if there are too many values.
+         *
+         * This method should only be called between startSet() and
+         * finishSet().
+         */
+        void appendValue(const std::string &value);
+        /*! \brief
+         * Performs validation and/or actions once a set of values has been
+         * added.
+         *
+         * \throws  InvalidInputError if too few values have been provided, or
+         *      if the valid values since previous startSet() are invalid as a
+         *      set.
+         *
+         * If the parameter is specified multiple times, finishSet() should be
+         * called after the values for each instance.
+         */
+        void finishSet();
+        /*! \brief
+         * Performs validation and/or actions once all values have been added.
+         *
+         * \throws InvalidInputError if the option is required but not set, or
+         *      if all valid values together are invalid as a set.
+         *
+         * This method should be called after all values have been provided
+         * with appendValue().
+         */
+        void finish();
+
+    protected:
+        /*! \brief
+         * Initializes the storage object from the settings object.
+         *
+         * \param[in] settings  Option settings.
+         * \param[in] options   Option collection that will contain the
+         *      option.
+         * \param[in] staticFlags Option flags that are always set and specify
+         *      generic behavior of the option.
+         * \throws  APIError if invalid settings have been provided.
+         */
+        AbstractOptionStorage(const AbstractOption &settings, Options *options,
+                              OptionFlags staticFlags);
+
+        //! Returns true if the given flag is set.
+        bool hasFlag(OptionFlag flag) const { return _flags.test(flag); }
+        //! Sets the given flag.
+        void setFlag(OptionFlag flag) { return _flags.set(flag); }
+        //! Clears the given flag.
+        void clearFlag(OptionFlag flag) { return _flags.clear(flag); }
+
+        //! Returns the minimum number of values required in one set.
+        int minValueCount() const { return _minValueCount; }
+        //! Returns the maximum allowed number of values in one set (-1 = no limit).
+        int maxValueCount() const { return _maxValueCount; }
+        /*! \brief
+         * Sets a new minimum number of values required in one set.
+         *
+         * \param[in] count  New minimum number of values (must be > 0).
+         * \throws InvalidInputError if already provided values violate the limit.
+         *
+         * If values have already been provided, it is checked that there are
+         * enough.
+         *
+         * Cannot be called for options with ::efMulti set, because it is
+         * impossible to check the requirement after the values have been set.
+         * If attempted, will assert.
+         */
+        void setMinValueCount(int count);
+        /*! \brief
+         * Sets a new maximum number of values required in one set.
+         *
+         * \param[in] count  New maximum number of values
+         *                   (must be > 0, or -1 for no limit).
+         * \throws InvalidInputError if already provided values violate the limit.
+         *
+         * If values have already been provided, it is checked that there are
+         * not too many.
+         *
+         * Cannot be called for options with ::efMulti set, because it is
+         * impossible to check the requirement after the values have been set.
+         * If attempted, will assert.
+         */
+        void setMaxValueCount(int count);
+
+        //! Returns the Options object that houses the option.
+        Options &hostOptions() { return *_options; }
+        //! \copydoc hostOptions()
+        const Options &hostOptions() const { return *_options; }
+
+        /*! \brief
+         * Removes all values from temporary storage for a set.
+         *
+         * This function is always called before starting to add values to
+         * a set, allowing the storage to clear its internal buffers.
+         *
+         * Should not throw.
+         */
+        virtual void clearSet() = 0;
+        /*! \brief
+         * Adds a new value, converting it from a string.
+         *
+         * \param[in] value  String value to convert.
+         * \throws  InvalidInputError if \p value is not valid for this option
+         *      or if there have been too many values in the set.
+         *
+         * This method may be called multiple times if the underlying
+         * option is defined to accept multiple values.
+         *
+         * \see OptionStorageTemplate::convertValue()
+         */
+        virtual void convertValue(const std::string &value) = 0;
+        /*! \brief
+         * Performs validation and/or actions once a set of values has been
+         * added.
+         *
+         * \throws  InvalidInputError if the values in the set are not valid
+         *      as a whole.
+         *
+         * This method may be called multiple times if the underlying option
+         * can be specified multiple times.
+         *
+         * \see OptionStorageTemplate::processSetValues()
+         */
+        virtual void processSet() = 0;
+        /*! \brief
+         * Performs validation and/or actions once all values have been added.
+         *
+         * \throws  InvalidInputError if all provided values are not valid as
+         *      a set.
+         *
+         * This method is always called once.
+         *
+         * If the method throws, implementation should take care to leave the
+         * option in a consistent, meaningful state.  However, currently none
+         * of the implementations actually throw in any situation where the
+         * option may be left in an inconsistent state.
+         */
+        virtual void processAll() = 0;
+
+    private:
+        std::string             _name;
+        std::string             _descr;
+        //! Flags for the option.
+        OptionFlags             _flags;
+        //! Minimum number of values required (in one set).
+        int                     _minValueCount;
+        //! Maximum allowed number of values (in one set), or -1 if no limit.
+        int                     _maxValueCount;
+        //! Whether we are currently assigning values to a set.
+        bool                    _inSet;
+        //! Parent Options object.
+        Options                *_options;
+
+        // Disallow copy and assign.
+        AbstractOptionStorage(const AbstractOptionStorage &);
+        void operator =(const AbstractOptionStorage &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/asciihelpwriter-impl.h b/src/gromacs/options/asciihelpwriter-impl.h
new file mode 100644 (file)
index 0000000..6976e51
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::AsciiHelpWriter.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_ASCIIHELPWRITER_IMPL_HPP
+#define GMX_OPTIONS_ASCIIHELPWRITER_IMPL_HPP
+
+#include "asciihelpwriter.h"
+
+#include "../utility/flags.h"
+
+namespace gmx
+{
+
+class Options;
+
+/*! \internal \brief
+ * Private implementation class for AsciiHelpWriter.
+ *
+ * \ingroup module_options
+ */
+class AsciiHelpWriter::Impl
+{
+    public:
+        /*! \brief
+         * Possible flags for controlling output.
+         */
+        enum Flag
+        {
+            efShowDescriptions  = 1<<0,
+            efShowHidden        = 1<<1
+        };
+
+        //! Sets the Options object to use for generating help.
+        explicit Impl(const Options &options);
+
+        //! Options object to use for generating help.
+        const Options          &_options;
+        //! Flags for controlling what to write.
+        FlagsTemplate<Flag>     _flags;
+};
+
+/*! \internal \brief
+ * Helper object for writing section descriptions to help.
+ *
+ * \ingroup module_options
+ */
+class AsciiDescriptionWriter : public OptionsVisitor
+{
+    public:
+        //! Creates a helper object for writing section descriptions.
+        explicit AsciiDescriptionWriter(FILE *fp) : _fp(fp) {}
+
+        virtual void visitSubSection(const Options &section);
+        virtual void visitOption(const OptionInfo & /*option*/) { }
+
+    private:
+        FILE                   *_fp;
+};
+
+/*! \internal \brief
+ * Helper object for writing help for file parameters.
+ *
+ * \ingroup module_options
+ */
+class AsciiFileParameterWriter : public OptionsVisitor
+{
+    public:
+        //! Creates a helper object for writing file parameters.
+        explicit AsciiFileParameterWriter(FILE *fp)
+            : _fp(fp), _bFirst(true)
+        {
+        }
+
+        //! Returns true if anything was written out.
+        bool didOutput() const { return !_bFirst; }
+
+        virtual void visitSubSection(const Options &section);
+        virtual void visitOption(const OptionInfo &option);
+
+    private:
+        FILE                   *_fp;
+        bool                    _bFirst;
+};
+
+/*! \internal \brief
+ * Helper object for writing help for non-file parameters.
+ *
+ * \ingroup module_options
+ */
+class AsciiParameterWriter : public OptionsVisitor
+{
+    public:
+        //! Creates a helper object for writing non-file parameters.
+        explicit AsciiParameterWriter(FILE *fp)
+            : _fp(fp), _bFirst(true), _bShowHidden(false)
+        {
+        }
+
+        //! Sets the writer to show hidden options.
+        void setShowHidden(bool bSet)
+        {
+            _bShowHidden = bSet;
+        }
+        //! Returns true if anything was written out.
+        bool didOutput() const { return !_bFirst; }
+
+        virtual void visitSubSection(const Options &section);
+        virtual void visitOption(const OptionInfo &option);
+
+    private:
+        FILE                   *_fp;
+        bool                    _bFirst;
+        bool                    _bShowHidden;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/asciihelpwriter.cpp b/src/gromacs/options/asciihelpwriter.cpp
new file mode 100644 (file)
index 0000000..c3832e2
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::AsciiHelpWriter.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/asciihelpwriter.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include "gromacs/options/options.h"
+#include "gromacs/options/optionsvisitor.h"
+
+#include "asciihelpwriter-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * AsciiHelpWriter::Impl
+ */
+
+AsciiHelpWriter::Impl::Impl(const Options &options)
+    : _options(options)
+{
+}
+
+
+/********************************************************************
+ * AsciiDescriptionWriter
+ */
+
+void AsciiDescriptionWriter::visitSubSection(const Options &section)
+{
+    if (!section.description().empty())
+    {
+        fprintf(_fp, "\n");
+        const std::string &title = section.title();
+        if (!title.empty())
+        {
+            fprintf(_fp, "%s\n\n", title.c_str());
+        }
+        // TODO: Wrap lines and do markup substitutions.
+        fprintf(_fp, "%s\n\n", section.description().c_str());
+    }
+    OptionsIterator(section).acceptSubSections(this);
+}
+
+
+/********************************************************************
+ * AsciiFileParameterWriter
+ */
+
+void AsciiFileParameterWriter::visitSubSection(const Options &section)
+{
+    OptionsIterator iterator(section);
+    iterator.acceptSubSections(this);
+    iterator.acceptOptions(this);
+}
+
+void AsciiFileParameterWriter::visitOption(const OptionInfo &option)
+{
+    if (!option.isFile())
+    {
+        return;
+    }
+
+    if (_bFirst)
+    {
+        fprintf(_fp, "%6s %12s  %-12s %s\n",
+                "Option", "Filename", "Type", "Description");
+        fprintf(_fp, "------------------------------------------------------------\n");
+        _bFirst = false;
+    }
+
+    std::string optionLine("-");
+    optionLine.reserve(30 + option.description().size());
+    optionLine.append(option.name()).append(" ");
+    if (optionLine.size() < 11)
+    {
+        optionLine.resize(11, ' ');
+    }
+    bool bTypePrinted = false;
+    size_t lineStart = 0;
+    for (int i = 0; i < option.valueCount(); ++i)
+    {
+        if (i > 0)
+        {
+            optionLine.append("\n");
+            lineStart = optionLine.size();
+            optionLine.append(11, ' ');
+        }
+        optionLine.append(option.formatValue(i)).append(" ");
+        // TODO: Do eliding
+        if (optionLine.size() <= lineStart + 21)
+        {
+            optionLine.resize(lineStart + 21, ' ');
+            if (!bTypePrinted)
+            {
+                optionLine.append(option.type()).append(" ");
+                bTypePrinted = true;
+            }
+        }
+    }
+    if (!bTypePrinted)
+    {
+        optionLine.append("\n");
+        lineStart = optionLine.size();
+        optionLine.append(21, ' ');
+        optionLine.append(option.type()).append(" ");
+    }
+    if (optionLine.size() > lineStart + 34)
+    {
+        if (!option.description().empty())
+        {
+            optionLine.append("\n");
+            optionLine.append(34, ' ');
+        }
+    }
+    else
+    {
+        optionLine.resize(lineStart + 34, ' ');
+    }
+    // TODO: Markup substitution.
+    optionLine.append(option.description());
+    // TODO: Wrap lines.
+    fprintf(_fp, "%s\n", optionLine.c_str());
+}
+
+
+/********************************************************************
+ * AsciiParameterWriter
+ */
+
+void AsciiParameterWriter::visitSubSection(const Options &section)
+{
+    OptionsIterator iterator(section);
+    iterator.acceptSubSections(this);
+    iterator.acceptOptions(this);
+}
+
+void AsciiParameterWriter::visitOption(const OptionInfo &option)
+{
+    if (option.isFile() || (!_bShowHidden && option.isHidden()))
+    {
+        return;
+    }
+
+    if (_bFirst)
+    {
+        fprintf(_fp, "%-12s %-6s %-6s  %s\n",
+                "Option", "Type", "Value", "Description");
+        fprintf(_fp, "----------------------------------------------------\n");
+        _bFirst = false;
+    }
+
+    std::string optionLine("-");
+    optionLine.reserve(30 + option.description().size());
+    if (option.isBoolean())
+    {
+        optionLine.append("[no]");
+    }
+    optionLine.append(option.name()).append(" ");
+    if (optionLine.size() < 13)
+    {
+        optionLine.resize(13, ' ');
+    }
+    optionLine.append(option.type()).append(" ");
+    if (optionLine.size() < 20)
+    {
+        optionLine.resize(20, ' ');
+    }
+    optionLine.append(option.formatValues()).append(" ");
+    if (optionLine.size() > 28)
+    {
+        // TODO: Wrap lines / do eliding
+        if (!option.description().empty())
+        {
+            optionLine.append("\n");
+            optionLine.append(28, ' ');
+        }
+    }
+    else
+    {
+        optionLine.resize(28, ' ');
+    }
+    // TODO: Markup substitution.
+    optionLine.append(option.description());
+    // TODO: Wrap lines.
+    fprintf(_fp, "%s\n", optionLine.c_str());
+}
+
+/********************************************************************
+ * AsciiHelpWriter
+ */
+
+AsciiHelpWriter::AsciiHelpWriter(const Options &options)
+    : _impl(new Impl(options))
+{
+}
+
+AsciiHelpWriter::~AsciiHelpWriter()
+{
+    delete _impl;
+}
+
+AsciiHelpWriter &AsciiHelpWriter::setShowHidden(bool bSet)
+{
+    _impl->_flags.set(Impl::efShowHidden, bSet);
+    return *this;
+}
+
+AsciiHelpWriter &AsciiHelpWriter::setShowDescriptions(bool bSet)
+{
+    _impl->_flags.set(Impl::efShowDescriptions, bSet);
+    return *this;
+}
+
+void AsciiHelpWriter::writeHelp(FILE *fp)
+{
+    if (_impl->_flags.test(Impl::efShowDescriptions))
+    {
+        fprintf(fp, "DESCRIPTION\n"
+                    "-----------\n");
+        AsciiDescriptionWriter(fp).visitSubSection(_impl->_options);
+    }
+    {
+        AsciiFileParameterWriter writer(fp);
+        writer.visitSubSection(_impl->_options);
+        if (writer.didOutput())
+        {
+            fprintf(fp, "\n");
+        }
+    }
+    {
+        AsciiParameterWriter writer(fp);
+        writer.setShowHidden(_impl->_flags.test(Impl::efShowHidden));
+        writer.visitSubSection(_impl->_options);
+        if (writer.didOutput())
+        {
+            fprintf(fp, "\n");
+        }
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/asciihelpwriter.h b/src/gromacs/options/asciihelpwriter.h
new file mode 100644 (file)
index 0000000..ff190e5
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::AsciiHelpWriter.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_ASCIIHELPWRITER_H
+#define GMX_OPTIONS_ASCIIHELPWRITER_H
+
+#include <cstdio>
+
+namespace gmx
+{
+
+class Options;
+
+/*! \brief
+ * Writes help information for Options in ascii format.
+ *
+ * \inpublicapi
+ * \ingroup module_options
+ */
+class AsciiHelpWriter
+{
+    public:
+        /*! \brief
+         * Creates an object that writer ascii-formatted help for Options.
+         *
+         * \param[in] options  Options for which help should be printed.
+         */
+        explicit AsciiHelpWriter(const Options &options);
+        ~AsciiHelpWriter();
+
+        /*! \brief
+         * Sets whether hidden options are shown in the help.
+         */
+        AsciiHelpWriter &setShowHidden(bool bShow);
+        /*! \brief
+         * Sets whether long descriptions for sections are shown in the help.
+         */
+        AsciiHelpWriter &setShowDescriptions(bool bShow);
+
+        /*! \brief
+         * Writes the help.
+         *
+         * \param[in] fp  File to write the help to.
+         */
+        void writeHelp(FILE *fp);
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        AsciiHelpWriter(const AsciiHelpWriter &);
+        void operator =(const AsciiHelpWriter &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/basicoptions.cpp b/src/gromacs/options/basicoptions.cpp
new file mode 100644 (file)
index 0000000..c3f1c52
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in basicoptions.h and basicoptionstorage.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/basicoptions.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <string>
+#include <vector>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/utility/format.h"
+
+#include "basicoptionstorage.h"
+
+template <typename T> static
+void expandVector(size_t length, std::vector<T> *values)
+{
+    if (length > 0 && values->size() > 0 && values->size() != length)
+    {
+        if (values->size() != 1)
+        {
+            GMX_THROW(gmx::InvalidInputError(gmx::formatString(
+                      "Expected 1 or %d values, got %d", length, values->size())));
+        }
+        const T &value = (*values)[0];
+        values->resize(length, value);
+    }
+}
+
+namespace gmx
+{
+
+/********************************************************************
+ * BooleanOptionStorage
+ */
+
+std::string BooleanOptionStorage::formatValue(int i) const
+{
+    bool value = values()[i];
+    return value ? "yes" : "no";
+}
+
+void BooleanOptionStorage::convertValue(const std::string &value)
+{
+    // TODO: Case-independence
+    if (value == "1" || value == "yes" || value == "true")
+    {
+        addValue(true);
+        return;
+    }
+    else if (value == "0" || value == "no" || value == "false")
+    {
+        addValue(false);
+        return;
+    }
+    GMX_THROW(InvalidInputError("Invalid value: '" + value + "'; supported values are: 1, 0, yes, no, true, false"));
+}
+
+/********************************************************************
+ * BooleanOption
+ */
+
+AbstractOptionStorage *BooleanOption::createDefaultStorage(Options *options) const
+{
+    return new BooleanOptionStorage(*this, options);
+}
+
+
+/********************************************************************
+ * IntegerOptionStorage
+ */
+
+std::string IntegerOptionStorage::formatValue(int i) const
+{
+    int value = values()[i];
+    return formatString("%d", value);
+}
+
+void IntegerOptionStorage::convertValue(const std::string &value)
+{
+    const char *ptr = value.c_str();
+    char *endptr = NULL;
+    long int ival = std::strtol(ptr, &endptr, 10);
+    if (*endptr != '\0')
+    {
+        GMX_THROW(InvalidInputError("Invalid value: " + value));
+    }
+    addValue(ival);
+}
+
+void IntegerOptionStorage::processSetValues(ValueList *values)
+{
+    if (hasFlag(efVector))
+    {
+        expandVector(maxValueCount(), values);
+    }
+}
+
+/********************************************************************
+ * IntegerOption
+ */
+
+AbstractOptionStorage *IntegerOption::createDefaultStorage(Options *options) const
+{
+    return new IntegerOptionStorage(*this, options);
+}
+
+
+/********************************************************************
+ * DoubleOptionStorage
+ */
+
+DoubleOptionStorage::DoubleOptionStorage(const DoubleOption &settings, Options *options)
+    : MyBase(settings, options), _bTime(settings._bTime)
+{
+    if (_bTime)
+    {
+        options->globalProperties().request(eogpTimeScaleFactor);
+    }
+}
+
+const char *DoubleOptionStorage::typeString() const
+{
+    return hasFlag(efVector) > 0 ? "vector" : (_bTime ? "time" : "double");
+}
+
+std::string DoubleOptionStorage::formatValue(int i) const
+{
+    double value = values()[i];
+    if (_bTime)
+    {
+        double factor = hostOptions().globalProperties().timeScaleFactor();
+        value /= factor;
+    }
+    return formatString("%g", value);
+}
+
+void DoubleOptionStorage::convertValue(const std::string &value)
+{
+    const char *ptr = value.c_str();
+    char *endptr = NULL;
+    double dval = std::strtod(ptr, &endptr);
+    if (*endptr != '\0')
+    {
+        GMX_THROW(InvalidInputError("Invalid value: " + value));
+    }
+    addValue(dval);
+}
+
+void DoubleOptionStorage::processSetValues(ValueList *values)
+{
+    if (hasFlag(efVector))
+    {
+        expandVector(maxValueCount(), values);
+    }
+}
+
+void DoubleOptionStorage::processAll()
+{
+    if (_bTime)
+    {
+        double factor = hostOptions().globalProperties().timeScaleFactor();
+        ValueList::iterator i;
+        for (i = values().begin(); i != values().end(); ++i)
+        {
+            (*i) *= factor;
+        }
+        refreshValues();
+    }
+}
+
+/********************************************************************
+ * DoubleOption
+ */
+
+AbstractOptionStorage *DoubleOption::createDefaultStorage(Options *options) const
+{
+    return new DoubleOptionStorage(*this, options);
+}
+
+
+/********************************************************************
+ * StringOptionStorage
+ */
+
+StringOptionStorage::StringOptionStorage(const StringOption &settings, Options *options)
+    : MyBase(settings, options), _enumIndexStore(NULL)
+{
+    if (settings._defaultEnumIndex >= 0 && settings._enumValues == NULL)
+    {
+        GMX_THROW(APIError("Cannot set default enum index without enum values"));
+    }
+    if (settings._enumIndexStore != NULL && settings._enumValues == NULL)
+    {
+        GMX_THROW(APIError("Cannot set enum index store without enum values"));
+    }
+    if (settings._enumIndexStore != NULL && settings._maxValueCount < 0)
+    {
+        GMX_THROW(APIError("Cannot set enum index store with arbitrary number of values"));
+    }
+    if (settings._enumValues != NULL)
+    {
+        _enumIndexStore = settings._enumIndexStore;
+        const std::string *defaultValue = settings.defaultValue();
+        int match = -1;
+        for (int i = 0; settings._enumValues[i] != NULL; ++i)
+        {
+            if (defaultValue != NULL && settings._enumValues[i] == *defaultValue)
+            {
+                match = i;
+            }
+            _allowed.push_back(settings._enumValues[i]);
+        }
+        if (defaultValue != NULL)
+        {
+            if (match < 0)
+            {
+                GMX_THROW(APIError("Default value is not one of allowed values"));
+            }
+        }
+        if (settings._defaultEnumIndex >= 0)
+        {
+            if (settings._defaultEnumIndex >= static_cast<int>(_allowed.size()))
+            {
+                GMX_THROW(APIError("Default enumeration index is out of range"));
+            }
+            if (defaultValue != NULL && *defaultValue != _allowed[settings._defaultEnumIndex])
+            {
+                GMX_THROW(APIError("Conflicting default values"));
+            }
+        }
+        // If there is no default value, match is still -1.
+        if (_enumIndexStore != NULL)
+        {
+            *_enumIndexStore = match;
+        }
+    }
+    if (settings._defaultEnumIndex >= 0)
+    {
+        clear();
+        addValue(_allowed[settings._defaultEnumIndex]);
+        commitValues();
+    }
+}
+
+std::string StringOptionStorage::formatValue(int i) const
+{
+    return values()[i];
+}
+
+void StringOptionStorage::convertValue(const std::string &value)
+{
+    if (_allowed.size() == 0)
+    {
+        addValue(value);
+    }
+    else
+    {
+        ValueList::const_iterator  i;
+        ValueList::const_iterator  match = _allowed.end();
+        for (i = _allowed.begin(); i != _allowed.end(); ++i)
+        {
+            // TODO: Case independence.
+            if (i->find(value) == 0)
+            {
+                if (match == _allowed.end() || i->size() < match->size())
+                {
+                    match = i;
+                }
+            }
+        }
+        if (match == _allowed.end())
+        {
+            GMX_THROW(InvalidInputError("Invalid value: " + value));
+        }
+        addValue(*match);
+    }
+}
+
+void StringOptionStorage::refreshValues()
+{
+    MyBase::refreshValues();
+    if (_enumIndexStore != NULL)
+    {
+        for (size_t i = 0; i < values().size(); ++i)
+        {
+            ValueList::const_iterator match =
+                std::find(_allowed.begin(), _allowed.end(), values()[i]);
+            _enumIndexStore[i] = (match - _allowed.begin());
+        }
+    }
+}
+
+/********************************************************************
+ * StringOption
+ */
+
+AbstractOptionStorage *StringOption::createDefaultStorage(Options *options) const
+{
+    return new StringOptionStorage(*this, options);
+}
+
+std::string StringOption::createDescription() const
+{
+    std::string value(MyBase::createDescription());
+
+    if (_enumValues != NULL)
+    {
+        value.append(": ");
+        for (int i = 0; _enumValues[i] != NULL; ++i)
+        {
+            value.append(_enumValues[i]);
+            if (_enumValues[i + 1] != NULL)
+            {
+                value.append(_enumValues[i + 2] != NULL ? ", " : ", or ");
+            }
+        }
+    }
+    return value;
+}
+
+
+/********************************************************************
+ * FileNameOptionStorage
+ */
+
+FileNameOptionStorage::FileNameOptionStorage(const FileNameOption &settings, Options *options)
+    : MyBase(settings, options), _filetype(settings._filetype)
+{
+    if (_filetype == eftPlot)
+    {
+        options->globalProperties().request(eogpPlotFormat);
+    }
+}
+
+std::string FileNameOptionStorage::formatValue(int i) const
+{
+    return values()[i];
+}
+
+void FileNameOptionStorage::convertValue(const std::string &value)
+{
+    // TODO: Proper implementation.
+    addValue(value);
+}
+
+/********************************************************************
+ * FileNameOption
+ */
+
+AbstractOptionStorage *FileNameOption::createDefaultStorage(Options *options) const
+{
+    return new FileNameOptionStorage(*this, options);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/basicoptions.h b/src/gromacs/options/basicoptions.h
new file mode 100644 (file)
index 0000000..809f09a
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares option settings objects for basic option types.
+ *
+ * Together with options.h, this header forms the part of the public API
+ * that most classes will use to provide options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_BASICOPTIONS_H
+#define GMX_OPTIONS_BASICOPTIONS_H
+
+#include <string>
+
+#include "../fatalerror/gmxassert.h"
+
+#include "abstractoption.h"
+#include "optionfiletype.h"
+
+namespace gmx
+{
+
+class IntegerOptionStorage;
+class DoubleOptionStorage;
+class StringOptionStorage;
+class FileNameOptionStorage;
+class Options;
+
+/*! \addtogroup module_options
+ * \{
+ */
+
+/*! \brief
+ * Specifies an option that provides boolean values.
+ *
+ * Example:
+ * \code
+bool  bPBC;
+using gmx::BooleanOption;
+options.addOption(BooleanOption("pbc").store(&bPBC));
+ * \endcode
+ *
+ * Public methods in this class do not throw.
+ *
+ * \inpublicapi
+ */
+class BooleanOption : public OptionTemplate<bool, BooleanOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit BooleanOption(const char *name) : MyBase(name)
+        {
+            setFlag(efBoolean);
+        }
+
+    private:
+        //! Creates a BooleanOptionStorage object.
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+};
+
+/*! \brief
+ * Specifies an option that provides integer values.
+ *
+ * Examples:
+ * \code
+using gmx::IntegerOption;
+// Simple option
+int  rcut = 0;
+options.addOption(IntegerOption("rcut").store(&rcut));
+// Vector-valued option
+int  box[3] = {1, 1, 1};  // Default value
+options.addOption(IntegerOption("box").store(box).vector());
+ * \endcode
+ *
+ * Public methods in this class do not throw.
+ *
+ * \inpublicapi
+ */
+class IntegerOption : public OptionTemplate<int, IntegerOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit IntegerOption(const char *name) : MyBase(name) {}
+
+        /*! \brief
+         * Sets the option to return a vector value.
+         *
+         * A vector value returns a fixed number of values, the default being
+         * three (can be changed with valueCount()).  However, it also accepts
+         * a single value, in which case the value is used to fill the whole
+         * vector.
+         */
+        MyClass &vector() { setVector(); return me(); }
+
+    private:
+        //! Creates an IntegerOptionStorage object.
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+
+        /*! \brief
+         * Needed to initialize IntegerOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class IntegerOptionStorage;
+};
+
+/*! \brief
+ * Specifies an option that provides floating-point (double) values.
+ *
+ * Public methods in this class do not throw.
+ *
+ * \inpublicapi
+ */
+class DoubleOption : public OptionTemplate<double, DoubleOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit DoubleOption(const char *name) : MyBase(name), _bTime(false)
+        {
+        }
+
+        //! \copydoc IntegerOption::vector()
+        MyClass &vector() { setVector(); return me(); }
+        /*! \brief
+         * Sets the option to obey time conversion rules.
+         *
+         * For options with this flag, the user can specify a global time unit
+         * using a global option that is added by Options::addDefaultOptions().
+         * For the program, the value is always converted to ps.
+         *
+         * When this flag is specified, the option value is available only
+         * after Options::finish() has been called instead of immediately after
+         * assignment.
+         */
+        MyClass &timeValue() { _bTime = true; return me(); }
+
+    private:
+        //! Creates a DoubleOptionStorage object.
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+
+        bool _bTime;
+
+        /*! \brief
+         * Needed to initialize DoubleOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class DoubleOptionStorage;
+};
+
+/*! \brief
+ * Specifies an option that provides string values.
+ *
+ * Examples:
+ * \code
+using gmx::StringOption;
+// Simple option
+std::string  str;
+options.addOption(StringOption("str").store(&str));
+// Option that only accepts predefined values
+const char * const  allowed[] = { "atom", "residue", "molecule", NULL };
+std::string  str;
+int          type;
+options.addOption(StringOption("type").enumValue(allowed).store(&str)
+                     .storeEnumIndex(&type));
+ * \endcode
+ *
+ * Public methods in this class do not throw.
+ *
+ * \inpublicapi
+ */
+class StringOption : public OptionTemplate<std::string, StringOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit StringOption(const char *name)
+            : MyBase(name), _enumValues(NULL), _defaultEnumIndex(-1),
+              _enumIndexStore(NULL)
+        {
+        }
+
+        /*! \brief
+         * Sets the option to only accept one of a fixed set of strings.
+         *
+         * \param[in] values  Array of strings to accept, a NULL pointer
+         *      following the last string.
+         *
+         * Also accepts prefixes of the strings; if a prefix matches more than
+         * one of the possible strings, the shortest one is used (in a tie, the
+         * first one is).
+         *
+         * It is not possible to provide multiple values for an option with
+         * this property set, i.e., valueCount() and similar attributes cannot
+         * be set.
+         *
+         * The strings are copied once the option is created.
+         */
+        MyClass &enumValue(const char *const *values)
+        { _enumValues = values; return me(); }
+        /*! \brief
+         * Sets the default value using an index into the enumeration table.
+         *
+         * Cannot be specified without enumValue().
+         */
+        MyClass &defaultEnumIndex(int index)
+        {
+            GMX_RELEASE_ASSERT(index >= 0, "Invalid enumeration index");
+            _defaultEnumIndex = index;
+            return me();
+        }
+        /*! \brief
+         * Stores the index of the selected value into the provided memory
+         * location.
+         *
+         * The index (zero-based) of the selected value in the array \p values
+         * provided to enumValues() is written into \p *store after the
+         * option gets its value.  If the option has not been provided,
+         * and there is no default value, -1 is stored.
+         *
+         * Cannot be specified without enumValue().
+         */
+        MyClass &storeEnumIndex(int *store)
+        { _enumIndexStore = store; return me(); }
+
+    private:
+        //! Creates a StringOptionStorage object.
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+        virtual std::string createDescription() const;
+
+        const char *const      *_enumValues;
+        int                     _defaultEnumIndex;
+        int                    *_enumIndexStore;
+
+        /*! \brief
+         * Needed to initialize StringOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class StringOptionStorage;
+};
+
+/*! \brief
+ * Specifies an option that provides file names.
+ *
+ * Public methods in this class do not throw.
+ *
+ * This class is currently a stub implementation.
+ *
+ * \inpublicapi
+ */
+class FileNameOption : public OptionTemplate<std::string, FileNameOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit FileNameOption(const char *name)
+            : MyBase(name), _filetype(eftUnknown)
+        {
+            setFlag(efFile);
+        }
+
+        /*! \brief
+         * Sets the type of the file this option accepts.
+         *
+         * This attribute must be provided.
+         */
+        MyClass &filetype(OptionFileType type)
+        { _filetype = type; return me(); }
+        //! Tells that the file provided by this option is used read-only.
+        MyClass &readOnly()
+        { setFlag(efFileRead); clearFlag(efFileWrite); return me(); }
+        //! Tells that the file provided by this option is used write-only.
+        MyClass &writeOnly()
+        { setFlag(efFileWrite); clearFlag(efFileRead); return me(); }
+        /*! \brief
+         * Tells that the file provided by this option is used for reading and
+         * writing.
+         */
+        MyClass &readwrite()
+        { setFlag(efFileRead); setFlag(efFileWrite); return me(); }
+        /*! \brief
+         * Tells that the file will be looked up in library directories in
+         * addition to working directory.
+         */
+        MyClass &libraryFile() { setFlag(efFileLibrary); return me(); }
+
+    private:
+        //! Creates a FileNameOptionStorage object.
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+
+        OptionFileType          _filetype;
+
+        /*! \brief
+         * Needed to initialize FileNameOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class FileNameOptionStorage;
+};
+
+/*!\}*/
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/basicoptionstorage.h b/src/gromacs/options/basicoptionstorage.h
new file mode 100644 (file)
index 0000000..7f0f651
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares storage classes for basic option types.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_BASICOPTIONSTORAGE_H
+#define GMX_OPTIONS_BASICOPTIONSTORAGE_H
+
+#include <string>
+#include <vector>
+
+#include "optionfiletype.h"
+#include "optionstoragetemplate.h"
+
+namespace gmx
+{
+
+class BooleanOption;
+class IntegerOption;
+class DoubleOption;
+class StringOption;
+class FileNameOption;
+
+/*! \addtogroup module_options
+ * \{
+ */
+
+/*! \internal \brief
+ * Converts, validates, and stores boolean values.
+ */
+class BooleanOptionStorage : public OptionStorageTemplate<bool>
+{
+    public:
+        /*! \brief
+         * Initializes the storage from option settings.
+         *
+         * \param[in] settings   Storage settings.
+         * \param[in] options    Options object.
+         */
+        BooleanOptionStorage(const BooleanOption &settings, Options *options)
+            : MyBase(settings, options)
+        {
+        }
+
+        virtual const char *typeString() const { return "bool"; }
+        virtual std::string formatValue(int i) const;
+
+    private:
+        virtual void convertValue(const std::string &value);
+};
+
+/*! \internal \brief
+ * Converts, validates, and stores integer values.
+ */
+class IntegerOptionStorage : public OptionStorageTemplate<int>
+{
+    public:
+        //! \copydoc BooleanOptionStorage::BooleanOptionStorage()
+        IntegerOptionStorage(const IntegerOption &settings, Options *options)
+            : MyBase(settings, options)
+        {
+        }
+
+        virtual const char *typeString() const
+        { return hasFlag(efVector) ? "vector" : "int"; }
+        virtual std::string formatValue(int i) const;
+
+    private:
+        virtual void convertValue(const std::string &value);
+        virtual void processSetValues(ValueList *values);
+};
+
+/*! \internal \brief
+ * Converts, validates, and stores floating-point (double) values.
+ */
+class DoubleOptionStorage : public OptionStorageTemplate<double>
+{
+    public:
+        //! \copydoc IntegerOptionStorage::IntegerOptionStorage()
+        DoubleOptionStorage(const DoubleOption &settings, Options *options);
+
+        virtual const char *typeString() const;
+        virtual std::string formatValue(int i) const;
+
+    private:
+        virtual void convertValue(const std::string &value);
+        virtual void processSetValues(ValueList *values);
+        virtual void processAll();
+
+        bool                    _bTime;
+};
+
+/*! \internal \brief
+ * Converts, validates, and stores string values.
+ */
+class StringOptionStorage : public OptionStorageTemplate<std::string>
+{
+    public:
+        //! \copydoc DoubleOptionStorage::DoubleOptionStorage()
+        StringOptionStorage(const StringOption &settings, Options *options);
+
+        virtual const char *typeString() const { return _allowed.empty() ? "string" : "enum"; }
+        virtual std::string formatValue(int i) const;
+
+    private:
+        virtual void convertValue(const std::string &value);
+        virtual void refreshValues();
+
+        ValueList               _allowed;
+        int                    *_enumIndexStore;
+};
+
+/*! \internal \brief
+ * Converts, validates, and stores file names.
+ */
+class FileNameOptionStorage : public OptionStorageTemplate<std::string>
+{
+    public:
+        //! \copydoc StringOptionStorage::StringOptionStorage()
+        FileNameOptionStorage(const FileNameOption &settings, Options *options);
+
+        virtual const char *typeString() const { return "file"; }
+        virtual std::string formatValue(int i) const;
+
+    private:
+        virtual void convertValue(const std::string &value);
+
+        OptionFileType          _filetype;
+};
+
+/*!\}*/
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/cmdlineparser-impl.h b/src/gromacs/options/cmdlineparser-impl.h
new file mode 100644 (file)
index 0000000..b87f458
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::CommandLineParser.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_CMDLINEPARSER_IMPL_H
+#define GMX_OPTIONS_CMDLINEPARSER_IMPL_H
+
+#include "cmdlineparser.h"
+#include "optionsassigner.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Private implementation class for CommandLineParser.
+ *
+ * \ingroup module_options
+ */
+class CommandLineParser::Impl
+{
+    public:
+        //! Sets the options object to parse to.
+        Impl(Options *options);
+
+        //! Helper object for assigning the options.
+        OptionsAssigner         _assigner;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/cmdlineparser.cpp b/src/gromacs/options/cmdlineparser.cpp
new file mode 100644 (file)
index 0000000..15cebfe
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::CommandLineParser.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/cmdlineparser.h"
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/options/optionsassigner.h"
+
+#include "cmdlineparser-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * CommandLineParser::Impl
+ */
+
+CommandLineParser::Impl::Impl(Options *options)
+    : _assigner(options)
+{
+    _assigner.setAcceptBooleanNoPrefix(true);
+    _assigner.setNoStrictSectioning(true);
+}
+
+/********************************************************************
+ * CommandLineParser
+ */
+
+CommandLineParser::CommandLineParser(Options *options)
+    : _impl(new Impl(options))
+{
+}
+
+CommandLineParser::~CommandLineParser()
+{
+    delete _impl;
+}
+
+void CommandLineParser::parse(int *argc, char *argv[])
+{
+    MessageStringCollector errors;
+    int  i = 1;
+    // Start in the discard phase to skip options that can't be understood.
+    bool bDiscard = true;
+
+    _impl->_assigner.start();
+    while (i < *argc)
+    {
+        // Lone '-' is passed as a value.
+        if (argv[i][0] == '-' && argv[i][1] != '\0')
+        {
+            if (!bDiscard)
+            {
+                try
+                {
+                    _impl->_assigner.finishOption();
+                }
+                catch (UserInputError &ex)
+                {
+                    errors.append(ex.what());
+                }
+                errors.finishContext();
+            }
+            errors.startContext("In command-line option " + std::string(argv[i]));
+            bDiscard = false;
+            try
+            {
+                const char *name = &argv[i][1];
+                _impl->_assigner.startOption(name);
+            }
+            catch (UserInputError &ex)
+            {
+                bDiscard = true;
+                errors.append(ex.what());
+                errors.finishContext();
+            }
+        }
+        else if (!bDiscard)
+        {
+            try
+            {
+                _impl->_assigner.appendValue(argv[i]);
+            }
+            catch (UserInputError &ex)
+            {
+                errors.append(ex.what());
+            }
+        }
+        ++i;
+    }
+    if (!bDiscard)
+    {
+        try
+        {
+            _impl->_assigner.finishOption();
+        }
+        catch (UserInputError &ex)
+        {
+            errors.append(ex.what());
+        }
+        errors.finishContext();
+    }
+    _impl->_assigner.finish();
+    if (!errors.isEmpty())
+    {
+        // TODO: This exception type may not always be appropriate.
+        GMX_THROW(InvalidInputError(errors.toString()));
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/cmdlineparser.h b/src/gromacs/options/cmdlineparser.h
new file mode 100644 (file)
index 0000000..4f480f2
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::CommandLineParser.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_CMDLINEPARSER_H
+#define GMX_OPTIONS_CMDLINEPARSER_H
+
+namespace gmx
+{
+
+class Options;
+
+/*! \brief
+ * Implements command-line parsing for Options objects.
+ *
+ * Typical usage (without error checking):
+ * \code
+gmx::Options options("name", "description");
+// Fill up options
+
+gmx::CommandLineParser(&options).parse(&argc, argv);
+options.finish();
+ * \endcode
+ *
+ * \inpublicapi
+ * \ingroup module_options
+ */
+class CommandLineParser
+{
+    public:
+        /*! \brief
+         * Creates a command-line parser that sets values for options.
+         *
+         * \param[in] options  Options object whose options should be set.
+         */
+        CommandLineParser(Options *options);
+        ~CommandLineParser();
+
+        /*! \brief
+         * Parses the command-line.
+         *
+         * \throws InvalidInputError if any errors were detected in the input.
+         *
+         * All command-line arguments are parsed, and an aggregate exception
+         * with all the detected errors is thrown in the end.
+         */
+        void parse(int *argc, char *argv[]);
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        CommandLineParser(const CommandLineParser &);
+        void operator =(const CommandLineParser &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/globalproperties.cpp b/src/gromacs/options/globalproperties.cpp
new file mode 100644 (file)
index 0000000..f479eaf
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::OptionsGlobalProperties.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/globalproperties.h"
+
+#include <cstddef>
+
+#include <smalloc.h>
+#include <statutil.h>
+
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+
+namespace gmx
+{
+
+static const char *const timeUnits[] = {
+    "fs", "ps", "ns", "us", "ms",  "s", NULL
+};
+static const char *const plotFormats[] = {
+    "none", "xmgrace", "xmgr", NULL
+};
+static const double timeScaleFactors[] = {
+    1e-3,    1,  1e3,  1e6,  1e9, 1e12
+};
+
+
+OptionsGlobalProperties::OptionsGlobalProperties()
+    : _usedProperties(0), _timeUnit(1), _plotFormat(1),
+      _selectionCollection(NULL), _oenv(NULL)
+{
+    // TODO: If/when this is refactored, exception safety should be considered
+    snew(_oenv, 1);
+    output_env_init_default(_oenv);
+}
+
+
+OptionsGlobalProperties::~OptionsGlobalProperties()
+{
+    if (_oenv != NULL)
+    {
+        output_env_done(_oenv);
+    }
+}
+
+
+double OptionsGlobalProperties::timeScaleFactor() const
+{
+    GMX_RELEASE_ASSERT(_timeUnit >= 0
+        && (size_t)_timeUnit < sizeof(timeScaleFactors)/sizeof(timeScaleFactors[0]),
+        "Time unit index has become out of range");
+    return timeScaleFactors[_timeUnit];
+}
+
+
+void OptionsGlobalProperties::addDefaultOptions(Options *options)
+{
+    if (isPropertyUsed(eogpTimeScaleFactor))
+    {
+        options->addOption(StringOption("tu").enumValue(timeUnits)
+                               .defaultValue("ps")
+                               .storeEnumIndex(&_timeUnit)
+                               .description("Unit for time values"));
+    }
+    if (isPropertyUsed(eogpPlotFormat))
+    {
+        options->addOption(StringOption("xvg").enumValue(plotFormats)
+                               .defaultValue("xmgrace")
+                               .storeEnumIndex(&_plotFormat)
+                               .description("Plot formatting"));
+    }
+}
+
+
+void OptionsGlobalProperties::finish()
+{
+    if (isPropertyUsed(eogpTimeScaleFactor))
+    {
+        _oenv->time_unit = static_cast<time_unit_t>(_timeUnit + 1);
+    }
+    if (isPropertyUsed(eogpPlotFormat))
+    {
+        if (_plotFormat == 0)
+        {
+            _oenv->xvg_format = exvgNONE;
+        }
+        else
+        {
+            _oenv->xvg_format = static_cast<xvg_format_t>(_plotFormat);
+        }
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/globalproperties.h b/src/gromacs/options/globalproperties.h
new file mode 100644 (file)
index 0000000..54aed81
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::OptionsGlobalProperties.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_GLOBALPROPERTIES_H
+#define GMX_OPTIONS_GLOBALPROPERTIES_H
+
+#include <typedefs.h>
+
+namespace gmx
+{
+
+class Options;
+class SelectionCollection;
+
+/*! \libinternal \brief
+ * ID numbers for global properties.
+ */
+enum OptionGlobalPropertyId
+{
+    eogpTimeScaleFactor,
+    eogpPlotFormat,
+    eogpSelectionCollection,
+};
+
+/*! \libinternal \brief
+ * Describes global properties of an Options collection.
+ *
+ * These properties are used to implement features that require all options of
+ * a certain type to access some global data.
+ * For example, if there are options that specify times, and in addition an
+ * option that specifies the unit for these times, all the time options need to
+ * know the scaling factor to get the time in internal units.
+ *
+ * \todo
+ * The current implementation introduces a "weak" cyclic dependency between the
+ * selection and options modules in that the SelectionCollection class has to
+ * be forward-declared here. Also, there are things in this class that would be
+ * better placed in the analysisdata module (for selecting plot formats).
+ * It should be considered whether this should be implemented in some other way
+ * (a generic implementation is possible, but is a lot more complex, and
+ * requires some RTTI, either in this class or somewhere else).
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+class OptionsGlobalProperties
+{
+    public:
+        ~OptionsGlobalProperties();
+
+        //! Request for a global property to be used.
+        void request(OptionGlobalPropertyId id)
+        {
+            _usedProperties |= (1<<id);
+        }
+
+        //! Set the selection collection for selection option output.
+        void setSelectionCollection(SelectionCollection *sc)
+        {
+            _selectionCollection = sc;
+        }
+
+        //! Returns the scaling factor to get times in ps.
+        double timeScaleFactor() const;
+        //! Returns the selection collection.
+        SelectionCollection *selectionCollection() const
+        {
+            return _selectionCollection;
+        }
+        /*! \brief
+         * Returns an output environment structure for interfacing with old
+         * code.
+         *
+         * Currently, the returned structure is always filled with default
+         * values for most fields.
+         *
+         * \deprecated
+         */
+        output_env_t output_env() const
+        {
+            return _oenv;
+        }
+
+    private:
+        OptionsGlobalProperties();
+
+        //! Returns true if request() has been called for the given property.
+        bool isPropertyUsed(OptionGlobalPropertyId id) const
+        {
+            return _usedProperties & (1<<id);
+        }
+        /*! \brief
+         * Adds options for setting requested global properties.
+         *
+         * \param[in,out] options Options to which the global property options
+         *      are added.
+         *
+         * If a global property has been requested and it can be set/customized
+         * by the user, this method adds the necessary option to \p options.
+         *
+         * This method performs the real work of Options::addDefaultOptions().
+         */
+        void addDefaultOptions(Options *options);
+        /*! \brief
+         * Initializes variables dependent on global properties.
+         *
+         * This method should be called after the values for the options
+         * generated with addDefaultOptions() have been set.
+         */
+        void finish();
+
+        unsigned long           _usedProperties;
+        int                     _timeUnit;
+        int                     _plotFormat;
+        SelectionCollection    *_selectionCollection;
+        output_env_t            _oenv;
+
+        friend class Options;
+
+        // Disallow copy and assign.
+        OptionsGlobalProperties(const OptionsGlobalProperties &);
+        void operator =(const OptionsGlobalProperties &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionfiletype.h b/src/gromacs/options/optionfiletype.h
new file mode 100644 (file)
index 0000000..aa53350
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Defines an enumeration type for specifying file types for options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONFILETYPE_HPP
+#define GMX_OPTIONS_OPTIONFILETYPE_HPP
+
+namespace gmx
+{
+
+/*! \brief
+ * Purpose of file(s) provided through an option.
+ *
+ * \ingroup module_options
+ */
+enum OptionFileType {
+    eftUnknown,
+    eftTopology,
+    eftRunInput,
+    eftTrajectory,
+    eftIndex,
+    eftPlot,
+    eftGenericData
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionflags.h b/src/gromacs/options/optionflags.h
new file mode 100644 (file)
index 0000000..c609ea0
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Defines flags used in option implementation.
+ *
+ * Symbols in this header are considered an implementation detail, and should
+ * not be accessed outside the module.
+ * Because of details in the implementation, it is still installed.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONFLAGS_H
+#define GMX_OPTIONS_OPTIONFLAGS_H
+
+#include "../utility/flags.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Flags for options.
+ *
+ * These flags are not part of the public interface, even though they are in an
+ * installed header.  They are needed in a few template class implementations.
+ */
+enum OptionFlag
+{
+    //! %Option has been set.
+    efSet                 = 1<<0,
+    /*! \brief
+     * The current value of the option is a default value.
+     *
+     * This flag is also set when a new option source starts, such that values
+     * from the new source will overwrite old ones.
+     */
+    efHasDefaultValue     = 1<<1,
+    //! %Option is required to be set.
+    efRequired            = 1<<2,
+    //! %Option can be specified multiple times.
+    efMulti               = 1<<3,
+    //! %Option is hidden from standard help.
+    efHidden              = 1<<4,
+    /*! \brief
+     * %Option provides a boolean value.
+     *
+     * This is used to optionally support an alternative syntax where an
+     * option provided with no value sets the value to true and an
+     * option prefixed with "no" clears the value.
+     */
+    efBoolean             = 1<<5,
+    /*! \brief
+     * %Option value is a vector, but a single value is also accepted.
+     *
+     * If only a single value is provided, the storage object should fill the
+     * whole vector with that value.  The length of the vector must be fixed.
+     * The default length is 3 elements.
+     */
+    efVector              = 1<<6,
+    efExternalStore       = 1<<8,
+    efExternalValueVector = 1<<10,
+    //! %Option does not support default values.
+    efNoDefaultValue      = 1<<7,
+    /*! \brief
+     * Storage object does its custom checking for minimum value count.
+     *
+     * If this flag is set, the class derived from OptionStorageTemplate should
+     * implement processSetValues(), processAll(), and possible other functions
+     * it provides such that it always fails if not enough values are provided.
+     * This is useful to override the default check, which is done in
+     * OptionStorageTemplate::processSet().
+     */
+    efDontCheckMinimumCount     = 1<<16,
+    efFile                = 1<<12,
+    efFileRead            = 1<<13,
+    efFileWrite           = 1<<14,
+    efFileLibrary         = 1<<15,
+    //efDynamic             = 1<<16,
+    //efRanges              = 1<<17,
+    //efEnum                = 1<<18,
+    //efStaticEnum          = 1<<19,
+    //efVarNum              = 1<<20,
+    //efAtomVal             = 1<<21,
+};
+
+//! Holds a combination of ::OptionFlag values.
+typedef FlagsTemplate<OptionFlag> OptionFlags;
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/options-impl.h b/src/gromacs/options/options-impl.h
new file mode 100644 (file)
index 0000000..d3e1252
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::Options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONS_IMPL_H
+#define GMX_OPTIONS_OPTIONS_IMPL_H
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "options.h"
+
+namespace gmx
+{
+
+class AbstractOptionStorage;
+class OptionsGlobalProperties;
+
+/*! \internal \brief
+ * Private implementation class for Options.
+ *
+ * Note that in addition to Options, the OptionsAssigner and OptionsIterator
+ * classes also directly access this class.
+ *
+ * \ingroup module_options
+ */
+class Options::Impl
+{
+    public:
+        //! Convenience type for list of sections.
+        typedef std::vector<Options *> SubSectionList;
+        //! Convenience type for list of options.
+        typedef std::vector<AbstractOptionStorage *> OptionList;
+
+        //! Sets the name and title.
+        Impl(const char *name, const char *title);
+        ~Impl();
+
+        /*! \brief
+         * Finds a subsection by name.
+         *
+         * \param[in] name  Name to search for.
+         * \returns Pointer to the found subsection, or NULL if not found.
+         *
+         * Does not throw.
+         */
+        Options *findSubSection(const char *name) const;
+        /*! \brief
+         * Finds an option by name.
+         *
+         * \param[in] name  Name to search for.
+         * \returns Pointer to the found option, or NULL if not found.
+         *
+         * Does not throw.
+         */
+        AbstractOptionStorage *findOption(const char *name) const;
+
+        /*! \brief
+         * Calls AbstractOptionStorage::startSource() for all options,
+         * including subsections.
+         *
+         * Does not throw.
+         */
+        void startSource();
+
+        //! Name for the Options object.
+        std::string             _name;
+        //! Description title for the Options object.
+        std::string             _title;
+        //! Full description for the Options object.
+        std::string             _description;
+        /*! \brief
+         * List of subsections, in insertion order.
+         *
+         * This container contains only references to external objects; memory
+         * management is performed elsewhere.
+         */
+        SubSectionList          _subSections;
+        /*! \brief
+         * List of options, in insertion order.
+         *
+         * All objects in this container are owned by this object, and are
+         * freed in the destructor.
+         */
+        OptionList              _options;
+        //! Options object that contains this object as a subsection, or NULL.
+        Options                *_parent;
+        /*! \brief
+         * Object that contains global properties, or NULL if \a _parent != NULL.
+         *
+         * This object is always owned by the Options object.
+         * For subsections, the global properties are kept in the parent, and
+         * this pointer is NULL.
+         */
+        // Could be scoped_ptr
+        std::auto_ptr<OptionsGlobalProperties>  _globalProperties;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/options.cpp b/src/gromacs/options/options.cpp
new file mode 100644 (file)
index 0000000..f9b1559
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::Options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/options.h"
+
+#include <cctype>
+#include <cstring>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/options/abstractoption.h"
+#include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/globalproperties.h"
+
+#include "options-impl.h"
+
+namespace gmx
+{
+
+// TODO: Move this into the utility module
+static std::string composeString(const char *const *sarray)
+{
+    std::string result;
+
+    for (int i = 0; sarray[i] != NULL; ++i)
+    {
+        if (sarray[i][0] != '\0')
+        {
+            result.append(sarray[i]);
+            char lastchar = sarray[i][std::strlen(sarray[i])-1];
+            if (!std::isspace(lastchar))
+            {
+                result.append(" ");
+            }
+        }
+    }
+    result.resize(result.find_last_not_of(" \n\r\t") + 1);
+    return result;
+}
+
+/********************************************************************
+ * Options::Impl
+ */
+
+Options::Impl::Impl(const char *name, const char *title)
+    : _name(name != NULL ? name : ""), _title(title != NULL ? title : ""),
+      _parent(NULL), _globalProperties(new OptionsGlobalProperties)
+{
+}
+
+Options::Impl::~Impl()
+{
+    OptionList::const_iterator i;
+    for (i = _options.begin(); i != _options.end(); ++i)
+    {
+        delete *i;
+    }
+}
+
+Options *Options::Impl::findSubSection(const char *name) const
+{
+    SubSectionList::const_iterator i;
+    for (i = _subSections.begin(); i != _subSections.end(); ++i)
+    {
+        if ((*i)->name() == name)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+AbstractOptionStorage *Options::Impl::findOption(const char *name) const
+{
+    OptionList::const_iterator i;
+    for (i = _options.begin(); i != _options.end(); ++i)
+    {
+        if ((*i)->name() == name)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+void Options::Impl::startSource()
+{
+    OptionList::const_iterator i;
+    for (i = _options.begin(); i != _options.end(); ++i)
+    {
+        AbstractOptionStorage *option = *i;
+        option->startSource();
+    }
+    SubSectionList::const_iterator j;
+    for (j = _subSections.begin(); j != _subSections.end(); ++j)
+    {
+        Options *section = *j;
+        section->_impl->startSource();
+    }
+}
+
+/********************************************************************
+ * Options
+ */
+
+Options::Options(const char *name, const char *title)
+    : _impl(new Impl(name, title))
+{
+}
+
+Options::~Options()
+{
+    delete _impl;
+}
+
+const std::string &Options::name() const
+{
+    return _impl->_name;
+}
+
+const std::string &Options::title() const
+{
+    return _impl->_title;
+}
+
+const std::string &Options::description() const
+{
+    return _impl->_description;
+}
+
+void Options::setDescription(const char *const *desc)
+{
+    _impl->_description = composeString(desc);
+}
+
+void Options::addSubSection(Options *section)
+{
+    // Make sure that section is not already inserted somewhere.
+    GMX_RELEASE_ASSERT(section->_impl->_parent == NULL,
+                       "Cannot add as subsection twice");
+    // Make sure that there are no duplicate sections.
+    GMX_RELEASE_ASSERT(_impl->findSubSection(section->name().c_str()) == NULL,
+                       "Duplicate subsection name");
+    _impl->_subSections.push_back(section);
+    section->_impl->_parent = this;
+
+    globalProperties()._usedProperties |=
+        section->_impl->_globalProperties->_usedProperties;
+    section->_impl->_globalProperties.reset();
+}
+
+void Options::addOption(const AbstractOption &settings)
+{
+    std::auto_ptr<AbstractOptionStorage> option(settings.createDefaultStorage(this));
+    if (_impl->findOption(option->name().c_str()) != NULL)
+    {
+        GMX_THROW(APIError("Duplicate option: " + option->name()));
+    }
+    _impl->_options.push_back(option.get());
+    option.release();
+}
+
+void Options::addDefaultOptions()
+{
+    globalProperties().addDefaultOptions(this);
+}
+
+bool Options::isSet(const char *name) const
+{
+    AbstractOptionStorage *option = _impl->findOption(name);
+    return (option != NULL ? option->isSet() : false);
+}
+
+void Options::finish()
+{
+    MessageStringCollector errors;
+    Impl::OptionList::const_iterator i;
+    for (i = _impl->_options.begin(); i != _impl->_options.end(); ++i)
+    {
+        AbstractOptionStorage *option = *i;
+        try
+        {
+            option->finish();
+        }
+        catch (UserInputError &ex)
+        {
+            MessageStringContext context(&errors, "In option " + option->name());
+            errors.append(ex.what());
+        }
+    }
+    Impl::SubSectionList::const_iterator j;
+    for (j = _impl->_subSections.begin(); j != _impl->_subSections.end(); ++j)
+    {
+        Options *section = *j;
+        try
+        {
+            section->finish();
+        }
+        catch (UserInputError &ex)
+        {
+            errors.append(ex.what());
+        }
+    }
+    if (_impl->_parent == NULL)
+    {
+        GMX_RELEASE_ASSERT(_impl->_globalProperties.get() != NULL,
+                           "Global properties should exist for the top-level options");
+        _impl->_globalProperties->finish();
+    }
+    if (!errors.isEmpty())
+    {
+        // TODO: This exception type may not always be appropriate.
+        GMX_THROW(InvalidInputError(errors.toString()));
+    }
+}
+
+OptionsGlobalProperties &Options::globalProperties()
+{
+    Options *section = this;
+    while (section->_impl->_parent != NULL)
+    {
+        section = section->_impl->_parent;
+    }
+    GMX_RELEASE_ASSERT(section->_impl->_globalProperties.get() != NULL,
+                       "Global properties should exist for the top-level options");
+    return *section->_impl->_globalProperties;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/options.h b/src/gromacs/options/options.h
new file mode 100644 (file)
index 0000000..7dcef77
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::Options.
+ *
+ * Together with basicoptions.h, this header forms the part of the public
+ * API that most classes will use to provide options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONS_H
+#define GMX_OPTIONS_OPTIONS_H
+
+#include <string>
+
+namespace gmx
+{
+
+class AbstractOption;
+class OptionsGlobalProperties;
+class OptionsAssigner;
+class OptionsIterator;
+
+/*! \brief
+ * Collection of options.
+ *
+ * This class provides a standard interface for implementing input options.
+ * Standard usage is to write a method that creates an Options that is owned by
+ * the object, populates it with supported options, and then returns it:
+ * \code
+// <as class attributes>
+using gmx::Options;
+Options      options("common", "Common Options");
+std::string  arg1;
+int          arg2;
+
+// <populating>
+using gmx::StringOption;
+using gmx::IntegerOption;
+options.addOption(StringOption("arg1").store(&arg1));
+options.addOption(IntegerOption("arg2").store(&arg2));
+return &options;
+ * \endcode
+ * The caller of that method can then use a parser implementation such as
+ * CommandLineParser to provide values for the options.
+ *
+ * Header basicoptions.h provides declarations of several standard
+ * option types for use with addOption().  Documentation of those classes
+ * also give more examples of how to define options.
+ *
+ * In order to keep the public interface of this class simple and to reduce
+ * build dependencies on objects that simply provide options, functionality
+ * to assign values to options is provided by a separate OptionsAssigner class.
+ * Similarly, functionality for looping over all options (e.g., for writing out
+ * help) is provided by OptionsIterator.
+ *
+ * \inpublicapi
+ * \ingroup module_options
+ */
+class Options
+{
+    public:
+        /*! \brief
+         * Initializes the name and title of an option collection.
+         *
+         * \param[in] name  Single-word name.
+         * \param[in] title Descriptive title.
+         *
+         * Copies the input strings.
+         */
+        Options(const char *name, const char *title);
+        ~Options();
+
+        //! Returns the short name of the option collection.
+        const std::string &name() const;
+        //! Returns the title of the option collection.
+        const std::string &title() const;
+        //! Returns the full description of the option collection.
+        const std::string &description() const;
+
+        /*! \brief
+         * Sets the full description of the option collection.
+         *
+         * \param[in] desc Array of strings to form the description, terminated
+         *      by a NULL pointer.
+         *
+         * The strings in the \p desc array are concatenated to form the
+         * description, adding a single space between the strings if there is
+         * no whitespace in the end of a string.
+         */
+        void setDescription(const char *const *desc);
+        //int addBugs(int nbugs, const char *const *bugs);
+
+        /*! \brief
+         * Adds an option collection as a subsection of this collection.
+         *
+         * \param[in] section Subsection to add.
+         *
+         * The name() field of \p section is used as the name of the
+         * subsection.  If an attempt is made to add two different subsections
+         * with the same name, this function asserts.
+         *
+         * For certain functionality to work properly, no options should
+         * be added to the subsection after it has been added to another
+         * collection.
+         *
+         * Only a pointer to the provided object is stored.  The caller is
+         * responsible that the object exists for the lifetime of the
+         * collection.
+         * It is not possible to add the same Options object as a subsection to
+         * several different Options.
+         * If an attempt is made, the function asserts.
+         */
+        void addSubSection(Options *section);
+        /*! \brief
+         * Adds a recognized option to the collection.
+         *
+         * \throws APIError if invalid option settings are provided.
+         *
+         * See \link Options class documentation \endlink for example usage.
+         */
+        void addOption(const AbstractOption &settings);
+        /*! \brief
+         * Adds default options to this collection.
+         *
+         * Adds default options for altering global properties such as the time
+         * unit into this collection.
+         *
+         * It is possible to call this method on a subsection of a collection.
+         * Even in that case, the generated options set the properties for the
+         * parent collection.
+         */
+        void addDefaultOptions();
+
+        //! Returns true if option \p name is set.
+        bool isSet(const char *name) const;
+        /*! \brief
+         * Notifies the collection that all option values are assigned.
+         *
+         * \throws InvalidInputError if invalid user input is detected.
+         *
+         * This function should be called after no more option values are
+         * to be assigned.  Values in storage variables are guaranteed to be
+         * available only after this call, although in most cases, they are
+         * available already during assignment.
+         *
+         * If invalid option values, e.g., missing required option, is detected
+         * at this point, this function throws.  The thrown exception contains
+         * information on all errors detected during the call.
+         */
+        void finish();
+
+        /*! \brief
+         * Returns the global property object for this collection.
+         *
+         * The caller should not store pointers or references to the object;
+         * it can change if this object is added as a subsection into
+         * another collection.
+         *
+         * The global property object is shared by all Options objects that
+         * are part of the same section/subsection hierarchy.
+         *
+         * \see OptionsGlobalProperties
+         */
+        OptionsGlobalProperties &globalProperties();
+        //! \copydoc globalProperties()
+        const OptionsGlobalProperties &globalProperties() const
+        { return const_cast<Options *>(this)->globalProperties(); }
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        friend class Impl;
+
+        //! Needed to be able to extend the interface of this object.
+        friend class OptionsAssigner;
+        //! Needed to be able to extend the interface of this object.
+        friend class OptionsIterator;
+
+        // Disallow copy and assign.
+        Options(const Options &);
+        void operator =(const Options &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionsassigner-impl.h b/src/gromacs/options/optionsassigner-impl.h
new file mode 100644 (file)
index 0000000..3db1c01
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::OptionsAssigner.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONSASSIGNER_IMPL_H
+#define GMX_OPTIONS_OPTIONSASSIGNER_IMPL_H
+
+#include <vector>
+
+#include "optionsassigner.h"
+
+namespace gmx
+{
+
+class AbstractOptionStorage;
+class Options;
+
+/*! \internal \brief
+ * Private implementation class for OptionsAssigner.
+ *
+ * \ingroup module_options
+ */
+class OptionsAssigner::Impl
+{
+    public:
+        //! Possible flags for controlling assignment behavior.
+        enum Flag
+        {
+            //! Recognize boolean option "name" also as "noname".
+            efAcceptBooleanNoPrefix     = 1<<0,
+            //! Look for options in all sections, not just the current one.
+            efNoStrictSectioning        = 1<<1,
+        };
+        //! Sets the option object to assign to.
+        Impl(Options *options);
+
+        //! Sets or clears the given flag.
+        void setFlag(Flag flag, bool bSet);
+
+        //! Returns true if the given flag is set.
+        bool hasFlag(Flag flag) const { return _flags & flag; }
+        //! Returns true if a subsection has been set.
+        bool inSubSection() const { return _sectionStack.size() > 1; }
+        //! Returns the Options object for the current section.
+        Options &currentSection() const { return *_sectionStack.back(); }
+        /*! \brief
+         * Finds an option by the given name.
+         *
+         * \param[in] name  Name of the option to look for.
+         * \returns Pointer to the found option, or NULL if none found.
+         *
+         * This function takes into account the flags specified, and may change
+         * the internal state of the assigner to match the option found.
+         * If no option is found, the internal state is not modified.
+         */
+        AbstractOptionStorage *findOption(const char *name);
+
+        //! Options object to assign to.
+        Options                &_options;
+        //! Flags that control assignment behavior.
+        unsigned long           _flags;
+        /*! \brief
+         * List of (sub)sections being assigned to.
+         *
+         * The first element always points to \a _options.
+         */
+        std::vector<Options *>  _sectionStack;
+        //! Current option being assigned to, or NULL if none.
+        AbstractOptionStorage  *_currentOption;
+        //! Number of values assigned so far to the current option.
+        int                     _currentValueCount;
+        //! If true, a "no" prefix was given for the current boolean option.
+        bool                    _reverseBoolean;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionsassigner.cpp b/src/gromacs/options/optionsassigner.cpp
new file mode 100644 (file)
index 0000000..af0991b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::OptionsAssigner.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/optionsassigner.h"
+
+#include <deque>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/options.h"
+
+#include "optionsassigner-impl.h"
+#include "options-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * OptionsAssigner::Impl
+ */
+
+OptionsAssigner::Impl::Impl(Options *options)
+    : _options(*options), _flags(0), _currentOption(NULL),
+      _currentValueCount(0), _reverseBoolean(false)
+{
+    _sectionStack.push_back(&_options);
+}
+
+void OptionsAssigner::Impl::setFlag(OptionsAssigner::Impl::Flag flag, bool bSet)
+{
+    if (bSet)
+    {
+        _flags |= flag;
+    }
+    else
+    {
+        _flags &= ~flag;
+    }
+}
+
+AbstractOptionStorage *
+OptionsAssigner::Impl::findOption(const char *name)
+{
+    GMX_RELEASE_ASSERT(_currentOption == NULL,
+                       "Cannot search for another option while processing one");
+    AbstractOptionStorage *option = NULL;
+    Options *section = NULL;
+    Options *root = &currentSection();
+    Options *oldRoot = NULL;
+    int      upcount = 0;
+    std::deque<Options *> searchList;
+    searchList.push_back(root);
+    while (option == NULL && !searchList.empty())
+    {
+        section = searchList.front();
+        option = section->_impl->findOption(name);
+        if (option == NULL && hasFlag(efAcceptBooleanNoPrefix))
+        {
+            if (name[0] == 'n' && name[1] == 'o')
+            {
+                option = section->_impl->findOption(name + 2);
+                if (option != NULL && option->isBoolean())
+                {
+                    _reverseBoolean = true;
+                }
+                else
+                {
+                    option = NULL;
+                }
+            }
+        }
+        searchList.pop_front();
+        if (hasFlag(efNoStrictSectioning))
+        {
+            Options::Impl::SubSectionList::const_iterator i;
+            for (i = section->_impl->_subSections.begin();
+                 i != section->_impl->_subSections.end(); ++i)
+            {
+                if (*i != oldRoot)
+                {
+                    searchList.push_back(*i);
+                }
+            }
+            if (searchList.empty() && root != &_options)
+            {
+                Options *oldRoot = root;
+                root = root->_impl->_parent;
+                ++upcount;
+                searchList.push_back(root);
+            }
+        }
+    }
+    if (hasFlag(efNoStrictSectioning) && option != NULL)
+    {
+        while (upcount > 0)
+        {
+            _sectionStack.pop_back();
+            --upcount;
+        }
+        std::vector<Options *> sections;
+        while (section != &currentSection())
+        {
+            sections.push_back(section);
+            section = section->_impl->_parent;
+        }
+        while (!sections.empty())
+        {
+            _sectionStack.push_back(sections.back());
+            sections.pop_back();
+        }
+    }
+    return option;
+}
+
+/********************************************************************
+ * OptionsAssigner
+ */
+
+OptionsAssigner::OptionsAssigner(Options *options)
+    : _impl(new Impl(options))
+{
+}
+
+OptionsAssigner::~OptionsAssigner()
+{
+    delete _impl;
+}
+
+void OptionsAssigner::setAcceptBooleanNoPrefix(bool enabled)
+{
+    _impl->setFlag(Impl::efAcceptBooleanNoPrefix, enabled);
+}
+
+void OptionsAssigner::setNoStrictSectioning(bool enabled)
+{
+    _impl->setFlag(Impl::efNoStrictSectioning, enabled);
+}
+
+void OptionsAssigner::start()
+{
+    _impl->_options._impl->startSource();
+}
+
+void OptionsAssigner::startSubSection(const char *name)
+{
+    Options *section = _impl->currentSection()._impl->findSubSection(name);
+    if (section == NULL)
+    {
+        GMX_THROW(InvalidInputError("Unknown subsection"));
+    }
+    _impl->_sectionStack.push_back(section);
+}
+
+void OptionsAssigner::startOption(const char *name)
+{
+    GMX_RELEASE_ASSERT(_impl->_currentOption == NULL, "finishOption() not called");
+    AbstractOptionStorage *option = _impl->findOption(name);
+    if (option == NULL)
+    {
+        GMX_THROW(InvalidInputError("Unknown option"));
+    }
+    option->startSet();
+    _impl->_currentOption = option;
+    _impl->_currentValueCount = 0;
+}
+
+void OptionsAssigner::appendValue(const std::string &value)
+{
+    AbstractOptionStorage *option = _impl->_currentOption;
+    GMX_RELEASE_ASSERT(option != NULL, "startOption() not called");
+    // Does not count correctly, but the actual count is not really used.
+    // TODO: Rename the variable to better reflect the usage.
+    ++_impl->_currentValueCount;
+    option->appendValue(value);
+}
+
+void OptionsAssigner::finishOption()
+{
+    AbstractOptionStorage *option = _impl->_currentOption;
+    GMX_RELEASE_ASSERT(option != NULL, "startOption() not called");
+    bool bBoolReverseValue = false;
+    if (option->isBoolean())
+    {
+        if (_impl->_currentValueCount == 0)
+        {
+            // Should not throw, otherwise something is wrong.
+            // TODO: Get rid of the hard-coded values.
+            option->appendValue(_impl->_reverseBoolean ? "0" : "1");
+        }
+        else if (_impl->_reverseBoolean)
+        {
+            bBoolReverseValue = true;
+        }
+    }
+    _impl->_currentOption = NULL;
+    _impl->_reverseBoolean = false;
+    option->finishSet();
+    if (bBoolReverseValue)
+    {
+        GMX_THROW(InvalidInputError("Cannot specify a value together with 'no' prefix"));
+    }
+}
+
+void OptionsAssigner::finishSubSection()
+{
+    // Should only be called if we are in a subsection.
+    GMX_RELEASE_ASSERT(_impl->inSubSection(), "startSubSection() not called");
+    _impl->_sectionStack.pop_back();
+}
+
+void OptionsAssigner::finish()
+{
+    GMX_RELEASE_ASSERT(_impl->_currentOption == NULL, "finishOption() not called");
+    if (_impl->hasFlag(Impl::efNoStrictSectioning))
+    {
+        while (_impl->inSubSection())
+        {
+            finishSubSection();
+        }
+    }
+    GMX_RELEASE_ASSERT(!_impl->inSubSection(), "finishSubSection() not called");
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/optionsassigner.h b/src/gromacs/options/optionsassigner.h
new file mode 100644 (file)
index 0000000..de6c557
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::OptionsAssigner.
+ *
+ * This header is only needed when implementing option parsers.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONSASSIGNER_H
+#define GMX_OPTIONS_OPTIONSASSIGNER_H
+
+#include <string>
+
+namespace gmx
+{
+
+class Options;
+
+/*! \libinternal \brief
+ * Decorator class for assigning values to Options.
+ *
+ * This class extends the interface of an Options object by providing methods
+ * to set values for options.  It also keeps track of necessary state variables
+ * to assign values to options in subsections within the Options object.
+ * Typical use (without error handling):
+ * \code
+gmx::options::Options options("name", "Title");
+// Set up options
+
+gmx::options::OptionsAssigner assigner(&options);
+assigner.start();
+assigner.startOption("opt1");
+assigner.appendValue("3");
+assigner.finishOption();
+assigner.startSubSection("section");
+assigner.startOption("opt2"); // Now in the subsection
+assigner.appendValue("yes");
+assigner.finishOption();
+assigner.finishSubSection()
+assigner.startOption("opt3"); // Again in the main options
+assigner.appendValue("2");
+assigner.finishOption();
+assigner.finish();
+ * \endcode
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+class OptionsAssigner
+{
+    public:
+        /*! \brief
+         * Creates an object that assigns to the given object.
+         */
+        OptionsAssigner(Options *options);
+        ~OptionsAssigner();
+
+        /*! \brief
+         * Sets the assigner to recognize boolean options with a "no" prefix.
+         *
+         * With this option set, \c startOption("noname") is interpreted as
+         * \c startOption("name") followed by \c appendValue("no"), if there is
+         * no option by the name "noname", but there is a boolean option with
+         * name "name".
+         *
+         * By default, the prefix is not recognized.
+         *
+         * Can be set or cleared at any time, and will have effect on all
+         * subsequent calls of startOption().
+         *
+         * Does not throw.
+         */
+        void setAcceptBooleanNoPrefix(bool enabled);
+        /*! \brief
+         * Sets the assigner to find options in non-active sections.
+         *
+         * By default, options are only looked for in the currently active
+         * subsection.  With this option set, if no matching option is found in
+         * the current section, a breadth-first search is performed, first on
+         * all subsections of the current section, and then going up one level
+         * at a time.  The first matching option is used, and the current
+         * section is changed to the section that contains the matching option.
+         *
+         * Can be set or cleared at any time, and will have effect on all
+         * subsequent calls of startOption().
+         *
+         * Does not throw.
+         */
+        void setNoStrictSectioning(bool enabled);
+
+        /*! \brief
+         * Start assigning values.
+         *
+         * Does not throw.
+         */
+        void start();
+        /*! \brief
+         * Start assigning values to options in a subsection.
+         *
+         * \param[in] name  Name of the subsection to start assigning to.
+         * \throws InvalidInputError if such a subsection is not found.
+         *
+         * Strong exception safety guarantee.
+         */
+        void startSubSection(const char *name);
+        /*! \brief
+         * Start assigning values for an option.
+         *
+         * \param[in] name  Name of the option to start assigning to.
+         * \throws InvalidInputError if such an option is not found, or if the
+         *      option is specified more than once but doesn't support it.
+         *
+         * Strong exception safety guarantee.
+         */
+        void startOption(const char *name);
+        /*! \brief
+         * Appends a value to the value list of the current option.
+         *
+         * \param[in] value  String representation of the value to assign.
+         * \throws InvalidInputError if the value cannot be converted or if
+         *      there are too many values for an option.
+         *
+         * Basic exception safety guarantee:
+         * If this method throws, erroneous values are ignored, but it is
+         * possible to continue assigning values to the same option.  However,
+         * if \p value would result in more than one value, and some of them
+         * can be converted, but some result in errors, it is currently
+         * possible that some values have been added to the option even if an
+         * exception is thrown.
+         *
+         * Strong exception safety guarantee if the option provides value
+         * conversion with the same guarantee.  All options where a single
+         * input value always results in a single output value provide this.
+         *
+         * \internal
+         * This method provides the same exception safety guarantee as the
+         * OptionStorageTemplate::convertValue() method of the storage class
+         * implementing the option where the value is assigned to.
+         */
+        void appendValue(const std::string &value);
+        /*! \brief
+         * Finish assigning values for the current option.
+         *
+         * \throws InvalidInputError if the set of values since startOption()
+         *      is not valid.
+         *
+         * If this method throws, it returns to the state where the option was
+         * before startOption(), i.e., all values added with appendValue()
+         * since the last startOption() are discarded.
+         *
+         * Independent of whether the method throws, the option opened with
+         * startOption() will be closed after the call.
+         */
+        void finishOption();
+        /*! \brief
+         * Finish assigning values to a subsection.
+         *
+         * Does not throw.
+         */
+        void finishSubSection();
+        /*! \brief
+         * Finish assigning options through the object.
+         *
+         * Does not throw.
+         */
+        void finish();
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        OptionsAssigner(const OptionsAssigner &);
+        void operator =(const OptionsAssigner &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionstoragetemplate.h b/src/gromacs/options/optionstoragetemplate.h
new file mode 100644 (file)
index 0000000..e0f6f63
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Defines gmx::OptionStorageTemplate template.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONSTORAGETEMPLATE_H
+#define GMX_OPTIONS_OPTIONSTORAGETEMPLATE_H
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "../fatalerror/exceptions.h"
+#include "../fatalerror/gmxassert.h"
+
+#include "abstractoption.h"
+#include "abstractoptionstorage.h"
+
+namespace gmx
+{
+
+class Options;
+
+/*! \libinternal \brief
+ * Templated base class for constructing option value storage classes.
+ *
+ * \tparam T Assignable type that stores a single option value.
+ *
+ * Provides an implementation of the clearSet(), valueCount(), and processSet()
+ * methods of AbstractOptionStorage, as well as a basic no-action
+ * implementation of processAll().  Two new virtual methods are added:
+ * processSetValues() and refreshValues().  The default implementation of
+ * processSetValues() does nothing, and refreshValues() is used to update
+ * secondary storage after values have been added/changed.
+ * This leaves typeString(), formatValue(), and convertValue() to be
+ * implemented in derived classes.  processSetValues() and processAll() can
+ * also be implemented if necessary.
+ *
+ * Implements transaction support for adding values within a set: all calls to
+ * addValue() add the value to a temporary storage, processSetValues() operates
+ * on this temporary storage, and commitValues() then copies these values to
+ * the real storage.  commitValues() provides a strong exception safety
+ * guarantee for the process (and it only throws if it runs out of memory).
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+template <typename T>
+class OptionStorageTemplate : public AbstractOptionStorage
+{
+    public:
+        //! Alias for the template class for use in base classes.
+        typedef OptionStorageTemplate<T> MyBase;
+        //! Type of the container that contains the current values.
+        typedef std::vector<T> ValueList;
+
+        virtual ~OptionStorageTemplate();
+
+        // No implementation in this class for the pure virtual methods, but
+        // the declarations are still included for clarity.
+        virtual const char *typeString() const = 0;
+        virtual int valueCount() const { return _values->size(); }
+        virtual std::string formatValue(int i) const = 0;
+
+    protected:
+        /*! \brief
+         * Initializes the storage from option settings.
+         *
+         * \param[in] settings  Option settings.
+         * \param[in] options   Option collection that will contain the
+         *     option.
+         * \param[in] staticFlags Option flags that are always set and specify
+         *      generic behavior of the option.
+         * \throws  APIError if invalid settings have been provided.
+         */
+        template <class U>
+        OptionStorageTemplate(const OptionTemplate<T, U> &settings, Options *options,
+                              OptionFlags staticFlags = OptionFlags());
+
+
+        virtual void clearSet();
+        /*! \copydoc AbstractOptionStorage::convertValue()
+         *
+         * Derived classes should call addValue() after they have converted
+         * \p value to the storage type.  It is allowed to call addValue()
+         * more than once, or not at all.  OptionsAssigner::appendValue()
+         * provides the same exception safety guarantee as this method, so it
+         * should be considered whether the implementation can be made strongly
+         * exception safe.
+         */
+        virtual void convertValue(const std::string &value) = 0;
+        /*! \brief
+         * Processes values for a set after all have been converted.
+         *
+         * \param[in,out] values Valid values in the set.
+         * \throws InvalidInputError if the values do not form a valid set.
+         *
+         * This method is called after all convertValue() calls for a set.
+         * \p values contains all values that were validly converted by
+         * convertValue().  The derived class may alter the values, but should
+         * in such a case ensure that a correct number of values is produced.
+         * If the derived class throws, all values in \p values are discarded.
+         */
+        virtual void processSetValues(ValueList *values)
+        {
+        }
+        /*! \copydoc AbstractOptionStorage::processSet()
+         *
+         * OptionStorage template implements transaction support for a set of
+         * values in this method (see the class description), and provides a
+         * more detailed processSetValues() method that can be overridden in
+         * subclasses to process the actual values.  Derived classes should
+         * override that method instead of this one if set value processing is
+         * necessary.
+         */
+        virtual void processSet();
+        /*! \copydoc AbstractOptionStorage::processAll()
+         *
+         * The implementation in OptionStorageTemplate does nothing.
+         */
+        virtual void processAll()
+        {
+        }
+
+        /*! \brief
+         * Removes all values from the storage.
+         *
+         * Does not throw.
+         */
+        void clear() { _values->clear(); }
+        /*! \brief
+         * Adds a value to a temporary storage.
+         *
+         * \param[in] value  Value to add. A copy is made.
+         * \throws InvalidInputError if the maximum value count has been reached.
+         *
+         * Derived classes should call this function from the convertValue()
+         * implementation to add converted values to the storage.
+         * If the maximum value cont has been reached, the value is discarded
+         * and an exception is thrown.
+         *
+         * If adding values outside convertValue() (e.g., to set a custom
+         * default value), derived classes should call clearSet() before adding
+         * values (unless in the constructor) and commitValues() once all
+         * values are added.
+         */
+        void addValue(const T &value);
+        /*! \brief
+         * Commits values added with addValue().
+         *
+         * If this function succeeds, values added with addValue() since the
+         * previous clearSet() are added to the storage for the option.
+         * Only throws in out-of-memory conditions, and provides the strong
+         * exception safety guarantee.
+         *
+         * See addValue() for cases where this method should be used in derived
+         * classes.
+         *
+         * Calls refreshValues() and clearSet() if it is successful.
+         */
+        void commitValues();
+        /*! \brief
+         * Updates alternative store locations.
+         *
+         * Derived classes should override this method if they implement
+         * alternative store locations, and copy/translate values from the
+         * values() vector to these alternative storages.  They should also
+         * call the base class implementation as part of their implementation.
+         *
+         * Should be called in derived classes if values are modified directly
+         * through the values() method, e.g., in processAll().  Does not need
+         * to be called if commitValues() is used.
+         *
+         * Does not throw, and derived classes should not change that.
+         */
+        virtual void refreshValues();
+
+        /*! \brief
+         * Provides derived classes access to the current list of values.
+         *
+         * The non-const variant should only be used from processAll() in
+         * derived classes if necessary, and refreshValues() should be called
+         * if any changes are made.
+         */
+        ValueList &values() { return *_values; }
+        //! Provides derived classes access to the current list of values.
+        const ValueList &values() const { return *_values; }
+
+    private:
+        /*! \brief
+         * Vector for temporary storage of values before commitSet() is called.
+         */
+        ValueList               _setValues;
+        /*! \brief
+         * Vector for primary storage of option values.
+         *
+         * Is never NULL; points either to externally provided vector, or an
+         * internally allocated one.  The allocation is performed by the
+         * constructor.
+         *
+         * Primarily, modifications to values are done only to this storage,
+         * and other storage locations are updated only when refreshValues() is
+         * called.
+         */
+        ValueList              *_values;
+        T                      *_store;
+        int                    *_countptr;
+        // Could be scoped_ptr
+        std::auto_ptr<T>        _defaultValueIfSet;
+
+        // Copy and assign disallowed by base.
+};
+
+
+template <typename T>
+template <class U>
+OptionStorageTemplate<T>::OptionStorageTemplate(const OptionTemplate<T, U> &settings,
+                                                Options *options,
+                                                OptionFlags staticFlags)
+    : AbstractOptionStorage(settings, options, staticFlags),
+      _values(settings._storeVector),
+      _store(settings._store),
+      _countptr(settings._countptr)
+{
+    std::auto_ptr<std::vector<T> > valueGuard;
+    if (!_values)
+    {
+        // The flag should be set for proper error checking.
+        GMX_RELEASE_ASSERT(!hasFlag(efExternalValueVector),
+                           "Internal inconsistency");
+        valueGuard.reset(new std::vector<T>);
+        _values = valueGuard.get();
+    }
+    if (hasFlag(efNoDefaultValue)
+        && (settings._defaultValue != NULL
+            || settings._defaultValueIfSet != NULL))
+    {
+        GMX_THROW(APIError("Option does not support default value, but one is set"));
+    }
+    if (_store != NULL && _countptr == NULL && !hasFlag(efVector)
+        && minValueCount() != maxValueCount())
+    {
+        GMX_THROW(APIError("Count storage is not set, although the number of produced values is not known"));
+    }
+    if (!hasFlag(efNoDefaultValue))
+    {
+        if (settings._defaultValue != NULL)
+        {
+            _values->clear();
+            addValue(*settings._defaultValue);
+            setFlag(efHasDefaultValue);
+            // TODO: This is a bit hairy, as it indirectly calls a virtual function.
+            commitValues();
+        }
+        else if (!hasFlag(efExternalValueVector) && _store != NULL)
+        {
+            _values->clear();
+            int count = (settings.isVector() ?
+                            settings._maxValueCount : settings._minValueCount);
+            for (int i = 0; i < count; ++i)
+            {
+                _values->push_back(_store[i]);
+            }
+            setFlag(efHasDefaultValue);
+        }
+        if (settings._defaultValueIfSet != NULL)
+        {
+            _defaultValueIfSet.reset(new T(*settings._defaultValueIfSet));
+        }
+    }
+    valueGuard.release();
+}
+
+
+template <typename T>
+OptionStorageTemplate<T>::~OptionStorageTemplate()
+{
+    if (!hasFlag(efExternalValueVector))
+    {
+        delete _values;
+    }
+}
+
+
+template <typename T>
+void OptionStorageTemplate<T>::clearSet()
+{
+    _setValues.clear();
+}
+
+
+template <typename T>
+void OptionStorageTemplate<T>::processSet()
+{
+    processSetValues(&_setValues);
+    if (_setValues.empty() && _defaultValueIfSet.get() != NULL)
+    {
+        addValue(*_defaultValueIfSet);
+    }
+    if (!hasFlag(efDontCheckMinimumCount)
+        && _setValues.size() < static_cast<size_t>(minValueCount()))
+    {
+        clearSet();
+        GMX_THROW(InvalidInputError("Too few (valid) values"));
+    }
+    commitValues();
+}
+
+
+template <typename T>
+void OptionStorageTemplate<T>::addValue(const T &value)
+{
+    if (maxValueCount() >= 0
+        && _setValues.size() >= static_cast<size_t>(maxValueCount()))
+    {
+        GMX_THROW(InvalidInputError("Too many values"));
+    }
+    _setValues.push_back(value);
+}
+
+
+template <typename T>
+void OptionStorageTemplate<T>::commitValues()
+{
+    if (hasFlag(efHasDefaultValue))
+    {
+        _values->swap(_setValues);
+        clearFlag(efHasDefaultValue);
+    }
+    else
+    {
+        _values->insert(_values->end(), _setValues.begin(), _setValues.end());
+    }
+    clearSet();
+    refreshValues();
+}
+
+
+template <typename T>
+void OptionStorageTemplate<T>::refreshValues()
+{
+    if (_countptr != NULL)
+    {
+        *_countptr = _values->size();
+    }
+    if (_store != NULL)
+    {
+        for (size_t i = 0; i < _values->size(); ++i)
+        {
+            _store[i] = (*_values)[i];
+        }
+    }
+}
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/optionsvisitor.cpp b/src/gromacs/options/optionsvisitor.cpp
new file mode 100644 (file)
index 0000000..fbf1f75
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in optionsvisitor.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include "gromacs/options/optionsvisitor.h"
+
+#include "gromacs/options/abstractoptionstorage.h"
+#include "gromacs/options/options.h"
+
+#include "options-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * OptionInfo
+ */
+
+OptionInfo::OptionInfo(const AbstractOptionStorage &option)
+    : _option(option)
+{
+}
+
+bool OptionInfo::isBoolean() const
+{
+    return _option.isBoolean();
+}
+
+bool OptionInfo::isFile() const
+{
+    return _option.isFile();
+}
+
+bool OptionInfo::isHidden() const
+{
+    return _option.isHidden();
+}
+
+const std::string &OptionInfo::name() const
+{
+    return _option.name();
+}
+
+const std::string &OptionInfo::description() const
+{
+    return _option.description();
+}
+
+const char *OptionInfo::type() const
+{
+    return _option.typeString();
+}
+
+int OptionInfo::valueCount() const
+{
+    return _option.valueCount();
+}
+
+std::string OptionInfo::formatValue(int i) const
+{
+    return _option.formatValue(i);
+}
+
+std::string OptionInfo::formatValues() const
+{
+    std::string result;
+    int count = valueCount();
+    for (int i = 0; i < count; ++i)
+    {
+        if (i != 0)
+        {
+            result.append(" ");
+        }
+        result.append(formatValue(i));
+    }
+    return result;
+}
+
+/********************************************************************
+ * OptionsIterator
+ */
+
+OptionsIterator::OptionsIterator(const Options &options)
+    : _options(options)
+{
+}
+
+void OptionsIterator::acceptSubSections(OptionsVisitor *visitor) const
+{
+    const Options::Impl::SubSectionList &subSectionList =
+        _options._impl->_subSections;
+    Options::Impl::SubSectionList::const_iterator i;
+    for (i = subSectionList.begin(); i != subSectionList.end(); ++i)
+    {
+        visitor->visitSubSection(*(*i));
+    }
+}
+
+void OptionsIterator::acceptOptions(OptionsVisitor *visitor) const
+{
+    const Options::Impl::OptionList &optionList =
+        _options._impl->_options;
+    Options::Impl::OptionList::const_iterator i;
+    for (i = optionList.begin(); i != optionList.end(); ++i)
+    {
+        visitor->visitOption(OptionInfo(*(*i)));
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/options/optionsvisitor.h b/src/gromacs/options/optionsvisitor.h
new file mode 100644 (file)
index 0000000..1c1349e
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::OptionsVisitor interface and supporting classes.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+#ifndef GMX_OPTIONS_OPTIONSVISITOR_H
+#define GMX_OPTIONS_OPTIONSVISITOR_H
+
+#include <string>
+
+namespace gmx
+{
+
+class AbstractOptionStorage;
+class Options;
+
+/*! \libinternal \brief
+ * Wrapper class for accessing option information.
+ *
+ * This class isolates the details of the internal option implementation
+ * from option visitors.
+ *
+ * \see OptionsVisitor
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+class OptionInfo
+{
+    public:
+        /*! \brief
+         * Wraps a given option object.
+         */
+        OptionInfo(const AbstractOptionStorage &option);
+
+        //! Returns true if the option is a boolean option.
+        bool isBoolean() const;
+        //! Returns true if the option is a file name option.
+        bool isFile() const;
+        //! Returns true if the option is a hidden option.
+        bool isHidden() const;
+        //! Returns the name of the option.
+        const std::string &name() const;
+        //! Returns the description of the option.
+        const std::string &description() const;
+        //! Returns the type of the option as a string.
+        const char *type() const;
+        //! Returns the number of values given for the option.
+        int valueCount() const;
+        //! Returns the i'th value of the option as a string.
+        std::string formatValue(int i) const;
+        //! Returns all the values of the option as a single string.
+        std::string formatValues() const;
+
+    private:
+        //! The wrapped option.
+        const AbstractOptionStorage &_option;
+
+        // Disallow copy and assign.
+        OptionInfo(const OptionInfo &);
+        void operator =(const OptionInfo &);
+
+        // This is a workaround for a buggy gcc 4.2, which seems to 
+        // require access to all constructors: 
+        friend class OptionsIterator;
+};
+
+/*! \libinternal \brief
+ * Pure interface for visiting options in a Options object.
+ *
+ * \see OptionsIterator
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+class OptionsVisitor
+{
+    public:
+        virtual ~OptionsVisitor() {}
+
+        /*! \brief
+         * Called for each subsection in Options.
+         */
+        virtual void visitSubSection(const Options &section) = 0;
+        /*! \brief
+         * Called for each option in Options.
+         */
+        virtual void visitOption(const OptionInfo &option) = 0;
+};
+
+/*! \libinternal \brief
+ * Decorator class for visiting options in a Options object.
+ *
+ * This class provides an interface for looping through subsections and
+ * options in a Options object.
+ *
+ * Typical use (loop over all options, iteratively descending into
+ * subsections):
+ * \code
+class Visitor : public gmx::options::OptionsVisitor
+{
+    public:
+        void visitSubSection(const Options &section)
+        {
+            OptionsIterator iterator(section);
+            iterator.acceptSubSections(this);
+            iterator.acceptOptions(this);
+        }
+
+        void visitOption(const OptionInfo &option)
+        {
+            // Do something.
+        }
+}
+
+Visitor().visitSubSection(options);
+ * \endcode
+ *
+ * \inlibraryapi
+ * \ingroup module_options
+ */
+class OptionsIterator
+{
+    public:
+        /*! \brief
+         * Creates an object for visiting options in a Options object.
+         */
+        OptionsIterator(const Options &options);
+
+        /*! \brief
+         * Visits each subsection in the wrapped Options object.
+         */
+        void acceptSubSections(OptionsVisitor *visitor) const;
+        /*! \brief
+         * Visits each option in the wrapped Options object.
+         */
+        void acceptOptions(OptionsVisitor *visitor) const;
+
+    private:
+        //! The wrapped Options object.
+        const Options          &_options;
+
+        // Disallow copy and assign.
+        OptionsIterator(const OptionsIterator &);
+        void operator =(const OptionsIterator &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/options/tests/.gitignore b/src/gromacs/options/tests/.gitignore
new file mode 100644 (file)
index 0000000..0672786
--- /dev/null
@@ -0,0 +1 @@
+options-test
diff --git a/src/gromacs/options/tests/CMakeLists.txt b/src/gromacs/options/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7c3f3df
--- /dev/null
@@ -0,0 +1,3 @@
+add_gtest_or_gmock_test(OptionsUnitTests options-test
+                        cmdlineparser.cpp option.cpp optionsassigner.cpp
+                        GMOCK_ONLY abstractoptionstorage.cpp)
diff --git a/src/gromacs/options/tests/abstractoptionstorage.cpp b/src/gromacs/options/tests/abstractoptionstorage.cpp
new file mode 100644 (file)
index 0000000..4eb48f9
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests proper handling of option storage.
+ *
+ * These tests check that methods in storage objects are called properly in all
+ * situations, and also that the OptionStorageTemplate class behaves properly.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include <vector>
+#include <string>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/abstractoption.h"
+#include "gromacs/options/options.h"
+#include "gromacs/options/optionstoragetemplate.h"
+#include "gromacs/options/optionsassigner.h"
+
+class MockOption;
+
+/*! \internal \brief
+ * Mock implementation of an option storage class for unit testing.
+ *
+ * Provides facilities for checking that correct methods are called, and for
+ * controlling how they add values using the base class methods.
+ *
+ * \ingroup module_options
+ */
+class MockOptionStorage : public gmx::OptionStorageTemplate<std::string>
+{
+    public:
+        /*! \brief
+         * Initializes the storage from option settings.
+         *
+         * \param[in] settings   Storage settings.
+         * \param[in] options    Options object.
+         */
+        MockOptionStorage(const MockOption &settings, gmx::Options *options);
+
+        /*! \brief
+         * Calls addValue("dummy") in the base class.
+         */
+        void addDummyValue()
+        {
+            addValue("dummy");
+        }
+        /*! \brief
+         * Calls setFlag(efSet).
+         */
+        void setOption()
+        {
+            setFlag(gmx::efSet);
+        }
+        using MyBase::addValue;
+        using MyBase::commitValues;
+
+        virtual const char *typeString() const { return "mock"; }
+        virtual std::string formatValue(int /*i*/) const { return ""; }
+
+        MOCK_METHOD1(convertValue, void(const std::string &value));
+        MOCK_METHOD1(processSetValues, void(ValueList *values));
+        MOCK_METHOD0(processAll, void());
+};
+
+/*! \internal \brief
+ * Specifies an option that has a mock storage object for unit testing.
+ *
+ * \ingroup module_options
+ */
+class MockOption : public gmx::OptionTemplate<std::string, MockOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit MockOption(const char *name)
+            : MyBase(name), _storagePtr(NULL)
+        {
+        }
+
+        //! Sets an output pointer to give access to the created storage object.
+        MyClass &storageObject(MockOptionStorage **storagePtr)
+        { _storagePtr = storagePtr; return me(); }
+
+    private:
+        virtual gmx::AbstractOptionStorage *createDefaultStorage(gmx::Options *options) const
+        {
+            MockOptionStorage *storage = new MockOptionStorage(*this, options);
+            if (_storagePtr != NULL)
+            {
+                *_storagePtr = storage;
+            }
+            return storage;
+        }
+
+        MockOptionStorage     **_storagePtr;
+};
+
+MockOptionStorage::MockOptionStorage(const MockOption &settings, gmx::Options *options)
+    : MyBase(settings, options)
+{
+    using ::testing::_;
+    using ::testing::Invoke;
+    using ::testing::WithArg;
+    ON_CALL(*this, convertValue(_))
+        .WillByDefault(WithArg<0>(Invoke(this, &MockOptionStorage::addValue)));
+}
+
+namespace
+{
+
+/*
+ * Tests that finish() can set a required option even if the user has not
+ * provided it.
+ */
+TEST(AbstractOptionStorageTest, HandlesSetInFinish)
+{
+    gmx::Options                options(NULL, NULL);
+    std::vector<std::string>    values;
+    MockOptionStorage          *mock;
+    ASSERT_NO_THROW(options.addOption(
+                        MockOption("name").storageObject(&mock).required()
+                            .storeVector(&values)));
+
+    {
+        ::testing::InSequence dummy;
+        using ::testing::DoAll;
+        using ::testing::InvokeWithoutArgs;
+        EXPECT_CALL(*mock, processAll())
+            .WillOnce(DoAll(InvokeWithoutArgs(mock, &MockOptionStorage::setOption),
+                            InvokeWithoutArgs(mock, &MockOptionStorage::addDummyValue),
+                            InvokeWithoutArgs(mock, &MockOptionStorage::commitValues)));
+    }
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    ASSERT_EQ(1U, values.size());
+    EXPECT_EQ("dummy", values[0]);
+}
+
+/*
+ * Tests that storage works if the storage object does not add a value in a
+ * call to appendValue().
+ */
+TEST(AbstractOptionStorageTest, HandlesValueRemoval)
+{
+    gmx::Options                options(NULL, NULL);
+    std::vector<std::string>    values;
+    MockOptionStorage          *mock;
+    ASSERT_NO_THROW(options.addOption(
+                        MockOption("name").storageObject(&mock)
+                            .storeVector(&values).multiValue()));
+
+    {
+        ::testing::InSequence dummy;
+        using ::testing::ElementsAre;
+        using ::testing::Pointee;
+        using ::testing::Return;
+        EXPECT_CALL(*mock, convertValue("a"));
+        EXPECT_CALL(*mock, convertValue("b"))
+            .WillOnce(Return());
+        EXPECT_CALL(*mock, convertValue("c"));
+        EXPECT_CALL(*mock, processSetValues(Pointee(ElementsAre("a", "c"))));
+        EXPECT_CALL(*mock, processAll());
+    }
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("name"));
+    EXPECT_NO_THROW(assigner.appendValue("a"));
+    EXPECT_NO_THROW(assigner.appendValue("b"));
+    EXPECT_NO_THROW(assigner.appendValue("c"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    ASSERT_EQ(2U, values.size());
+    EXPECT_EQ("a", values[0]);
+    EXPECT_EQ("c", values[1]);
+}
+
+/*
+ * Tests that storage works if the storage object adds more than one value in
+ * one call to appendValue().
+ */
+TEST(AbstractOptionStorageTest, HandlesValueAddition)
+{
+    gmx::Options                options(NULL, NULL);
+    std::vector<std::string>    values;
+    MockOptionStorage          *mock;
+    ASSERT_NO_THROW(options.addOption(
+                        MockOption("name").storageObject(&mock)
+                            .storeVector(&values).multiValue()));
+
+    {
+        ::testing::InSequence dummy;
+        using ::testing::DoAll;
+        using ::testing::ElementsAre;
+        using ::testing::InvokeWithoutArgs;
+        using ::testing::Pointee;
+        EXPECT_CALL(*mock, convertValue("a"));
+        EXPECT_CALL(*mock, convertValue("b"))
+            .WillOnce(DoAll(InvokeWithoutArgs(mock, &MockOptionStorage::addDummyValue),
+                            InvokeWithoutArgs(mock, &MockOptionStorage::addDummyValue)));
+        EXPECT_CALL(*mock, processSetValues(Pointee(ElementsAre("a", "dummy", "dummy"))));
+        EXPECT_CALL(*mock, processAll());
+    }
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("name"));
+    EXPECT_NO_THROW(assigner.appendValue("a"));
+    EXPECT_NO_THROW(assigner.appendValue("b"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    ASSERT_EQ(3U, values.size());
+    EXPECT_EQ("a", values[0]);
+    EXPECT_EQ("dummy", values[1]);
+    EXPECT_EQ("dummy", values[2]);
+}
+
+/*
+ * Tests that storage works if the storage object adds more than one value in
+ * one call to appendValue(), and this results in too many values.
+ */
+TEST(AbstractOptionStorageTest, HandlesTooManyValueAddition)
+{
+    gmx::Options                options(NULL, NULL);
+    std::vector<std::string>    values;
+    MockOptionStorage          *mock;
+    ASSERT_NO_THROW(options.addOption(
+                        MockOption("name").storageObject(&mock)
+                            .storeVector(&values).valueCount(2)));
+
+    {
+        ::testing::InSequence dummy;
+        using ::testing::DoAll;
+        using ::testing::ElementsAre;
+        using ::testing::InvokeWithoutArgs;
+        using ::testing::Pointee;
+        EXPECT_CALL(*mock, convertValue("a"));
+        EXPECT_CALL(*mock, convertValue("b"))
+            .WillOnce(DoAll(InvokeWithoutArgs(mock, &MockOptionStorage::addDummyValue),
+                            InvokeWithoutArgs(mock, &MockOptionStorage::addDummyValue)));
+        EXPECT_CALL(*mock, processSetValues(Pointee(ElementsAre("a", "dummy"))));
+        EXPECT_CALL(*mock, processAll());
+    }
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("name"));
+    EXPECT_NO_THROW(assigner.appendValue("a"));
+    EXPECT_THROW(assigner.appendValue("b"), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    ASSERT_EQ(2U, values.size());
+    EXPECT_EQ("a", values[0]);
+    EXPECT_EQ("dummy", values[1]);
+}
+
+/*
+ * Tests that the storage object is properly invoked even if no output values
+ * should be produced.
+ */
+TEST(AbstractOptionStorageTest, AllowsEmptyValues)
+{
+    gmx::Options                options(NULL, NULL);
+    std::vector<std::string>    values;
+    MockOptionStorage          *mock;
+    ASSERT_NO_THROW(options.addOption(
+                        MockOption("name").storageObject(&mock)
+                            .storeVector(&values).valueCount(0)));
+
+    {
+        ::testing::InSequence dummy;
+        using ::testing::DoAll;
+        using ::testing::ElementsAre;
+        using ::testing::Pointee;
+        using ::testing::Return;
+        EXPECT_CALL(*mock, convertValue("a"))
+            .WillOnce(Return());
+        EXPECT_CALL(*mock, processSetValues(Pointee(ElementsAre())));
+        EXPECT_CALL(*mock, processAll());
+    }
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.startOption("name"));
+    EXPECT_NO_THROW(assigner.appendValue("a"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    ASSERT_EQ(0U, values.size());
+}
+
+} // namespace
diff --git a/src/gromacs/options/tests/cmdlineparser.cpp b/src/gromacs/options/tests/cmdlineparser.cpp
new file mode 100644 (file)
index 0000000..a2409eb
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests gmx::CommandLineParser.
+ *
+ * These tests exercise a large fraction of the code, so they may
+ * catch errors in other parts than just in command-line parsing.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/cmdlineparser.h"
+#include "gromacs/options/options.h"
+
+namespace
+{
+
+class CommandLineParserTest : public ::testing::Test
+{
+    public:
+        CommandLineParserTest();
+        ~CommandLineParserTest();
+
+        void createArguments(const char *cmdline[]);
+
+        gmx::Options            _options;
+        gmx::CommandLineParser  _parser;
+        bool                    _flag;
+        std::vector<int>        _ivalues;
+        std::vector<double>     _dvalues;
+        int                     _argc;
+        char                  **_argv;
+};
+
+CommandLineParserTest::CommandLineParserTest()
+    : _options(NULL, NULL), _parser(&_options),
+      _flag(false),
+      _argc(0), _argv(NULL)
+{
+    using gmx::BooleanOption;
+    using gmx::IntegerOption;
+    using gmx::DoubleOption;
+    _options.addOption(BooleanOption("flag").store(&_flag));
+    _options.addOption(IntegerOption("mvi").storeVector(&_ivalues).multiValue());
+    _options.addOption(DoubleOption("mvd").storeVector(&_dvalues).allowMultiple());
+}
+
+CommandLineParserTest::~CommandLineParserTest()
+{
+    if (_argv != NULL)
+    {
+        for (int i = 0; i < _argc; ++i)
+        {
+            free(_argv[i]);
+        }
+    }
+    delete [] _argv;
+}
+
+void CommandLineParserTest::createArguments(const char *cmdline[])
+{
+    _argc = 0;
+    while (cmdline[_argc] != NULL) ++_argc;
+    ++_argc;
+
+    _argv = new char *[_argc];
+    _argv[0] = strdup("test");
+    for (int i = 1; i < _argc; ++i)
+    {
+        _argv[i] = strdup(cmdline[i - 1]);
+    }
+}
+
+TEST_F(CommandLineParserTest, HandlesSingleValues)
+{
+    const char *cmdline[] = {"-flag", "yes", "-mvi", "2", "-mvd", "2.7", NULL};
+    createArguments(cmdline);
+    ASSERT_NO_THROW(_parser.parse(&_argc, _argv));
+    ASSERT_NO_THROW(_options.finish());
+
+    EXPECT_TRUE(_flag);
+    ASSERT_EQ(1U, _ivalues.size());
+    EXPECT_EQ(2, _ivalues[0]);
+    ASSERT_EQ(1U, _dvalues.size());
+    EXPECT_DOUBLE_EQ(2.7, _dvalues[0]);
+}
+
+} // namespace
diff --git a/src/gromacs/options/tests/option.cpp b/src/gromacs/options/tests/option.cpp
new file mode 100644 (file)
index 0000000..b3e2cfa
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests creation of basic option types.
+ *
+ * Most of the tests for the basic options are in optionsassigner.cpp.
+ * This file only tests behavior that should fail in initialization.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include <vector>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+
+namespace
+{
+
+TEST(OptionsTest, FailsOnNonsafeStorage)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_THROW(options.addOption(IntegerOption("name").store(&value)
+                                       .multiValue()),
+                 gmx::APIError);
+}
+
+TEST(OptionsTest, FailsOnIncorrectEnumDefaultValue)
+{
+    gmx::Options options(NULL, NULL);
+    std::string                 value;
+    const char * const          allowed[] = { "none", "test", "value", NULL };
+    using gmx::StringOption;
+    ASSERT_THROW(options.addOption(StringOption("name").store(&value)
+                                       .enumValue(allowed)
+                                       .defaultValue("unknown")),
+                 gmx::APIError);
+}
+
+} // namespace
diff --git a/src/gromacs/options/tests/optionsassigner.cpp b/src/gromacs/options/tests/optionsassigner.cpp
new file mode 100644 (file)
index 0000000..c5afbec
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests option assignment.
+ *
+ * In addition to testing gmx::OptionsAssigner, these are the main
+ * tests for the classes from basicoptions.h and basicoptionstorage.h (and
+ * their base classes) that actually implement the behavior, as well as for the
+ * internal implementation of the gmx::Options and gmx::AbstractOptionStorage
+ * classes.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_options
+ */
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+#include "gromacs/options/optionsassigner.h"
+
+namespace
+{
+
+TEST(OptionsAssignerTest, HandlesMissingRequiredParameter)
+{
+    gmx::Options options(NULL, NULL);
+    int value = 0;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").store(&value).required()));
+
+    EXPECT_THROW(options.finish(), gmx::InvalidInputError);
+}
+
+TEST(OptionsAssignerTest, HandlesInvalidMultipleParameter)
+{
+    gmx::Options options(NULL, NULL);
+    std::vector<int> values;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").storeVector(&values).multiValue()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("1"));
+    ASSERT_NO_THROW(assigner.finishOption());
+    EXPECT_THROW(assigner.startOption("p"), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_TRUE(options.isSet("p"));
+    ASSERT_EQ(1U, values.size());
+    EXPECT_EQ(1, values[0]);
+}
+
+TEST(OptionsAssignerTest, HandlesMultipleParameter)
+{
+    gmx::Options options(NULL, NULL);
+    std::vector<int> values;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").storeVector(&values).allowMultiple()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("1"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("2"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_TRUE(options.isSet("p"));
+    ASSERT_EQ(2U, values.size());
+    EXPECT_EQ(1, values[0]);
+    EXPECT_EQ(2, values[1]);
+}
+
+TEST(OptionsAssignerTest, HandlesMissingValue)
+{
+    gmx::Options options(NULL, NULL);
+    int value1 = 0, value2 = 0;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value1)));
+    ASSERT_NO_THROW(options.addOption(IntegerOption("q").store(&value2)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
+    ASSERT_NO_THROW(assigner.startOption("q"));
+    ASSERT_NO_THROW(assigner.appendValue("2"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value2);
+}
+
+TEST(OptionsAssignerTest, HandlesExtraValue)
+{
+    gmx::Options options(NULL, NULL);
+    int value1 = 0;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value1)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("2"));
+    EXPECT_THROW(assigner.appendValue("3"), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value1);
+}
+
+TEST(OptionsAssignerTest, HandlesSubSections)
+{
+    gmx::Options options(NULL, NULL);
+    gmx::Options sub1("section1", NULL);
+    gmx::Options sub2("section2", NULL);
+    int value = 3;
+    int value1 = 1;
+    int value2 = 2;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
+    ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&value1)));
+    ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&value2)));
+    ASSERT_NO_THROW(options.addSubSection(&sub1));
+    ASSERT_NO_THROW(options.addSubSection(&sub2));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startSubSection("section1"));
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("5"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finishSubSection());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("4"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    ASSERT_NO_THROW(assigner.startSubSection("section2"));
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("6"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finishSubSection());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(4, value);
+    EXPECT_EQ(5, value1);
+    EXPECT_EQ(6, value2);
+}
+
+TEST(OptionsAssignerTest, HandlesNoStrictSubSections)
+{
+    gmx::Options options(NULL, NULL);
+    gmx::Options sub1("section1", NULL);
+    gmx::Options sub2("section2", NULL);
+    int pvalue = 3;
+    int pvalue1 = 1;
+    int qvalue  = 4;
+    int pvalue2 = 2;
+    int rvalue  = 5;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&pvalue)));
+    ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&pvalue1)));
+    ASSERT_NO_THROW(sub1.addOption(IntegerOption("q").store(&qvalue)));
+    ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&pvalue2)));
+    ASSERT_NO_THROW(sub2.addOption(IntegerOption("r").store(&rvalue)));
+    ASSERT_NO_THROW(options.addSubSection(&sub1));
+    ASSERT_NO_THROW(options.addSubSection(&sub2));
+
+    gmx::OptionsAssigner assigner(&options);
+    assigner.setNoStrictSectioning(true);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("q"));
+    EXPECT_NO_THROW(assigner.appendValue("6"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("7"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    ASSERT_NO_THROW(assigner.startOption("r"));
+    EXPECT_NO_THROW(assigner.appendValue("8"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("9"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finishSubSection());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("10"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(6, qvalue);
+    EXPECT_EQ(7, pvalue1);
+    EXPECT_EQ(8, rvalue);
+    EXPECT_EQ(9, pvalue2);
+    EXPECT_EQ(10, pvalue);
+}
+
+TEST(OptionsAssignerTest, HandlesMultipleSources)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
+
+    {
+        gmx::OptionsAssigner assigner(&options);
+        EXPECT_NO_THROW(assigner.start());
+        ASSERT_NO_THROW(assigner.startOption("p"));
+        EXPECT_NO_THROW(assigner.appendValue("1"));
+        EXPECT_NO_THROW(assigner.finishOption());
+        EXPECT_NO_THROW(assigner.finish());
+    }
+    {
+        gmx::OptionsAssigner assigner2(&options);
+        EXPECT_NO_THROW(assigner2.start());
+        ASSERT_NO_THROW(assigner2.startOption("p"));
+        EXPECT_NO_THROW(assigner2.appendValue("2"));
+        EXPECT_NO_THROW(assigner2.finishOption());
+        EXPECT_NO_THROW(assigner2.finish());
+    }
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value);
+}
+
+
+TEST(OptionsAssignerBooleanTest, StoresYesValue)
+{
+    gmx::Options options(NULL, NULL);
+    bool  value = false;
+    using gmx::BooleanOption;
+    ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("yes"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_TRUE(value);
+}
+
+TEST(OptionsAssignerBooleanTest, SetsBooleanWithoutExplicitValue)
+{
+    gmx::Options options(NULL, NULL);
+    bool value = false;
+    using gmx::BooleanOption;
+    ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_TRUE(value);
+}
+
+TEST(OptionsAssignerBooleanTest, ClearsBooleanWithPrefixNo)
+{
+    gmx::Options options(NULL, NULL);
+    bool value = true;
+    using gmx::BooleanOption;
+    ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    assigner.setAcceptBooleanNoPrefix(true);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("nop"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_FALSE(value);
+}
+
+TEST(OptionsAssignerBooleanTest, HandlesBooleanWithPrefixAndValue)
+{
+    gmx::Options options(NULL, NULL);
+    bool value = false;
+    using gmx::BooleanOption;
+    ASSERT_NO_THROW(options.addOption(BooleanOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    assigner.setAcceptBooleanNoPrefix(true);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("nop"));
+    // It's OK to fail, but if it doesn't, it should work.
+    try
+    {
+        assigner.appendValue("no");
+        assigner.finishOption();
+        EXPECT_NO_THROW(assigner.finish());
+        EXPECT_TRUE(value);
+    }
+    catch (gmx::InvalidInputError &)
+    {
+    }
+}
+
+
+TEST(OptionsAssignerIntegerTest, StoresSingleValue)
+{
+    gmx::Options options(NULL, NULL);
+    int value = 1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("3"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(3, value);
+}
+
+TEST(OptionsAssignerIntegerTest, StoresDefaultValue)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").store(&value).defaultValue(2)));
+    EXPECT_EQ(2, value);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value);
+}
+
+TEST(OptionsAssignerIntegerTest, StoresDefaultValueIfSet)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").store(&value).defaultValueIfSet(2)));
+    EXPECT_EQ(-1, value);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesDefaultValueIfSetWhenNotSet)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").store(&value).defaultValueIfSet(2)));
+    EXPECT_EQ(-1, value);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(-1, value);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesBothDefaultValues)
+{
+    gmx::Options options(NULL, NULL);
+    int value = -1;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").store(&value)
+                            .defaultValue(1).defaultValueIfSet(2)));
+    EXPECT_EQ(1, value);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, value);
+}
+
+TEST(OptionsAssignerIntegerTest, StoresToVector)
+{
+    gmx::Options          options(NULL, NULL);
+    std::vector<int>      values;
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(
+                        IntegerOption("p").storeVector(&values).multiValue()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("-2"));
+    ASSERT_NO_THROW(assigner.appendValue("1"));
+    ASSERT_NO_THROW(assigner.appendValue("4"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(3U, values.size());
+    EXPECT_EQ(-2, values[0]);
+    EXPECT_EQ(1, values[1]);
+    EXPECT_EQ(4, values[2]);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesVectors)
+{
+    gmx::Options options(NULL, NULL);
+    int  vec[3] = {0, 0, 0};
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("-2"));
+    ASSERT_NO_THROW(assigner.appendValue("1"));
+    ASSERT_NO_THROW(assigner.appendValue("4"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(-2, vec[0]);
+    EXPECT_EQ(1, vec[1]);
+    EXPECT_EQ(4, vec[2]);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesVectorFromSingleValue)
+{
+    gmx::Options options(NULL, NULL);
+    int  vec[3] = {0, 0, 0};
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("2"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(2, vec[0]);
+    EXPECT_EQ(2, vec[1]);
+    EXPECT_EQ(2, vec[2]);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValue)
+{
+    gmx::Options options(NULL, NULL);
+    int  vec[3] = {3, 2, 1};
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec).vector()));
+
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(3, vec[0]);
+    EXPECT_EQ(2, vec[1]);
+    EXPECT_EQ(1, vec[2]);
+}
+
+TEST(OptionsAssignerIntegerTest, HandlesVectorsWithDefaultValueWithInvalidAssignment)
+{
+    gmx::Options options(NULL, NULL);
+    int  vec[3] = {3, 2, 1};
+    std::vector<int> vec2(vec, vec+3);
+    using gmx::IntegerOption;
+    ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(vec)
+                                          .storeVector(&vec2).vector()));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    EXPECT_NO_THROW(assigner.appendValue("1"));
+    EXPECT_NO_THROW(assigner.appendValue("3"));
+    EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ(3, vec[0]);
+    EXPECT_EQ(2, vec[1]);
+    EXPECT_EQ(1, vec[2]);
+    ASSERT_EQ(3U, vec2.size());
+    EXPECT_EQ(3, vec2[0]);
+    EXPECT_EQ(2, vec2[1]);
+    EXPECT_EQ(1, vec2[2]);
+}
+
+TEST(OptionsAssignerDoubleTest, StoresSingleValue)
+{
+    gmx::Options options(NULL, NULL);
+    double value = 0.0;
+    using gmx::DoubleOption;
+    ASSERT_NO_THROW(options.addOption(DoubleOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("2.7"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_DOUBLE_EQ(2.7, value);
+}
+
+
+TEST(OptionsAssignerStringTest, StoresSingleValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(StringOption("p").store(&value)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("value"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ("value", value);
+}
+
+TEST(OptionsAssignerStringTest, HandlesEnumValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -1;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).storeEnumIndex(&index)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("test"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+}
+
+TEST(OptionsAssignerStringTest, HandlesIncorrectEnumValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -1;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).storeEnumIndex(&index)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_THROW(assigner.appendValue("unknown"), gmx::InvalidInputError);
+}
+
+TEST(OptionsAssignerStringTest, CompletesEnumValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -1;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).storeEnumIndex(&index)));
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("p"));
+    ASSERT_NO_THROW(assigner.appendValue("te"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+}
+
+TEST(OptionsAssignerStringTest, HandlesEnumWithNoValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -3;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).storeEnumIndex(&index)));
+    EXPECT_TRUE(value.empty());
+    EXPECT_EQ(-1, index);
+
+    ASSERT_NO_THROW(options.finish());
+
+    EXPECT_TRUE(value.empty());
+    EXPECT_EQ(-1, index);
+}
+
+TEST(OptionsAssignerStringTest, HandlesEnumDefaultValue)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -1;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).defaultValue("test")
+                            .storeEnumIndex(&index)));
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+}
+
+TEST(OptionsAssignerStringTest, HandlesEnumDefaultIndex)
+{
+    gmx::Options           options(NULL, NULL);
+    std::string            value;
+    const char * const     allowed[] = { "none", "test", "value", NULL };
+    int                    index = -1;
+    using gmx::StringOption;
+    ASSERT_NO_THROW(options.addOption(
+                        StringOption("p").store(&value)
+                            .enumValue(allowed).defaultEnumIndex(1)
+                            .storeEnumIndex(&index)));
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+
+    gmx::OptionsAssigner assigner(&options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(options.finish());
+
+    EXPECT_EQ("test", value);
+    EXPECT_EQ(1, index);
+}
+
+} // namespace
diff --git a/src/gromacs/selection.h b/src/gromacs/selection.h
new file mode 100644 (file)
index 0000000..53d38bd
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \defgroup module_selection Parsing and Evaluation of Analysis Selections
+ * \ingroup group_analysismodules
+ * \brief
+ * Provides functionality for initializing and evaluating selections.
+ *
+ * \internal
+ * Implementation details of different parts of the module are discussed on
+ * separate pages:
+ *   - \ref page_module_selection_custom
+ *   - \ref page_module_selection_parser
+ *   - \ref page_module_selection_compiler
+ *   - \ref page_module_selection_insolidangle
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \file
+ * \brief
+ * Public API convenience header for selection handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_H
+#define GMX_SELECTION_H
+
+#include "selection/selection.h"
+#include "selection/selectionoption.h"
+
+#endif
diff --git a/src/gromacs/selection/CMakeLists.txt b/src/gromacs/selection/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b7df5bc
--- /dev/null
@@ -0,0 +1,22 @@
+file(GLOB SELECTION_SOURCES *.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${SELECTION_SOURCES} PARENT_SCOPE)
+
+set(SELECTION_PUBLIC_HEADERS
+    centerofmass.h
+    nbsearch.h
+    poscalc.h
+    indexutil.h
+    position.h
+    selection.h
+    selectionenums.h
+    selectionoption.h
+    selparam.h
+    selmethod.h
+    selvalue.h)
+install(FILES ${SELECTION_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/selection
+        COMPONENT development)
+
+if (BUILD_TESTING)
+    add_subdirectory(tests)
+endif (BUILD_TESTING)
diff --git a/src/gromacs/selection/centerofmass.cpp b/src/gromacs/selection/centerofmass.cpp
new file mode 100644 (file)
index 0000000..9a21ab9
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in centerofmass.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <typedefs.h>
+#include <pbc.h>
+#include <vec.h>
+
+#include "gromacs/selection/centerofmass.h"
+
+/*!
+ * \param[in]  top    Topology structure (unused, can be NULL).
+ * \param[in]  x      Position vectors of all atoms.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index  Indices of atoms.
+ * \param[out] xout   COG position for the indexed atoms.
+ * \returns    0 on success.
+ */
+int
+gmx_calc_cog(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
+{
+    int                 m, j, ai;
+
+    clear_rvec(xout);
+    for (m = 0; m < nrefat; ++m)
+    {
+        ai = index[m];
+        rvec_inc(xout, x[ai]);
+    }
+    svmul(1.0/nrefat, xout, xout);
+    return 0;
+}
+
+/*!
+ * \param[in]  top    Topology structure with masses.
+ * \param[in]  x      Position vectors of all atoms.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index  Indices of atoms.
+ * \param[out] xout   COM position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL.
+ *
+ * Works exactly as gmx_calc_cog() with the exception that a center of
+ * mass are calculated, and hence a topology with masses is required.
+ */
+int
+gmx_calc_com(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout)
+{
+    int                 m, j, ai;
+    real                mass, mtot;
+
+    if (!top)
+    {
+        gmx_incons("no masses available while mass weighting was requested");
+        return EINVAL;
+    }
+    clear_rvec(xout);
+    mtot = 0;
+    for (m = 0; m < nrefat; ++m)
+    {
+        ai = index[m];
+        mass = top->atoms.atom[ai].m;
+        for (j = 0; j < DIM; ++j)
+        {
+            xout[j] += mass * x[ai][j];
+        }
+        mtot += mass;
+    }
+    svmul(1.0/mtot, xout, xout);
+    return 0;
+}
+
+/*!
+ * \param[in]  top    Topology structure with masses.
+ * \param[in]  f      Forces on all atoms.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index  Indices of atoms.
+ * \param[out] fout   Force on the COG position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL.
+ *
+ * No special function is provided for calculating the force on the center of
+ * mass, because this can be achieved with gmx_calc_cog().
+ */
+int
+gmx_calc_cog_f(t_topology *top, rvec f[], int nrefat, atom_id index[], rvec fout)
+{
+    int                 m, j, ai;
+    real                mass, mtot;
+
+    if (!top)
+    {
+        gmx_incons("no masses available while mass weighting was needed");
+        return EINVAL;
+    }
+    clear_rvec(fout);
+    mtot = 0;
+    for (m = 0; m < nrefat; ++m)
+    {
+        ai = index[m];
+        mass = top->atoms.atom[ai].m;
+        for (j = 0; j < DIM; ++j)
+        {
+            fout[j] += f[ai][j] / mass;
+        }
+        mtot += mass;
+    }
+    svmul(mtot, fout, fout);
+    return 0;
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==FALSE).
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index Indices of atoms.
+ * \param[in]  bMass If TRUE, mass weighting is used.
+ * \param[out] xout  COM/COG position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
+ *
+ * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
+ * \p bMass.
+ * Other parameters are passed unmodified to these functions.
+ */
+int
+gmx_calc_comg(t_topology *top, rvec x[], int nrefat, atom_id index[],
+              gmx_bool bMass, rvec xout)
+{
+    if (bMass)
+    {
+        return gmx_calc_com(top, x, nrefat, index, xout);
+    }
+    else
+    {
+        return gmx_calc_cog(top, x, nrefat, index, xout);
+    }
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==TRUE).
+ * \param[in]  f     Forces on all atoms.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index Indices of atoms.
+ * \param[in]  bMass If TRUE, force on COM is calculated.
+ * \param[out] fout  Force on the COM/COG position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is FALSE.
+ *
+ * Calls either gmx_calc_cog() or gmx_calc_cog_f() depending on the value of
+ * \p bMass.
+ * Other parameters are passed unmodified to these functions.
+ */
+int
+gmx_calc_comg_f(t_topology *top, rvec f[], int nrefat, atom_id index[],
+                gmx_bool bMass, rvec fout)
+{
+    if (bMass)
+    {
+        return gmx_calc_cog(top, f, nrefat, index, fout);
+    }
+    else
+    {
+        return gmx_calc_cog_f(top, f, nrefat, index, fout);
+    }
+}
+
+
+/*!
+ * \param[in]  top    Topology structure (unused, can be NULL).
+ * \param[in]  x      Position vectors of all atoms.
+ * \param[in]  pbc    Periodic boundary conditions structure.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index  Indices of atoms.
+ * \param[out] xout   COG position for the indexed atoms.
+ * \returns    0 on success.
+ *
+ * Works exactly as gmx_calc_com_pbc(), but calculates the center of geometry.
+ */
+int
+gmx_calc_cog_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                 int nrefat, atom_id index[], rvec xout)
+{
+    const real          tol = 1e-4;
+    gmx_bool                bChanged;
+    int                 m, j, ai, iter;
+    rvec                dx, xtest;
+
+    /* First simple calculation */
+    gmx_calc_cog(top, x, nrefat, index, xout);
+    /* Now check if any atom is more than half the box from the COM */
+    if (pbc)
+    {
+        iter = 0;
+        do
+        {
+            bChanged = FALSE;
+            for (m = 0; m < nrefat; ++m)
+            {
+                ai = index[m];
+                pbc_dx(pbc, x[ai], xout, dx);
+                rvec_add(xout, dx, xtest);
+                for (j = 0; j < DIM; ++j)
+                {
+                    if (fabs(xtest[j] - x[ai][j]) > tol)
+                    {
+                        /* Here we have used the wrong image for contributing to the COM */
+                        xout[j] += (xtest[j] - x[ai][j]) / nrefat;
+                        x[ai][j] = xtest[j];
+                        bChanged = TRUE;
+                    }
+                }
+            }
+            iter++;
+        }
+        while (bChanged);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top    Topology structure with masses.
+ * \param[in]  x      Position vectors of all atoms.
+ * \param[in]  pbc    Periodic boundary conditions structure.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index  Indices of atoms.
+ * \param[out] xout   COM position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL.
+ *
+ * Works as gmx_calc_com(), but takes into account periodic boundary
+ * conditions: If any atom is more than half the box from the COM,
+ * it is wrapped around and a new COM is calculated. This is repeated
+ * until no atoms violate the condition.
+ *
+ * Modified from src/tools/gmx_sorient.c in Gromacs distribution.
+ */
+int
+gmx_calc_com_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                 int nrefat, atom_id index[], rvec xout)
+{
+    const real          tol = 1e-4;
+    gmx_bool                bChanged;
+    int                 m, j, ai, iter;
+    real                mass, mtot;
+    rvec                dx, xtest;
+
+    if (!top)
+    {
+        gmx_incons("no masses available while mass weighting was requested");
+        return EINVAL;
+    }
+    /* First simple calculation */
+    clear_rvec(xout);
+    mtot = 0;
+    for (m = 0; m < nrefat; ++m)
+    {
+        ai = index[m];
+        mass = top->atoms.atom[ai].m;
+        for (j = 0; j < DIM; ++j)
+        {
+            xout[j] += mass * x[ai][j];
+        }
+        mtot += mass;
+    }
+    svmul(1.0/mtot, xout, xout);
+    /* Now check if any atom is more than half the box from the COM */
+    if (pbc)
+    {
+        iter = 0;
+        do
+        {
+            bChanged = FALSE;
+            for (m = 0; m < nrefat; ++m)
+            {
+                ai = index[m];
+                mass = top->atoms.atom[ai].m / mtot;
+                pbc_dx(pbc, x[ai], xout, dx);
+                rvec_add(xout, dx, xtest);
+                for (j = 0; j < DIM; ++j)
+                {
+                    if (fabs(xtest[j] - x[ai][j]) > tol)
+                    {
+                        /* Here we have used the wrong image for contributing to the COM */
+                        xout[j] += mass * (xtest[j] - x[ai][j]);
+                        x[ai][j] = xtest[j];
+                        bChanged = TRUE;
+                    }
+                }
+            }
+            iter++;
+        }
+        while (bChanged);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==FALSE).
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  pbc    Periodic boundary conditions structure.
+ * \param[in]  nrefat Number of atoms in the index.
+ * \param[in]  index Indices of atoms.
+ * \param[in]  bMass If TRUE, mass weighting is used.
+ * \param[out] xout  COM/COG position for the indexed atoms.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
+ *
+ * Calls either gmx_calc_com() or gmx_calc_cog() depending on the value of
+ * \p bMass.
+ * Other parameters are passed unmodified to these functions.
+ */
+int
+gmx_calc_comg_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                  int nrefat, atom_id index[], gmx_bool bMass, rvec xout)
+{
+    if (bMass)
+    {
+        return gmx_calc_com_pbc(top, x, pbc, nrefat, index, xout);
+    }
+    else
+    {
+        return gmx_calc_cog_pbc(top, x, pbc, nrefat, index, xout);
+    }
+}
+
+
+/*!
+ * \param[in]  top   Topology structure (unused, can be NULL).
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  block t_block structure that divides \p index into blocks.
+ * \param[in]  index Indices of atoms.
+ * \param[out] xout  \p block->nr COG positions.
+ * \returns    0 on success.
+ */
+int
+gmx_calc_cog_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
+                   rvec xout[])
+{
+    int                 b, i, ai;
+    rvec                xb;
+
+    for (b = 0; b < block->nr; ++b)
+    {
+        clear_rvec(xb);
+        for (i = block->index[b]; i < block->index[b+1]; ++i)
+        {
+            ai = index[i];
+            rvec_inc(xb, x[ai]);
+        }
+        svmul(1.0/(block->index[b+1] - block->index[b]), xb, xout[b]);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses.
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  block t_block structure that divides \p index into blocks.
+ * \param[in]  index Indices of atoms.
+ * \param[out] xout  \p block->nr COM positions.
+ * \returns    0 on success, EINVAL if \p top is NULL.
+ *
+ * Works exactly as gmx_calc_cog_block() with the exception that centers of
+ * mass are calculated, and hence a topology with masses is required.
+ */
+int
+gmx_calc_com_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
+                   rvec xout[])
+{
+    int                 b, i, ai, d;
+    rvec                xb;
+    real                mass, mtot;
+
+    if (!top)
+    {
+        gmx_incons("no masses available while mass weighting was requested");
+        return EINVAL;
+    }
+    for (b = 0; b < block->nr; ++b)
+    {
+        clear_rvec(xb);
+        mtot = 0;
+        for (i = block->index[b]; i < block->index[b+1]; ++i)
+        {
+            ai = index[i];
+            mass = top->atoms.atom[ai].m;
+            for (d = 0; d < DIM; ++d)
+            {
+                xb[d] += mass * x[ai][d];
+            }
+            mtot += mass;
+        }
+        svmul(1.0/mtot, xb, xout[b]);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses.
+ * \param[in]  f     Forces on all atoms.
+ * \param[in]  block t_block structure that divides \p index into blocks.
+ * \param[in]  index Indices of atoms.
+ * \param[out] fout  \p block->nr Forces on COG positions.
+ * \returns    0 on success, EINVAL if \p top is NULL.
+ */
+int
+gmx_calc_cog_f_block(t_topology *top, rvec f[], t_block *block, atom_id index[],
+                     rvec fout[])
+{
+    int                 b, i, ai, d;
+    rvec                fb;
+    real                mass, mtot;
+
+    if (!top)
+    {
+        gmx_incons("no masses available while mass weighting was needed");
+        return EINVAL;
+    }
+    for (b = 0; b < block->nr; ++b)
+    {
+        clear_rvec(fb);
+        mtot = 0;
+        for (i = block->index[b]; i < block->index[b+1]; ++i)
+        {
+            ai = index[i];
+            mass = top->atoms.atom[ai].m;
+            for (d = 0; d < DIM; ++d)
+            {
+                fb[d] += f[ai][d] / mass;
+            }
+            mtot += mass;
+        }
+        svmul(mtot, fb, fout[b]);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==FALSE).
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  block t_block structure that divides \p index into blocks.
+ * \param[in]  index Indices of atoms.
+ * \param[in]  bMass If TRUE, mass weighting is used.
+ * \param[out] xout  \p block->nr COM/COG positions.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
+ *
+ * Calls either gmx_calc_com_block() or gmx_calc_cog_block() depending on the
+ * value of \p bMass.
+ * Other parameters are passed unmodified to these functions.
+ */
+int
+gmx_calc_comg_block(t_topology *top, rvec x[], t_block *block, atom_id index[],
+                    gmx_bool bMass, rvec xout[])
+{
+    if (bMass)
+    {
+        return gmx_calc_com_block(top, x, block, index, xout);
+    }
+    else
+    {
+        return gmx_calc_cog_block(top, x, block, index, xout);
+    }
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==FALSE).
+ * \param[in]  f     Forces on all atoms.
+ * \param[in]  block t_block structure that divides \p index into blocks.
+ * \param[in]  index Indices of atoms.
+ * \param[in]  bMass If TRUE, force on COM is calculated.
+ * \param[out] fout  \p block->nr forces on the COM/COG positions.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
+ *
+ * Calls either gmx_calc_com_block() or gmx_calc_cog_block() depending on the
+ * value of \p bMass.
+ * Other parameters are passed unmodified to these functions.
+ */
+int
+gmx_calc_comg_f_block(t_topology *top, rvec f[], t_block *block, atom_id index[],
+                      gmx_bool bMass, rvec fout[])
+{
+    if (bMass)
+    {
+        return gmx_calc_cog_block(top, f, block, index, fout);
+    }
+    else
+    {
+        return gmx_calc_cog_f_block(top, f, block, index, fout);
+    }
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==FALSE).
+ * \param[in]  x     Position vectors of all atoms.
+ * \param[in]  block Blocks for calculation.
+ * \param[in]  bMass If TRUE, mass weighting is used.
+ * \param[out] xout  \p block->nr COM/COG positions.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is TRUE.
+ *
+ * Calls gmx_calc_comg_block(), converting the \p t_blocka structure into
+ * a \p t_block and an index. Other parameters are passed unmodified.
+ *
+ * \attention
+ * This function assumes that a pointer to \c t_blocka can be safely typecast
+ * into \c t_block such that the index fields can still be referenced.
+ * With the present Gromacs defitions of these types, this is the case,
+ * but if the layout of these structures is changed, this may lead to strange
+ * crashes.
+ */
+int
+gmx_calc_comg_blocka(t_topology *top, rvec x[], t_blocka *block,
+                     gmx_bool bMass, rvec xout[])
+{
+    /* TODO: It would probably be better to do this without the type cast */
+    return gmx_calc_comg_block(top, x, (t_block *)block, block->a, bMass, xout);
+}
+
+/*!
+ * \param[in]  top   Topology structure with masses
+ *   (can be NULL if \p bMASS==TRUE).
+ * \param[in]  f     Forces on all atoms.
+ * \param[in]  block Blocks for calculation.
+ * \param[in]  bMass If TRUE, force on COM is calculated.
+ * \param[out] fout  \p block->nr forces on the COM/COG positions.
+ * \returns    0 on success, EINVAL if \p top is NULL and \p bMass is FALSE.
+ *
+ * Calls gmx_calc_comg_f_block(), converting the \p t_blocka structure into
+ * a \p t_block and an index. Other parameters are passed unmodified.
+ *
+ * \attention
+ * This function assumes that a pointer to \c t_blocka can be safely typecast
+ * into \c t_block such that the index fields can still be referenced.
+ * With the present Gromacs defitions of these types, this is the case,
+ * but if the layout of these structures is changed, this may lead to strange
+ * crashes.
+ */
+int
+gmx_calc_comg_f_blocka(t_topology *top, rvec f[], t_blocka *block,
+                       gmx_bool bMass, rvec fout[])
+{
+    /* TODO: It would probably be better to do this without the type cast */
+    return gmx_calc_comg_f_block(top, f, (t_block *)block, block->a, bMass, fout);
+}
diff --git a/src/gromacs/selection/centerofmass.h b/src/gromacs/selection/centerofmass.h
new file mode 100644 (file)
index 0000000..52226e9
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief API for calculation of centers of mass/geometry.
+ *
+ * This header defines a few functions that can be used to calculate
+ * centers of mass/geometry for a group of atoms.
+ * These routines can be used independently of the other parts of the
+ * library, but they are also used internally by the selection engine.
+ * In most cases, it should not be necessary to call these functions
+ * directly.
+ * Instead, one should write an analysis tool such that it gets all
+ * positions through selections.
+ *
+ * The functions in the header can be divided into a few groups based on the
+ * parameters they take. The simplest group of functions calculates the center
+ * of a single group of atoms:
+ *  - gmx_calc_cog(): Calculates the center of geometry (COG) of a given
+ *    group of atoms.
+ *  - gmx_calc_com(): Calculates the center of mass (COM) of a given group
+ *    of atoms.
+ *  - gmx_calc_comg(): Calculates either the COM or COG, based on a
+ *    gmx_boolean flag.
+ *
+ * A second set of routines is provided for calculating the centers for groups
+ * that wrap over periodic boundaries (gmx_calc_cog_pbc(), gmx_calc_com_pbc(),
+ * gmx_calc_comg_pbc()). These functions are slower, because they need to
+ * adjust the center iteratively.
+ *
+ * It is also possible to calculate centers for several groups of atoms in
+ * one call. The functions gmx_calc_cog_block(), gmx_calc_com_block() and
+ * gmx_calc_comg_block() take an index group and a partitioning of that index
+ * group (as a \c t_block structure), and calculate the centers for
+ * each group defined by the \c t_block structure separately.
+ *
+ * Finally, there is a function gmx_calc_comg_blocka() that takes both the
+ * index group and the partitioning as a single \c t_blocka structure.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_CENTEROFMASS_H
+#define GMX_SELECTION_CENTEROFMASS_H
+
+#include "../legacyheaders/typedefs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** Calculate a single center of geometry. */
+int
+gmx_calc_cog(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout);
+/** Calculate a single center of mass. */
+int
+gmx_calc_com(t_topology *top, rvec x[], int nrefat, atom_id index[], rvec xout);
+/** Calculate force on a single center of geometry. */
+int
+gmx_calc_cog_f(t_topology *top, rvec f[], int nrefat, atom_id index[], rvec fout);
+/** Calculate a single center of mass/geometry. */
+int
+gmx_calc_comg(t_topology *top, rvec x[], int nrefat, atom_id index[],
+              gmx_bool bMass, rvec xout);
+/** Calculate force on a single center of mass/geometry. */
+int
+gmx_calc_comg_f(t_topology *top, rvec f[], int nrefat, atom_id index[],
+                gmx_bool bMass, rvec fout);
+
+/** Calculate a single center of geometry iteratively, taking PBC into account. */
+int
+gmx_calc_cog_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                 int nrefat, atom_id index[], rvec xout);
+/** Calculate a single center of mass iteratively, taking PBC into account. */
+int
+gmx_calc_com_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                 int nrefat, atom_id index[], rvec xout);
+/** Calculate a single center of mass/geometry iteratively with PBC. */
+int
+gmx_calc_comg_pbc(t_topology *top, rvec x[], t_pbc *pbc,
+                  int nrefat, atom_id index[], gmx_bool bMass, rvec xout);
+
+/** Calculate centers of geometry for a blocked index. */
+int
+gmx_calc_cog_block(t_topology *top, rvec x[], t_block *block,
+                   atom_id index[], rvec xout[]);
+/** Calculate centers of mass for a blocked index. */
+int
+gmx_calc_com_block(t_topology *top, rvec x[], t_block *block,
+                   atom_id index[], rvec xout[]);
+/** Calculate forces on centers of geometry for a blocked index. */
+int
+gmx_calc_cog_f_block(t_topology *top, rvec f[], t_block *block,
+                     atom_id index[], rvec fout[]);
+/** Calculate centers of mass/geometry for a blocked index. */
+int
+gmx_calc_comg_block(t_topology *top, rvec x[], t_block *block,
+                    atom_id index[], gmx_bool bMass, rvec xout[]);
+/** Calculate forces on centers of mass/geometry for a blocked index. */
+int
+gmx_calc_comg_f_block(t_topology *top, rvec f[], t_block *block,
+                      atom_id index[], gmx_bool bMass, rvec fout[]);
+/** Calculate centers of mass/geometry for a set of blocks; */
+int
+gmx_calc_comg_blocka(t_topology *top, rvec x[], t_blocka *block,
+                     gmx_bool bMass, rvec xout[]);
+/** Calculate forces on centers of mass/geometry for a set of blocks; */
+int
+gmx_calc_comg_f_blocka(t_topology *top, rvec x[], t_blocka *block,
+                       gmx_bool bMass, rvec xout[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/selection/compiler.cpp b/src/gromacs/selection/compiler.cpp
new file mode 100644 (file)
index 0000000..055f47d
--- /dev/null
@@ -0,0 +1,2778 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Selection compilation and optimization.
+ *
+ * \todo
+ * Better error handling and memory management in error situations.
+ * At least, the main compilation function leaves the selection collection in
+ * a bad state if an error occurs.
+ *
+ * \todo
+ * The memory usage could still be optimized.
+ * Use of memory pooling could still be extended, and a lot of redundant
+ * gmin/gmax data could be eliminated for complex arithmetic expressions.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+/*! \internal
+ * \page page_module_selection_compiler Selection compilation
+ *
+ * The compiler takes the selection element tree from the selection parser
+ * (see \ref page_module_selection_parser) as input.
+ * The selection parser is quite independent of selection evaluation details,
+ * and the compiler processes the tree to conform to what the evaluation
+ * functions expect.
+ * For better control and optimization possibilities, the compilation is
+ * done on all selections simultaneously.
+ * Hence, all the selections should be parsed before the compiler can be
+ * called.
+ *
+ * The compiler initializes all fields in \c t_selelem not initialized by
+ * the parser: \c t_selelem::v (some fields have already been initialized by
+ * the parser), \c t_selelem::evaluate, and \c t_selelem::u (again, some
+ * elements have been initialized in the parser).
+ * The \c t_selelem::cdata field is used during the compilation to store
+ * internal data, but the data is freed when the compiler returns.
+ *
+ * In addition to initializing the elements, the compiler reorganizes the tree
+ * to simplify and optimize evaluation. The compiler also evaluates the static
+ * parts of the selection: in the end of the compilation, static parts have
+ * been replaced by the result of the evaluation.
+ *
+ * The compiler is called by calling gmx_ana_selcollection_compile().
+ * This functions then does the compilation in several passes over the
+ * \c t_selelem tree.
+ *  -# Defaults are set for the position type and flags of position calculation
+ *     methods that were not explicitly specified in the user input.
+ *  -# Subexpressions are extracted: a separate root is created for each
+ *     subexpression, and placed before the expression is first used.
+ *     Currently, only variables and expressions used to evaluate parameter
+ *     values are extracted, but common subexpression could also be detected
+ *     here.
+ *  -# A second pass with simple reordering and initialization is done:
+ *    -# Boolean expressions are combined such that one element can evaluate,
+ *       e.g., "A and B and C". The subexpressions in gmx_boolean expression are
+ *       reordered such that static expressions come first without otherwise
+ *       altering the relative order of the expressions.
+ *    -# The \c t_selelem::evaluate field is set to the correct evaluation
+ *       function from evaluate.h.
+ *    -# The compiler data structure is allocated for each element, and
+ *       the fields are initialized, with the exception of the contents of
+ *       \c gmax and \c gmin fields.  In reality, several passes are made
+ *       to completely initialize the structure, because some flags are set
+ *       recursively based on which elements refer to an element, and these
+ *       flags need to be set to initialize other fields.
+ *    .
+ *  -# The evaluation function of all elements is replaced with the
+ *     analyze_static() function to be able to initialize the element before
+ *     the actual evaluation function is called.
+ *     The evaluation machinery is then called to initialize the whole tree,
+ *     while simultaneously evaluating the static expressions.
+ *     During the evaluation, track is kept of the smallest and largest
+ *     possible selections, and these are stored in the internal compiler
+ *     data structure for each element.
+ *     To be able to do this for all possible values of dynamical expressions,
+ *     special care needs to be taken with gmx_boolean expressions because they
+ *     are short-circuiting. This is done through the
+ *     \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
+ *     of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
+ *     of \c BOOL_AND are evaluated to largest possible groups.
+ *     Memory is also allocated to store the results of the evaluation.
+ *     For each element, analyze_static() calls the actual evaluation function
+ *     after the element has been properly initialized.
+ *  -# Another evaluation pass is done over subexpressions with more than
+ *     one reference to them. These cannot be completely processed during the
+ *     first pass, because it is not known whether later references require
+ *     additional evaluation of static expressions.
+ *  -# Unused subexpressions are removed. For efficiency reasons (and to avoid
+ *     some checks), this is actually done several times already earlier in
+ *     the compilation process.
+ *  -# Most of the processing is now done, and the next pass simply sets the
+ *     evaluation group of root elements to the largest selection as determined
+ *     in pass 4.  For root elements of subexpressions that should not be
+ *     evaluated before they are referred to, the evaluation group/function is
+ *     cleared.  At the same time, position calculation data is initialized for
+ *     for selection method elements that require it.  Compiler data is also
+ *     freed as it is no longer needed.
+ *  -# A final pass initializes the total masses and charges in the
+ *     \c gmx_ana_selection_t data structures.
+ *
+ * The actual evaluation of the selection is described in the documentation
+ * of the functions in evaluate.h.
+ *
+ * \todo
+ * Some combinations of method parameter flags are not yet properly treated by
+ * the compiler or the evaluation functions in evaluate.cpp. All the ones used by
+ * currently implemented methods should work, but new combinations might not.
+ *
+ *
+ * \section selcompiler_tree Element tree after compilation
+ *
+ * After the compilation, the selection element tree is suitable for
+ * gmx_ana_selcollection_evaluate().
+ * Enough memory has been allocated for \ref t_selelem::v
+ * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
+ * selection to be evaluated without allocating any memory.
+ *
+ *
+ * \subsection selcompiler_tree_root Root elements
+ *
+ * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
+ * These are used for two purposes:
+ *  -# A selection that should be evaluated.
+ *     These elements appear in the same order as the selections in the input.
+ *     For these elements, \ref t_selelem::v has been set to the maximum
+ *     possible group that the selection can evaluate to (only for dynamic
+ *     selections), and \ref t_selelem::cgrp has been set to use a NULL group
+ *     for evaluation.
+ *  -# A subexpression that appears in one or more selections.
+ *     Each selection that gives a value for a method parameter is a
+ *     potential subexpression, as is any variable value.
+ *     Only subexpressions that require evaluation for each frame are left
+ *     after the selection is compiled.
+ *     Each subexpression appears in the chain before any references to it.
+ *     For these elements, \c t_selelem::cgrp has been set to the group
+ *     that should be used to evaluate the subexpression.
+ *     If \c t_selelem::cgrp is empty, the total evaluation group is not known
+ *     in advance or it is more efficient to evaluate the subexpression only
+ *     when it is referenced.  If this is the case, \c t_selelem::evaluate is
+ *     also NULL.
+ *
+ * The children of the \ref SEL_ROOT elements can be used to distinguish
+ * the two types of root elements from each other; the rules are the same
+ * as for the parsed tree (see \ref selparser_tree_root).
+ * Subexpressions are treated as if they had been provided through variables.
+ *
+ * Selection names are stored as after parsing (see \ref selparser_tree_root).
+ *
+ *
+ * \subsection selcompiler_tree_const Constant elements
+ *
+ * All (sub)selections that do not require particle positions have been
+ * replaced with \ref SEL_CONST elements.
+ * Constant elements from the parser are also retained if present in
+ * dynamic parts of the selections.
+ * Several constant elements with a NULL \c t_selelem::evaluate are left for
+ * debugging purposes; of these, only the ones for \ref BOOL_OR expressions are
+ * used during evaluation.
+ *
+ * The value is stored in \c t_selelem::v, and for group values with an
+ * evaluation function set, also in \c t_selelem::cgrp.
+ * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
+ * could never be selected) have been removed from the value.
+ *
+ * \ref SEL_CONST elements have no children.
+ *
+ *
+ * \subsection selcompiler_tree_method Method evaluation elements
+ *
+ * All selection methods that need to be evaluated dynamically are described
+ * by a \ref SEL_EXPRESSION element. The \c t_selelem::method and
+ * \c t_selelem::mdata fields have already been initialized by the parser,
+ * and the compiler only calls the initialization functions in the method
+ * data structure to do some additional initialization of these fields at
+ * appropriate points. If the \c t_selelem::pc data field has been created by
+ * the parser, the compiler initializes the data structure properly once the
+ * required positions are known. If the \c t_selelem::pc field is NULL after
+ * the parser, but the method provides only sel_updatefunc_pos(), an
+ * appropriate position calculation data structure is created.
+ * If \c t_selelem::pc is not NULL, \c t_selelem::pos is also initialized
+ * to hold the positions calculated.
+ *
+ * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
+ * parameter values that need to be evaluated for each frame. See the next
+ * section for more details.
+ * \ref SEL_CONST children can also appear, and stand for parameters that get
+ * their value from a static expression. These elements are present only for
+ * debugging purposes: they always have a NULL evaluation function.
+ *
+ *
+ * \subsection selcompiler_tree_subexpr Subexpression elements
+ *
+ * As described in \ref selcompiler_tree_root, subexpressions are created
+ * for each variable and each expression that gives a value to a selection
+ * method parameter. As the only child of the \ref SEL_ROOT element,
+ * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
+ * element has a single child, which evaluates the actual expression.
+ * After compilation, only subexpressions that require particle positions
+ * for evaluation are left.
+ * For non-variable subexpression, automatic names have been generated to
+ * help in debugging.
+ *
+ * For \ref SEL_SUBEXPR elements, memory has been allocated for
+ * \c t_selelem::cgrp to store the group for which the expression has been
+ * evaluated during the current frame.  This is only done if full subexpression
+ * evaluation by _gmx_sel_evaluate_subexpr() is needed; the other evaluation
+ * functions do not require this memory.
+ *
+ * \ref SEL_SUBEXPRREF elements are used to describe references to
+ * subexpressions. They have always a single child, which is the
+ * \ref SEL_SUBEXPR element being referenced.
+ *
+ * If a subexpression is used only once, the evaluation has been optimized by
+ * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
+ * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
+ * by the evaluation functions).  In such cases, the evaluation routines for the
+ * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
+ * information, but do not unnecessarily copy the values.
+ *
+ *
+ * \subsection selcompiler_tree_gmx_bool Boolean elements
+ *
+ * \ref SEL_BOOLEAN elements have been merged such that one element
+ * may carry out evaluation of more than one operation of the same type.
+ * The static parts of the expressions have been evaluated, and are placed
+ * in the first child. These are followed by the dynamic expressions, in the
+ * order provided by the user.
+ *
+ *
+ * \subsection selcompiler_tree_arith Arithmetic elements
+ *
+ * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
+ * calculated.
+ * Currently, no other processing is done.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdarg.h>
+
+#include <smalloc.h>
+#include <string2.h>
+#include <vec.h>
+
+// FIXME: Should really be in the beginning, but causes compilation errors
+#include <algorithm>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "evaluate.h"
+#include "keywords.h"
+#include "mempool.h"
+#include "selectioncollection-impl.h"
+#include "selelem.h"
+
+using std::min;
+
+/*! \internal \brief
+ * Compiler flags.
+ */
+enum
+{
+    /*! \brief
+     * Whether a subexpression needs to evaluated for all atoms.
+     *
+     * This flag is set for \ref SEL_SUBEXPR elements that are used to
+     * evaluate non-atom-valued selection method parameters, as well as
+     * those that are used directly as values of selections.
+     */
+    SEL_CDATA_FULLEVAL    =  1,
+    /*! \brief
+     * Whether the whole subexpression should be treated as static.
+     *
+     * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
+     * but it is also FALSE for static elements within common subexpressions.
+     */
+    SEL_CDATA_STATIC      =  2,
+    /** Whether the subexpression will always be evaluated in the same group. */
+    SEL_CDATA_STATICEVAL  =  4,
+    /** Whether the compiler evaluation routine should return the maximal selection. */
+    SEL_CDATA_EVALMAX     =  8,
+    /** Whether memory has been allocated for \p gmin and \p gmax. */
+    SEL_CDATA_MINMAXALLOC = 16,
+    /** Whether to update \p gmin and \p gmax in static analysis. */
+    SEL_CDATA_DOMINMAX      = 128,
+    /** Whether subexpressions use simple pass evaluation functions. */
+    SEL_CDATA_SIMPLESUBEXPR = 32,
+    /** Whether this expressions is a part of a common subexpression. */
+    SEL_CDATA_COMMONSUBEXPR = 64 
+};
+
+/*! \internal \brief
+ * Internal data structure used by the compiler.
+ */
+typedef struct t_compiler_data
+{
+    /** The real evaluation method. */
+    sel_evalfunc     evaluate;
+    /** Flags for specifying how to treat this element during compilation. */
+    int              flags;
+    /** Smallest selection that can be selected by the subexpression. */
+    gmx_ana_index_t *gmin;
+    /** Largest selection that can be selected by the subexpression. */
+    gmx_ana_index_t *gmax;
+} t_compiler_data;
+
+
+/********************************************************************
+ * COMPILER UTILITY FUNCTIONS
+ ********************************************************************/
+
+static void
+print_group_info(FILE *fp, const char *name, t_selelem *sel, gmx_ana_index_t *g)
+{
+    fprintf(fp, " %s=", name);
+    if (!g)
+    {
+        fprintf(fp, "(null)");
+    }
+    else if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+    {
+        fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
+    }
+    else if (sel->v.type == GROUP_VALUE && g == sel->v.u.g)
+    {
+        fprintf(fp, "(static, %p)", (void*)g);
+    }
+    else
+    {
+        fprintf(fp, "%p", (void*)g);
+    }
+}
+
+/*!
+ * \param[in] fp      File handle to receive the output.
+ * \param[in] sel     Selection element to print.
+ * \param[in] level   Indentation level, starting from zero.
+ */
+void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level)
+{
+    if (!sel->cdata)
+    {
+        return;
+    }
+    fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
+    if (sel->cdata->flags & SEL_CDATA_FULLEVAL)
+    {
+        fprintf(fp, "F");
+    }
+    if (!(sel->cdata->flags & SEL_CDATA_STATIC))
+    {
+        fprintf(fp, "D");
+    }
+    if (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+    {
+        fprintf(fp, "S");
+    }
+    if (sel->cdata->flags & SEL_CDATA_EVALMAX)
+    {
+        fprintf(fp, "M");
+    }
+    if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+    {
+        fprintf(fp, "A");
+    }
+    if (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+    {
+        fprintf(fp, "Ss");
+    }
+    if (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+    {
+        fprintf(fp, "Sc");
+    }
+    if (!sel->cdata->flags)
+    {
+        fprintf(fp, "0");
+    }
+    fprintf(fp, " eval=");
+    _gmx_sel_print_evalfunc_name(fp, sel->cdata->evaluate);
+    print_group_info(fp, "gmin", sel, sel->cdata->gmin);
+    print_group_info(fp, "gmax", sel, sel->cdata->gmax);
+    fprintf(fp, "\n");
+}
+
+/*!
+ * \param  sel Selection to free.
+ *
+ * This function only frees the data for the given selection, not its children.
+ * It is safe to call the function when compiler data has not been allocated
+ * or has already been freed; in such a case, nothing is done.
+ */
+void
+_gmx_selelem_free_compiler_data(t_selelem *sel)
+{
+    if (sel->cdata)
+    {
+        sel->evaluate = sel->cdata->evaluate;
+        if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+        {
+            sel->cdata->gmin->name = NULL;
+            sel->cdata->gmax->name = NULL;
+            gmx_ana_index_deinit(sel->cdata->gmin);
+            gmx_ana_index_deinit(sel->cdata->gmax);
+            sfree(sel->cdata->gmin);
+            sfree(sel->cdata->gmax);
+        }
+        sfree(sel->cdata);
+    }
+    sel->cdata = NULL;
+}
+
+/*! \brief
+ * Allocates memory for storing the evaluated value of a selection element.
+ *
+ * \param     sel   Selection element to initialize
+ * \param[in] isize Maximum evaluation group size.
+ * \param[in] bChildEval TRUE if children have already been processed.
+ * \returns   TRUE if the memory was allocated, FALSE if children need to
+ *   be processed first.
+ *
+ * If called more than once, memory is (re)allocated to ensure that the
+ * maximum of the \p isize values can be stored.
+ */
+static gmx_bool
+alloc_selection_data(t_selelem *sel, int isize, gmx_bool bChildEval)
+{
+    int        nalloc;
+
+    if (sel->mempool)
+    {
+        return TRUE;
+    }
+    /* Find out the number of elements to allocate */
+    if (sel->flags & SEL_SINGLEVAL)
+    {
+        nalloc = 1;
+    }
+    else if (sel->flags & SEL_ATOMVAL)
+    {
+        nalloc = isize;
+    }
+    else /* sel->flags should contain SEL_VARNUMVAL */
+    {
+        t_selelem *child;
+
+        if (!bChildEval)
+        {
+            return FALSE;
+        }
+        child = (sel->type == SEL_SUBEXPRREF ? sel->child : sel);
+        if (child->type == SEL_SUBEXPR)
+        {
+            child = child->child;
+        }
+        nalloc = (sel->v.type == POS_VALUE) ? child->v.u.p->nr : child->v.nr;
+    }
+    /* For positions, we actually want to allocate just a single structure
+     * for nalloc positions. */
+    if (sel->v.type == POS_VALUE)
+    {
+        isize  = nalloc;
+        nalloc = 1;
+    }
+    /* Allocate memory for sel->v.u if needed */
+    if (sel->flags & SEL_ALLOCVAL)
+    {
+        _gmx_selvalue_reserve(&sel->v, nalloc);
+    }
+    /* Reserve memory inside group and position structures if
+     * SEL_ALLOCDATA is set. */
+    if (sel->flags & SEL_ALLOCDATA)
+    {
+        if (sel->v.type == GROUP_VALUE)
+        {
+            gmx_ana_index_reserve(sel->v.u.g, isize);
+        }
+        else if (sel->v.type == POS_VALUE)
+        {
+            gmx_ana_pos_reserve(sel->v.u.p, isize, 0);
+        }
+    }
+    return TRUE;
+}
+
+/*! \brief
+ * Replace the evaluation function of each element in the subtree.
+ *
+ * \param     sel  Root of the selection subtree to process.
+ * \param[in] eval The new evaluation function.
+ */
+static void
+set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
+{
+    sel->evaluate = eval;
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child = sel->child;
+        while (child)
+        {
+            set_evaluation_function(child, eval);
+            child = child->next;
+        }
+    }
+}
+
+
+/********************************************************************
+ * POSITION KEYWORD DEFAULT INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes default values for position keyword evaluation.
+ *
+ * \param[in,out] root       Root of the element tree to initialize.
+ * \param[in]     spost      Default output position type.
+ * \param[in]     rpost      Default reference position type.
+ * \param[in]     sel        Selection that the element evaluates the positions
+ *      for, or NULL if the element is an internal element.
+ */
+static void
+init_pos_keyword_defaults(t_selelem *root, const char *spost,
+                          const char *rpost, const gmx::Selection *sel)
+{
+    /* Selections use largest static group by default, while
+     * reference positions use the whole residue/molecule. */
+    if (root->type == SEL_EXPRESSION)
+    {
+        bool bSelection = (sel != NULL);
+        int flags = bSelection ? POS_COMPLMAX : POS_COMPLWHOLE;
+        if (bSelection)
+        {
+            if (sel->hasFlag(gmx::efDynamicMask))
+            {
+                flags |= POS_MASKONLY;
+            }
+            if (sel->hasFlag(gmx::efEvaluateVelocities))
+            {
+                flags |= POS_VELOCITIES;
+            }
+            if (sel->hasFlag(gmx::efEvaluateForces))
+            {
+                flags |= POS_FORCES;
+            }
+        }
+        _gmx_selelem_set_kwpos_type(root, bSelection ? spost : rpost);
+        _gmx_selelem_set_kwpos_flags(root, flags);
+    }
+    /* Change the defaults once we are no longer processing modifiers */
+    if (root->type != SEL_ROOT && root->type != SEL_MODIFIER
+        && root->type != SEL_SUBEXPRREF && root->type != SEL_SUBEXPR)
+    {
+        sel = NULL;
+    }
+    /* Recurse into children */
+    t_selelem *child = root->child;
+    while (child)
+    {
+        init_pos_keyword_defaults(child, spost, rpost, sel);
+        child = child->next;
+    }
+}
+
+
+/********************************************************************
+ * SUBEXPRESSION PROCESSING
+ ********************************************************************/
+
+/*! \brief
+ * Reverses the chain of selection elements starting at \p root.
+ *
+ * \param   root First selection in the whole selection chain.
+ * \returns The new first element for the chain.
+ */
+static t_selelem *
+reverse_selelem_chain(t_selelem *root)
+{
+    t_selelem *item;
+    t_selelem *prev;
+    t_selelem *next;
+
+    prev = NULL;
+    item = root;
+    while (item)
+    {
+        next = item->next;
+        item->next = prev;
+        prev = item;
+        item = next;
+    }
+    return prev;
+}
+
+/*! \brief
+ * Removes subexpressions that don't have any references.
+ *
+ * \param     root First selection in the whole selection chain.
+ * \returns   The new first element for the chain.
+ *
+ * The elements are processed in reverse order to correctly detect
+ * subexpressions only referred to by other subexpressions.
+ */
+static t_selelem *
+remove_unused_subexpressions(t_selelem *root)
+{
+    t_selelem *item;
+    t_selelem *prev;
+    t_selelem *next;
+
+    if (root == NULL)
+    {
+        return NULL;
+    }
+    root = reverse_selelem_chain(root);
+    while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
+    {
+        next = root->next;
+        _gmx_selelem_free(root);
+        root = next;
+    }
+    prev = root;
+    item = root->next;
+    while (item)
+    {
+        next = item->next;
+        if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
+        {
+            prev->next = next;
+            _gmx_selelem_free(item);
+        }
+        else
+        {
+            prev = item;
+        }
+        item = next;
+    }
+    return reverse_selelem_chain(root);
+}
+
+/*! \brief
+ * Creates a name with a running number for a subexpression.
+ *
+ * \param[in,out] sel The subexpression to be named.
+ * \param[in]     i   Running number for the subexpression.
+ *
+ * The name of the selection becomes "SubExpr N", where N is \p i;
+ * Memory is allocated for the name and the name is stored both in
+ * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
+ * is freed by _gmx_selelem_free().
+ */
+static void
+create_subexpression_name(t_selelem *sel, int i)
+{
+    int   len, ret;
+    char *name;
+
+    len = 8 + (int)log10(abs(i)) + 3;
+    snew(name, len+1);
+    /* FIXME: snprintf used to be used here for extra safety, but this
+     * requires extra checking on Windows since it only provides a
+     * non-C99-conforming implementation as _snprintf()... */
+    ret = sprintf(name, "SubExpr %d", i);
+    if (ret < 0 || ret > len)
+    {
+        sfree(name);
+        name = NULL;
+    }
+    sel->name        = name;
+    sel->u.cgrp.name = name;
+}
+
+/*! \brief
+ * Processes and extracts subexpressions from a given selection subtree.
+ *
+ * \param   sel      Root of the subtree to process.
+ * \param   subexprn Pointer to a subexpression counter.
+ * \returns Pointer to a chain of subselections, or NULL if none were found.
+ *
+ * This function finds recursively all \ref SEL_SUBEXPRREF elements below
+ * the given root element and ensures that their children are within
+ * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
+ * that contain the subexpression as their children and returns the first
+ * of these root elements.
+ */
+static t_selelem *
+extract_item_subselections(t_selelem *sel, int *subexprn)
+{
+    t_selelem *root;
+    t_selelem *subexpr;
+    t_selelem *child;
+
+    root = subexpr = NULL;
+    child = sel->child;
+    while (child)
+    {
+        if (!root)
+        {
+            root = subexpr = extract_item_subselections(child, subexprn);
+        }
+        else
+        {
+            subexpr->next = extract_item_subselections(child, subexprn);
+        }
+        while (subexpr && subexpr->next)
+        {
+            subexpr = subexpr->next;
+        }
+        /* The latter check excludes variable references.
+         * It also excludes subexpression elements that have already been
+         * processed, because they are given a name when they are first
+         * encountered.
+         * TODO: There should be a more robust mechanism (probably a dedicated
+         * flag) for detecting parser-generated subexpressions than relying on
+         * a NULL name field. */
+        if (child->type == SEL_SUBEXPRREF && (child->child->type != SEL_SUBEXPR
+                                              || child->child->name == NULL))
+        {
+            /* Create the root element for the subexpression */
+            if (!root)
+            {
+                root = subexpr = _gmx_selelem_create(SEL_ROOT);
+            }
+            else
+            {
+                subexpr->next = _gmx_selelem_create(SEL_ROOT);
+                subexpr       = subexpr->next;
+            }
+            /* Create the subexpression element and/or
+             * move the actual subexpression under the created element. */
+            if (child->child->type != SEL_SUBEXPR)
+            {
+                subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
+                _gmx_selelem_set_vtype(subexpr->child, child->v.type);
+                subexpr->child->child = child->child;
+                child->child          = subexpr->child;
+            }
+            else
+            {
+                subexpr->child = child->child;
+            }
+            create_subexpression_name(subexpr->child, ++*subexprn);
+            subexpr->child->refcount++;
+            /* Set the flags for the created elements */
+            subexpr->flags          |= (child->flags & SEL_VALFLAGMASK);
+            subexpr->child->flags   |= (child->flags & SEL_VALFLAGMASK);
+        }
+        child = child->next;
+    }
+
+    return root;
+}
+
+/*! \brief
+ * Extracts subexpressions of the selection chain.
+ * 
+ * \param   sel First selection in the whole selection chain.
+ * \returns The new first element for the chain.
+ *
+ * Finds all the subexpressions (and their subexpressions) in the
+ * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
+ * elements for them.
+ * \ref SEL_ROOT elements are also created for each subexpression
+ * and inserted into the selection chain before the expressions that
+ * refer to them.
+ */
+static t_selelem *
+extract_subexpressions(t_selelem *sel)
+{
+    t_selelem   *root, *item, *next;
+    int          subexprn;
+
+    subexprn = 0;
+    root = NULL;
+    next = sel;
+    while (next)
+    {
+        item = extract_item_subselections(next, &subexprn);
+        if (item)
+        {
+            if (!root)
+            {
+                root = item;
+            }
+            else
+            {
+                sel->next = item;
+            }
+            while (item->next)
+            {
+                item = item->next;
+            }
+            item->next = next;
+        }
+        else if (!root)
+        {
+            root = next;
+        }
+        sel = next;
+        next = next->next;
+    }
+    return root;
+}
+
+
+/********************************************************************
+ * BOOLEAN OPERATION REORDERING
+ ********************************************************************/
+
+/*! \brief
+ * Removes redundant gmx_boolean selection elements.
+ *
+ * \param  sel Root of the selection subtree to optimize.
+ *
+ * This function merges similar gmx_boolean operations (e.g., (A or B) or C becomes
+ * a single OR operation with three operands).
+ */
+static void
+optimize_gmx_boolean_expressions(t_selelem *sel)
+{
+    t_selelem *child, *prev;
+
+    /* Do recursively for children */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        prev  = NULL;
+        child = sel->child;
+        while (child)
+        {
+            optimize_gmx_boolean_expressions(child);
+            /* Remove double negations */
+            if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
+                && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
+            {
+                /* Move the doubly negated expression up two levels */
+                if (!prev)
+                {
+                    sel->child = child->child->child;
+                    prev       = sel->child;
+                }
+                else
+                {
+                    prev->next = child->child->child;
+                    prev       = prev->next;
+                }
+                child->child->child->next = child->next;
+                /* Remove the two negations */
+                child->child->child = NULL;
+                child->next         = NULL;
+                _gmx_selelem_free(child);
+                child = prev;
+            }
+            prev  = child;
+            child = child->next;
+        }
+    }
+    if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
+    {
+        return;
+    }
+    /* Merge subsequent binary operations */
+    prev  = NULL;
+    child = sel->child;
+    while (child)
+    {
+        if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
+        {
+            if (!prev)
+            {
+                sel->child = child->child;
+                prev       = sel->child;
+            }
+            else
+            {
+                prev->next = child->child;
+            }
+            while (prev->next)
+            {
+                prev = prev->next;
+            }
+            prev->next = child->next;
+            sfree(child->v.u.g);
+            sfree(child);
+            child = prev->next;
+        }
+        else
+        {
+            prev = child;
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Reorders children of gmx_boolean expressions such that static selections
+ * come first.
+ *
+ * \param  sel Root of the selection subtree to reorder.
+ *
+ * The relative order of static expressions does not change.
+ * The same is true for the dynamic expressions.
+ */
+static void
+reorder_gmx_boolean_static_children(t_selelem *sel)
+{
+    t_selelem *child, *prev, *next;
+
+    /* Do recursively for children */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        child = sel->child;
+        while (child)
+        {
+            reorder_gmx_boolean_static_children(child);
+            child = child->next;
+        }
+    }
+
+    /* Reorder gmx_boolean expressions such that static selections come first */
+    if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
+    {
+        t_selelem  start;
+
+        start.next = sel->child;
+        prev  = &start;
+        child = &start;
+        while (child->next)
+        {
+            /* child is the last handled static expression */
+            /* prev is the last handled non-static expression */
+            next = prev->next;
+            while (next && (next->flags & SEL_DYNAMIC))
+            {
+                prev = next;
+                next = next->next;
+            }
+            /* next is now the first static expression after child */
+            if (!next)
+            {
+                break;
+            }
+            /* Reorder such that next comes after child */
+            if (prev != child)
+            {
+                prev->next  = next->next;
+                next->next  = child->next;
+                child->next = next;
+            }
+            else
+            {
+                prev = prev->next;
+            }
+            /* Advance child by one */
+            child = next;
+        }
+
+        sel->child = start.next;
+    }
+}
+
+
+/********************************************************************
+ * ARITHMETIC EXPRESSION PROCESSING
+ ********************************************************************/
+
+/*! \brief
+ * Processes arithmetic expressions to simplify and speed up evaluation.
+ *
+ * \param  sel Root of the selection subtree to process.
+ *
+ * Currently, this function only converts integer constants to reals
+ * within arithmetic expressions.
+ */
+static void
+optimize_arithmetic_expressions(t_selelem *sel)
+{
+    t_selelem  *child;
+
+    /* Do recursively for children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        child = sel->child;
+        while (child)
+        {
+            optimize_arithmetic_expressions(child);
+            child = child->next;
+        }
+    }
+
+    if (sel->type != SEL_ARITHMETIC)
+    {
+        return;
+    }
+
+    /* Convert integer constants to reals. */
+    child = sel->child;
+    while (child)
+    {
+        if (child->v.type == INT_VALUE)
+        {
+            real  *r;
+
+            if (child->type != SEL_CONST)
+            {
+                GMX_THROW(gmx::InconsistentInputError("Non-constant integer expressions not implemented in arithmetic evaluation"));
+            }
+            snew(r, 1);
+            r[0] = child->v.u.i[0];
+            sfree(child->v.u.i);
+            child->v.u.r = r;
+            child->v.type = REAL_VALUE;
+        }
+        else if (child->v.type != REAL_VALUE)
+        {
+            GMX_THROW(gmx::InternalError("Non-numerical value in arithmetic expression"));
+        }
+        child = child->next;
+    }
+}
+
+
+/********************************************************************
+ * EVALUATION PREPARATION COMPILER
+ ********************************************************************/
+
+/*! \brief
+ * Sets the evaluation functions for the selection (sub)tree.
+ *
+ * \param[in,out] sel Root of the selection subtree to process.
+ *
+ * This function sets the evaluation function (\c t_selelem::evaluate)
+ * for the selection elements.
+ */
+static void
+init_item_evalfunc(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            init_item_evalfunc(child);
+            child = child->next;
+        }
+    }
+
+    /* Set the evaluation function */
+    switch (sel->type)
+    {
+        case SEL_CONST:
+            if (sel->v.type == GROUP_VALUE)
+            {
+                sel->evaluate = &_gmx_sel_evaluate_static;
+            }
+            break;
+
+        case SEL_EXPRESSION:
+            if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
+                && sel->u.expr.method->init_frame)
+            {
+                sel->flags |= SEL_INITFRAME;
+            }
+            sel->evaluate = &_gmx_sel_evaluate_method;
+            break;
+
+        case SEL_ARITHMETIC:
+            sel->evaluate = &_gmx_sel_evaluate_arithmetic;
+            break;
+
+        case SEL_MODIFIER:
+            if (sel->v.type != NO_VALUE)
+            {
+                sel->evaluate = &_gmx_sel_evaluate_modifier;
+            }
+            break;
+
+        case SEL_BOOLEAN:
+            switch (sel->u.boolt)
+            {
+                case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
+                case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
+                case BOOL_OR:  sel->evaluate = &_gmx_sel_evaluate_or;  break;
+                case BOOL_XOR:
+                    GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
+            }
+            break;
+
+        case SEL_ROOT:
+            sel->evaluate = &_gmx_sel_evaluate_root;
+            break;
+
+        case SEL_SUBEXPR:
+            sel->evaluate = (sel->refcount == 2
+                             ? &_gmx_sel_evaluate_subexpr_simple
+                             : &_gmx_sel_evaluate_subexpr);
+            break;
+
+        case SEL_SUBEXPRREF:
+            sel->name     = sel->child->name;
+            sel->evaluate = (sel->child->refcount == 2
+                             ? &_gmx_sel_evaluate_subexprref_simple
+                             : &_gmx_sel_evaluate_subexprref);
+            break;
+
+        case SEL_GROUPREF:
+            GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
+    }
+}
+
+/*! \brief
+ * Sets the memory pool for selection elements that can use it.
+ *
+ * \param     sel      Root of the selection subtree to process.
+ * \param[in] mempool  Memory pool to use.
+ */
+static void
+setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
+{
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem         *child;
+
+        child = sel->child;
+        while (child)
+        {
+            if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
+                || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
+                    && !(child->flags & SEL_SINGLEVAL))
+                || (sel->type == SEL_SUBEXPR && sel->refcount > 2))
+            {
+                child->mempool = mempool;
+                if (child->type == SEL_SUBEXPRREF
+                    && child->child->refcount == 2)
+                {
+                    child->child->child->mempool = mempool;
+                }
+            }
+            setup_memory_pooling(child, mempool);
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Prepares the selection (sub)tree for evaluation.
+ *
+ * \param[in,out] sel Root of the selection subtree to prepare.
+ *
+ * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
+ * structure if required.
+ */
+static void
+init_item_evaloutput(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            init_item_evaloutput(child);
+            child = child->next;
+        }
+    }
+
+    if (sel->type == SEL_SUBEXPR && sel->refcount == 2)
+    {
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+        }
+    }
+    else if (sel->type == SEL_SUBEXPR
+             && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
+        sel->cdata->evaluate = sel->evaluate;
+        sel->child->mempool = NULL;
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+        }
+    }
+    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+    {
+        if (sel->v.u.ptr)
+        {
+            _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+            _gmx_selelem_free_values(sel->child->child);
+            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+            sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
+            _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
+        }
+        else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+        }
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+    }
+
+    /* Make sure that the group/position structure is allocated. */
+    if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
+    {
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_reserve(&sel->v, 1);
+            sel->v.nr = 1;
+        }
+    }
+}
+
+
+/********************************************************************
+ * COMPILER DATA INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Allocates memory for the compiler data and initializes the structure.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_compilerdata(t_selelem *sel)
+{
+    t_selelem   *child;
+
+    /* Allocate the compiler data structure */
+    snew(sel->cdata, 1);
+
+    /* Store the real evaluation method because the compiler will replace it */
+    sel->cdata->evaluate = sel->evaluate;
+
+    /* Initialize the flags */
+    sel->cdata->flags = SEL_CDATA_STATICEVAL;
+    if (!(sel->flags & SEL_DYNAMIC))
+    {
+        sel->cdata->flags |= SEL_CDATA_STATIC;
+    }
+    if (sel->type == SEL_SUBEXPR)
+    {
+        sel->cdata->flags |= SEL_CDATA_EVALMAX;
+    }
+    /* Set the full evaluation flag for subexpressions that require it;
+     * the subexpression has already been initialized, so we can simply
+     * access its compilation flags.*/
+    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+    {
+        child = sel->child;
+        while (child)
+        {
+            if (!(child->flags & SEL_ATOMVAL) && child->child)
+            {
+                child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
+            }
+            child = child->next;
+        }
+    }
+    else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
+    {
+        sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
+    }
+
+    /* Initialize children */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        child = sel->child;
+        while (child)
+        {
+            init_item_compilerdata(child);
+            child = child->next;
+        }
+    }
+
+    /* Determine whether we should evaluate the minimum or the maximum
+     * for the children of this element. */
+    if (sel->type == SEL_BOOLEAN)
+    {
+        gmx_bool  bEvalMax;
+
+        bEvalMax = (sel->u.boolt == BOOL_AND);
+        child = sel->child;
+        while (child)
+        {
+            if (bEvalMax)
+            {
+                child->cdata->flags |= SEL_CDATA_EVALMAX;
+            }
+            else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
+            {
+                child->child->cdata->flags |= SEL_CDATA_EVALMAX;
+            }
+            child = child->next;
+        }
+    }
+    else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
+             || sel->type == SEL_SUBEXPR)
+    {
+        child = sel->child;
+        while (child)
+        {
+            child->cdata->flags |= SEL_CDATA_EVALMAX;
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Initializes the static evaluation flag for a selection subtree.
+ *
+ * \param[in,out] sel  Root of the selection subtree to process.
+ *
+ * Sets the \c bStaticEval in the compiler data structure:
+ * for any element for which the evaluation group may depend on the trajectory
+ * frame, the flag is cleared.
+ *
+ * reorder_gmx_boolean_static_children() should have been called.
+ */
+static void
+init_item_staticeval(t_selelem *sel)
+{
+    t_selelem   *child;
+
+    /* Subexpressions with full evaluation should always have bStaticEval,
+     * so don't do anything if a reference to them is encountered. */
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        return;
+    }
+
+    /* Propagate the bStaticEval flag to children if it is not set */
+    if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
+    {
+        child = sel->child;
+        while (child)
+        {
+            if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
+                || (child->flags & SEL_ATOMVAL))
+            {
+                if (child->cdata->flags & SEL_CDATA_STATICEVAL)
+                {
+                    child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
+                    init_item_staticeval(child);
+                }
+            }
+            child = child->next;
+        }
+    }
+    else /* bStaticEval is set */
+    {
+        /* For gmx_boolean expressions, any expression after the first dynamic
+         * expression should not have bStaticEval. */
+        if (sel->type == SEL_BOOLEAN)
+        {
+            child = sel->child;
+            while (child && !(child->flags & SEL_DYNAMIC))
+            {
+                child = child->next;
+            }
+            if (child)
+            {
+                child = child->next;
+            }
+            while (child)
+            {
+                child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
+                child = child->next;
+            }
+        }
+
+        /* Process the children */
+        child = sel->child;
+        while (child)
+        {
+            init_item_staticeval(child);
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Initializes compiler flags for subexpressions.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_subexpr_flags(t_selelem *sel)
+{
+    if (sel->type == SEL_SUBEXPR)
+    {
+        if (sel->refcount == 2)
+        {
+            sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+        }
+        else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
+        {
+            sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
+        }
+    }
+    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+    {
+        sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+    }
+
+    /* Process children, but only follow subexpression references if the
+     * common subexpression flag needs to be propagated. */
+    if (sel->type != SEL_SUBEXPRREF
+        || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+            && sel->child->refcount > 2))
+    {
+        t_selelem *child = sel->child;
+
+        while (child)
+        {
+            if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
+            {
+                if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
+                {
+                    child->cdata->flags |=
+                        (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
+                }
+                init_item_subexpr_flags(child);
+            }
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Initializes the gmin and gmax fields of the compiler data structure.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_minmax_groups(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            init_item_minmax_groups(child);
+            child = child->next;
+        }
+    }
+
+    /* Initialize the minimum and maximum evaluation groups. */
+    if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
+    {
+        if (sel->v.type == GROUP_VALUE
+            && (sel->cdata->flags & SEL_CDATA_STATIC))
+        {
+            sel->cdata->gmin = sel->v.u.g;
+            sel->cdata->gmax = sel->v.u.g;
+        }
+        else if (sel->type == SEL_SUBEXPR
+                 && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                     || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
+        {
+            sel->cdata->gmin = sel->child->cdata->gmin;
+            sel->cdata->gmax = sel->child->cdata->gmax;
+        }
+        else
+        {
+            sel->cdata->flags |= SEL_CDATA_MINMAXALLOC | SEL_CDATA_DOMINMAX;
+            snew(sel->cdata->gmin, 1);
+            snew(sel->cdata->gmax, 1);
+        }
+    }
+}
+
+
+/********************************************************************
+ * EVALUATION GROUP INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes evaluation groups for root items.
+ *
+ * \param[in,out] sc   Selection collection data.
+ *
+ * The evaluation group of each \ref SEL_ROOT element corresponding to a
+ * selection in \p sc is set to \p gall.  The same is done for \ref SEL_ROOT
+ * elements corresponding to subexpressions that need full evaluation.
+ */
+static void
+initialize_evalgrps(gmx_ana_selcollection_t *sc)
+{
+    t_selelem   *root;
+
+    root = sc->root;
+    while (root)
+    {
+        if (root->child->type != SEL_SUBEXPR
+            || (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
+        {
+            gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
+                              root->u.cgrp.name, 0);
+        }
+        root = root->next;
+    }
+}
+
+
+/********************************************************************
+ * STATIC ANALYSIS
+ ********************************************************************/
+
+/*! \brief
+ * Marks a subtree completely dynamic or undoes such a change.
+ *
+ * \param     sel      Selection subtree to mark.
+ * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
+ *   selection subtree is cleared. If FALSE, the flag is restored to
+ *   using \ref SEL_DYNAMIC.
+ *
+ * Does not descend into parameters of methods unless the parameters
+ * are evaluated for each atom.
+ */
+static void
+mark_subexpr_dynamic(t_selelem *sel, gmx_bool bDynamic)
+{
+    t_selelem *child;
+
+    if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
+    {
+        sel->cdata->flags |= SEL_CDATA_STATIC;
+    }
+    else
+    {
+        sel->cdata->flags &= ~SEL_CDATA_STATIC;
+    }
+    child = sel->child;
+    while (child)
+    {
+        if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
+            || (child->u.param->flags & SPAR_ATOMVAL))
+        {
+            mark_subexpr_dynamic(child, bDynamic);
+        }
+        child = child->next;
+    }
+}
+
+/*! \brief
+ * Frees memory for subexpressions that are no longer needed.
+ *
+ * \param     sel      Selection subtree to check.
+ *
+ * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
+ * elements that are not referred to by anything else except their own root
+ * element. If such elements are found, all memory allocated for them is freed
+ * except the actual element. The element is left because otherwise a dangling
+ * pointer would be left at the root element, which is not traversed by this
+ * function. Later compilation passes remove the stub elements.
+ */
+static void
+release_subexpr_memory(t_selelem *sel)
+{
+    if (sel->type == SEL_SUBEXPR)
+    {
+        if (sel->refcount == 2)
+        {
+            release_subexpr_memory(sel->child);
+            sel->name = NULL;
+            _gmx_selelem_free_chain(sel->child);
+            _gmx_selelem_free_values(sel);
+            _gmx_selelem_free_exprdata(sel);
+            _gmx_selelem_free_compiler_data(sel);
+            sel->child = NULL;
+        }
+    }
+    else
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            release_subexpr_memory(child);
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Makes an evaluated selection element static.
+ *
+ * \param     sel   Selection element to make static.
+ *
+ * The evaluated value becomes the value of the static element.
+ * The element type is changed to SEL_CONST and the children are
+ * deleted.
+ */
+static void
+make_static(t_selelem *sel)
+{
+    /* If this is a subexpression reference and the data is stored in the
+     * child, we transfer data ownership before doing anything else. */
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+    {
+        if (sel->child->child->flags & SEL_ALLOCDATA)
+        {
+            sel->flags |= SEL_ALLOCDATA;
+            sel->child->child->flags &= ~SEL_ALLOCDATA;
+        }
+        if (sel->child->child->flags & SEL_ALLOCVAL)
+        {
+            sel->flags |= SEL_ALLOCVAL;
+            sel->v.nalloc = sel->child->child->v.nalloc;
+            sel->child->child->flags &= ~SEL_ALLOCVAL;
+            sel->child->child->v.nalloc = -1;
+        }
+    }
+    /* Free the children. */
+    release_subexpr_memory(sel);
+    _gmx_selelem_free_chain(sel->child);
+    sel->child           = NULL;
+    /* Free the expression data as it is no longer needed */
+    _gmx_selelem_free_exprdata(sel);
+    /* Make the item static */
+    sel->name            = NULL;
+    sel->type            = SEL_CONST;
+    sel->evaluate        = NULL;
+    sel->cdata->evaluate = NULL;
+    /* Set the group value.
+     * free_exprdata above frees the cgrp group, so we can just override it. */
+    if (sel->v.type == GROUP_VALUE)
+    {
+        gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
+    }
+}
+
+/*! \brief
+ * Evaluates a constant expression during analyze_static().
+ *
+ * \param[in]     data Evaluation data.
+ * \param[in,out] sel Selection to process.
+ * \param[in]     g   The evaluation group.
+ * \returns       0 on success, a non-zero error code on error.
+ */
+static void
+process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (sel->v.type == GROUP_VALUE)
+    {
+        if (sel->cdata->evaluate)
+        {
+            sel->cdata->evaluate(data, sel, g);
+        }
+    }
+    /* Other constant expressions do not need evaluation */
+}
+
+/*! \brief
+ * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
+ *
+ * \param[in,out] sel Selection to process.
+ *
+ * Copies the value pointer of \p sel to \c sel->u.param if one is present
+ * and should receive the value from the compiler
+ * (most parameter values are handled during parsing).
+ * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
+ * the function does nothing.
+ * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
+ * \ref SPAR_ATOMVAL, the function returns immediately.
+ */
+static void
+store_param_val(t_selelem *sel)
+{
+    /* Return immediately if there is no parameter. */
+    if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
+    {
+        return;
+    }
+
+    /* Or if the value does not need storing. */
+    if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
+    {
+        return;
+    }
+
+    if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
+        || sel->v.type == STR_VALUE)
+    {
+        _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
+    }
+}
+
+/*! \brief
+ * Handles the initialization of a selection method during analyze_static() pass.
+ *
+ * \param[in,out] sel Selection element to process.
+ * \param[in]     top Topology structure.
+ * \param[in]     isize Size of the evaluation group for the element.
+ * \returns       0 on success, a non-zero error code on return.
+ *
+ * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
+ * method.
+ * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
+ * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
+ */
+static void
+init_method(t_selelem *sel, t_topology *top, int isize)
+{
+    t_selelem *child;
+    gmx_bool       bAtomVal;
+
+    /* Find out whether there are any atom-valued parameters */
+    bAtomVal = FALSE;
+    child = sel->child;
+    while (child)
+    {
+        if (child->flags & SEL_ATOMVAL)
+        {
+            bAtomVal = TRUE;
+        }
+        child = child->next;
+    }
+
+    /* Initialize the method */
+    if (sel->u.expr.method->init
+        && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
+    {
+        sel->flags |= SEL_METHODINIT;
+        sel->u.expr.method->init(top, sel->u.expr.method->nparams,
+                sel->u.expr.method->param, sel->u.expr.mdata);
+    }
+    if (bAtomVal || !(sel->flags & SEL_OUTINIT))
+    {
+        sel->flags |= SEL_OUTINIT;
+        if (sel->u.expr.method->outinit)
+        {
+            sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
+            if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
+            {
+                alloc_selection_data(sel, isize, TRUE);
+            }
+        }
+        else
+        {
+            alloc_selection_data(sel, isize, TRUE);
+            if ((sel->flags & SEL_DYNAMIC)
+                && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
+            {
+                sel->v.nr = isize;
+            }
+            /* If the method is char-valued, pre-allocate the strings. */
+            if (sel->u.expr.method->flags & SMETH_CHARVAL)
+            {
+                int  i;
+
+                /* A sanity check */
+                if (sel->v.type != STR_VALUE)
+                {
+                    GMX_THROW(gmx::InternalError("Char-valued selection method in non-string element"));
+                }
+                sel->flags |= SEL_ALLOCDATA;
+                for (i = 0; i < isize; ++i)
+                {
+                    if (sel->v.u.s[i] == NULL)
+                    {
+                        snew(sel->v.u.s[i], 2);
+                    }
+                }
+            }
+        }
+        /* Clear the values for dynamic output to avoid valgrind warnings. */
+        if ((sel->flags & SEL_DYNAMIC) && sel->v.type == REAL_VALUE)
+        {
+            int i;
+
+            for (i = 0; i < sel->v.nr; ++i)
+            {
+                sel->v.u.r[i] = 0.0;
+            }
+        }
+    }
+}
+
+/*! \brief
+ * Evaluates the static part of a gmx_boolean expression.
+ *
+ * \param[in]     data Evaluation data.
+ * \param[in,out] sel Boolean selection element whose children should be
+ *   processed.
+ * \param[in]     g   The evaluation group.
+ * \returns       0 on success, a non-zero error code on error.
+ *
+ * reorder_item_static_children() should have been called.
+ */
+static void
+evaluate_gmx_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
+                             gmx_ana_index_t *g)
+{
+    t_selelem *child, *next;
+
+    /* Find the last static subexpression */
+    child = sel->child;
+    while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
+    {
+        child = child->next;
+    }
+    if (!(child->cdata->flags & SEL_CDATA_STATIC))
+    {
+        return;
+    }
+
+    /* Evalute the static part if there is more than one expression */
+    if (child != sel->child)
+    {
+        next  = child->next;
+        child->next = NULL;
+        sel->cdata->evaluate(data, sel, g);
+        /* Replace the subexpressions with the result */
+        _gmx_selelem_free_chain(sel->child);
+        snew(child, 1);
+        child->type       = SEL_CONST;
+        child->flags      = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
+        _gmx_selelem_set_vtype(child, GROUP_VALUE);
+        child->evaluate   = NULL;
+        _gmx_selvalue_reserve(&child->v, 1);
+        gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
+        init_item_compilerdata(child);
+        init_item_minmax_groups(child);
+        child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
+        child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
+        child->next = next;
+        sel->child = child;
+    }
+    else if (child->evaluate)
+    {
+        child->evaluate(data, child, g);
+    }
+    /* Set the evaluation function for the constant element.
+     * We never need to evaluate the element again during compilation,
+     * but we may need to evaluate the static part again if the
+     * expression is not an OR with a static evaluation group.
+     * If we reach here with a NOT expression, the NOT expression
+     * is also static, and will be made a constant later, so don't waste
+     * time copying the group. */
+    child->evaluate = NULL;
+    if (sel->u.boolt == BOOL_NOT
+        || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
+            && sel->u.boolt == BOOL_OR))
+    {
+        child->cdata->evaluate = NULL;
+    }
+    else
+    {
+        child->cdata->evaluate = &_gmx_sel_evaluate_static;
+        /* The cgrp has only been allocated if it originated from an
+         * external index group. In that case, we need special handling
+         * to preserve the name of the group and to not leak memory.
+         * If cgrp has been set in make_static(), it is not allocated,
+         * and hence we can overwrite it safely. */
+        if (child->u.cgrp.nalloc_index > 0)
+        {
+            char *name = child->u.cgrp.name;
+            gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, FALSE);
+            gmx_ana_index_squeeze(&child->u.cgrp);
+            child->u.cgrp.name = name;
+        }
+        else
+        {
+            gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, TRUE);
+        }
+    }
+}
+
+/*! \brief
+ * Evaluates the minimum and maximum groups for a gmx_boolean expression.
+ *
+ * \param[in]  sel  \ref SEL_BOOLEAN element currently being evaluated.
+ * \param[in]  g    Group for which \p sel has been evaluated.
+ * \param[out] gmin Largest subset of the possible values of \p sel.
+ * \param[out] gmax Smallest superset of the possible values of \p sel.
+ *
+ * This is a helper function for analyze_static() that is called for
+ * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
+ * It uses the minimum and maximum groups of the children to calculate
+ * the minimum and maximum groups for \p sel, and also updates the static
+ * part of \p sel (which is in the first child) if the children give
+ * cause for this.
+ *
+ * This function may allocate some extra memory for \p gmin and \p gmax,
+ * but as these groups are freed at the end of analyze_static() (which is
+ * reached shortly after this function returns), this should not be a major
+ * problem.
+ */
+static void
+evaluate_gmx_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
+                             gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
+{
+    t_selelem *child;
+
+    switch (sel->u.boolt)
+    {
+        case BOOL_NOT:
+            gmx_ana_index_reserve(gmin, g->isize);
+            gmx_ana_index_reserve(gmax, g->isize);
+            gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
+            gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
+            break;
+
+        case BOOL_AND:
+            gmx_ana_index_copy(gmin, sel->child->cdata->gmin, TRUE);
+            gmx_ana_index_copy(gmax, sel->child->cdata->gmax, TRUE);
+            child = sel->child->next;
+            while (child && gmax->isize > 0)
+            {
+                gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
+                gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
+                child = child->next;
+            }
+            /* Update the static part if other expressions limit it */
+            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
+                && sel->child->v.u.g->isize > gmax->isize)
+            {
+                gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
+                gmx_ana_index_squeeze(sel->child->v.u.g);
+                if (sel->child->u.cgrp.isize > 0)
+                {
+                    gmx_ana_index_copy(&sel->child->u.cgrp, gmax, FALSE);
+                    gmx_ana_index_squeeze(&sel->child->u.cgrp);
+                }
+            }
+            break;
+
+        case BOOL_OR:
+            /* We can assume here that the gmin of children do not overlap
+             * because of the way _gmx_sel_evaluate_or() works. */
+            gmx_ana_index_reserve(gmin, g->isize);
+            gmx_ana_index_reserve(gmax, g->isize);
+            gmx_ana_index_copy(gmin, sel->child->cdata->gmin, FALSE);
+            gmx_ana_index_copy(gmax, sel->child->cdata->gmax, FALSE);
+            child = sel->child->next;
+            while (child && gmin->isize < g->isize)
+            {
+                gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
+                gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
+                child = child->next;
+            }
+            /* Update the static part if other expressions have static parts
+             * that are not included. */
+            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
+                && sel->child->v.u.g->isize < gmin->isize)
+            {
+                gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
+                gmx_ana_index_copy(sel->child->v.u.g, gmin, FALSE);
+                if (sel->child->u.cgrp.isize > 0)
+                {
+                    gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
+                    gmx_ana_index_copy(&sel->child->u.cgrp, gmin, FALSE);
+                }
+            }
+            break;
+
+        case BOOL_XOR: /* Should not be reached */
+            GMX_THROW(gmx::NotImplementedError("xor expressions not implemented"));
+            break;
+    }
+}
+
+/*! \brief
+ * Evaluates the static parts of \p sel and analyzes the structure.
+ * 
+ * \param[in]     data Evaluation data.
+ * \param[in,out] sel  Selection currently being evaluated.
+ * \param[in]     g    Group for which \p sel should be evaluated.
+ * \returns       0 on success, a non-zero error code on error.
+ *
+ * This function is used as the replacement for the \c t_selelem::evaluate
+ * function pointer.
+ * It does the single most complex task in the compiler: after all elements
+ * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
+ * have been properly initialized, enough memory has been allocated for
+ * storing the value of each expression, and the static parts of the 
+ * expressions have been evaluated.
+ * The above is exactly true only for elements other than subexpressions:
+ * another pass is required for subexpressions that are referred to more than
+ * once and whose evaluation group is not known in advance.
+ */
+static void
+analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    t_selelem       *child, *next;
+    gmx_bool             bDoMinMax;
+
+    if (sel->type != SEL_ROOT && g)
+    {
+        alloc_selection_data(sel, g->isize, FALSE);
+    }
+
+    bDoMinMax = (sel->cdata->flags & SEL_CDATA_DOMINMAX);
+    if (sel->type != SEL_SUBEXPR && bDoMinMax)
+    {
+        gmx_ana_index_deinit(sel->cdata->gmin);
+        gmx_ana_index_deinit(sel->cdata->gmax);
+    }
+
+    /* TODO: This switch is awfully long... */
+    switch (sel->type)
+    {
+        case SEL_CONST:
+            process_const(data, sel, g);
+            break;
+
+        case SEL_EXPRESSION:
+        case SEL_MODIFIER:
+            _gmx_sel_evaluate_method_params(data, sel, g);
+            init_method(sel, data->top, g->isize);
+            if (!(sel->flags & SEL_DYNAMIC))
+            {
+                sel->cdata->evaluate(data, sel, g);
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
+                {
+                    make_static(sel);
+                }
+            }
+            else
+            {
+                /* Modifiers need to be evaluated even though they process
+                 * positions to get the modified output groups from the
+                 * maximum possible selections. */
+                if (sel->type == SEL_MODIFIER)
+                {
+                    sel->cdata->evaluate(data, sel, g);
+                }
+                if (bDoMinMax)
+                {
+                    gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
+                }
+            }
+            break;
+
+        case SEL_BOOLEAN:
+            if (!(sel->flags & SEL_DYNAMIC))
+            {
+                sel->cdata->evaluate(data, sel, g);
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
+                {
+                    make_static(sel);
+                }
+            }
+            else
+            {
+                /* Evalute the static part if there is more than one expression */
+                evaluate_gmx_boolean_static_part(data, sel, g);
+
+                /* Evaluate the selection.
+                 * If the type is gmx_boolean, we must explicitly handle the
+                 * static part evaluated in evaluate_gmx_boolean_static_part()
+                 * here because g may be larger. */
+                if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
+                {
+                    sel->cdata->evaluate(data, sel, sel->child->v.u.g);
+                }
+                else
+                {
+                    sel->cdata->evaluate(data, sel, g);
+                }
+
+                /* Evaluate minimal and maximal selections */
+                evaluate_gmx_boolean_minmax_grps(sel, g, sel->cdata->gmin,
+                                             sel->cdata->gmax);
+            }
+            break;
+
+        case SEL_ARITHMETIC:
+            sel->cdata->evaluate(data, sel, g);
+            if (!(sel->flags & SEL_DYNAMIC))
+            {
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
+                {
+                    make_static(sel);
+                }
+            }
+            else if (bDoMinMax)
+            {
+                gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
+            }
+            break;
+
+        case SEL_ROOT:
+            sel->cdata->evaluate(data, sel, g);
+            break;
+
+        case SEL_SUBEXPR:
+            if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
+            {
+                sel->cdata->evaluate(data, sel, g);
+                _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+            }
+            else if (sel->u.cgrp.isize == 0)
+            {
+                gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
+                sel->cdata->evaluate(data, sel, g);
+                if (bDoMinMax)
+                {
+                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
+                }
+            }
+            else
+            {
+                int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
+                if (isize > 0)
+                {
+                    isize += sel->u.cgrp.isize;
+                    gmx_ana_index_reserve(&sel->u.cgrp, isize);
+                    alloc_selection_data(sel, isize, FALSE);
+                }
+                sel->cdata->evaluate(data, sel, g);
+                if (isize > 0 && bDoMinMax)
+                {
+                    gmx_ana_index_reserve(sel->cdata->gmin,
+                                          sel->cdata->gmin->isize
+                                          + sel->child->cdata->gmin->isize);
+                    gmx_ana_index_reserve(sel->cdata->gmax,
+                                          sel->cdata->gmax->isize
+                                          + sel->child->cdata->gmax->isize);
+                    gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
+                                        sel->child->cdata->gmin);
+                    gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
+                                        sel->child->cdata->gmax);
+                }
+            }
+            break;
+
+        case SEL_SUBEXPRREF:
+            if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+            {
+                /* The subexpression should have been evaluated if g is NULL
+                 * (i.e., this is a method parameter or a direct value of a
+                 * selection). */
+                alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
+            }
+            sel->cdata->evaluate(data, sel, g);
+            if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                && (sel->child->child->flags & SEL_ALLOCVAL))
+            {
+                _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+            }
+            /* Store the parameter value if required */
+            store_param_val(sel);
+            if (!(sel->flags & SEL_DYNAMIC))
+            {
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
+                {
+                    make_static(sel);
+                }
+            }
+            else if (bDoMinMax)
+            {
+                if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
+                {
+                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
+                }
+                else
+                {
+                    gmx_ana_index_reserve(sel->cdata->gmin,
+                                          min(g->isize, sel->child->cdata->gmin->isize));
+                    gmx_ana_index_reserve(sel->cdata->gmax,
+                                          min(g->isize, sel->child->cdata->gmax->isize));
+                    gmx_ana_index_intersection(sel->cdata->gmin,
+                                               sel->child->cdata->gmin, g);
+                    gmx_ana_index_intersection(sel->cdata->gmax,
+                                               sel->child->cdata->gmax, g);
+                }
+            }
+            break;
+
+        case SEL_GROUPREF:
+            GMX_THROW(gmx::APIError("Unresolved group reference in compilation"));
+    }
+
+    /* Update the minimal and maximal evaluation groups */
+    if (bDoMinMax)
+    {
+        gmx_ana_index_squeeze(sel->cdata->gmin);
+        gmx_ana_index_squeeze(sel->cdata->gmax);
+        sfree(sel->cdata->gmin->name);
+        sfree(sel->cdata->gmax->name);
+        sel->cdata->gmin->name = NULL;
+        sel->cdata->gmax->name = NULL;
+    }
+
+    /* Replace the result of the evaluation */
+    /* This is not necessary for subexpressions or for gmx_boolean negations
+     * because the evaluation function already has done it properly. */
+    if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
+        && sel->type != SEL_SUBEXPR
+        && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
+    {
+        if (sel->cdata->flags & SEL_CDATA_EVALMAX)
+        {
+            gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
+        }
+        else
+        {
+            gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, FALSE);
+        }
+    }
+}
+
+
+/********************************************************************
+ * EVALUATION GROUP INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes the evaluation group for a \ref SEL_ROOT element.
+ *
+ * \param     root Root element to initialize.
+ * \param[in] gall Group of all atoms.
+ *
+ * Checks whether it is necessary to evaluate anything through the root
+ * element, and either clears the evaluation function or initializes the
+ * evaluation group.
+ */
+static void
+init_root_item(t_selelem *root, gmx_ana_index_t *gall)
+{
+    t_selelem   *expr;
+    char        *name;
+
+    expr = root->child;
+    /* Subexpressions with non-static evaluation group should not be
+     * evaluated by the root, and neither should be single-reference
+     * subexpressions that don't evaluate for all atoms. */
+    if (expr->type == SEL_SUBEXPR
+        && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
+            || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
+    {
+        root->evaluate = NULL;
+        if (root->cdata)
+        {
+            root->cdata->evaluate = NULL;
+        }
+    }
+
+    /* Set the evaluation group */
+    name = root->u.cgrp.name;
+    if (root->evaluate)
+    {
+        /* Non-atom-valued non-group expressions don't care about the group, so
+         * don't allocate any memory for it. */
+        if ((expr->flags & SEL_VARNUMVAL)
+            || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
+        {
+            gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
+        }
+        else if (expr->cdata->gmax->isize == gall->isize)
+        {
+            /* Save some memory by only referring to the global group. */
+            gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
+        }
+        else
+        {
+            gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
+        }
+        /* For selections, store the maximum group for
+         * gmx_ana_selcollection_evaluate_fin() as the value of the root
+         * element (unused otherwise). */
+        if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
+        {
+            t_selelem *child = expr;
+
+            /* TODO: This code is copied from parsetree.c; it would be better
+             * to have this hardcoded only in one place. */
+            while (child->type == SEL_MODIFIER)
+            {
+                child = child->child;
+                if (child->type == SEL_SUBEXPRREF)
+                {
+                    child = child->child->child;
+                }
+            }
+            if (child->type == SEL_SUBEXPRREF)
+            {
+                child = child->child->child;
+            }
+            if (child->child->flags & SEL_DYNAMIC)
+            {
+                _gmx_selelem_set_vtype(root, GROUP_VALUE);
+                root->flags  |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
+                _gmx_selvalue_reserve(&root->v, 1);
+                gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
+            }
+        }
+    }
+    else
+    {
+        gmx_ana_index_clear(&root->u.cgrp);
+    }
+    root->u.cgrp.name = name;
+}
+
+
+/********************************************************************
+ * FINAL SUBEXPRESSION OPTIMIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Optimizes subexpression evaluation.
+ *
+ * \param     sel Root of the selection subtree to process.
+ *
+ * Optimizes away some unnecessary evaluation of subexpressions that are only
+ * referenced once.
+ */
+static void
+postprocess_item_subexpressions(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            postprocess_item_subexpressions(child);
+            child = child->next;
+        }
+    }
+
+    /* Replace the evaluation function of statically evaluated subexpressions
+     * for which the static group was not known in advance. */
+    if (sel->type == SEL_SUBEXPR && sel->refcount > 2
+        && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+        && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        char *name;
+
+        /* We need to free memory allocated for the group, because it is no
+         * longer needed (and would be lost on next call to the evaluation
+         * function). But we need to preserve the name. */
+        name = sel->u.cgrp.name;
+        gmx_ana_index_deinit(&sel->u.cgrp);
+        sel->u.cgrp.name = name;
+
+        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
+        if (sel->cdata)
+        {
+            sel->cdata->evaluate = sel->evaluate;
+        }
+        _gmx_selelem_free_values(sel->child);
+        sel->child->mempool = NULL;
+        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+    }
+
+    /* Adjust memory allocation flags for subexpressions that are used only
+     * once.  This is not strictly necessary, but we do it to have the memory
+     * managed consistently for all types of subexpressions. */
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+    {
+        if (sel->child->child->flags & SEL_ALLOCVAL)
+        {
+            sel->flags |= SEL_ALLOCVAL;
+            sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
+            sel->v.nalloc = sel->child->child->v.nalloc;
+            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+            sel->child->child->v.nalloc = -1;
+        }
+    }
+
+    /* Do the same for subexpressions that are evaluated at once for all atoms. */
+    if (sel->type == SEL_SUBEXPR
+        && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+        && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        sel->flags |= SEL_ALLOCVAL;
+        sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
+        sel->v.nalloc = sel->child->v.nalloc;
+        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        sel->child->v.nalloc = -1;
+    }
+}
+
+
+/********************************************************************
+ * COM CALCULATION INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes COM/COG calculation for method expressions that require it.
+ *
+ * \param     sel    Selection subtree to process.
+ * \param[in,out] pcc   Position calculation collection to use.
+ * \param[in] type   Default position calculation type.
+ * \param[in] flags  Flags for default position calculation.
+ *
+ * Searches recursively through the selection tree for dynamic
+ * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
+ * function.
+ * For each such element found, position calculation is initialized
+ * for the maximal evaluation group.
+ * The type of the calculation is determined by \p type and \p flags.
+ * No calculation is initialized if \p type equals \ref POS_ATOM and
+ * the method also defines the \c gmx_ana_selmethod_t::update method.
+ */
+static void
+init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
+               e_poscalc_t type, int flags)
+{
+    t_selelem *child;
+
+    /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
+    if (sel->type == SEL_EXPRESSION && sel->u.expr.method
+        && sel->u.expr.method->pupdate)
+    {
+        if (!sel->u.expr.method->update || type != POS_ATOM)
+        {
+            /* Create a default calculation if one does not yet exist */
+            int cflags = 0;
+            if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
+            {
+                cflags |= POS_DYNAMIC;
+            }
+            if (!sel->u.expr.pc)
+            {
+                cflags |= flags;
+                gmx_ana_poscalc_create(&sel->u.expr.pc, pcc, type, cflags);
+            }
+            else
+            {
+                gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
+            }
+            gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
+            snew(sel->u.expr.pos, 1);
+            gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
+        }
+    }
+
+    /* Call recursively for all children unless the children have already been processed */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        child = sel->child;
+        while (child)
+        {
+            init_item_comg(child, pcc, type, flags);
+            child = child->next;
+        }
+    }
+}
+
+
+/********************************************************************
+ * COMPILER DATA FREEING
+ ********************************************************************/
+
+/*! \brief
+ * Frees the allocated compiler data recursively.
+ *
+ * \param     sel Root of the selection subtree to process.
+ *
+ * Frees the data allocated for the compilation process.
+ */
+static void
+free_item_compilerdata(t_selelem *sel)
+{
+    t_selelem *child;
+
+    /* Free compilation data */
+    _gmx_selelem_free_compiler_data(sel);
+
+    /* Call recursively for all children unless the children have already been processed */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        child = sel->child;
+        while (child)
+        {
+            free_item_compilerdata(child);
+            child = child->next;
+        }
+    }
+}
+
+
+/********************************************************************
+ * MASS AND CHARGE CALCULATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes total masses and charges for selections.
+ *
+ * \param[in,out] selections Array of selections to update.
+ * \param[in]     top   Topology information.
+ */
+static void
+calculate_mass_charge(std::vector<gmx::Selection *> *selections,
+                      t_topology *top)
+{
+    int   b, i;
+
+    for (size_t g = 0; g < selections->size(); ++g)
+    {
+        gmx_ana_selection_t *sel = &selections->at(g)->_sel;
+        bool bMaskOnly = selections->at(g)->hasFlag(gmx::efDynamicMask);
+
+        sel->g = sel->p.g;
+        snew(sel->orgm, sel->p.nr);
+        snew(sel->orgq, sel->p.nr);
+        for (b = 0; b < sel->p.nr; ++b)
+        {
+            sel->orgq[b] = 0;
+            if (top)
+            {
+                sel->orgm[b] = 0;
+                for (i = sel->p.m.mapb.index[b]; i < sel->p.m.mapb.index[b+1]; ++i)
+                {
+                    sel->orgm[b] += top->atoms.atom[sel->g->index[i]].m;
+                    sel->orgq[b] += top->atoms.atom[sel->g->index[i]].q;
+                }
+            }
+            else
+            {
+                sel->orgm[b] = 1;
+            }
+        }
+        if (sel->bDynamic && !bMaskOnly)
+        {
+            snew(sel->m, sel->p.nr);
+            snew(sel->q, sel->p.nr);
+            for (b = 0; b < sel->p.nr; ++b)
+            {
+                sel->m[b] = sel->orgm[b];
+                sel->q[b] = sel->orgq[b];
+            }
+        }
+        else
+        {
+            sel->m = sel->orgm;
+            sel->q = sel->orgq;
+        }
+    }
+}
+
+
+/********************************************************************
+ * MAIN COMPILATION FUNCTION
+ ********************************************************************/
+
+/*!
+ * \param[in,out] coll Selection collection to be compiled.
+ * \returns       0 on successful compilation, a non-zero error code on error.
+ *
+ * Before compilation, the selection collection should have been initialized
+ * with gmx_ana_selcollection_parse_*().
+ * The compiled selection collection can be passed to
+ * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
+ * If an error occurs, \p sc is cleared.
+ *
+ * The covered fraction information in \p sc is initialized to
+ * \ref CFRAC_NONE.
+ */
+void
+gmx_ana_selcollection_compile(gmx::SelectionCollection *coll)
+{
+    gmx_ana_selcollection_t *sc = &coll->_impl->_sc;
+    gmx_sel_evaluate_t  evaldata;
+    t_selelem   *item;
+    e_poscalc_t  post;
+    size_t       i;
+    int          flags;
+    bool         bDebug = (coll->_impl->_debugLevel >= 2
+                           && coll->_impl->_debugLevel != 3);
+
+    /* FIXME: Clean up the collection on exceptions */
+
+    sc->mempool = _gmx_sel_mempool_create();
+    _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
+                           sc->top, NULL, NULL);
+
+    /* Clear the symbol table because it is not possible to parse anything
+     * after compilation, and variable references in the symbol table can
+     * also mess up the compilation and/or become invalid.
+     */
+    coll->_impl->clearSymbolTable();
+
+    /* Loop through selections and initialize position keyword defaults if no
+     * other value has been provided.
+     */
+    for (i = 0; i < sc->sel.size(); ++i)
+    {
+        gmx::Selection *sel = sc->sel[i];
+        init_pos_keyword_defaults(sel->_sel.selelem,
+                                  coll->_impl->_spost.c_str(),
+                                  coll->_impl->_rpost.c_str(),
+                                  sel);
+    }
+
+    /* Remove any unused variables. */
+    sc->root = remove_unused_subexpressions(sc->root);
+    /* Extract subexpressions into separate roots */
+    sc->root = extract_subexpressions(sc->root);
+
+    /* Initialize the evaluation callbacks and process the tree structure
+     * to conform to the expectations of the callback functions. */
+    /* Also, initialize and allocate the compiler data structure */
+    item = sc->root;
+    while (item)
+    {
+        /* Process gmx_boolean and arithmetic expressions. */
+        optimize_gmx_boolean_expressions(item);
+        reorder_gmx_boolean_static_children(item);
+        optimize_arithmetic_expressions(item);
+        /* Initialize evaluation */
+        init_item_evalfunc(item);
+        setup_memory_pooling(item, sc->mempool);
+        /* Initialize the compiler data */
+        init_item_compilerdata(item);
+        init_item_staticeval(item);
+        item = item->next;
+    }
+    /* Initialize subexpression flags and evaluation output.
+     * Requires compiler flags for the full tree. */
+    item = sc->root;
+    while (item)
+    {
+        init_item_subexpr_flags(item);
+        init_item_evaloutput(item);
+        item = item->next;
+    }
+    /* Initialize minimum/maximum index groups.
+     * Requires evaluation output for the full tree. */
+    item = sc->root;
+    while (item)
+    {
+        init_item_minmax_groups(item);
+        item = item->next;
+    }
+    /* Initialize the evaluation index groups */
+    initialize_evalgrps(sc);
+
+    if (bDebug)
+    {
+        fprintf(stderr, "\nTree after initial compiler processing:\n");
+        coll->printTree(stderr, false);
+    }
+
+    /* Evaluate all static parts of the selection and analyze the tree
+     * to allocate enough memory to store the value of each dynamic subtree. */
+    item = sc->root;
+    while (item)
+    {
+        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+        {
+            mark_subexpr_dynamic(item->child, TRUE);
+        }
+        set_evaluation_function(item, &analyze_static);
+        item->evaluate(&evaldata, item, NULL);
+        item = item->next;
+    }
+
+    /* At this point, static subexpressions no longer have references to them,
+     * so they can be removed. */
+    sc->root = remove_unused_subexpressions(sc->root);
+
+    if (bDebug)
+    {
+        fprintf(stderr, "\nTree after first analysis pass:\n");
+        coll->printTree(stderr, false);
+    }
+
+    /* Do a second pass to evaluate static parts of common subexpressions */
+    item = sc->root;
+    while (item)
+    {
+        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+        {
+            bool bMinMax = item->child->cdata->flags & SEL_CDATA_DOMINMAX;
+
+            mark_subexpr_dynamic(item->child, FALSE);
+            item->child->u.cgrp.isize = 0;
+            /* We won't clear item->child->v.u.g here, because it may
+             * be static, and hence actually point to item->child->cdata->gmax,
+             * which is used below. We could also check whether this is the
+             * case and only clear the group otherwise, but because the value
+             * is actually overwritten immediately in the evaluate call, we
+             * won't, because similar problems may arise if gmax handling ever
+             * changes and the check were not updated.
+             * For the same reason, we clear the min/max flag so that the
+             * evaluation group doesn't get messed up. */
+            set_evaluation_function(item, &analyze_static);
+            item->child->cdata->flags &= ~SEL_CDATA_DOMINMAX;
+            item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
+            if (bMinMax)
+            {
+                item->child->cdata->flags |= SEL_CDATA_DOMINMAX;
+            }
+        }
+        item = item->next;
+    }
+
+    /* We need a yet another pass of subexpression removal to remove static
+     * subexpressions referred to by common dynamic subexpressions. */
+    sc->root = remove_unused_subexpressions(sc->root);
+
+    if (bDebug)
+    {
+        fprintf(stderr, "\nTree after second analysis pass:\n");
+        coll->printTree(stderr, false);
+    }
+
+    /* Initialize evaluation groups, position calculations for methods, perform
+     * some final optimization, and free the memory allocated for the
+     * compilation. */
+    /* By default, use whole residues/molecules. */
+    flags = POS_COMPLWHOLE;
+    gmx_ana_poscalc_type_from_enum(coll->_impl->_rpost.c_str(), &post, &flags);
+    item = sc->root;
+    while (item)
+    {
+        init_root_item(item, &sc->gall);
+        postprocess_item_subexpressions(item);
+        init_item_comg(item, sc->pcc, post, flags);
+        free_item_compilerdata(item);
+        item = item->next;
+    }
+
+    /* Allocate memory for the evaluation memory pool. */
+    _gmx_sel_mempool_reserve(sc->mempool, 0);
+
+    /* Finish up by calculating total masses and charges. */
+    calculate_mass_charge(&sc->sel, sc->top);
+}
diff --git a/src/gromacs/selection/evaluate.cpp b/src/gromacs/selection/evaluate.cpp
new file mode 100644 (file)
index 0000000..a74b916
--- /dev/null
@@ -0,0 +1,1080 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in evaluate.h.
+ *
+ * \todo
+ * One of the major bottlenecks for selection performance is that all the
+ * evaluation is carried out for atoms.
+ * There are several cases when the evaluation could be done for residues
+ * or molecules instead, including keywords that select by residue and
+ * cases where residue centers are used as reference positions.
+ * Implementing this would require a mechanism for recognizing whether
+ * something can be evaluated by residue/molecule instead by atom, and
+ * converting selections by residue/molecule into selections by atom
+ * when necessary.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <maths.h>
+#include <smalloc.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "evaluate.h"
+#include "mempool.h"
+#include "selectioncollection-impl.h"
+#include "selelem.h"
+
+/*! \internal \brief
+ * Reserves memory for a selection element from the evaluation memory pool.
+ */
+class MempoolSelelemReserver
+{
+    public:
+        MempoolSelelemReserver() : sel_(NULL) {}
+        MempoolSelelemReserver(t_selelem *sel, int count)
+            : sel_(NULL)
+        {
+            reserve(sel, count);
+        }
+        ~MempoolSelelemReserver()
+        {
+            if (sel_ != NULL)
+            {
+                _gmx_selelem_mempool_release(sel_);
+            }
+        }
+
+        void reserve(t_selelem *sel, int count)
+        {
+            GMX_RELEASE_ASSERT(sel_ == NULL, "Can only reserve one element with one instance");
+            _gmx_selelem_mempool_reserve(sel, count);
+            sel_ = sel;
+        }
+
+    private:
+        t_selelem              *sel_;
+};
+
+/*! \internal \brief
+ * Reserves memory for an index group from the evaluation memory pool.
+ */
+class MempoolGroupReserver
+{
+    public:
+        explicit MempoolGroupReserver(gmx_sel_mempool_t *mp)
+            : mp_(mp), g_(NULL)
+        {
+        }
+        ~MempoolGroupReserver()
+        {
+            if (g_ != NULL)
+            {
+                _gmx_sel_mempool_free_group(mp_, g_);
+            }
+        }
+
+        void reserve(gmx_ana_index_t *g, int count)
+        {
+            GMX_RELEASE_ASSERT(g_ == NULL, "Can only reserve one element with one instance");
+            _gmx_sel_mempool_alloc_group(mp_, g, count);
+            g_ = g;
+        }
+
+    private:
+        gmx_sel_mempool_t      *mp_;
+        gmx_ana_index_t        *g_;
+};
+
+/*! \internal \brief
+ * Assigns a temporary value for a selection element.
+ */
+class SelelemTemporaryValueAssigner
+{
+    public:
+        SelelemTemporaryValueAssigner()
+            : sel_(NULL), old_ptr_(NULL), old_nalloc_(0)
+        {
+        }
+        SelelemTemporaryValueAssigner(t_selelem *sel, t_selelem *vsource)
+            : sel_(NULL)
+        {
+            assign(sel, vsource);
+        }
+        ~SelelemTemporaryValueAssigner()
+        {
+            if (sel_ != NULL)
+            {
+                _gmx_selvalue_setstore_alloc(&sel_->v, old_ptr_, old_nalloc_);
+            }
+        }
+
+        void assign(t_selelem *sel, t_selelem *vsource)
+        {
+            GMX_RELEASE_ASSERT(sel_ == NULL, "Can only assign one element with one instance");
+            old_ptr_ = sel->v.u.ptr;
+            old_nalloc_ = sel->v.nalloc;
+            _gmx_selvalue_setstore(&sel->v, vsource->v.u.ptr);
+            sel_ = sel;
+        }
+
+    private:
+        t_selelem              *sel_;
+        void                   *old_ptr_;
+        int                     old_nalloc_;
+};
+
+/*!
+ * \param[in] fp       File handle to receive the output.
+ * \param[in] evalfunc Function pointer to print.
+ */
+void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc)
+{
+    if (!evalfunc)
+        fprintf(fp, "none");
+    else if (evalfunc == &_gmx_sel_evaluate_root)
+        fprintf(fp, "root");
+    else if (evalfunc == &_gmx_sel_evaluate_static)
+        fprintf(fp, "static");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr_simple)
+        fprintf(fp, "subexpr_simple");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr_staticeval)
+        fprintf(fp, "subexpr_staticeval");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr)
+        fprintf(fp, "subexpr");
+    else if (evalfunc == &_gmx_sel_evaluate_subexprref_simple)
+        fprintf(fp, "ref_simple");
+    else if (evalfunc == &_gmx_sel_evaluate_subexprref)
+        fprintf(fp, "ref");
+    else if (evalfunc == &_gmx_sel_evaluate_method)
+        fprintf(fp, "method");
+    else if (evalfunc == &_gmx_sel_evaluate_modifier)
+        fprintf(fp, "mod");
+    else if (evalfunc == &_gmx_sel_evaluate_not)
+        fprintf(fp, "not");
+    else if (evalfunc == &_gmx_sel_evaluate_and)
+        fprintf(fp, "and");
+    else if (evalfunc == &_gmx_sel_evaluate_or)
+        fprintf(fp, "or");
+    else if (evalfunc == &_gmx_sel_evaluate_arithmetic)
+        fprintf(fp, "arithmetic");
+    else
+        fprintf(fp, "%p", (void*)(evalfunc));
+}
+
+/*!
+ * \param[out] data Evaluation data structure to initialize.
+ * \param[in]  mp   Memory pool for intermediate evaluation values.
+ * \param[in]  gall Index group with all the atoms.
+ * \param[in]  top  Topology structure for evaluation.
+ * \param[in]  fr   New frame for evaluation.
+ * \param[in]  pbc  New PBC information for evaluation.
+ */
+void
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+                       gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
+                       t_topology *top, t_trxframe *fr, t_pbc *pbc)
+{
+    data->mp   = mp;
+    data->gall = gall;
+    data->top  = top;
+    data->fr   = fr;
+    data->pbc  = pbc;
+}
+
+/*! \brief
+ * Recursively initializes the flags for evaluation.
+ *
+ * \param[in,out] sel Selection element to clear.
+ *
+ * The \ref SEL_INITFRAME flag is set for \ref SEL_EXPRESSION elements whose
+ * method defines the \p init_frame callback (see sel_framefunc()), and
+ * cleared for other elements.
+ *
+ * The \ref SEL_EVALFRAME flag is cleared for all elements.
+ */
+static void
+init_frame_eval(t_selelem *sel)
+{
+    while (sel)
+    {
+        sel->flags &= ~(SEL_INITFRAME | SEL_EVALFRAME);
+        if (sel->type == SEL_EXPRESSION)
+        {
+            if (sel->u.expr.method && sel->u.expr.method->init_frame)
+            {
+                sel->flags |= SEL_INITFRAME;
+            }
+        }
+        if (sel->child && sel->type != SEL_SUBEXPRREF)
+        {
+            init_frame_eval(sel->child);
+        }
+        sel = sel->next;
+    }
+}
+
+/*!
+ * \param[in,out] sc  The selection collection to evaluate.
+ * \param[in] fr  Frame for which the evaluation should be carried out.
+ * \param[in] pbc PBC data, or NULL if no PBC should be used.
+ * \returns   0 on successful evaluation, a non-zero error code on error.
+ *
+ * This functions sets the global variables for topology, frame and PBC,
+ * clears some information in the selection to initialize the evaluation
+ * for a new frame, and evaluates \p sel and all the selections pointed by
+ * the \p next pointers of \p sel.
+ *
+ * This is the only function that user code should call if they want to
+ * evaluate a selection for a new frame.
+ */
+void
+gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
+                               t_trxframe *fr, t_pbc *pbc)
+{
+    gmx_sel_evaluate_t  data;
+    t_selelem          *sel;
+
+    _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
+    init_frame_eval(sc->root);
+    sel = sc->root;
+    while (sel)
+    {
+        /* Clear the evaluation group of subexpressions */
+        if (sel->child && sel->child->type == SEL_SUBEXPR)
+        {
+            sel->child->u.cgrp.isize = 0;
+            /* Not strictly necessary, because the value will be overwritten
+             * during first evaluation of the subexpression anyways, but we
+             * clear the group for clarity. Note that this is _not_ done during
+             * compilation because of some additional complexities involved
+             * (see compiler.c), so it should not be relied upon in
+             * _gmx_sel_evaluate_subexpr(). */
+            if (sel->child->v.type == GROUP_VALUE)
+            {
+                sel->child->v.u.g->isize = 0;
+            }
+        }
+        if (sel->evaluate)
+        {
+            sel->evaluate(&data, sel, NULL);
+        }
+        sel = sel->next;
+    }
+    /* Update selection information */
+    for (size_t g = 0; g < sc->sel.size(); ++g)
+    {
+        gmx_ana_selection_t *sel = &sc->sel[g]->_sel;
+
+        if (sel->m != sel->orgm)
+        {
+            for (int i = 0; i < sel->p.nr; ++i)
+            {
+                sel->m[i] = sel->orgm[sel->p.m.refid[i]];
+                sel->q[i] = sel->orgq[sel->p.m.refid[i]];
+            }
+        }
+        if (sel->bCFracDyn)
+        {
+            sel->cfrac = _gmx_selelem_estimate_coverfrac(sel->selelem);
+            sel->avecfrac += sel->cfrac;
+        }
+    }
+}
+
+/*!
+ * \param[in,out] sc  The selection collection to evaluate.
+ * \param[in]     nframes Total number of frames.
+ */
+void
+gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes)
+{
+    t_selelem          *sel;
+
+    for (size_t g = 0; g < sc->sel.size(); ++g)
+    {
+        gmx_ana_selection_t *sel = &sc->sel[g]->_sel;
+        bool bMaskOnly = sc->sel[g]->hasFlag(gmx::efDynamicMask);
+        t_selelem *elem = sel->selelem;
+        if (sel->bDynamic)
+        {
+            gmx_ana_index_copy(sel->g, elem->v.u.g, FALSE);
+            sel->g->name = NULL;
+            gmx_ana_indexmap_update(&sel->p.m, sel->g, bMaskOnly);
+            sel->p.nr = sel->p.m.nr;
+        }
+
+        if (sel->bCFracDyn)
+        {
+            sel->avecfrac /= nframes;
+        }
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates each child of \p sel in \p g.
+ */
+void
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel,
+                           gmx_ana_index_t *g)
+{
+    t_selelem  *child;
+
+    child = sel->child;
+    while (child)
+    {
+        if (child->evaluate)
+        {
+            child->evaluate(data, child, g);
+        }
+        child = child->next;
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated
+ *   (not used, can be NULL).
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates the first child element in the group defined by \p sel->u.cgrp.
+ * If \p sel->u.cgrp is empty, nothing is done.
+ * The value of \p sel is not touched (root elements do not evaluate to
+ * values).
+ *
+ * This function can be used as \c t_selelem::evaluate for \ref SEL_ROOT
+ * elements.
+ */
+void
+_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (sel->u.cgrp.isize == 0 || !sel->child->evaluate)
+    {
+        return;
+    }
+
+    sel->child->evaluate(data, sel->child,
+                         sel->u.cgrp.isize < 0 ? NULL : &sel->u.cgrp);
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 for success.
+ *
+ * Sets the value of \p sel to the intersection of \p g and \p sel->u.cgrp.
+ *
+ * This function can be used as \c t_selelem::evaluate for \ref SEL_CONST
+ * elements with value type \ref GROUP_VALUE.
+ */
+void
+_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    gmx_ana_index_intersection(sel->v.u.g, &sel->u.cgrp, g);
+}
+
+
+/*********************************************************************
+ * SUBEXPRESSION EVALUATION
+ *********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates the child element (there should be exactly one) in \p g.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
+ * elements that are used only once, and hence do not need full subexpression
+ * handling.
+ */
+void
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (sel->child->evaluate)
+    {
+        sel->child->evaluate(data, sel->child, g);
+    }
+    sel->v.nr = sel->child->v.nr;
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * If this is the first call for this frame, evaluates the child element
+ * there should be exactly one in \p g.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
+ * Assumes that \p g is persistent for the duration of the whole evaluation.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
+ * elements that have a static evaluation group, and hence do not need full
+ * subexpression handling.
+ */
+void
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (sel->u.cgrp.isize == 0)
+    {
+        sel->child->evaluate(data, sel->child, g);
+        sel->v.nr = sel->child->v.nr;
+        gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, sel->u.cgrp.name, 0);
+    }
+}
+
+/*!
+ * \param[in]  data  Data for the current frame.
+ * \param[in]  sel   Selection element being evaluated.
+ * \param[in]  g     Group for which \p sel should be evaluated.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Finds the part of \p g for which the subexpression
+ * has not yet been evaluated by comparing \p g to \p sel->u.cgrp.
+ * If the part is not empty, the child expression is evaluated for this
+ * part, and the results merged to the old values of the child.
+ * The value of \p sel itself is undefined after the call.
+ *
+ * \todo
+ * The call to gmx_ana_index_difference() can take quite a lot of unnecessary
+ * time if the subexpression is evaluated either several times for the same
+ * group or for completely distinct groups.
+ * However, in the majority of cases, these situations occur when
+ * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a
+ * major problem.
+ */
+void
+_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    gmx_ana_index_t  gmiss;
+
+    MempoolGroupReserver gmissreserver(data->mp);
+    if (sel->u.cgrp.isize == 0)
+    {
+        {
+            SelelemTemporaryValueAssigner assigner(sel->child, sel);
+            sel->child->evaluate(data, sel->child, g);
+        }
+        /* We need to keep the name for the cgrp across the copy to avoid
+         * problems if g has a name set. */
+        char *name = sel->u.cgrp.name;
+        gmx_ana_index_copy(&sel->u.cgrp, g, FALSE);
+        sel->u.cgrp.name = name;
+        gmiss.isize = 0;
+    }
+    else
+    {
+        gmissreserver.reserve(&gmiss, g->isize);
+        gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
+    }
+    if (gmiss.isize > 0)
+    {
+        MempoolSelelemReserver reserver(sel->child, gmiss.isize);
+        /* Evaluate the missing values for the child */
+        sel->child->evaluate(data, sel->child, &gmiss);
+        /* Merge the missing values to the existing ones. */
+        if (sel->v.type == GROUP_VALUE)
+        {
+            gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g);
+        }
+        else
+        {
+            int  i, j, k;
+
+            i = sel->u.cgrp.isize - 1;
+            j = gmiss.isize - 1;
+            /* TODO: This switch is kind of ugly, but it may be difficult to
+             * do this portably without C++ templates. */
+            switch (sel->v.type)
+            {
+                case INT_VALUE:
+                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
+                    {
+                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
+                        {
+                            sel->v.u.i[k] = sel->v.u.i[j--];
+                        }
+                        else
+                        {
+                            sel->v.u.i[k] = sel->child->v.u.i[i--];
+                        }
+                    }
+                    break;
+
+                case REAL_VALUE:
+                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
+                    {
+                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
+                        {
+                            sel->v.u.r[k] = sel->v.u.r[j--];
+                        }
+                        else
+                        {
+                            sel->v.u.r[k] = sel->child->v.u.r[i--];
+                        }
+                    }
+                    break;
+
+                case STR_VALUE:
+                    for (k = sel->u.cgrp.isize + gmiss.isize - 1; k >= 0; k--)
+                    {
+                        if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
+                        {
+                            sel->v.u.s[k] = sel->v.u.s[j--];
+                        }
+                        else
+                        {
+                            sel->v.u.s[k] = sel->child->v.u.s[i--];
+                        }
+                    }
+                    break;
+
+                case POS_VALUE:
+                    /* TODO: Implement this */
+                    GMX_THROW(gmx::NotImplementedError("position subexpressions not implemented properly"));
+
+                case NO_VALUE:
+                case GROUP_VALUE:
+                    GMX_THROW(gmx::InternalError("Invalid subexpression type"));
+            }
+        }
+        gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 for success.
+ *
+ * Sets the value pointers of the child and its child to point to the same
+ * memory as the value pointer of this element to avoid copying, and then
+ * evaluates evaluates the child.
+ *
+ * This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
+ * elements for which the \ref SEL_SUBEXPR does not have other references.
+ */
+void
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (g)
+    {
+        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+        _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
+                                     sel->child->child->v.nalloc);
+        sel->child->evaluate(data, sel->child, g);
+    }
+    sel->v.nr = sel->child->v.nr;
+    if (sel->u.param)
+    {
+        sel->u.param->val.nr = sel->v.nr;
+        if (sel->u.param->nvalptr)
+        {
+            *sel->u.param->nvalptr = sel->u.param->val.nr;
+        }
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * If the value type is \ref POS_VALUE, the value of the child is simply
+ * copied to set the value of \p sel (the child subexpression should
+ * already have been evaluated by its root).
+ * If the value type is something else, the child is evaluated for the
+ * group \p g, and the value of the child is then copied.
+ * There should be only one child element.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPRREF
+ * elements.
+ */
+void
+_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    t_selelem *expr;
+    int        i, j;
+
+    if (g)
+    {
+        sel->child->evaluate(data, sel->child, g);
+    }
+    expr = sel->child;
+    switch (sel->v.type)
+    {
+        case INT_VALUE:
+            if (!g)
+            {
+                sel->v.nr = expr->v.nr;
+                memcpy(sel->v.u.i, expr->v.u.i, sel->v.nr*sizeof(*sel->v.u.i));
+            }
+            else
+            {
+                sel->v.nr = g->isize;
+                /* Extract the values corresponding to g */
+                for (i = j = 0; i < g->isize; ++i, ++j)
+                {
+                    while (sel->child->u.cgrp.index[j] < g->index[i])
+                    {
+                        ++j;
+                    }
+                    sel->v.u.i[i] = expr->v.u.i[j];
+                }
+            }
+            break;
+
+        case REAL_VALUE:
+            if (!g)
+            {
+                sel->v.nr = expr->v.nr;
+                memcpy(sel->v.u.r, expr->v.u.r, sel->v.nr*sizeof(*sel->v.u.r));
+            }
+            else
+            {
+                sel->v.nr = g->isize;
+                /* Extract the values corresponding to g */
+                for (i = j = 0; i < g->isize; ++i, ++j)
+                {
+                    while (sel->child->u.cgrp.index[j] < g->index[i])
+                    {
+                        ++j;
+                    }
+                    sel->v.u.r[i] = expr->v.u.r[j];
+                }
+            }
+            break;
+
+        case STR_VALUE:
+            if (!g)
+            {
+                sel->v.nr = expr->v.nr;
+                memcpy(sel->v.u.s, expr->v.u.s, sel->v.nr*sizeof(*sel->v.u.s));
+            }
+            else
+            {
+                sel->v.nr = g->isize;
+                /* Extract the values corresponding to g */
+                for (i = j = 0; i < g->isize; ++i, ++j)
+                {
+                    while (sel->child->u.cgrp.index[j] < g->index[i])
+                    {
+                        ++j;
+                    }
+                    sel->v.u.s[i] = expr->v.u.s[j];
+                }
+            }
+            break;
+
+        case POS_VALUE:
+            /* Currently, there is no need to do anything fancy here,
+             * but some future extensions may need a more flexible
+             * implementation. */
+            gmx_ana_pos_copy(sel->v.u.p, expr->v.u.p, FALSE);
+            break;
+
+        case GROUP_VALUE:
+            if (!g)
+            {
+                gmx_ana_index_copy(sel->v.u.g, expr->v.u.g, FALSE);
+            }
+            else
+            {
+                gmx_ana_index_intersection(sel->v.u.g, expr->v.u.g, g);
+            }
+            break;
+
+        default: /* should not be reached */
+            GMX_THROW(gmx::InternalError("Invalid subexpression reference type"));
+    }
+    /* Store the number of values if needed */
+    if (sel->u.param)
+    {
+        sel->u.param->val.nr = sel->v.nr;
+        if (sel->u.param->nvalptr)
+        {
+            *sel->u.param->nvalptr = sel->u.param->val.nr;
+        }
+    }
+}
+
+/********************************************************************
+ * METHOD EXPRESSION EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates each child of a \ref SEL_EXPRESSION element.
+ * The value of \p sel is not touched.
+ *
+ * This function is not used as \c t_selelem::evaluate,
+ * but is used internally.
+ */
+void
+_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    t_selelem *child;
+
+    child = sel->child;
+    while (child)
+    {
+        if (child->evaluate && !(child->flags & SEL_EVALFRAME))
+        {
+            if (child->flags & SEL_ATOMVAL)
+            {
+                child->evaluate(data, child, g);
+            }
+            else
+            {
+                child->flags |= SEL_EVALFRAME;
+                child->evaluate(data, child, NULL);
+            }
+        }
+        child = child->next;
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
+ * to evaluate any parameter values.
+ * If this is the first time this expression is evaluated for
+ * the frame, sel_framefunc() callback is called if one is provided.
+ * If a reference position calculation has been initialized for this element,
+ * the positions are also updated, and sel_updatefunc_pos() is used to
+ * evaluate the value. Otherwise, sel_updatefunc() is used.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_EXPRESSION
+ * elements.
+ */
+void
+_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    _gmx_sel_evaluate_method_params(data, sel, g);
+    if (sel->flags & SEL_INITFRAME)
+    {
+        sel->flags &= ~SEL_INITFRAME;
+        sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
+                                       sel->u.expr.mdata);
+    }
+    if (sel->u.expr.pc)
+    {
+        gmx_ana_poscalc_update(sel->u.expr.pc, sel->u.expr.pos, g,
+                               data->fr, data->pbc);
+        sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
+                                    sel->u.expr.pos, &sel->v,
+                                    sel->u.expr.mdata);
+    }
+    else
+    {
+        sel->u.expr.method->update(data->top, data->fr, data->pbc, g,
+                                   &sel->v, sel->u.expr.mdata);
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates all child selections (using _gmx_sel_evaluate_method_params())
+ * to evaluate any parameter values.
+ * If this is the first time this expression is evaluated for
+ * the frame, sel_framefunc() callback is called if one is provided.
+ * The modifier is then evaluated using sel_updatefunc_pos().
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_MODIFIER
+ * elements.
+ */
+void
+_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    _gmx_sel_evaluate_method_params(data, sel, g);
+    if (sel->flags & SEL_INITFRAME)
+    {
+        sel->flags &= ~SEL_INITFRAME;
+        sel->u.expr.method->init_frame(data->top, data->fr, data->pbc,
+                                            sel->u.expr.mdata);
+    }
+    if (sel->child->v.type != POS_VALUE)
+    {
+        GMX_THROW(gmx::NotImplementedError("Non-position valued modifiers not implemented"));
+    }
+    sel->u.expr.method->pupdate(data->top, data->fr, data->pbc,
+                                sel->child->v.u.p,
+                                &sel->v, sel->u.expr.mdata);
+}
+
+
+/********************************************************************
+ * BOOLEAN EXPRESSION EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates the child element (there should be only one) in the group
+ * \p g, and then sets the value of \p sel to the complement of the 
+ * child value.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
+ * elements with \ref BOOL_NOT.
+ */
+void
+_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    MempoolSelelemReserver reserver(sel->child, g->isize);
+    sel->child->evaluate(data, sel->child, g);
+    gmx_ana_index_difference(sel->v.u.g, g, sel->child->v.u.g);
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Short-circuiting evaluation of logical AND expressions.
+ *
+ * Starts by evaluating the first child element in the group \p g.
+ * The each following child element is evaluated in the intersection
+ * of all the previous values until all children have been evaluated
+ * or the intersection becomes empty.
+ * The value of \p sel is set to the intersection of all the (evaluated)
+ * child values.
+ *
+ * If the first child does not have an evaluation function, it is skipped
+ * and the evaluation is started at the second child.
+ * This happens if the first child is a constant expression and during
+ * compilation it was detected that the evaluation group is always a subset
+ * of the constant group
+ * (currently, the compiler never detects this).
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
+ * elements with \ref BOOL_AND.
+ */
+void
+_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    t_selelem *child;
+
+    child = sel->child;
+    /* Skip the first child if it does not have an evaluation function. */
+    if (!child->evaluate)
+    {
+        child = child->next;
+    }
+    /* Evaluate the first child */
+    {
+        MempoolSelelemReserver reserver(child, g->isize);
+        child->evaluate(data, child, g);
+        gmx_ana_index_copy(sel->v.u.g, child->v.u.g, FALSE);
+    }
+    child = child->next;
+    while (child && sel->v.u.g->isize > 0)
+    {
+        MempoolSelelemReserver reserver(child, sel->v.u.g->isize);
+        child->evaluate(data, child, sel->v.u.g);
+        gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
+        child = child->next;
+    }
+}
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel Selection element being evaluated.
+ * \param[in] g   Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Short-circuiting evaluation of logical OR expressions.
+ *
+ * Starts by evaluating the first child element in the group \p g.
+ * For each subsequent child, finds the part of \p g that is not
+ * included the value of any previous child, and evaluates the child
+ * in that group until the last child is evaluated or all of \p g
+ * is included in some child value.
+ * The value of \p sel is set to the union of all the (evaluated)
+ * child values.
+ *
+ * If the first child does not have an evaluation function, its value is
+ * used without evaluation.
+ * This happens if the first child is a constant expression, the selection
+ * has been compiled, and the evaluation group is the same for each frame.
+ * In this case, the compiler has taken care of that the child value is a
+ * subset of \p g, making it unnecessary to evaluate it.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
+ * elements with \ref BOOL_OR.
+ */
+void
+_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    t_selelem     *child;
+    gmx_ana_index_t  tmp, tmp2;
+
+    child = sel->child;
+    if (child->evaluate)
+    {
+        MempoolSelelemReserver reserver(child, g->isize);
+        child->evaluate(data, child, g);
+        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
+    }
+    else
+    {
+        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
+    }
+    child = child->next;
+    while (child && tmp.isize > 0)
+    {
+        tmp.name = NULL;
+        {
+            MempoolSelelemReserver reserver(child, tmp.isize);
+            child->evaluate(data, child, &tmp);
+            gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
+        }
+        sel->v.u.g->isize += tmp.isize;
+        tmp.isize = tmp2.isize;
+        tmp.index = tmp2.index;
+        child = child->next;
+    }
+    gmx_ana_index_sort(sel->v.u.g);
+}
+
+
+/********************************************************************
+ * ARITHMETIC EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ */
+void
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel,
+                             gmx_ana_index_t *g)
+{
+    t_selelem  *left, *right;
+    int         n, i, i1, i2;
+    real        lval, rval=0., val=0.;
+
+    left  = sel->child;
+    right = left->next;
+
+    SelelemTemporaryValueAssigner assigner;
+    MempoolSelelemReserver reserver;
+    if (left->mempool)
+    {
+        assigner.assign(left, sel);
+        if (right)
+        {
+            reserver.reserve(right, g->isize);
+        }
+    }
+    else if (right && right->mempool)
+    {
+        assigner.assign(right, sel);
+    }
+    _gmx_sel_evaluate_children(data, sel, g);
+
+    n = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
+    sel->v.nr = n;
+    for (i = i1 = i2 = 0; i < n; ++i)
+    {
+        lval = left->v.u.r[i1];
+        if (sel->u.arith.type != ARITH_NEG)
+        {
+            rval = right->v.u.r[i2];
+        }
+        switch (sel->u.arith.type)
+        {
+            case ARITH_PLUS:    val = lval + rval;     break;
+            case ARITH_MINUS:   val = lval - rval;     break;
+            case ARITH_NEG:     val = -lval;           break;
+            case ARITH_MULT:    val = lval * rval;     break;
+            case ARITH_DIV:     val = lval / rval;     break;
+            case ARITH_EXP:     val = pow(lval, rval); break;
+        }
+        sel->v.u.r[i] = val;
+        if (!(left->flags & SEL_SINGLEVAL))
+        {
+            ++i1;
+        }
+        if (sel->u.arith.type != ARITH_NEG && !(right->flags & SEL_SINGLEVAL))
+        {
+            ++i2;
+        }
+    }
+}
diff --git a/src/gromacs/selection/evaluate.h b/src/gromacs/selection/evaluate.h
new file mode 100644 (file)
index 0000000..3947e43
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Evaluation functions for sel_evalfunc().
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ * Users should only use SelectionCollection::evaluate() to evaluate
+ * selections.
+ *
+ * The functions defined in this header file are all the possible values
+ * for the \c t_selelem::evaluate field (in addition to NULL).
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_EVALUATE_H
+#define GMX_SELECTION_EVALUATE_H
+
+#include <typedefs.h>
+
+#include "gromacs/selection/indexutil.h"
+
+#include "selelem.h"
+
+struct gmx_sel_mempool_t;
+
+/*! \internal \brief
+ * Data structure for passing information required during evaluation.
+ */
+typedef struct gmx_sel_evaluate_t
+{
+    /** Memory pool for intermediate values. */
+    struct gmx_sel_mempool_t *mp;
+    /** Index group that contains all the atoms. */
+    gmx_ana_index_t         *gall;
+    /** Topology information. */
+    t_topology              *top;
+    /** Current frame. */
+    t_trxframe              *fr;
+    /** PBC data. */
+    t_pbc                   *pbc;
+} gmx_sel_evaluate_t;
+
+/*! \name Utility functions
+ */
+/*@{*/
+/** Initializes an evaluation data structure. */
+void
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+                       struct gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
+                       t_topology *top, t_trxframe *fr, t_pbc *pbc);
+/** Evaluates the children of a general selection element. */
+void
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates the children of a \ref SEL_EXPRESSION element. */
+void
+_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Misc. evaluation functions
+ */
+/*@{*/
+/** Evaluates a root selection element. */
+void
+_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a static group selection element. */
+void
+_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates an arithmetic expression element. */
+void
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Subexpression evaluation functions
+ */
+/*@{*/
+/** Evaluates a subexpression when there is only one reference. */
+void
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression when the evaluation group is static. */
+void
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression. */
+void
+_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression reference when there are no other references. */
+void
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression reference. */
+void
+_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Method evaluation functions
+ */
+/*@{*/
+
+/** Evaluates a method expression. */
+void
+_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a modifier expression. */
+void
+_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Boolean evaluation functions
+ */
+/*@{*/
+/** Evaluates a boolean NOT element. */
+void
+_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a boolean AND element with short-circuiting. */
+void
+_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a boolean OR element with short-circuiting. */
+void
+_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/*@}*/
+
+#endif
diff --git a/src/gromacs/selection/indexutil.cpp b/src/gromacs/selection/indexutil.cpp
new file mode 100644 (file)
index 0000000..02f2848
--- /dev/null
@@ -0,0 +1,1459 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in indexutil.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <index.h>
+#include <smalloc.h>
+#include <string2.h>
+#include <typedefs.h>
+#include <gmx_fatal.h>
+
+#include "gromacs/selection/indexutil.h"
+
+/********************************************************************
+ * gmx_ana_indexgrps_t functions
+ ********************************************************************/
+
+/*! \internal \brief
+ * Stores a set of index groups.
+ */
+struct gmx_ana_indexgrps_t
+{
+    /** Number of index groups. */
+    int                 nr;
+    /** Array of index groups. */
+    gmx_ana_index_t    *g;
+};
+
+/*!
+ * \param[out] g     Index group structure.
+ * \param[in]  ngrps Number of groups for which memory is allocated.
+ */
+void
+gmx_ana_indexgrps_alloc(gmx_ana_indexgrps_t **g, int ngrps)
+{
+    snew(*g, 1);
+    (*g)->nr = ngrps;
+    snew((*g)->g,    ngrps);
+}
+
+/*!
+ * \param[out] g     Index group structure.
+ * \param[in]  ngrps Number of index groups.
+ * \param[in]  isize Array of index group sizes.
+ * \param[in]  index Array of pointers to indices of each group.
+ * \param[in]  name  Array of names of the groups.
+ * \param[in]  bFree If TRUE, the \p isize, \p index and \p name arrays
+ *   are freed after they have been copied.
+ */
+void
+gmx_ana_indexgrps_set(gmx_ana_indexgrps_t **g, int ngrps, int *isize,
+                      atom_id **index, char **name, gmx_bool bFree)
+{
+    int  i;
+
+    gmx_ana_indexgrps_alloc(g, ngrps);
+    for (i = 0; i < ngrps; ++i)
+    {
+        gmx_ana_index_set(&(*g)->g[i], isize[i], index[i], name[i], isize[i]);
+    }
+    if (bFree)
+    {
+        sfree(isize);
+        sfree(index);
+        sfree(name);
+    }
+}
+
+/*!
+ * \param[out] g     Index group structure.
+ * \param[in]  top   Topology structure.
+ * \param[in]  fnm   File name for the index file.
+ *   Memory is automatically allocated.
+ *
+ * One or both of \p top or \p fnm can be NULL.
+ * If \p top is NULL, an index file is required and the groups are read
+ * from the file (uses Gromacs routine init_index()).
+ * If \p fnm is NULL, default groups are constructed based on the
+ * topology (uses Gromacs routine analyse()).
+ * If both are null, the index group structure is initialized empty.
+ */
+void
+gmx_ana_indexgrps_init(gmx_ana_indexgrps_t **g, t_topology *top, 
+                       const char *fnm)
+{
+    t_blocka *block = NULL;
+    char    **names = NULL;
+    int       i, j;
+
+    if (fnm)
+    {
+        block = init_index(fnm, &names);
+    }
+    else if (top)
+    {
+        block = new_blocka();
+        analyse(&top->atoms, block, &names, FALSE, FALSE);
+    }
+    else
+    {
+        snew(*g, 1);
+        (*g)->nr    = 0;
+        (*g)->g     = NULL;
+        return;
+    }
+
+    gmx_ana_indexgrps_alloc(g, block->nr);
+    for (i = 0; i < block->nr; ++i)
+    {
+        gmx_ana_index_t *grp = &(*g)->g[i];
+
+        grp->isize = block->index[i+1] - block->index[i];
+        snew(grp->index, grp->isize);
+        for (j = 0; j < grp->isize; ++j)
+        {
+            grp->index[j] = block->a[block->index[i]+j];
+        }
+        grp->name = names[i];
+        grp->nalloc_index = grp->isize;
+    }
+
+    done_blocka(block);
+    sfree(block);
+    sfree(names);
+}
+
+/*!
+ * \param[out] g     Index group structure.
+ * \param[in]  top   Topology structure.
+ * \param[in]  fnm   File name for the index file.
+ * \param[in]  ngrps Number of required groups.
+ *   Memory is automatically allocated.
+ *
+ * One of \p top or \p fnm can be NULL, but not both.
+ * If \p top is NULL, an index file is required and the groups are read
+ * from the file (uses Gromacs routine rd_index()).
+ * If \p fnm is NULL, default groups are constructed based on the
+ * topology (uses Gromacs routine get_index()).
+ */
+void
+gmx_ana_indexgrps_get(gmx_ana_indexgrps_t **g, t_topology *top, 
+                      const char *fnm, int ngrps)
+{
+    int      *isize;
+    atom_id **index;
+    char    **name;
+
+    snew(isize, ngrps);
+    snew(index, ngrps);
+    snew(name,  ngrps);
+    if (!top)
+    {
+        rd_index(fnm, ngrps, isize, index, name);
+    }
+    else
+    {
+        get_index(&(top->atoms), fnm, ngrps, isize, index, name);
+    }
+    gmx_ana_indexgrps_set(g, ngrps, isize, index, name, TRUE);
+}
+
+/*!
+ * \param[out] g     Index group structure.
+ * \param[in]  fnm   File name for the index file.
+ * \param[in]  ngrps Number of required groups.
+ *   Memory is automatically allocated.
+ *
+ * This is a convenience function for calling the Gromacs routine
+ * rd_index().
+ */
+void
+gmx_ana_indexgrps_rd(gmx_ana_indexgrps_t **g, const char *fnm, int ngrps)
+{
+    gmx_ana_indexgrps_get(g, NULL, fnm, ngrps);
+}
+
+/*!
+ * \param[in] g  Index groups structure.
+ *
+ * The pointer \p g is invalid after the call.
+ */
+void
+gmx_ana_indexgrps_free(gmx_ana_indexgrps_t *g)
+{
+    int  i;
+
+    if (g->nr == 0)
+    {
+        sfree(g);
+        return;
+    }
+    for (i = 0; i < g->nr; ++i)
+    {
+        gmx_ana_index_deinit(&g->g[i]);
+    }
+    sfree(g->g);
+    g->nr    = 0;
+    g->g     = NULL;
+    sfree(g);
+}
+
+/*!
+ * \param[out] dest Destination index groups.
+ * \param[in]  src  Source index groups.
+ *
+ * A deep copy is made for all fields, including the group names.
+ */
+void
+gmx_ana_indexgrps_clone(gmx_ana_indexgrps_t **dest, gmx_ana_indexgrps_t *src)
+{
+    int g;
+
+    gmx_ana_indexgrps_alloc(dest, src->nr);
+    for (g = 0; g < src->nr; ++g)
+    {
+        gmx_ana_index_copy(&(*dest)->g[g], &src->g[g], TRUE);
+    }
+}
+
+/*!
+ * \param[out] g     Index group structure.
+ * \returns    TRUE if \p g is empty, i.e., has 0 index groups.
+ */
+gmx_bool
+gmx_ana_indexgrps_is_empty(gmx_ana_indexgrps_t *g)
+{
+    return g->nr == 0;
+}
+
+/*!
+ * \param[in]  g     Index groups structure.
+ * \param[in]  n     Index group number to get.
+ * \returns    Pointer to the \p n'th index group in \p g.
+ *
+ * The returned pointer should not be freed.
+ */
+gmx_ana_index_t *
+gmx_ana_indexgrps_get_grp(gmx_ana_indexgrps_t *g, int n)
+{
+    if (n < 0 || n >= g->nr)
+    {
+        return NULL;
+    }
+    return &g->g[n];
+}
+
+/*!
+ * \param[out] dest Output structure.
+ * \param[in]  src  Input index groups.
+ * \param[in]  n    Number of the group to extract.
+ * \returns TRUE if \p n is a valid group in \p src, FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_indexgrps_extract(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, int n)
+{
+    if (n < 0 || n >= src->nr)
+    {
+        dest->isize = 0;
+        return FALSE;
+    }
+
+    gmx_ana_index_copy(dest, &src->g[n], TRUE);
+    return TRUE;
+}
+
+/*!
+ * \param[out] dest Output structure.
+ * \param[in]  src  Input index groups.
+ * \param[in]  name Name (or part of the name) of the group to extract.
+ * \returns TRUE if \p name is a valid group in \p src, FALSE otherwise.
+ *
+ * Uses the Gromacs routine find_group() to find the actual group;
+ * the comparison is case-insensitive.
+ */
+gmx_bool
+gmx_ana_indexgrps_find(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, char *name)
+{
+    int    i;
+    char **names;
+
+    snew(names, src->nr);
+    for (i = 0; i < src->nr; ++i)
+    {
+        names[i] = src->g[i].name;
+    }
+    i = find_group(name, src->nr, names);
+    sfree(names);
+    if (i == NOTSET)
+    {
+        dest->isize = 0;
+        return FALSE;
+    }
+
+    return gmx_ana_indexgrps_extract(dest, src, i);
+}
+
+/*!
+ * \param[in]  fp     Where to print the output.
+ * \param[in]  g      Index groups to print.
+ * \param[in]  maxn   Maximum number of indices to print
+ *      (-1 = print all, 0 = print only names).
+ */
+void
+gmx_ana_indexgrps_print(FILE *fp, gmx_ana_indexgrps_t *g, int maxn)
+{
+    int  i;
+
+    for (i = 0; i < g->nr; ++i)
+    {
+        fprintf(fp, " %2d: ", i);
+        gmx_ana_index_dump(fp, &g->g[i], i, maxn);
+    }
+}
+
+/********************************************************************
+ * gmx_ana_index_t functions
+ ********************************************************************/
+
+/*!
+ * \param[in,out] g      Index group structure.
+ * \param[in]     isize  Maximum number of atoms to reserve space for.
+ */
+void
+gmx_ana_index_reserve(gmx_ana_index_t *g, int isize)
+{
+    if (g->nalloc_index < isize)
+    {
+        srenew(g->index, isize);
+        g->nalloc_index = isize;
+    }
+}
+
+/*!
+ * \param[in,out] g      Index group structure.
+ *
+ * Resizes the memory allocated for holding the indices such that the
+ * current contents fit.
+ */
+void
+gmx_ana_index_squeeze(gmx_ana_index_t *g)
+{
+    srenew(g->index, g->isize);
+    g->nalloc_index = g->isize;
+}
+
+/*!
+ * \param[out] g      Output structure.
+ *
+ * Any contents of \p g are discarded without freeing.
+ */
+void
+gmx_ana_index_clear(gmx_ana_index_t *g)
+{
+    g->isize        = 0;
+    g->index        = NULL;
+    g->name         = NULL;
+    g->nalloc_index = 0;
+}
+
+/*!
+ * \param[out] g      Output structure.
+ * \param[in]  isize  Number of atoms in the new group.
+ * \param[in]  index  Array of \p isize atoms (can be NULL if \p isize is 0).
+ * \param[in]  name   Name for the new group (can be NULL).
+ * \param[in]  nalloc Number of elements allocated for \p index
+ *   (if 0, \p index is not freed in gmx_ana_index_deinit())
+ *
+ * No copy if \p index is made.
+ */
+void
+gmx_ana_index_set(gmx_ana_index_t *g, int isize, atom_id *index, char *name,
+                  int nalloc)
+{
+    g->isize        = isize;
+    g->index        = index;
+    g->name         = name;
+    g->nalloc_index = nalloc;
+}
+
+/*!
+ * \param[out] g      Output structure.
+ * \param[in]  natoms Number of atoms.
+ * \param[in]  name   Name for the new group (can be NULL).
+ */
+void
+gmx_ana_index_init_simple(gmx_ana_index_t *g, int natoms, char *name)
+{
+    int  i;
+
+    g->isize = natoms;
+    snew(g->index, natoms);
+    for (i = 0; i < natoms; ++i)
+    {
+        g->index[i] = i;
+    }
+    g->name = name;
+    g->nalloc_index = natoms;
+}
+
+/*!
+ * \param[in] g  Index group structure.
+ *
+ * The pointer \p g is not freed.
+ */
+void
+gmx_ana_index_deinit(gmx_ana_index_t *g)
+{
+    if (g->nalloc_index > 0)
+    {
+        sfree(g->index);
+    }
+    sfree(g->name);
+    gmx_ana_index_clear(g);
+}
+
+/*!
+ * \param[out] dest   Destination index group.
+ * \param[in]  src    Source index group.
+ * \param[in]  bAlloc If TRUE, memory is allocated at \p dest; otherwise,
+ *   it is assumed that enough memory has been allocated for index.
+ *
+ * A deep copy of the name is only made if \p bAlloc is TRUE.
+ */
+void
+gmx_ana_index_copy(gmx_ana_index_t *dest, gmx_ana_index_t *src, gmx_bool bAlloc)
+{
+    dest->isize = src->isize;
+    if (dest->isize > 0)
+    {
+        if (bAlloc)
+        {
+            snew(dest->index, dest->isize);
+            dest->nalloc_index = dest->isize;
+        }
+        memcpy(dest->index, src->index, dest->isize*sizeof(*dest->index));
+    }
+    if (bAlloc && src->name)
+    {
+        dest->name = strdup(src->name);
+    }
+    else if (bAlloc || src->name)
+    {
+        dest->name = src->name;
+    }
+}
+
+/*!
+ * \param[in]  fp     Where to print the output.
+ * \param[in]  g      Index group to print.
+ * \param[in]  i      Group number to use if the name is NULL.
+ * \param[in]  maxn   Maximum number of indices to print (-1 = print all).
+ */
+void
+gmx_ana_index_dump(FILE *fp, gmx_ana_index_t *g, int i, int maxn)
+{
+    int  j, n;
+
+    if (g->name)
+    {
+        fprintf(fp, "\"%s\"", g->name);
+    }
+    else
+    {
+        fprintf(fp, "Group %d", i+1);
+    }
+    fprintf(fp, " (%d atoms)", g->isize);
+    if (maxn != 0)
+    {
+        fprintf(fp, ":");
+        n = g->isize;
+        if (maxn >= 0 && n > maxn)
+        {
+            n = maxn;
+        }
+        for (j = 0; j < n; ++j)
+        {
+            fprintf(fp, " %d", g->index[j]+1);
+        }
+        if (n < g->isize)
+        {
+            fprintf(fp, " ...");
+        }
+    }
+    fprintf(fp, "\n");
+}
+
+/*!
+ * \param[in]  g      Input index group.
+ * \param[in]  natoms Number of atoms to check against.
+ *
+ * If any atom index in the index group is less than zero or >= \p natoms,
+ * gmx_fatal() is called.
+ */
+void
+gmx_ana_index_check(gmx_ana_index_t *g, int natoms)
+{
+    int  j;
+
+    for (j = 0; j < g->isize; ++j)
+    {
+        if (g->index[j] >= natoms)
+        {
+            gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) "
+              "larger than number of atoms in trajectory (%d atoms)",
+              g->index[j], g->name, g->isize, natoms);
+        }
+        else if (g->index[j] < 0)
+        {
+            gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) "
+              "is less than zero",
+              g->index[j], g->name, g->isize);
+        }
+    }
+}
+
+/*!
+ * \param[in]  g      Index group to check.
+ * \returns    TRUE if the index group is sorted and has no duplicates,
+ *   FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_index_check_sorted(gmx_ana_index_t *g)
+{
+    int  i;
+
+    for (i = 0; i < g->isize-1; ++i)
+    {
+        if (g->index[i+1] <= g->index[i])
+        {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/********************************************************************
+ * Set operations
+ ********************************************************************/
+
+/** Helper function for gmx_ana_index_sort(). */
+static int
+cmp_atomid(const void *a, const void *b)
+{
+    if (*(atom_id *)a < *(atom_id *)b) return -1;
+    if (*(atom_id *)a > *(atom_id *)b) return 1;
+    return 0;
+}
+
+/*!
+ * \param[in,out] g  Index group to be sorted.
+ */
+void
+gmx_ana_index_sort(gmx_ana_index_t *g)
+{
+    qsort(g->index, g->isize, sizeof(*g->index), cmp_atomid);
+}
+
+/*!
+ * \param[in]  a      Index group to check.
+ * \param[in]  b      Index group to check.
+ * \returns    TRUE if \p a and \p b are equal, FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_index_equals(gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int  i;
+
+    if (a->isize != b->isize)
+    {
+        return FALSE;
+    }
+    for (i = 0; i < a->isize; ++i)
+    {
+        if (a->index[i] != b->index[i])
+        {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[in]  a      Index group to check against.
+ * \param[in]  b      Index group to check.
+ * \returns    TRUE if \p b is contained in \p a,
+ *   FALSE otherwise.
+ *
+ * If the elements are not in the same order in both groups, the function
+ * fails. However, the groups do not need to be sorted.
+ */
+gmx_bool
+gmx_ana_index_contains(gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int  i, j;
+
+    for (i = j = 0; j < b->isize; ++i, ++j) {
+        while (i < a->isize && a->index[i] != b->index[j])
+        {
+            ++i;
+        }
+        if (i == a->isize)
+        {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[out] dest Output index group (the intersection of \p a and \p b).
+ * \param[in]  a    First index group.
+ * \param[in]  b    Second index group.
+ *
+ * \p dest can be the same as \p a or \p b.
+ */
+void
+gmx_ana_index_intersection(gmx_ana_index_t *dest,
+                           gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int i, j, k;
+
+    for (i = j = k = 0; i < a->isize && j < b->isize; ++i) {
+        while (j < b->isize && b->index[j] < a->index[i])
+        {
+            ++j;
+        }
+        if (j < b->isize && b->index[j] == a->index[i])
+        {
+            dest->index[k++] = b->index[j++];
+        }
+    }
+    dest->isize = k;
+}
+
+/*!
+ * \param[out] dest Output index group (the difference \p a - \p b).
+ * \param[in]  a    First index group.
+ * \param[in]  b    Second index group.
+ *
+ * \p dest can equal \p a, but not \p b.
+ */
+void
+gmx_ana_index_difference(gmx_ana_index_t *dest,
+                         gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int i, j, k;
+
+    for (i = j = k = 0; i < a->isize; ++i)
+    {
+        while (j < b->isize && b->index[j] < a->index[i])
+        {
+            ++j;
+        }
+        if (j == b->isize || b->index[j] != a->index[i])
+        {
+            dest->index[k++] = a->index[i];
+        }
+    }
+    dest->isize = k;
+}
+
+/*!
+ * \param[in]  a    First index group.
+ * \param[in]  b    Second index group.
+ * \returns    Size of the difference \p a - \p b.
+ */
+int
+gmx_ana_index_difference_size(gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int i, j, k;
+
+    for (i = j = k = 0; i < a->isize; ++i)
+    {
+        while (j < b->isize && b->index[j] < a->index[i])
+        {
+            ++j;
+        }
+        if (j == b->isize || b->index[j] != a->index[i])
+        {
+            ++k;
+        }
+    }
+    return k;
+}
+
+/*!
+ * \param[out] dest1 Output group 1 (will equal \p g).
+ * \param[out] dest2 Output group 2 (will equal \p src - \p g).
+ * \param[in]  src   Group to be partitioned.
+ * \param[in]  g     One partition.
+ *
+ * \pre \p g is a subset of \p src and both sets are sorted
+ * \pre \p dest1 has allocated storage to store \p src
+ * \post \p dest1 == \p g
+ * \post \p dest2 == \p src - \p g
+ *
+ * No storage should be allocated for \p dest2; after the call,
+ * \p dest2->index points to the memory allocated for \p dest1
+ * (to a part that is not used by \p dest1).
+ *
+ * The calculation can be performed in-place by setting \p dest1 equal to
+ * \p src.
+ */
+void
+gmx_ana_index_partition(gmx_ana_index_t *dest1, gmx_ana_index_t *dest2,
+                        gmx_ana_index_t *src, gmx_ana_index_t *g)
+                     
+{
+    int i, j, k;
+
+    dest2->index = dest1->index + g->isize;
+    dest2->isize = src->isize - g->isize;
+    for (i = g->isize-1, j = src->isize-1, k = dest2->isize-1; i >= 0; --i, --j)
+    {
+        while (j >= 0 && src->index[j] != g->index[i])
+        {
+            dest2->index[k--] = src->index[j--];
+        }
+    }
+    while (j >= 0)
+    {
+        dest2->index[k--] = src->index[j--];
+    }
+    gmx_ana_index_copy(dest1, g, FALSE);
+}
+
+/*!
+ * \param[out] dest Output index group (the union of \p a and \p b).
+ * \param[in]  a    First index group.
+ * \param[in]  b    Second index group.
+ *
+ * \p a and \p b can have common items.
+ * \p dest can equal \p a or \p b.
+ *
+ * \see gmx_ana_index_merge()
+ */
+void
+gmx_ana_index_union(gmx_ana_index_t *dest,
+                    gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int dsize;
+    int i, j, k;
+
+    dsize = gmx_ana_index_difference_size(b, a);
+    i = a->isize - 1;
+    j = b->isize - 1;
+    dest->isize = a->isize + dsize;
+    for (k = dest->isize - 1; k >= 0; k--)
+    {
+        if (i < 0 || (j >= 0 && a->index[i] < b->index[j]))
+        {
+            dest->index[k] = b->index[j--];
+        }
+        else
+        {
+            if (j >= 0 && a->index[i] == b->index[j])
+            {
+                --j;
+            }
+            dest->index[k] = a->index[i--];
+        }
+    }
+}
+
+/*!
+ * \param[out] dest Output index group (the union of \p a and \p b).
+ * \param[in]  a    First index group.
+ * \param[in]  b    Second index group.
+ *
+ * \p a and \p b should not have common items.
+ * \p dest can equal \p a or \p b.
+ *
+ * \see gmx_ana_index_union()
+ */
+void
+gmx_ana_index_merge(gmx_ana_index_t *dest,
+                    gmx_ana_index_t *a, gmx_ana_index_t *b)
+{
+    int i, j, k;
+
+    i = a->isize - 1;
+    j = b->isize - 1;
+    dest->isize = a->isize + b->isize;
+    for (k = dest->isize - 1; k >= 0; k--)
+    {
+        if (i < 0 || (j >= 0 && a->index[i] < b->index[j]))
+        {
+            dest->index[k] = b->index[j--];
+        }
+        else
+        {
+            dest->index[k] = a->index[i--];
+        }
+    }
+}
+
+/********************************************************************
+ * gmx_ana_indexmap_t and related things
+ ********************************************************************/
+
+/*!
+ * \param[in,out] t    Output block.
+ * \param[in]  top  Topology structure
+ *   (only used if \p type is \ref INDEX_RES or \ref INDEX_MOL, can be NULL
+ *   otherwise).
+ * \param[in]  g    Index group
+ *   (can be NULL if \p type is \ref INDEX_UNKNOWN).
+ * \param[in]  type Type of partitioning to make.
+ * \param[in]  bComplete
+ *   If TRUE, the index group is expanded to include any residue/molecule
+ *   (depending on \p type) that is partially contained in the group.
+ *   If \p type is not INDEX_RES or INDEX_MOL, this has no effect.
+ *
+ * \p m should have been initialized somehow (calloc() is enough) unless
+ * \p type is INDEX_UNKNOWN.
+ * \p g should be sorted.
+ */
+void
+gmx_ana_index_make_block(t_blocka *t, t_topology *top, gmx_ana_index_t *g,
+                         e_index_t type, gmx_bool bComplete)
+{
+    int      i, j, ai;
+    int      id, cur;
+
+    if (type == INDEX_UNKNOWN)
+    {
+        t->nr           = 1;
+        snew(t->index, 2);
+        t->nalloc_index = 2;
+        t->index[0]     = 0;
+        t->index[1]     = 0;
+        t->nra          = 0;
+        t->a            = NULL;
+        t->nalloc_a     = 0;
+        return;
+    }
+
+    /* bComplete only does something for INDEX_RES or INDEX_MOL, so turn it
+     * off otherwise. */
+    if (type != INDEX_RES && type != INDEX_MOL)
+    {
+        bComplete = FALSE;
+    }
+    /* Allocate memory for the atom array and fill it unless we are using
+     * completion. */
+    if (bComplete)
+    {
+        t->nra = 0;
+        /* We may allocate some extra memory here because we don't know in
+         * advance how much will be needed. */
+        if (t->nalloc_a < top->atoms.nr)
+        {
+            srenew(t->a, top->atoms.nr);
+            t->nalloc_a = top->atoms.nr;
+        }
+    }
+    else
+    {
+        t->nra      = g->isize;
+        if (t->nalloc_a < g->isize)
+        {
+            srenew(t->a, g->isize);
+            t->nalloc_a = g->isize;
+        }
+        memcpy(t->a, g->index, g->isize*sizeof(*(t->a)));
+    }
+
+    /* Allocate memory for the block index. We don't know in advance
+     * how much will be needed, so we allocate some extra and free it in the
+     * end. */
+    if (t->nalloc_index < g->isize + 1)
+    {
+        srenew(t->index, g->isize + 1);
+        t->nalloc_index = g->isize + 1;
+    }
+    /* Clear counters */
+    t->nr = 0;
+    j = 0; /* j is used by residue completion for the first atom not stored */
+    id = cur = -1;
+    for (i = 0; i < g->isize; ++i)
+    {
+        ai = g->index[i];
+        /* Find the ID number of the atom/residue/molecule corresponding to
+         * atom ai. */
+        switch (type)
+        {
+            case INDEX_ATOM:
+                id = ai;
+                break;
+            case INDEX_RES:
+                id = top->atoms.atom[ai].resind;
+                break;
+            case INDEX_MOL:
+                while (ai >= top->mols.index[id+1])
+                {
+                    id++;
+                }
+                break;
+            case INDEX_UNKNOWN: /* Should not occur */
+            case INDEX_ALL:
+                id = 0;
+                break;
+        }
+        /* If this is the first atom in a new block, initialize the block. */
+        if (id != cur)
+        {
+            if (bComplete)
+            {
+                /* For completion, we first set the start of the block. */
+                t->index[t->nr++] = t->nra;
+                /* And then we find all the atoms that should be included. */
+                switch (type)
+                {
+                    case INDEX_RES:
+                        while (top->atoms.atom[j].resind != id)
+                        {
+                            ++j;
+                        }
+                        while (j < top->atoms.nr && top->atoms.atom[j].resind == id)
+                        {
+                            t->a[t->nra++] = j;
+                            ++j;
+                        }
+                        break;
+
+                    case INDEX_MOL:
+                        for (j = top->mols.index[id]; j < top->mols.index[id+1]; ++j)
+                        {
+                            t->a[t->nra++] = j;
+                        }
+                        break;
+
+                    default: /* Should not be reached */
+                        gmx_bug("internal error");
+                        break;
+                }
+            }
+            else
+            {
+                /* If not using completion, simply store the start of the block. */
+                t->index[t->nr++] = i;
+            }
+            cur = id;
+        }
+    }
+    /* Set the end of the last block */
+    t->index[t->nr] = t->nra;
+    /* Free any unnecessary memory */
+    srenew(t->index, t->nr+1);
+    t->nalloc_index = t->nr+1;
+    if (bComplete)
+    {
+        srenew(t->a, t->nra);
+        t->nalloc_a = t->nra;
+    }
+}
+
+/*!
+ * \param[in] g   Index group to check.
+ * \param[in] b   Block data to check against.
+ * \returns   TRUE if \p g consists of one or more complete blocks from \p b,
+ *   FALSE otherwise.
+ *
+ * The atoms in \p g are assumed to be sorted.
+ */
+gmx_bool
+gmx_ana_index_has_full_blocks(gmx_ana_index_t *g, t_block *b)
+{
+    int  i, j, bi;
+
+    i = bi = 0;
+    /* Each round in the loop matches one block */
+    while (i < g->isize)
+    {
+        /* Find the block that begins with the first unmatched atom */
+        while (bi < b->nr && b->index[bi] != g->index[i])
+        {
+            ++bi;
+        }
+        /* If not found, or if too large, return */
+        if (bi == b->nr || i + b->index[bi+1] -  b->index[bi] > g->isize)
+        {
+            return FALSE;
+        }
+        /* Check that the block matches the index */
+        for (j = b->index[bi]; j < b->index[bi+1]; ++j, ++i)
+        {
+            if (g->index[i] != j)
+            {
+                return FALSE;
+            }
+        }
+        /* Move the search to the next block */
+        ++bi;
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[in] g   Index group to check.
+ * \param[in] b   Block data to check against.
+ * \returns   TRUE if \p g consists of one or more complete blocks from \p b,
+ *   FALSE otherwise.
+ *
+ * The atoms in \p g and \p b->a are assumed to be in the same order.
+ */
+gmx_bool
+gmx_ana_index_has_full_ablocks(gmx_ana_index_t *g, t_blocka *b)
+{
+    int  i, j, bi;
+
+    i = bi = 0;
+    /* Each round in the loop matches one block */
+    while (i < g->isize)
+    {
+        /* Find the block that begins with the first unmatched atom */
+        while (bi < b->nr && b->a[b->index[bi]] != g->index[i])
+        {
+            ++bi;
+        }
+        /* If not found, or if too large, return */
+        if (bi == b->nr || i + b->index[bi+1] -  b->index[bi] > g->isize)
+        {
+            return FALSE;
+        }
+        /* Check that the block matches the index */
+        for (j = b->index[bi]; j < b->index[bi+1]; ++j, ++i)
+        {
+            if (b->a[j] != g->index[i])
+            {
+                return FALSE;
+            }
+        }
+        /* Move the search to the next block */
+        ++bi;
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[in] g     Index group to check.
+ * \param[in] type  Block data to check against.
+ * \param[in] top   Topology data.
+ * \returns   TRUE if \p g consists of one or more complete elements of type
+ *   \p type, FALSE otherwise.
+ *
+ * If \p type is \ref INDEX_ATOM, the return value is always TRUE.
+ * If \p type is \ref INDEX_UNKNOWN or \ref INDEX_ALL, the return value is
+ * always FALSE.
+ */
+gmx_bool
+gmx_ana_index_has_complete_elems(gmx_ana_index_t *g, e_index_t type,
+                                 t_topology *top)
+{
+    switch (type)
+    {
+        case INDEX_UNKNOWN:
+        case INDEX_ALL:
+            return FALSE;
+
+        case INDEX_ATOM:
+            return TRUE;
+
+        case INDEX_RES:
+        {
+            int      i, ai;
+            int      id, prev;
+
+            prev = -1;
+            for (i = 0; i < g->isize; ++i)
+            {
+                ai = g->index[i];
+                id = top->atoms.atom[ai].resind;
+                if (id != prev)
+                {
+                    if (ai > 0 && top->atoms.atom[ai-1].resind == id)
+                    {
+                        return FALSE;
+                    }
+                    if (i > 0 && g->index[i-1] < top->atoms.nr - 1
+                        && top->atoms.atom[g->index[i-1]+1].resind == prev)
+                    {
+                        return FALSE;
+                    }
+                }
+                prev = id;
+            }
+            if (g->index[i-1] < top->atoms.nr - 1
+                && top->atoms.atom[g->index[i-1]+1].resind == prev)
+            {
+                return FALSE;
+            }
+            break;
+        }
+
+        case INDEX_MOL:
+            return gmx_ana_index_has_full_blocks(g, &top->mols);
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[out] m      Output structure.
+ *
+ * Any contents of \p m are discarded without freeing.
+ */
+void
+gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m)
+{
+    m->type              = INDEX_UNKNOWN;
+    m->nr                = 0;
+    m->refid             = NULL;
+    m->mapid             = NULL;
+    m->mapb.nr           = 0;
+    m->mapb.index        = NULL;
+    m->mapb.nalloc_index = 0;
+    m->orgid             = NULL;
+    m->b.nr              = 0;
+    m->b.index           = NULL;
+    m->b.nra             = 0;
+    m->b.a               = NULL;
+    m->b.nalloc_index    = 0;
+    m->b.nalloc_a        = 0;
+    m->bStatic           = TRUE;
+    m->bMapStatic        = TRUE;
+}
+
+/*!
+ * \param[in,out] m      Mapping structure.
+ * \param[in]     nr     Maximum number of blocks to reserve space for.
+ * \param[in]     isize  Maximum number of atoms to reserve space for.
+ */
+void
+gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize)
+{
+    if (m->mapb.nalloc_index < nr + 1)
+    {
+        srenew(m->refid,      nr);
+        srenew(m->mapid,      nr);
+        srenew(m->orgid,      nr);
+        srenew(m->mapb.index, nr + 1);
+        srenew(m->b.index,    nr + 1);
+        m->mapb.nalloc_index = nr + 1;
+        m->b.nalloc_index    = nr + 1;
+    }
+    if (m->b.nalloc_a < isize)
+    {
+        srenew(m->b.a,        isize);
+        m->b.nalloc_a = isize;
+    }
+}
+
+/*!
+ * \param[in,out] m    Mapping structure to initialize.
+ * \param[in]     g    Index group to map
+ *   (can be NULL if \p type is \ref INDEX_UNKNOWN).
+ * \param[in]     top  Topology structure
+ *   (can be NULL if \p type is not \ref INDEX_RES or \ref INDEX_MOL).
+ * \param[in]     type Type of mapping to construct.
+ *
+ * Initializes a new index group mapping.
+ * The index group provided to gmx_ana_indexmap_update() should always be a
+ * subset of the \p g given here.
+ *
+ * \p m should have been initialized somehow (calloc() is enough).
+ */
+void
+gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
+                      t_topology *top, e_index_t type)
+{
+    int      i, ii, mi;
+
+    m->type   = type;
+    gmx_ana_index_make_block(&m->b, top, g, type, FALSE);
+    gmx_ana_indexmap_reserve(m, m->b.nr, m->b.nra);
+    m->nr = m->b.nr;
+    for (i = mi = 0; i < m->nr; ++i)
+    {
+        ii = (type == INDEX_UNKNOWN ? 0 : m->b.a[m->b.index[i]]);
+        switch (type)
+        {
+            case INDEX_ATOM:
+                m->orgid[i] = ii;
+                break;
+            case INDEX_RES:
+                m->orgid[i] = top->atoms.atom[ii].resind;
+                break;
+            case INDEX_MOL:
+                while (top->mols.index[mi+1] <= ii)
+                {
+                    ++mi;
+                }
+                m->orgid[i] = mi;
+                break;
+            case INDEX_ALL:
+            case INDEX_UNKNOWN:
+                m->orgid[i] = 0;
+                break;
+        }
+    }
+    for (i = 0; i < m->nr; ++i)
+    {
+        m->refid[i] = i;
+        m->mapid[i] = m->orgid[i];
+    }
+    m->mapb.nr = m->nr;
+    memcpy(m->mapb.index, m->b.index, (m->nr+1)*sizeof(*(m->mapb.index)));
+    m->bStatic    = TRUE;
+    m->bMapStatic = TRUE;
+}
+
+/*!
+ * \param[in,out] m    Mapping structure to initialize.
+ * \param[in]     b    Block information to use for data.
+ *
+ * Frees some memory that is not necessary for static index group mappings.
+ * Internal pointers are set to point to data in \p b; it is the responsibility
+ * of the caller to ensure that the block information matches the contents of
+ * the mapping.
+ * After this function has been called, the index group provided to
+ * gmx_ana_indexmap_update() should always be the same as \p g given here.
+ *
+ * This function breaks modularity of the index group mapping interface in an
+ * ugly way, but allows reducing memory usage of static selections by a
+ * significant amount.
+ */
+void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b)
+{
+    sfree(m->mapid);
+    m->mapid = m->orgid;
+    sfree(m->b.index);
+    m->b.nalloc_index = 0;
+    m->b.index = b->index;
+    sfree(m->mapb.index);
+    m->mapb.nalloc_index = 0;
+    m->mapb.index = m->b.index;
+    sfree(m->b.a);
+    m->b.nalloc_a = 0;
+    m->b.a = b->a;
+}
+
+/*!
+ * \param[in,out] dest Destination data structure.
+ * \param[in]     src  Source mapping.
+ * \param[in]     bFirst If TRUE, memory is allocated for \p dest and a full
+ *   copy is made; otherwise, only variable parts are copied, and no memory
+ *   is allocated.
+ *
+ * \p dest should have been initialized somehow (calloc() is enough).
+ */
+void
+gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, gmx_bool bFirst)
+{
+    if (bFirst)
+    {
+        gmx_ana_indexmap_reserve(dest, src->b.nr, src->b.nra);
+        dest->type       = src->type;
+        dest->b.nr       = src->b.nr;
+        dest->b.nra      = src->b.nra;
+        memcpy(dest->orgid,      src->orgid,      dest->b.nr*sizeof(*dest->orgid));
+        memcpy(dest->b.index,    src->b.index,   (dest->b.nr+1)*sizeof(*dest->b.index));
+        memcpy(dest->b.a,        src->b.a,        dest->b.nra*sizeof(*dest->b.a));
+    }
+    dest->nr         = src->nr;
+    dest->mapb.nr    = src->mapb.nr;
+    memcpy(dest->refid,      src->refid,      dest->nr*sizeof(*dest->refid));
+    memcpy(dest->mapid,      src->mapid,      dest->nr*sizeof(*dest->mapid));
+    memcpy(dest->mapb.index, src->mapb.index,(dest->mapb.nr+1)*sizeof(*dest->mapb.index));
+    dest->bStatic    = src->bStatic;
+    dest->bMapStatic = src->bMapStatic;
+}
+
+/*!
+ * \param[in,out] m         Mapping structure.
+ * \param[in]     g         Current index group.
+ * \param[in]     bMaskOnly TRUE if the unused blocks should be masked with
+ *   -1 instead of removing them.
+ *
+ * Updates the index group mapping with the new index group \p g.
+ *
+ * \see gmx_ana_indexmap_t
+ */
+void
+gmx_ana_indexmap_update(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
+                        gmx_bool bMaskOnly)
+{
+    int i, j, bi, bj;
+    gmx_bool bStatic;
+
+    /* Process the simple cases first */
+    if (m->type == INDEX_UNKNOWN && m->b.nra == 0)
+    {
+        return;
+    }
+    if (m->type == INDEX_ALL)
+    {
+        if (m->b.nr > 0)
+        {
+            m->mapb.index[1] = g->isize;
+        }
+        return;
+    }
+    /* Reset the reference IDs and mapping if necessary */
+    bStatic = (g->isize == m->b.nra && m->nr == m->b.nr);
+    if (bStatic || bMaskOnly)
+    {
+        if (!m->bStatic)
+        {
+            for (bj = 0; bj < m->b.nr; ++bj)
+            {
+                m->refid[bj] = bj;
+            }
+        }
+        if (!m->bMapStatic)
+        {
+            for (bj = 0; bj < m->b.nr; ++bj)
+            {
+                m->mapid[bj] = m->orgid[bj];
+            }
+            for (bj = 0; bj <= m->b.nr; ++bj)
+            {
+                m->mapb.index[bj] = m->b.index[bj];
+            }
+            m->bMapStatic = TRUE;
+        }
+    }
+    /* Exit immediately if the group is static */
+    if (bStatic)
+    {
+        m->bStatic = TRUE;
+        return;
+    }
+
+    if (bMaskOnly)
+    {
+        m->nr = m->b.nr;
+        for (i = j = bj = 0; i < g->isize; ++i, ++j)
+        {
+            /* Find the next atom in the block */
+            while (m->b.a[j] != g->index[i])
+            {
+                ++j;
+            }
+            /* Mark blocks that did not contain any atoms */
+            while (bj < m->b.nr && m->b.index[bj+1] <= j)
+            {
+                m->refid[bj++] = -1;
+            }
+            /* Advance the block index if we have reached the next block */
+            if (m->b.index[bj] <= j)
+            {
+                ++bj;
+            }
+        }
+        /* Mark the last blocks as not accessible */
+        while (bj < m->b.nr)
+        {
+            m->refid[bj++] = -1;
+        }
+    }
+    else
+    {
+        for (i = j = bi = 0, bj = -1; i < g->isize; ++i)
+        {
+            /* Find the next atom in the block */
+            while (m->b.a[j] != g->index[i])
+            {
+                ++j;
+            }
+            /* If we have reached a new block, add it */
+            if (m->b.index[bj+1] <= j)
+            {
+                /* Skip any blocks in between */
+                while (bj < m->b.nr && m->b.index[bj+1] <= j)
+                {
+                    ++bj;
+                }
+                m->refid[bi] = bj;
+                m->mapid[bi] = m->orgid[bj];
+                m->mapb.index[bi] = i;
+                bi++;
+            }
+        }
+        /* Update the number of blocks */
+        m->mapb.index[bi] = g->isize;
+        m->nr             = bi;
+        m->bMapStatic     = FALSE;
+    }
+    m->mapb.nr = m->nr;
+    m->bStatic = FALSE;
+}
+
+/*!
+ * \param[in,out] m         Mapping structure to free.
+ *
+ * All the memory allocated for the mapping structure is freed, and
+ * the pointers set to NULL.
+ * The pointer \p m is not freed.
+ */
+void
+gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m)
+{
+    sfree(m->refid);
+    if (m->mapid != m->orgid)
+    {
+        sfree(m->mapid);
+    }
+    if (m->mapb.nalloc_index > 0)
+    {
+        sfree(m->mapb.index);
+    }
+    sfree(m->orgid);
+    if (m->b.nalloc_index > 0)
+    {
+        sfree(m->b.index);
+    }
+    if (m->b.nalloc_a > 0)
+    {
+        sfree(m->b.a);
+    }
+    gmx_ana_indexmap_clear(m);
+}
diff --git a/src/gromacs/selection/indexutil.h b/src/gromacs/selection/indexutil.h
new file mode 100644 (file)
index 0000000..b7b6668
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief API for handling index files and index groups.
+ *
+ * The API contains functions and data structures for handling index
+ * files more conveniently than as several separate variables.
+ * In addition to basic functions for initializing the data structures and
+ * making copies, functions are provided for performing (most) set operations
+ * on sorted index groups.
+ * There is also a function for partitioning a index group based on
+ * topology information such as residues or molecules.
+ * Finally, there is a set of functions for constructing mappings between
+ * an index group and its subgroups such.
+ * These can be used with dynamic index group in calculations if one
+ * needs to have a unique ID for each possible atom/residue/molecule in the
+ * selection, e.g., for analysis of dynamics or for look-up tables.
+ *
+ * Mostly, these functions are used internally by the library and the
+ * selection engine.
+ * However, some of the checking functions can be useful in user code to
+ * check the validity of input groups.
+ * Also, the mapping functions are useful when dealing with dynamic index
+ * groups.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_INDEXUTIL_H
+#define GMX_SELECTION_INDEXUTIL_H
+
+#include "../legacyheaders/typedefs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** Stores a set of index groups. */
+typedef struct gmx_ana_indexgrps_t gmx_ana_indexgrps_t;
+
+/*! \brief
+ * Specifies the type of index partition or index mapping in several contexts.
+ *
+ * \see gmx_ana_index_make_block(), gmx_ana_indexmap_init()
+ */
+typedef enum
+{
+    INDEX_UNKNOWN, /**< Unknown index type.*/
+    INDEX_ATOM,    /**< Each atom in a separate block.*/
+    INDEX_RES,     /**< Each residue in a separate block.*/
+    INDEX_MOL,     /**< Each molecule in a separate block.*/
+    INDEX_ALL      /**< All atoms in a single block.*/
+} e_index_t;
+
+/*! \brief
+ * Stores a single index group.
+ */
+typedef struct gmx_ana_index_t
+{
+    /** Number of atoms. */
+    int                 isize;
+    /** List of atoms. */
+    atom_id            *index;
+    /** Group name. */
+    char               *name;
+    /** Number of items allocated for \p index. */
+    int                 nalloc_index;
+} gmx_ana_index_t;
+
+/*! \brief
+ * Data structure for calculating index group mappings.
+ */
+typedef struct gmx_ana_indexmap_t
+{
+    /** Type of the mapping. */
+    e_index_t           type;
+    /*! \brief
+     * Current number of mapped values.
+     *
+     * This is the current number of values in the \p refid and \p mapid
+     * arrays.
+     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), this
+     * is always equal to \p b.nr, i.e., the number of blocks in the
+     * original index group.
+     */
+    int                 nr;
+    /*! \brief
+     * Current reference IDs.
+     *
+     * This array provides a mapping from the current index group (last given
+     * to gmx_ana_indexmap_update()) to the blocks in \p b, i.e., the
+     * original index group used in gmx_ana_indexmap_init().
+     * The mapping is zero-based.
+     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), the indices
+     * for blocks not present in the current group are set to -1, otherwise
+     * they are removed completely and the \p nr field updated.
+     */
+    int                *refid;
+    /*! \brief
+     * Current mapped IDs.
+     *
+     * This array provides an arbitrary mapping from the current index group
+     * to the original index group. Instead of a zero-based mapping, the
+     * values from the \p orgid array are used. That is,
+     * \c mapid[i]=orgid[refid[i]].
+     * If \p bMaskOnly is provided to gmx_ana_indexmap_update(), this array
+     * equals \p orgid.
+     */
+    int                *mapid;
+    /*! \brief
+     * Mapped block structure.
+     *
+     * A block structure that corresponds to the current index group.
+     */
+    t_block             mapb;
+
+    /*! \brief
+     * Arbitrary ID numbers for the blocks.
+     *
+     * This array has \p b.nr elements, each defining an ID number for a
+     * block in \p b.
+     * These are initialized in gmx_ana_indexmap_init() based on the type:
+     *  - \ref INDEX_ATOM : the atom indices
+     *  - \ref INDEX_RES :  the residue numbers
+     *  - \ref INDEX_MOL :  the molecule numbers
+     *
+     * All the above numbers are zero-based.
+     * After gmx_ana_indexmap_init(), the user is free to change these values
+     * if the above are not appropriate.
+     * The mapped values can be read through \p mapid.
+     */
+    int                *orgid;
+
+    /*! \brief
+     * Block data that defines the mapping (internal use only).
+     *
+     * The data is initialized by gmx_ana_indexmap_init() and is not changed
+     * after that.
+     * Hence, it cannot be directly applied to the index group passed to
+     * gmx_ana_indexmap_update() unless \p bMaskOnly was specified or the
+     * index group is identical to the one provided to gmx_ana_indexmap_init().
+     */
+    t_blocka            b;
+    /*! \brief
+     * TRUE if the current reference IDs are for the whole group (internal use only).
+     *
+     * This is used internally to optimize the evaluation such that
+     * gmx_ana_indexmap_update() does not take any time if the group is
+     * actually static.
+     */
+    gmx_bool                bStatic;
+    /*! \brief
+     * TRUE if the current mapping is for the whole group (internal use only).
+     *
+     * This is used internally to optimize the evaluation such that
+     * gmx_ana_indexmap_update() does not take any time if the group is
+     * actually static.
+     */
+    gmx_bool                bMapStatic;
+} gmx_ana_indexmap_t;
+
+
+/*! \name Functions for handling gmx_ana_indexgrps_t
+ */
+/*@{*/
+/** Allocate memory for index groups. */
+void
+gmx_ana_indexgrps_alloc(gmx_ana_indexgrps_t **g, int ngrps);
+/** Initializes index groups from arrays. */
+void
+gmx_ana_indexgrps_set(gmx_ana_indexgrps_t **g, int ngrps, int *isize,
+                      atom_id **index, char **name, gmx_bool bFree);
+/** Reads index groups from a file or constructs them from topology. */
+void
+gmx_ana_indexgrps_init(gmx_ana_indexgrps_t **g, t_topology *top, 
+                       const char *fnm);
+/** Ask user to select index groups, possibly constructing groups from 
+ *  topology. */
+void
+gmx_ana_indexgrps_get(gmx_ana_indexgrps_t **g, t_topology *top, 
+                      const char *fnm, int ngrps);
+/** Ask user to select index groups from those specified in a file. */
+void
+gmx_ana_indexgrps_rd(gmx_ana_indexgrps_t **g, const char *fnm, int ngrps);
+/** Frees memory allocated for index groups. */
+void
+gmx_ana_indexgrps_free(gmx_ana_indexgrps_t *g);
+/** Create a deep copy of \c gmx_ana_indexgrps_t. */
+void
+gmx_ana_indexgrps_clone(gmx_ana_indexgrps_t **dest, gmx_ana_indexgrps_t *src);
+/** Returns TRUE if the index group structure is emtpy. */
+gmx_bool
+gmx_ana_indexgrps_is_empty(gmx_ana_indexgrps_t *g);
+
+/** Returns a pointer to an index group. */
+gmx_ana_index_t *
+gmx_ana_indexgrps_get_grp(gmx_ana_indexgrps_t *g, int n);
+/** Extracts a single index group. */
+gmx_bool
+gmx_ana_indexgrps_extract(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, int n);
+/** Finds and extracts a single index group by name. */
+gmx_bool
+gmx_ana_indexgrps_find(gmx_ana_index_t *dest, gmx_ana_indexgrps_t *src, char *name);
+
+/** Writes out a list of index groups. */
+void
+gmx_ana_indexgrps_print(FILE *fp, gmx_ana_indexgrps_t *g, int maxn);
+/*@}*/
+
+/*! \name Functions for handling gmx_ana_index_t
+ */
+/*@{*/
+/** Reserves memory to store an index group of size \p isize. */
+void
+gmx_ana_index_reserve(gmx_ana_index_t *g, int isize);
+/** Frees any memory not necessary to hold the current contents. */
+void
+gmx_ana_index_squeeze(gmx_ana_index_t *g);
+/** Initializes an empty index group. */
+void
+gmx_ana_index_clear(gmx_ana_index_t *g);
+/** Constructs a \c gmx_ana_index_t from given values. */
+void
+gmx_ana_index_set(gmx_ana_index_t *g, int isize, atom_id *index, char *name,
+                  int nalloc);
+/** Creates a simple index group from the first to the \p natoms'th atom. */
+void
+gmx_ana_index_init_simple(gmx_ana_index_t *g, int natoms, char *name);
+/** Frees memory allocated for an index group. */
+void
+gmx_ana_index_deinit(gmx_ana_index_t *g);
+/** Copies a \c gmx_ana_index_t. */
+void
+gmx_ana_index_copy(gmx_ana_index_t *dest, gmx_ana_index_t *src, gmx_bool bAlloc);
+
+/** Writes out the contents of a index group. */
+void
+gmx_ana_index_dump(FILE *fp, gmx_ana_index_t *g, int i, int maxn);
+
+/** Checks whether all indices are between 0 and \p natoms. */
+void
+gmx_ana_index_check(gmx_ana_index_t *g, int natoms);
+/** Checks whether an index group is sorted. */
+gmx_bool
+gmx_ana_index_check_sorted(gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Functions for set operations on gmx_ana_index_t
+ */
+/*@{*/
+/** Sorts the indices within an index group. */
+void
+gmx_ana_index_sort(gmx_ana_index_t *g);
+/** Checks whether two index groups are equal. */
+gmx_bool
+gmx_ana_index_equals(gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Checks whether a sorted index group contains another sorted index group. */
+gmx_bool
+gmx_ana_index_contains(gmx_ana_index_t *a, gmx_ana_index_t *b);
+
+/** Calculates the intersection between two sorted index groups. */
+void
+gmx_ana_index_intersection(gmx_ana_index_t *dest,
+                           gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Calculates the set difference between two sorted index groups. */
+void
+gmx_ana_index_difference(gmx_ana_index_t *dest,
+                         gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Calculates the size of the difference between two sorted index groups. */
+int
+gmx_ana_index_difference_size(gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Calculates the union of two sorted index groups. */
+void
+gmx_ana_index_union(gmx_ana_index_t *dest,
+                    gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Merges two distinct sorted index groups. */
+void
+gmx_ana_index_merge(gmx_ana_index_t *dest,
+                    gmx_ana_index_t *a, gmx_ana_index_t *b);
+/** Calculates the intersection and the difference in one call. */
+void
+gmx_ana_index_partition(gmx_ana_index_t *dest1, gmx_ana_index_t *dest2,
+                        gmx_ana_index_t *src, gmx_ana_index_t *g);
+/*@}*/
+
+/*! \name Functions for handling gmx_ana_indexmap_t and related things
+ */
+/*@{*/
+/** Partition a group based on topology information. */
+void
+gmx_ana_index_make_block(t_blocka *t, t_topology *top, gmx_ana_index_t *g,
+                         e_index_t type, gmx_bool bComplete);
+/** Checks whether a group consists of full blocks. */
+gmx_bool
+gmx_ana_index_has_full_blocks(gmx_ana_index_t *g, t_block *b);
+/** Checks whether a group consists of full blocks. */
+gmx_bool
+gmx_ana_index_has_full_ablocks(gmx_ana_index_t *g, t_blocka *b);
+/** Checks whether a group consists of full residues/molecules. */
+gmx_bool
+gmx_ana_index_has_complete_elems(gmx_ana_index_t *g, e_index_t type, t_topology *top);
+
+/** Initializes an empty index group mapping. */
+void
+gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m);
+/** Reserves memory for an index group mapping. */
+void
+gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize);
+/** Initializes an index group mapping. */
+void
+gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
+                      t_topology *top, e_index_t type);
+/** Sets an index group mapping to be static. */
+void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b);
+/** Frees memory allocated for index group mapping. */
+void
+gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m);
+/** Makes a deep copy of an index group mapping. */
+void
+gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, gmx_bool bFirst);
+/** Updates an index group mapping. */
+void
+gmx_ana_indexmap_update(gmx_ana_indexmap_t *m, gmx_ana_index_t *g, gmx_bool bMaskOnly);
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/selection/keywords.h b/src/gromacs/selection/keywords.h
new file mode 100644 (file)
index 0000000..3e8e9ad
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Definitions of generic keyword evaluation structures.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef SELECTION_KEYWORDS_H
+#define SELECTION_KEYWORDS_H
+
+struct gmx_ana_selmethod_t;
+struct t_selelem;
+struct t_selexpr_param;
+
+/** Selection method data for comparison expression evaluation. */
+extern struct gmx_ana_selmethod_t sm_compare;
+
+/** Selection method data for integer keyword evaluation. */
+extern struct gmx_ana_selmethod_t sm_keyword_int;
+/** Selection method data for real keyword evaluation. */
+extern struct gmx_ana_selmethod_t sm_keyword_real;
+/** Selection method data for string keyword evaluation. */
+extern struct gmx_ana_selmethod_t sm_keyword_str;
+/** Selection method data for position keyword evaluation. */
+extern struct gmx_ana_selmethod_t sm_keyword_pos;
+
+/** Prints information about a comparison expression. */
+void
+_gmx_selelem_print_compare_info(FILE *fp, void *data);
+
+/** Sets the position type for position keyword evaluation. */
+void
+_gmx_selelem_set_kwpos_type(struct t_selelem *sel, const char *type);
+/** Sets the flags for position keyword evaluation. */
+void
+_gmx_selelem_set_kwpos_flags(struct t_selelem *sel, int flags);
+
+/** Does custom processing for parameters of the \c same selection method. */
+int
+_gmx_selelem_custom_init_same(struct gmx_ana_selmethod_t **method,
+                              struct t_selexpr_param *params, void *scanner);
+
+/** Initializes a selection element for evaluating a keyword in a given group. */
+int
+_gmx_sel_init_keyword_evaluator(struct t_selelem **sel,
+                                struct gmx_ana_selmethod_t *method,
+                                struct t_selexpr_param *param, void *scanner);
+
+#endif
diff --git a/src/gromacs/selection/mempool.cpp b/src/gromacs/selection/mempool.cpp
new file mode 100644 (file)
index 0000000..e6a1fec
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in mempool.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <new>
+
+#include <smalloc.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/selection/indexutil.h"
+
+#include "mempool.h"
+
+//! Alignment in bytes for all returned blocks.
+#define ALIGN_STEP 8
+
+/*! \internal \brief
+ * Describes a single block allocated from the memory pool.
+ */
+typedef struct gmx_sel_mempool_block_t
+{
+    //! Pointer to the start of the block (as returned to the user).
+    void                       *ptr;
+    //! Size of the block, including padding required to align next block.
+    size_t                      size;
+} gmx_sel_mempool_block_t;
+
+/*! \internal \brief
+ * Describes a memory pool.
+ */
+struct gmx_sel_mempool_t
+{
+    //! Number of bytes currently allocated from the pool.
+    size_t                      currsize;
+    //! Number of bytes free in the pool, or 0 if \a buffer is NULL.
+    size_t                      freesize;
+    //! Memory area allocated for the pool, or NULL if not yet reserved.
+    char                       *buffer;
+    //! Pointer to the first free byte (aligned at ::ALIGN_STEP) in \a buffer.
+    char                       *freeptr;
+    //! Number of blocks allocated from the pool.
+    int                         nblocks;
+    //! Array describing the allocated blocks.
+    gmx_sel_mempool_block_t    *blockstack;
+    //! Number of elements allocated for the \a blockstack array.
+    int                         blockstack_nalloc;
+    /*! \brief
+     * Maximum number of bytes that have been reserved from the pool
+     * simultaneously.
+     */
+    size_t                      maxsize;
+};
+
+gmx_sel_mempool_t *
+_gmx_sel_mempool_create()
+{
+    gmx_sel_mempool_t *mp;
+
+    snew(mp, 1);
+    mp->currsize          = 0;
+    mp->freesize          = 0;
+    mp->buffer            = NULL;
+    mp->freeptr           = NULL;
+    mp->nblocks           = 0;
+    mp->blockstack        = NULL;
+    mp->blockstack_nalloc = 0;
+    mp->maxsize           = 0;
+    return mp;
+}
+
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp)
+{
+    if (!mp->buffer)
+    {
+        int  i;
+
+        for (i = 0; i < mp->nblocks; ++i)
+        {
+            sfree(mp->blockstack[i].ptr);
+        }
+    }
+    sfree(mp->buffer);
+    sfree(mp->blockstack);
+    sfree(mp);
+}
+
+void *
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, size_t size)
+{
+    void   *ptr = NULL;
+    size_t  size_walign;
+
+    size_walign = ((size + ALIGN_STEP - 1) / ALIGN_STEP) * ALIGN_STEP;
+    if (mp->buffer)
+    {
+        if (mp->freesize < size)
+        {
+            GMX_THROW(gmx::InternalError("Out of memory pool memory"));
+        }
+        ptr = mp->freeptr;
+        mp->freeptr  += size_walign;
+        mp->freesize -= size_walign;
+        mp->currsize += size_walign;
+    }
+    else
+    {
+        ptr = malloc(size);
+        if (!ptr)
+        {
+            throw std::bad_alloc();
+        }
+        mp->currsize += size_walign;
+        if (mp->currsize > mp->maxsize)
+        {
+            mp->maxsize = mp->currsize;
+        }
+    }
+
+    if (mp->nblocks >= mp->blockstack_nalloc)
+    {
+        mp->blockstack_nalloc = mp->nblocks + 10;
+        srenew(mp->blockstack, mp->blockstack_nalloc);
+    }
+    mp->blockstack[mp->nblocks].ptr  = ptr;
+    mp->blockstack[mp->nblocks].size = size_walign;
+    mp->nblocks++;
+
+    return ptr;
+}
+
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr)
+{
+    int size;
+
+    if (ptr == NULL)
+    {
+        return;
+    }
+    GMX_RELEASE_ASSERT(mp->nblocks > 0 && mp->blockstack[mp->nblocks - 1].ptr == ptr,
+                       "Invalid order of memory pool free calls");
+    mp->nblocks--;
+    size = mp->blockstack[mp->nblocks].size;
+    mp->currsize -= size;
+    if (mp->buffer)
+    {
+        mp->freeptr = (char *)ptr;
+        mp->freesize += size;
+    }
+    else
+    {
+        sfree(ptr);
+    }
+}
+
+void
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size)
+{
+    GMX_RELEASE_ASSERT(mp->nblocks == 0,
+                       "Cannot reserve memory pool when there is something allocated");
+    GMX_RELEASE_ASSERT(!mp->buffer, "Cannot reserve memory pool twice");
+    if (size == 0)
+    {
+        size = mp->maxsize;
+    }
+    mp->buffer = (char *)malloc(size);
+    if (!mp->buffer)
+    {
+        throw std::bad_alloc();
+    }
+    mp->freesize = size;
+    mp->freeptr  = mp->buffer;
+}
+
+void
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g,
+                             int isize)
+{
+    void *ptr = _gmx_sel_mempool_alloc(mp, sizeof(*g->index)*isize);
+    g->index = static_cast<int *>(ptr);
+}
+
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g)
+{
+    _gmx_sel_mempool_free(mp, g->index);
+    g->index = NULL;
+}
diff --git a/src/gromacs/selection/mempool.h b/src/gromacs/selection/mempool.h
new file mode 100644 (file)
index 0000000..7a6305b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Declarations for memory pooling functions.
+ *
+ * \todo
+ * Document these functions.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_MEMPOOL_H
+#define GMX_SELECTION_MEMPOOL_H
+
+struct gmx_ana_index_t;
+
+/** Opaque struct for memory pooling. */
+typedef struct gmx_sel_mempool_t gmx_sel_mempool_t;
+
+/** Create an empty memory pool. */
+gmx_sel_mempool_t *
+_gmx_sel_mempool_create();
+/** Destroy a memory pool. */
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp);
+
+/** Allocate memory from a memory pool. */
+void *
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, size_t size);
+/** Release memory allocated from a memory pool. */
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr);
+/** Set the size of a memory pool. */
+void
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size);
+
+/** Convenience function for allocating an index group from a memory pool. */
+void
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g,
+                             int isize);
+/** Convenience function for freeing an index group from a memory pool. */
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g);
+
+#endif
diff --git a/src/gromacs/selection/nbsearch.cpp b/src/gromacs/selection/nbsearch.cpp
new file mode 100644 (file)
index 0000000..716087b
--- /dev/null
@@ -0,0 +1,788 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \page nbsearch Neighborhood search routines
+ *
+ * Functions to find particles within a neighborhood of a set of particles
+ * are defined in nbsearch.h.
+ * The usage is simple: a data structure is allocated with
+ * gmx_ana_nbsearch_create(), and the box shape and reference positions for a
+ * frame are set using gmx_ana_nbsearch_init() or gmx_ana_nbsearch_pos_init().
+ * Searches can then be performed with gmx_ana_nbsearch_is_within() and
+ * gmx_ana_nbsearch_mindist(), or with versions that take the \c gmx_ana_pos_t
+ * data structure.
+ * When the data structure is no longer required, it can be freed with
+ * gmx_ana_nbsearch_free().
+ *
+ * \internal
+ *
+ * \todo
+ * The grid implementation could still be optimized in several different ways:
+ *   - Triclinic grid cells are not the most efficient shape, but make PBC
+ *     handling easier.
+ *   - Precalculating the required PBC shift for a pair of cells outside the
+ *     inner loop. After this is done, it should be quite straightforward to
+ *     move to rectangular cells.
+ *   - Pruning grid cells from the search list if they are completely outside
+ *     the sphere that is being considered.
+ *   - A better heuristic could be added for falling back to simple loops for a
+ *     small number of reference particles.
+ *   - A better heuristic for selecting the grid size.
+ *   - A multi-level grid implementation could be used to be able to use small
+ *     grids for short cutoffs with very inhomogeneous particle distributions
+ *     without a memory cost.
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in nbsearch.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+
+#include <smalloc.h>
+#include <typedefs.h>
+#include <pbc.h>
+#include <vec.h>
+
+#include "gromacs/selection/nbsearch.h"
+#include "gromacs/selection/position.h"
+
+/*! \internal \brief
+ * Data structure for neighborhood searches.
+ */
+struct gmx_ana_nbsearch_t
+{
+    /** The cutoff. */
+    real           cutoff;
+    /** The cutoff squared. */
+    real           cutoff2;
+    /** Maximum number of reference points. */
+    int            maxnref;
+
+    /** Number of reference points for the current frame. */
+    int            nref;
+    /** Reference point positions. */
+    rvec          *xref;
+    /** Reference position ids (NULL if not available). */
+    int           *refid;
+    /** PBC data. */
+    t_pbc         *pbc;
+
+    /** Number of excluded reference positions for current test particle. */
+    int            nexcl;
+    /** Exclusions for current test particle. */
+    int           *excl;
+
+    /** Whether to try grid searching. */
+    gmx_bool           bTryGrid;
+    /** Whether grid searching is actually used for the current positions. */
+    gmx_bool           bGrid;
+    /** Array allocated for storing in-unit-cell reference positions. */
+    rvec          *xref_alloc;
+    /** FALSE if the box is rectangular. */
+    gmx_bool           bTric;
+    /** Box vectors of a single grid cell. */
+    matrix         cellbox;
+    /** The reciprocal cell vectors as columns; the inverse of \p cellbox. */
+    matrix         recipcell;
+    /** Number of cells along each dimension. */
+    ivec           ncelldim;
+    /** Total number of cells. */
+    int            ncells;
+    /** Number of reference positions in each cell. */
+    int           *ncatoms;
+    /** List of reference positions in each cell. */
+    atom_id      **catom;
+    /** Allocation counts for each \p catom[i]. */
+    int           *catom_nalloc;
+    /** Allocation count for the per-cell arrays. */
+    int            cells_nalloc;
+    /** Number of neighboring cells to consider. */
+    int            ngridnb;
+    /** Offsets of the neighboring cells to consider. */
+    ivec          *gnboffs;
+    /** Allocation count for \p gnboffs. */
+    int            gnboffs_nalloc;
+
+    /** Stores test position during a pair loop. */
+    rvec           xtest;
+    /** Stores the previous returned position during a pair loop. */
+    int            previ;
+    /** Stores the current exclusion index during loops. */
+    int            exclind;
+    /** Stores the test particle cell index during loops. */
+    ivec           testcell;
+    /** Stores the current cell neighbor index during pair loops. */
+    int            prevnbi;
+    /** Stores the index within the current cell during pair loops. */
+    int            prevcai;
+};
+
+/*!
+ * \param[in]  cutoff Cutoff distance for the search
+ *   (<=0 stands for no cutoff).
+ * \param[in]  maxn   Maximum number of reference particles.
+ * \returns  Created neighborhood search data structure.
+ */
+gmx_ana_nbsearch_t *
+gmx_ana_nbsearch_create(real cutoff, int maxn)
+{
+    gmx_ana_nbsearch_t *d;
+
+    snew(d, 1);
+    d->bTryGrid = TRUE;
+    if (cutoff <= 0)
+    {
+        cutoff = GMX_REAL_MAX;
+        d->bTryGrid = FALSE;
+    }
+    d->cutoff = cutoff;
+    d->cutoff2 = sqr(cutoff);
+    d->maxnref = maxn;
+
+    d->xref = NULL;
+    d->nexcl = 0;
+    d->exclind = 0;
+
+    d->xref_alloc = NULL;
+    d->ncells = 0;
+    d->ncatoms = NULL;
+    d->catom = NULL;
+    d->catom_nalloc = 0;
+    d->cells_nalloc = 0;
+
+    d->ngridnb = 0;
+    d->gnboffs = NULL;
+    d->gnboffs_nalloc = 0;
+
+    return d;
+}
+
+/*!
+ * \param     d Data structure to free.
+ *
+ * After the call, the pointer \p d is no longer valid.
+ */
+void
+gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d)
+{
+    sfree(d->xref_alloc);
+    sfree(d->ncatoms);
+    if (d->catom)
+    {
+        int ci;
+
+        for (ci = 0; ci < d->ncells; ++ci)
+        {
+            sfree(d->catom[ci]);
+        }
+        sfree(d->catom);
+    }
+    sfree(d->catom_nalloc);
+    sfree(d->gnboffs);
+    sfree(d);
+}
+
+/*! \brief
+ * Calculates offsets to neighboring grid cells that should be considered.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ */
+static void
+grid_init_cell_nblist(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    int   maxx, maxy, maxz;
+    int   x, y, z, i;
+    real  rvnorm;
+
+    /* Find the extent of the sphere in triclinic coordinates */
+    maxz = (int)(d->cutoff * d->recipcell[ZZ][ZZ]) + 1;
+    rvnorm = sqrt(sqr(d->recipcell[YY][YY]) + sqr(d->recipcell[ZZ][YY]));
+    maxy = (int)(d->cutoff * rvnorm) + 1;
+    rvnorm = sqrt(sqr(d->recipcell[XX][XX]) + sqr(d->recipcell[YY][XX])
+                  + sqr(d->recipcell[ZZ][XX]));
+    maxx = (int)(d->cutoff * rvnorm) + 1;
+
+    /* Calculate the number of cells and reallocate if necessary */
+    d->ngridnb = (2 * maxx + 1) * (2 * maxy + 1) * (2 * maxz + 1);
+    if (d->gnboffs_nalloc < d->ngridnb)
+    {
+        d->gnboffs_nalloc = d->ngridnb;
+        srenew(d->gnboffs, d->gnboffs_nalloc);
+    }
+
+    /* Store the whole cube */
+    /* TODO: Prune off corners that are not needed */
+    i = 0;
+    for (x = -maxx; x <= maxx; ++x)
+    {
+        for (y = -maxy; y <= maxy; ++y)
+        {
+            for (z = -maxz; z <= maxz; ++z)
+            {
+                d->gnboffs[i][XX] = x;
+                d->gnboffs[i][YY] = y;
+                d->gnboffs[i][ZZ] = z;
+                ++i;
+            }
+        }
+    }
+}
+
+/*! \brief
+ * Determines a suitable grid size.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ * \returns  FALSE if grid search is not suitable.
+ */
+static gmx_bool
+grid_setup_cells(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    real targetsize;
+    int  dd;
+
+#ifdef HAVE_CBRT
+    targetsize = cbrt(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+                      * 10 / d->nref);
+#else
+    targetsize = pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+                      * 10 / d->nref, 1./3.);
+#endif
+
+    d->ncells = 1;
+    for (dd = 0; dd < DIM; ++dd)
+    {
+        d->ncelldim[dd] = (int)(pbc->box[dd][dd] / targetsize);
+        d->ncells *= d->ncelldim[dd];
+        if (d->ncelldim[dd] < 3)
+        {
+            return FALSE;
+        }
+    }
+    /* Reallocate if necessary */
+    if (d->cells_nalloc < d->ncells)
+    {
+        int  i;
+
+        srenew(d->ncatoms, d->ncells);
+        srenew(d->catom, d->ncells);
+        srenew(d->catom_nalloc, d->ncells);
+        for (i = d->cells_nalloc; i < d->ncells; ++i)
+        {
+            d->catom[i] = NULL;
+            d->catom_nalloc[i] = 0;
+        }
+        d->cells_nalloc = d->ncells;
+    }
+    return TRUE;
+}
+
+/*! \brief
+ * Sets ua a search grid for a given box.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ * \returns  FALSE if grid search is not suitable.
+ */
+static gmx_bool
+grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    int dd;
+
+    /* TODO: This check could be improved. */
+    if (0.5*pbc->max_cutoff2 < d->cutoff2)
+    {
+        return FALSE;
+    }
+
+    if (!grid_setup_cells(d, pbc))
+    {
+        return FALSE;
+    }
+
+    d->bTric = TRICLINIC(pbc->box);
+    if (d->bTric)
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]);
+        }
+        m_inv_ur0(d->cellbox, d->recipcell);
+    }
+    else
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd];
+            d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd];
+        }
+    }
+    grid_init_cell_nblist(d, pbc);
+    return TRUE;
+}
+
+/*! \brief
+ * Maps a point into a grid cell.
+ *
+ * \param[in]  d    Grid information.
+ * \param[in]  x    Point to map.
+ * \param[out] cell Indices of the grid cell in which \p x lies.
+ *
+ * \p x should be in the triclinic unit cell.
+ */
+static void
+grid_map_onto(gmx_ana_nbsearch_t *d, const rvec x, ivec cell)
+{
+    int dd;
+
+    if (d->bTric)
+    {
+        rvec tx;
+
+        tmvmul_ur0(d->recipcell, x, tx);
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            cell[dd] = (int)tx[dd];
+        }
+    }
+    else
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            cell[dd] = (int)(x[dd] * d->recipcell[dd][dd]);
+        }
+    }
+}
+
+/*! \brief
+ * Calculates linear index of a grid cell.
+ *
+ * \param[in]  d    Grid information.
+ * \param[in]  cell Cell indices.
+ * \returns    Linear index of \p cell.
+ */
+static int
+grid_index(gmx_ana_nbsearch_t *d, const ivec cell)
+{
+    return cell[XX] + cell[YY] * d->ncelldim[XX]
+        + cell[ZZ] * d->ncelldim[XX] * d->ncelldim[YY];
+}
+
+/*! \brief
+ * Clears all grid cells.
+ *
+ * \param[in,out] d    Grid information.
+ */
+static void
+grid_clear_cells(gmx_ana_nbsearch_t *d)
+{
+    int  ci;
+
+    for (ci = 0; ci < d->ncells; ++ci)
+    {
+        d->ncatoms[ci] = 0;
+    }
+}
+
+/*! \brief
+ * Adds an index into a grid cell.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     cell Cell into which \p i should be added.
+ * \param[in]     i    Index to add.
+ */
+static void
+grid_add_to_cell(gmx_ana_nbsearch_t *d, const ivec cell, int i)
+{
+    int ci = grid_index(d, cell);
+
+    if (d->ncatoms[ci] == d->catom_nalloc[ci])
+    {
+        d->catom_nalloc[ci] += 10;
+        srenew(d->catom[ci], d->catom_nalloc[ci]);
+    }
+    d->catom[ci][d->ncatoms[ci]++] = i;
+}
+
+/*!
+ * \param[in,out] d   Neighborhood search data structure.
+ * \param[in]     pbc PBC information for the frame.
+ * \param[in]     n   Number of reference positions for the frame.
+ * \param[in]     x   \p n reference positions for the frame.
+ *
+ * Initializes the data structure \p d such that it can be used to search
+ * for the neighbors of \p x.
+ */
+void
+gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, const rvec x[])
+{
+    d->pbc  = pbc;
+    d->nref = n;
+    if (!pbc)
+    {
+        d->bGrid = FALSE;
+    }
+    else if (d->bTryGrid)
+    {
+        d->bGrid = grid_set_box(d, pbc);
+    }
+    if (d->bGrid)
+    {
+        int  i;
+
+        if (!d->xref_alloc)
+        {
+            snew(d->xref_alloc, d->maxnref);
+        }
+        d->xref = d->xref_alloc;
+        grid_clear_cells(d);
+
+        for (i = 0; i < n; ++i)
+        {
+            copy_rvec(x[i], d->xref[i]);
+        }
+        put_atoms_in_triclinic_unitcell(ecenterTRIC, pbc->box, n, d->xref);
+        for (i = 0; i < n; ++i)
+        {
+            ivec refcell;
+
+            grid_map_onto(d, d->xref[i], refcell);
+            grid_add_to_cell(d, refcell, i);
+        }
+    }
+    else
+    {
+        // Won't be modified in this case, but when a grid is used,
+        // xref _is_ modified, so it can't be const.
+        d->xref = const_cast<rvec *>(x);
+    }
+    d->refid = NULL;
+}
+
+/*!
+ * \param[in,out] d   Neighborhood search data structure.
+ * \param[in]     pbc PBC information for the frame.
+ * \param[in]     p   Reference positions for the frame.
+ *
+ * A convenience wrapper for gmx_ana_nbsearch_init().
+ */
+void
+gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, const gmx_ana_pos_t *p)
+{
+    gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
+    d->refid = (p->nr < d->maxnref ? p->m.refid : NULL);
+}
+
+/*!
+ * \param[in,out] d     Neighborhood search data structure.
+ * \param[in]     nexcl Number of reference positions to exclude from next
+ *      search.
+ * \param[in]     excl  Indices of reference positions to exclude.
+ *
+ * The set exclusions remain in effect until the next call of this function.
+ */
+void
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
+{
+
+    d->nexcl = nexcl;
+    d->excl = excl;
+}
+
+/*! \brief
+ * Helper function to check whether a reference point should be excluded.
+ */
+static gmx_bool
+is_excluded(gmx_ana_nbsearch_t *d, int j)
+{
+    if (d->exclind < d->nexcl)
+    {
+        if (d->refid)
+        {
+            while (d->exclind < d->nexcl && d->refid[j] > d->excl[d->exclind])
+            {
+                ++d->exclind;
+            }
+            if (d->exclind < d->nexcl && d->refid[j] == d->excl[d->exclind])
+            {
+                ++d->exclind;
+                return TRUE;
+            }
+        }
+        else
+        {
+            while (d->bGrid && d->exclind < d->nexcl && d->excl[d->exclind] < j)
+            {
+                ++d->exclind;
+            }
+            if (d->excl[d->exclind] == j)
+            {
+                ++d->exclind;
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*! \brief
+ * Initializes a grid search to find reference positions neighboring \p x.
+ */
+static void
+grid_search_start(gmx_ana_nbsearch_t *d, const rvec x)
+{
+    copy_rvec(x, d->xtest);
+    if (d->bGrid)
+    {
+        put_atoms_in_triclinic_unitcell(ecenterTRIC, d->pbc->box, 1, &d->xtest);
+        grid_map_onto(d, d->xtest, d->testcell);
+        d->prevnbi = 0;
+        d->prevcai = -1;
+    }
+    else
+    {
+        d->previ = -1;
+    }
+    d->exclind = 0;
+}
+
+/*! \brief
+ * Does a grid search.
+ */
+static gmx_bool
+grid_search(gmx_ana_nbsearch_t *d,
+            gmx_bool (*action)(gmx_ana_nbsearch_t *d, int i, real r2))
+{
+    int  i;
+    rvec dx;
+    real r2;
+
+    if (d->bGrid)
+    {
+        int  nbi, ci, cai;
+
+        nbi = d->prevnbi;
+        cai = d->prevcai + 1;
+
+        for ( ; nbi < d->ngridnb; ++nbi)
+        {
+            ivec cell;
+
+            ivec_add(d->testcell, d->gnboffs[nbi], cell);
+            /* TODO: Support for 2D and screw PBC */
+            cell[XX] = (cell[XX] + d->ncelldim[XX]) % d->ncelldim[XX];
+            cell[YY] = (cell[YY] + d->ncelldim[YY]) % d->ncelldim[YY];
+            cell[ZZ] = (cell[ZZ] + d->ncelldim[ZZ]) % d->ncelldim[ZZ];
+            ci = grid_index(d, cell);
+            /* TODO: Calculate the required PBC shift outside the inner loop */
+            for ( ; cai < d->ncatoms[ci]; ++cai)
+            {
+                i = d->catom[ci][cai];
+                if (is_excluded(d, i))
+                {
+                    continue;
+                }
+                pbc_dx_aiuc(d->pbc, d->xtest, d->xref[i], dx);
+                r2 = norm2(dx);
+                if (r2 <= d->cutoff2)
+                {
+                    if (action(d, i, r2))
+                    {
+                        d->prevnbi = nbi;
+                        d->prevcai = cai;
+                        d->previ   = i;
+                        return TRUE;
+                    }
+                }
+            }
+            d->exclind = 0;
+            cai = 0;
+        }
+    }
+    else
+    {
+        i = d->previ + 1;
+        for ( ; i < d->nref; ++i)
+        {
+            if (is_excluded(d, i))
+            {
+                continue;
+            }
+            if (d->pbc)
+            {
+                pbc_dx(d->pbc, d->xtest, d->xref[i], dx);
+            }
+            else
+            {
+                rvec_sub(d->xtest, d->xref[i], dx);
+            }
+            r2 = norm2(dx);
+            if (r2 <= d->cutoff2)
+            {
+                if (action(d, i, r2))
+                {
+                    d->previ = i;
+                    return TRUE;
+                }
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*! \brief
+ * Helper function to use with grid_search() to find the next neighbor.
+ *
+ * Simply breaks the loop on the first found neighbor.
+ */
+static gmx_bool
+within_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+    return TRUE;
+}
+
+/*! \brief
+ * Helper function to use with grid_search() to find the minimum distance.
+ */
+static gmx_bool
+mindist_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+    d->cutoff2 = r2;
+    return FALSE;
+}
+
+/*!
+ * \param[in] d   Neighborhood search data structure.
+ * \param[in] x   Test position.
+ * \returns   TRUE if \p x is within the cutoff of any reference position,
+ *   FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, const rvec x)
+{
+    grid_search_start(d, x);
+    return grid_search(d, &within_action);
+}
+
+/*!
+ * \param[in] d   Neighborhood search data structure.
+ * \param[in] p   Test positions.
+ * \param[in] i   Use the i'th position in \p p for testing.
+ * \returns   TRUE if the test position is within the cutoff of any reference
+ *   position, FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_nbsearch_pos_is_within(gmx_ana_nbsearch_t *d, const gmx_ana_pos_t *p, int i)
+{
+    return gmx_ana_nbsearch_is_within(d, p->x[i]);
+}
+
+/*!
+ * \param[in] d   Neighborhood search data structure.
+ * \param[in] x   Test position.
+ * \returns   The distance to the nearest reference position, or the cutoff
+ *   value if there are no reference positions within the cutoff.
+ */
+real
+gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, const rvec x)
+{
+    real mind;
+
+    grid_search_start(d, x);
+    grid_search(d, &mindist_action);
+    mind = sqrt(d->cutoff2);
+    d->cutoff2 = sqr(d->cutoff);
+    return mind;
+}
+
+/*!
+ * \param[in] d   Neighborhood search data structure.
+ * \param[in] p   Test positions.
+ * \param[in] i   Use the i'th position in \p p for testing.
+ * \returns   The distance to the nearest reference position, or the cutoff
+ *   value if there are no reference positions within the cutoff.
+ */
+real
+gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d, const gmx_ana_pos_t *p, int i)
+{
+    return gmx_ana_nbsearch_mindist(d, p->x[i]);
+}
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[in]  x   Test positions.
+ * \param[out] jp  Index of the reference position in the first pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+gmx_bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, const rvec x, int *jp)
+{
+    grid_search_start(d, x);
+    return gmx_ana_nbsearch_next_within(d, jp);
+}
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[in]  p   Test positions.
+ * \param[in]  i   Use the i'th position in \p p.
+ * \param[out] jp  Index of the reference position in the first pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+gmx_bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d, const gmx_ana_pos_t *p,
+                                  int i, int *jp)
+{
+    return gmx_ana_nbsearch_first_within(d, p->x[i], jp);
+}
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[out] jp  Index of the test position in the next pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+gmx_bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp)
+{
+    if (grid_search(d, &within_action))
+    {
+        *jp = d->previ;
+        return TRUE;
+    }
+    *jp = -1;
+    return FALSE;
+}
diff --git a/src/gromacs/selection/nbsearch.h b/src/gromacs/selection/nbsearch.h
new file mode 100644 (file)
index 0000000..0e671fc
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief API for neighborhood searching.
+ *
+ * The API is documented in more detail on a separate page:
+ * \ref nbsearch
+ *
+ * The functions within this file can be used independently of the other parts
+ * of the library.
+ * The library also uses the functions internally.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_NBSEARCH_H
+#define GMX_SELECTION_NBSEARCH_H
+
+#include "../legacyheaders/typedefs.h"
+
+#include "indexutil.h"
+
+struct gmx_ana_pos_t;
+
+/** Data structure for neighborhood searches. */
+typedef struct gmx_ana_nbsearch_t gmx_ana_nbsearch_t;
+
+/** Create a new neighborhood search data structure. */
+gmx_ana_nbsearch_t *
+gmx_ana_nbsearch_create(real cutoff, int maxn);
+/** Free memory allocated for neighborhood search. */
+void
+gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d);
+
+/** Initializes neighborhood search for a new frame. */
+void
+gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, const rvec x[]);
+/** Initializes neighborhood search for a frame using \c gmx_ana_pos_t.  */
+void
+gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc,
+                          const struct gmx_ana_pos_t *p);
+/** Sets the exclusions for the next neighborhood search. */
+void
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[]);
+/** Check whether a point is within a neighborhood. */
+gmx_bool
+gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, const rvec x);
+/** Check whether a position is within a neighborhood. */
+gmx_bool
+gmx_ana_nbsearch_pos_is_within(gmx_ana_nbsearch_t *d,
+                               const struct gmx_ana_pos_t *p, int i);
+/** Calculates the minimun distance from the reference points. */
+real
+gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, const rvec x);
+/** Calculates the minimun distance from the reference points. */
+real
+gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d,
+                             const struct gmx_ana_pos_t *p, int i);
+/** Finds the first reference position within the cutoff. */
+gmx_bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, const rvec x, int *jp);
+/** Finds the first reference position within the cutoff. */
+gmx_bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d,
+                                  const struct gmx_ana_pos_t *p, int i, int *jp);
+/** Finds the next reference position within the cutoff. */
+gmx_bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp);
+
+#endif
diff --git a/src/gromacs/selection/params.cpp b/src/gromacs/selection/params.cpp
new file mode 100644 (file)
index 0000000..e761297
--- /dev/null
@@ -0,0 +1,1289 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in selparam.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <smalloc.h>
+#include <string2.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+#include "gromacs/selection/selparam.h"
+#include "gromacs/utility/format.h"
+
+#include "parsetree.h"
+#include "position.h"
+#include "scanner.h"
+#include "selelem.h"
+
+template <typename T>
+static T min(T a, T b)
+{
+    return (a < b) ? a : b;
+}
+
+template <typename T>
+static T max(T a, T b)
+{
+    return (a > b) ? a : b;
+}
+
+/*!
+ * \param[in] name   Name of the parameter to search.
+ * \param[in] nparam Number of parameters in the \p param array.
+ * \param[in] param  Parameter array to search.
+ * \returns   Pointer to the parameter in the \p param
+ *   or NULL if no parameter with name \p name was found.
+ *
+ * The comparison is case-sensitive.
+ */
+gmx_ana_selparam_t *
+gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param)
+{
+    int                i;
+
+    if (nparam == 0)
+    {
+        return NULL;
+    }
+    /* Find the first non-null parameter */
+    i = 0;
+    while (i < nparam && param[i].name == NULL)
+    {
+        ++i;
+    }
+    /* Process the special case of a NULL parameter */
+    if (name == NULL)
+    {
+        return (i == 0) ? NULL : &param[i-1];
+    }
+    for ( ; i < nparam; ++i)
+    {
+        if (!strcmp(param[i].name, name))
+        {
+            return &param[i];
+        }
+        /* Check for 'no' prefix on gmx_boolean parameters */
+        if (param[i].val.type == NO_VALUE
+            && strlen(name) > 2 && name[0] == 'n' && name[1] == 'o'
+            && !strcmp(param[i].name, name+2))
+        {
+            return &param[i];
+        }
+    }
+    return NULL;
+}
+
+/*! \brief
+ * Does a type conversion on a \c t_selexpr_value.
+ *
+ * \param[in,out] value    Value to convert.
+ * \param[in]     type     Type to convert to.
+ * \param[in]     scanner  Scanner data structure.
+ * \returns       0 on success, a non-zero value on error.
+ */
+static int
+convert_value(t_selexpr_value *value, e_selvalue_t type, void *scanner)
+{
+    if (value->type == type || type == NO_VALUE)
+    {
+        return 0;
+    }
+    if (value->bExpr)
+    {
+        /* Conversion from atom selection to position using default
+         * reference positions. */
+        if (value->type == GROUP_VALUE && type == POS_VALUE)
+        {
+            value->u.expr =
+                _gmx_sel_init_position(value->u.expr, NULL, scanner);
+            if (value->u.expr == NULL)
+            {
+                return -1;
+            }
+            value->type = type;
+            return 0;
+        }
+        return -1;
+    }
+    else
+    {
+        /* Integers to floating point are easy */
+        if (value->type == INT_VALUE && type == REAL_VALUE)
+        {
+            real r1 = (real)value->u.i.i1;
+            real r2 = (real)value->u.i.i2;
+            value->u.r.r1 = r1;
+            value->u.r.r2 = r2;
+            value->type = type;
+            return 0;
+        }
+        /* Reals that are integer-valued can also be converted */
+        if (value->type == REAL_VALUE && type == INT_VALUE
+            && gmx_within_tol(value->u.r.r1, (int)value->u.r.r1, GMX_REAL_EPS)
+            && gmx_within_tol(value->u.r.r2, (int)value->u.r.r2, GMX_REAL_EPS))
+        {
+            int i1 = (int)value->u.r.r1;
+            int i2 = (int)value->u.r.r2;
+            value->u.i.i1 = i1;
+            value->u.i.i2 = i2;
+            value->type = type;
+            return 0;
+        }
+    }
+    return -1;
+}
+
+/*! \brief
+ * Does a type conversion on a list of values.
+ *
+ * \param[in,out] values   Values to convert.
+ * \param[in]     type     Type to convert to.
+ * \param[in]     scanner  Scanner data structure.
+ * \returns       0 on success, a non-zero value on error.
+ */
+static int
+convert_values(t_selexpr_value *values, e_selvalue_t type, void *scanner)
+{
+    t_selexpr_value *value;
+    int              rc, rc1;
+
+    rc = 0;
+    value = values;
+    while (value)
+    {
+        rc1 = convert_value(value, type, scanner);
+        if (rc1 != 0 && rc == 0)
+        {
+            rc = rc1;
+        }
+        value = value->next;
+    }
+    /* FIXME: More informative error messages */
+    return rc;
+}
+
+/*! \brief
+ * Adds a child element for a parameter, keeping the parameter order.
+ *
+ * \param[in,out] root  Root element to which the child is added.
+ * \param[in]     child Child to add.
+ * \param[in]     param Parameter for which this child is a value.
+ *
+ * Puts \p child in the child list of \p root such that the list remains
+ * in the same order as the corresponding parameters.
+ */
+static void
+place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
+{
+    gmx_ana_selparam_t *ps;
+    int                 n;
+
+    ps = root->u.expr.method->param;
+    n  = param - ps;
+    /* Put the child element in the correct place */
+    if (!root->child || n < root->child->u.param - ps)
+    {
+        child->next = root->child;
+        root->child = child;
+    }
+    else
+    {
+        t_selelem *prev;
+
+        prev = root->child;
+        while (prev->next && prev->next->u.param - ps >= n)
+        {
+            prev = prev->next;
+        }
+        child->next = prev->next;
+        prev->next  = child;
+    }
+}
+
+/*! \brief
+ * Comparison function for sorting integer ranges.
+ * 
+ * \param[in] a Pointer to the first range.
+ * \param[in] b Pointer to the second range.
+ * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
+ *
+ * The ranges are primarily sorted based on their starting point, and
+ * secondarily based on length (longer ranges come first).
+ */
+static int
+cmp_int_range(const void *a, const void *b)
+{
+    if (((int *)a)[0] < ((int *)b)[0])
+    {
+        return -1;
+    }
+    if (((int *)a)[0] > ((int *)b)[0])
+    {
+        return 1;
+    }
+    if (((int *)a)[1] > ((int *)b)[1])
+    {
+        return -1;
+    }
+    return 0;
+}
+
+/*! \brief
+ * Comparison function for sorting real ranges.
+ *
+ * \param[in] a Pointer to the first range.
+ * \param[in] b Pointer to the second range.
+ * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
+ *
+ * The ranges are primarily sorted based on their starting point, and
+ * secondarily based on length (longer ranges come first).
+ */
+static int
+cmp_real_range(const void *a, const void *b)
+{
+    if (((real *)a)[0] < ((real *)b)[0])
+    {
+        return -1;
+    }
+    if (((real *)a)[0] > ((real *)b)[0])
+    {
+        return 1;
+    }
+    if (((real *)a)[1] > ((real *)b)[1])
+    {
+        return -1;
+    }
+    return 0;
+}
+
+/*! \brief
+ * Parses the values for a parameter that takes integer or real ranges.
+ * 
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ */
+static gmx_bool
+parse_values_range(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
+                   void *scanner)
+{
+    t_selexpr_value    *value;
+    int                *idata;
+    real               *rdata;
+    int                 i, j, n;
+
+    param->flags &= ~SPAR_DYNAMIC;
+    if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError, "Invalid range parameter type");
+        return FALSE;
+    }
+    idata = NULL;
+    rdata = NULL;
+    if (param->val.type == INT_VALUE)
+    {
+        snew(idata, nval*2);
+    }
+    else
+    {
+        snew(rdata, nval*2);
+    }
+    value = values;
+    i = 0;
+    while (value)
+    {
+        if (value->bExpr)
+        {
+            _gmx_selparser_error(scanner, "expressions not supported within range parameters");
+            return FALSE;
+        }
+        if (value->type != param->val.type)
+        {
+            GMX_ERROR_NORET(gmx::eeInternalError, "Invalid range value type");
+            return FALSE;
+        }
+        if (param->val.type == INT_VALUE)
+        {
+            /* Make sure the input range is in increasing order */
+            if (value->u.i.i1 > value->u.i.i2)
+            {
+                int tmp       = value->u.i.i1;
+                value->u.i.i1 = value->u.i.i2;
+                value->u.i.i2 = tmp;
+            }
+            /* Check if the new range overlaps or extends the previous one */
+            if (i > 0 && value->u.i.i1 <= idata[i-1]+1 && value->u.i.i2 >= idata[i-2]-1)
+            {
+                idata[i-2] = min(idata[i-2], value->u.i.i1);
+                idata[i-1] = max(idata[i-1], value->u.i.i2);
+            }
+            else
+            {
+                idata[i++] = value->u.i.i1;
+                idata[i++] = value->u.i.i2;
+            }
+        }
+        else
+        {
+            /* Make sure the input range is in increasing order */
+            if (value->u.r.r1 > value->u.r.r2)
+            {
+                real tmp      = value->u.r.r1;
+                value->u.r.r1 = value->u.r.r2;
+                value->u.r.r2 = tmp;
+            }
+            /* Check if the new range overlaps or extends the previous one */
+            if (i > 0 && value->u.r.r1 <= rdata[i-1] && value->u.r.r2 >= rdata[i-2])
+            {
+                rdata[i-2] = min(rdata[i-2], value->u.r.r1);
+                rdata[i-1] = max(rdata[i-1], value->u.r.r2);
+            }
+            else
+            {
+                rdata[i++] = value->u.r.r1;
+                rdata[i++] = value->u.r.r2;
+            }
+        }
+        value = value->next;
+    }
+    n = i/2;
+    /* Sort the ranges and merge consequent ones */
+    if (param->val.type == INT_VALUE)
+    {
+        qsort(idata, n, 2*sizeof(int), &cmp_int_range);
+        for (i = j = 2; i < 2*n; i += 2)
+        {
+            if (idata[j-1]+1 >= idata[i])
+            {
+                if (idata[i+1] > idata[j-1])
+                {
+                    idata[j-1] = idata[i+1];
+                }
+            }
+            else
+            {
+                idata[j]   = idata[i];
+                idata[j+1] = idata[i+1];
+                j += 2;
+            }
+        }
+    }
+    else
+    {
+        qsort(rdata, n, 2*sizeof(real), &cmp_real_range);
+        for (i = j = 2; i < 2*n; i += 2)
+        {
+            if (rdata[j-1]+1 >= rdata[i])
+            {
+                if (rdata[i+1] > rdata[j-1])
+                {
+                    rdata[j-1] = rdata[i+1];
+                }
+            }
+            else
+            {
+                rdata[j]   = rdata[i];
+                rdata[j+1] = rdata[i+1];
+                j += 2;
+            }
+        }
+    }
+    n = j/2;
+    /* Store the values */
+    if (param->flags & SPAR_VARNUM)
+    {
+        param->val.nr  = n;
+        if (param->val.type == INT_VALUE)
+        {
+            srenew(idata, j);
+            _gmx_selvalue_setstore_alloc(&param->val, idata, j);
+        }
+        else
+        {
+            srenew(rdata, j);
+            _gmx_selvalue_setstore_alloc(&param->val, rdata, j);
+        }
+    }
+    else
+    {
+        if (n != param->val.nr)
+        {
+            _gmx_selparser_error(scanner, "the value should consist of exactly one range");
+            sfree(idata);
+            sfree(rdata);
+            return FALSE;
+        }
+        if (param->val.type == INT_VALUE)
+        {
+            memcpy(param->val.u.i, idata, 2*n*sizeof(int));
+            sfree(idata);
+        }
+        else
+        {
+            memcpy(param->val.u.r, rdata, 2*n*sizeof(real));
+            sfree(rdata);
+        }
+    }
+    if (param->nvalptr)
+    {
+        *param->nvalptr = param->val.nr;
+    }
+    param->nvalptr = NULL;
+
+    return TRUE;
+}
+
+/*! \brief
+ * Parses the values for a parameter that takes a variable number of values.
+ * 
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param     root   Selection element to which child expressions are added.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ *
+ * For integer ranges, the sequence of numbers from the first to second value
+ * is stored, each as a separate value.
+ */
+static gmx_bool
+parse_values_varnum(int nval, t_selexpr_value *values,
+                    gmx_ana_selparam_t *param, t_selelem *root, void *scanner)
+{
+    t_selexpr_value    *value;
+    int                 i, j;
+
+    param->flags &= ~SPAR_DYNAMIC;
+    /* Update nval if there are integer ranges. */
+    if (param->val.type == INT_VALUE)
+    {
+        value = values;
+        while (value)
+        {
+            if (value->type == INT_VALUE && !value->bExpr)
+            {
+                nval += abs(value->u.i.i2 - value->u.i.i1);
+            }
+            value = value->next;
+        }
+    }
+
+    /* Check that the value type is actually implemented */
+    if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE
+        && param->val.type != STR_VALUE && param->val.type != POS_VALUE)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError,
+                        "Variable-count value type not implemented");
+        return FALSE;
+    }
+
+    /* Reserve appropriate amount of memory */
+    if (param->val.type == POS_VALUE)
+    {
+        gmx_ana_pos_reserve(param->val.u.p, nval, 0);
+        gmx_ana_pos_set_nr(param->val.u.p, nval);
+        gmx_ana_indexmap_init(&param->val.u.p->m, NULL, NULL, INDEX_UNKNOWN);
+    }
+    else
+    {
+        _gmx_selvalue_reserve(&param->val, nval);
+    }
+
+    value = values;
+    i     = 0;
+    while (value)
+    {
+        if (value->bExpr)
+        {
+            _gmx_selparser_error(scanner, "expressions not supported within value lists");
+            return FALSE;
+        }
+        if (value->type != param->val.type)
+        {
+            GMX_ERROR_NORET(gmx::eeInternalError, "Invalid value type");
+            return FALSE;
+        }
+        switch (param->val.type)
+        {
+            case INT_VALUE:
+                if (value->u.i.i1 <= value->u.i.i2)
+                {
+                    for (j = value->u.i.i1; j <= value->u.i.i2; ++j)
+                    {
+                        param->val.u.i[i++] = j;
+                    }
+                }
+                else
+                {
+                    for (j = value->u.i.i1; j >= value->u.i.i2; --j)
+                    {
+                        param->val.u.i[i++] = j;
+                    }
+                }
+                break;
+            case REAL_VALUE:
+                if (value->u.r.r1 != value->u.r.r2)
+                {
+                    _gmx_selparser_error(scanner, "real ranges not supported");
+                    return FALSE;
+                }
+                param->val.u.r[i++] = value->u.r.r1;
+                break;
+            case STR_VALUE:  param->val.u.s[i++] = strdup(value->u.s); break;
+            case POS_VALUE:  copy_rvec(value->u.x, param->val.u.p->x[i++]); break;
+            default: /* Should not be reached */
+                GMX_ERROR_NORET(gmx::eeInternalError, "Invalid value type");
+                return FALSE;
+        }
+        value = value->next;
+    }
+    param->val.nr = i;
+    if (param->nvalptr)
+    {
+        *param->nvalptr = param->val.nr;
+    }
+    param->nvalptr = NULL;
+    /* Create a dummy child element to store the string values.
+     * This element is responsible for freeing the values, but carries no
+     * other function. */
+    if (param->val.type == STR_VALUE)
+    {
+        t_selelem *child;
+
+        child = _gmx_selelem_create(SEL_CONST);
+        _gmx_selelem_set_vtype(child, STR_VALUE);
+        child->name = param->name;
+        child->flags &= ~SEL_ALLOCVAL;
+        child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
+        child->v.nr = param->val.nr;
+        _gmx_selvalue_setstore(&child->v, param->val.u.s);
+        /* Because the child is not group-valued, the u union is not used
+         * for anything, so we can abuse it by storing the parameter value
+         * as place_child() expects, but this is really ugly... */
+        child->u.param = param;
+        place_child(root, child, param);
+    }
+
+    return TRUE;
+}
+
+/*! \brief
+ * Adds a new subexpression reference to a selection element.
+ *
+ * \param[in,out] root  Root element to which the subexpression is added.
+ * \param[in]     param Parameter for which this expression is a value.
+ * \param[in]     expr  Expression to add.
+ * \param[in]     scanner Scanner data structure.
+ * \returns       The created child element.
+ *
+ * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
+ * list of \p root.
+ * If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
+ * \ref SEL_ALLOCVAL is cleared for the returned element.
+ */
+static t_selelem *
+add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr,
+          void *scanner)
+{
+    t_selelem          *child;
+    int                 rc;
+
+    if (root->type != SEL_EXPRESSION && root->type != SEL_MODIFIER)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError,
+                        "Unsupported root element for selection parameter parser");
+        return NULL;
+    }
+    /* Create a subexpression reference element if necessary */
+    if (expr->type == SEL_SUBEXPRREF)
+    {
+        child = expr;
+    }
+    else
+    {
+        child = _gmx_selelem_create(SEL_SUBEXPRREF);
+        if (!child)
+        {
+            return NULL;
+        }
+        _gmx_selelem_set_vtype(child, expr->v.type);
+        child->child  = expr;
+    }
+    /* Setup the child element */
+    child->flags &= ~SEL_ALLOCVAL;
+    child->u.param = param;
+    if (child->v.type != param->val.type)
+    {
+        _gmx_selparser_error(scanner, "invalid expression value");
+        goto on_error;
+    }
+    rc = _gmx_selelem_update_flags(child, scanner);
+    if (rc != 0)
+    {
+        goto on_error;
+    }
+    if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
+    {
+        _gmx_selparser_error(scanner, "dynamic values not supported");
+        goto on_error;
+    }
+    if (!(child->flags & SEL_DYNAMIC))
+    {
+        param->flags &= ~SPAR_DYNAMIC;
+    }
+    /* Put the child element in the correct place */
+    place_child(root, child, param);
+    return child;
+
+on_error:
+    if (child != expr)
+    {
+        _gmx_selelem_free(child);
+    }
+    return NULL;
+}
+
+/*! \brief
+ * Parses an expression value for a parameter that takes a variable number of values.
+ * 
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param     root   Selection element to which child expressions are added.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ */
+static gmx_bool
+parse_values_varnum_expr(int nval, t_selexpr_value *values,
+                         gmx_ana_selparam_t *param, t_selelem *root,
+                         void *scanner)
+{
+    t_selexpr_value    *value;
+    t_selelem          *child;
+    t_selelem          *expr;
+
+    if (nval != 1 || !values->bExpr)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError, "Invalid expression value");
+        return FALSE;
+    }
+
+    value = values;
+    child = add_child(root, param, value->u.expr, scanner);
+    value->u.expr = NULL;
+    if (!child)
+    {
+        return FALSE;
+    }
+
+    /* Process single-valued expressions */
+    /* TODO: We should also handle SEL_SINGLEVAL expressions here */
+    if (child->v.type == POS_VALUE || child->v.type == GROUP_VALUE)
+    {
+        /* Set the value storage */
+        _gmx_selvalue_setstore(&child->v, param->val.u.ptr);
+        param->val.nr = 1;
+        if (param->nvalptr)
+        {
+            *param->nvalptr = param->val.nr;
+        }
+        param->nvalptr = NULL;
+        return TRUE;
+    }
+
+    if (!(child->flags & SEL_VARNUMVAL))
+    {
+        _gmx_selparser_error(scanner, "invalid expression value");
+        return FALSE;
+    }
+
+    child->flags   |= SEL_ALLOCVAL;
+    param->val.nr   = -1;
+    *param->nvalptr = param->val.nr;
+    /* Rest of the initialization is done during compilation in
+     * init_method(). */
+
+    return TRUE;
+}
+
+/*! \brief
+ * Initializes the storage of an expression value.
+ *
+ * \param[in,out] sel   Selection element that evaluates the value.
+ * \param[in]     param Parameter to receive the value.
+ * \param[in]     i     The value of \p sel evaluates the value \p i for
+ *   \p param.
+ * \param[in]     scanner Scanner data structure.
+ *
+ * Initializes the data pointer of \p sel such that the result is stored
+ * as the value \p i of \p param.
+ * This function is used internally by parse_values_std().
+ */
+static gmx_bool
+set_expr_value_store(t_selelem *sel, gmx_ana_selparam_t *param, int i,
+                     void *scanner)
+{
+    if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
+    {
+        _gmx_selparser_error(scanner, "invalid expression value");
+        return FALSE;
+    }
+    switch (sel->v.type)
+    {
+        case INT_VALUE:   sel->v.u.i = &param->val.u.i[i]; break;
+        case REAL_VALUE:  sel->v.u.r = &param->val.u.r[i]; break;
+        case STR_VALUE:   sel->v.u.s = &param->val.u.s[i]; break;
+        case POS_VALUE:   sel->v.u.p = &param->val.u.p[i]; break;
+        case GROUP_VALUE: sel->v.u.g = &param->val.u.g[i]; break;
+        default: /* Error */
+            GMX_ERROR_NORET(gmx::eeInternalError, "Invalid value type");
+            return FALSE;
+    }
+    sel->v.nr = 1;
+    sel->v.nalloc = -1;
+    return TRUE;
+}
+
+/*! \brief
+ * Parses the values for a parameter that takes a constant number of values.
+ * 
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param     root   Selection element to which child expressions are added.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ *
+ * For integer ranges, the sequence of numbers from the first to second value
+ * is stored, each as a separate value.
+ */
+static gmx_bool
+parse_values_std(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
+                 t_selelem *root, void *scanner)
+{
+    t_selexpr_value   *value;
+    t_selelem         *child;
+    int                i, j;
+    gmx_bool               bDynamic;
+
+    /* Handle atom-valued parameters */
+    if (param->flags & SPAR_ATOMVAL)
+    {
+        if (nval > 1)
+        {
+            _gmx_selparser_error(scanner, "more than one value not supported");
+            return FALSE;
+        }
+        value = values;
+        if (value->bExpr)
+        {
+            child = add_child(root, param, value->u.expr, scanner);
+            value->u.expr = NULL;
+            if (!child)
+            {
+                return FALSE;
+            }
+            child->flags |= SEL_ALLOCVAL;
+            if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
+            {
+                /* Rest of the initialization is done during compilation in
+                 * init_method(). */
+                /* TODO: Positions are not correctly handled */
+                param->val.nr = -1;
+                if (param->nvalptr)
+                {
+                    *param->nvalptr = -1;
+                }
+                return TRUE;
+            }
+            param->flags  &= ~SPAR_ATOMVAL;
+            param->val.nr  = 1;
+            if (param->nvalptr)
+            {
+                *param->nvalptr = 1;
+            }
+            param->nvalptr = NULL;
+            if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
+                || param->val.type == STR_VALUE)
+            {
+                _gmx_selvalue_reserve(&param->val, 1);
+            }
+            return set_expr_value_store(child, param, 0, scanner);
+        }
+        /* If we reach here, proceed with normal parameter handling */
+        param->val.nr = 1;
+        if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
+            || param->val.type == STR_VALUE)
+        {
+            _gmx_selvalue_reserve(&param->val, 1);
+        }
+        param->flags &= ~SPAR_ATOMVAL;
+        param->flags &= ~SPAR_DYNAMIC;
+    }
+
+    value = values;
+    i = 0;
+    bDynamic = FALSE;
+    while (value && i < param->val.nr)
+    {
+        if (value->type != param->val.type)
+        {
+            _gmx_selparser_error(scanner, "incorrect value skipped");
+            value = value->next;
+            continue;
+        }
+        if (value->bExpr)
+        {
+            child = add_child(root, param, value->u.expr, scanner);
+            /* Clear the expression from the value once it is stored */
+            value->u.expr = NULL;
+            /* Check that the expression is valid */
+            if (!child)
+            {
+                return FALSE;
+            }
+            if (!set_expr_value_store(child, param, i, scanner))
+            {
+                return FALSE;
+            }
+            if (child->flags & SEL_DYNAMIC)
+            {
+                bDynamic = TRUE;
+            }
+        }
+        else
+        {
+            /* Value is not an expression */
+            switch (value->type)
+            {
+                case INT_VALUE:
+                    if (value->u.i.i1 <= value->u.i.i2)
+                    {
+                        for (j = value->u.i.i1; j <= value->u.i.i2 && i < param->val.nr; ++j)
+                        {
+                            param->val.u.i[i++] = j;
+                        }
+                        if (j != value->u.i.i2 + 1)
+                        {
+                            _gmx_selparser_error(scanner, "extra values skipped");
+                        }
+                    }
+                    else
+                    {
+                        for (j = value->u.i.i1; j >= value->u.i.i2 && i < param->val.nr; --j)
+                        {
+                            param->val.u.i[i++] = j;
+                        }
+                        if (j != value->u.i.i2 - 1)
+                        {
+                            _gmx_selparser_error(scanner, "extra values skipped");
+                        }
+                    }
+                    --i;
+                    break;
+                case REAL_VALUE:
+                    if (value->u.r.r1 != value->u.r.r2)
+                    {
+                        _gmx_selparser_error(scanner, "real ranges not supported");
+                        return FALSE;
+                    }
+                    param->val.u.r[i] = value->u.r.r1;
+                    break;
+                case STR_VALUE:
+                    param->val.u.s[i] = strdup(value->u.s);
+                    break;
+                case POS_VALUE:
+                    gmx_ana_pos_init_const(&param->val.u.p[i], value->u.x);
+                    break;
+                case NO_VALUE:
+                case GROUP_VALUE:
+                    GMX_ERROR_NORET(gmx::eeInternalError,
+                                    "Invalid non-expression value");
+                    return FALSE;
+            }
+        }
+        ++i;
+        value = value->next;
+    }
+    if (value != NULL)
+    {
+        _gmx_selparser_error(scanner, "extra values'");
+        return FALSE;
+    }
+    if (i < param->val.nr)
+    {
+        _gmx_selparser_error(scanner, "not enough values");
+        return FALSE;
+    }
+    if (!bDynamic)
+    {
+        param->flags &= ~SPAR_DYNAMIC;
+    }
+    if (param->nvalptr)
+    {
+        *param->nvalptr = param->val.nr;
+    }
+    param->nvalptr = NULL;
+
+    return TRUE;
+}
+
+/*! \brief
+ * Parses the values for a boolean parameter.
+ *
+ * \param[in] name   Name by which the parameter was given.
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ */
+static gmx_bool
+parse_values_bool(const char *name, int nval, t_selexpr_value *values,
+                  gmx_ana_selparam_t *param, void *scanner)
+{
+    gmx_bool bSetNo;
+    int  len;
+
+    if (param->val.type != NO_VALUE)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError, "Invalid boolean parameter");
+        return FALSE;
+    }
+    if (nval > 1 || (values && values->type != INT_VALUE))
+    {
+        _gmx_selparser_error(scanner, "parameter takes only a yes/no/on/off/0/1 value");
+        return FALSE;
+    }
+
+    bSetNo = FALSE;
+    /* Check if the parameter name is given with a 'no' prefix */
+    len = strlen(name);
+    if (len > 2 && name[0] == 'n' && name[1] == 'o'
+        && strncmp(name+2, param->name, len-2) == 0)
+    {
+        bSetNo = TRUE;
+    }
+    if (bSetNo && nval > 0)
+    {
+        _gmx_selparser_error(scanner, "parameter 'no%s' should not have a value",
+                             param->name);
+        return FALSE;
+    }
+    if (values && values->u.i.i1 == 0)
+    {
+        bSetNo = TRUE;
+    }
+
+    *param->val.u.b = bSetNo ? FALSE : TRUE;
+    return TRUE;
+}
+
+/*! \brief
+ * Parses the values for an enumeration parameter.
+ *
+ * \param[in] nval   Number of values in \p values.
+ * \param[in] values Pointer to the list of values.
+ * \param     param  Parameter to parse.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
+ */
+static gmx_bool
+parse_values_enum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
+                  void *scanner)
+{
+    int  i, len, match;
+
+    if (nval != 1)
+    {
+        _gmx_selparser_error(scanner, "a single value is required");
+        return FALSE;
+    }
+    if (values->type != STR_VALUE || param->val.type != STR_VALUE)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError, "Invalid enum parameter");
+        return FALSE;
+    }
+    if (values->bExpr)
+    {
+        _gmx_selparser_error(scanner, "expression value for enumerated parameter not supported");
+        return FALSE;
+    }
+
+    len = strlen(values->u.s);
+    i = 1;
+    match = 0;
+    while (param->val.u.s[i] != NULL)
+    {
+        if (strncmp(values->u.s, param->val.u.s[i], len) == 0)
+        {
+            /* Check if there is a duplicate match */
+            if (match > 0)
+            {
+                _gmx_selparser_error(scanner, "ambiguous value");
+                return FALSE;
+            }
+            match = i;
+        }
+        ++i;
+    }
+    if (match == 0)
+    {
+        _gmx_selparser_error(scanner, "invalid value");
+        return FALSE;
+    }
+    param->val.u.s[0] = param->val.u.s[match];
+    return TRUE;
+}
+
+/*! \brief
+ * Replaces constant expressions with their values.
+ *
+ * \param[in,out] values First element in the value list to process.
+ */
+static void
+convert_const_values(t_selexpr_value *values)
+{
+    t_selexpr_value *val;
+
+    val = values;
+    while (val)
+    {
+        if (val->bExpr && val->u.expr->v.type != GROUP_VALUE &&
+            val->u.expr->type == SEL_CONST)
+        {
+            t_selelem *expr = val->u.expr;
+            val->bExpr = FALSE;
+            switch (expr->v.type)
+            {
+                case INT_VALUE:
+                    val->u.i.i1 = val->u.i.i2 = expr->v.u.i[0];
+                    break;
+                case REAL_VALUE:
+                    val->u.r.r1 = val->u.r.r2 = expr->v.u.r[0];
+                    break;
+                case STR_VALUE:
+                    val->u.s = expr->v.u.s[0];
+                    break;
+                case POS_VALUE:
+                    copy_rvec(expr->v.u.p->x[0], val->u.x);
+                    break;
+                default:
+                    GMX_ERROR_NORET(gmx::eeInternalError,
+                                    "Unsupported value type");
+                    break;
+            }
+            _gmx_selelem_free(expr);
+        }
+        val = val->next;
+    }
+}
+
+/*!
+ * \param     pparams List of parameters from the selection parser.
+ * \param[in] nparam  Number of parameters in \p params.
+ * \param     params  Array of parameters to parse.
+ * \param     root    Selection element to which child expressions are added.
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the parameters were parsed successfully, FALSE otherwise.
+ *
+ * Initializes the \p params array based on the parameters in \p pparams.
+ * See the documentation of \c gmx_ana_selparam_t for different options
+ * available for parsing.
+ *
+ * The list \p pparams and any associated values are freed after the parameters
+ * have been processed, no matter is there was an error or not.
+ */
+gmx_bool
+_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *params,
+                      t_selelem *root, void *scanner)
+{
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    t_selexpr_param    *pparam;
+    gmx_ana_selparam_t *oparam;
+    gmx_bool                bOk, rc;
+    int                 i;
+
+    /* Check that the value pointers of SPAR_VARNUM parameters are NULL and
+     * that they are not NULL for other parameters */
+    bOk = TRUE;
+    for (i = 0; i < nparam; ++i)
+    {
+        std::string contextStr = gmx::formatString("In parameter '%s'", params[i].name);
+        gmx::MessageStringContext  context(errors, contextStr);
+        if (params[i].val.type != POS_VALUE && (params[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
+        {
+            if (params[i].val.u.ptr != NULL)
+            {
+                _gmx_selparser_error(scanner, "value pointer is not NULL "
+                                     "although it should be for SPAR_VARNUM "
+                                     "and SPAR_ATOMVAL parameters");
+            }
+            if ((params[i].flags & SPAR_VARNUM)
+                && (params[i].flags & SPAR_DYNAMIC) && !params[i].nvalptr)
+            {
+                _gmx_selparser_error(scanner, "nvalptr is NULL but both "
+                                     "SPAR_VARNUM and SPAR_DYNAMIC are specified");
+                bOk = FALSE;
+            }
+        }
+        else
+        {
+            if (params[i].val.u.ptr == NULL)
+            {
+                _gmx_selparser_error(scanner, "value pointer is NULL");
+                bOk = FALSE;
+            }
+        }
+    }
+    if (!bOk)
+    {
+        _gmx_selexpr_free_params(pparams);
+        return FALSE;
+    }
+    /* Parse the parameters */
+    pparam = pparams;
+    i      = 0;
+    while (pparam)
+    {
+        std::string contextStr;
+        /* Find the parameter and make some checks */
+        if (pparam->name != NULL)
+        {
+            contextStr = gmx::formatString("In parameter '%s'", pparam->name);
+            i = -1;
+            oparam = gmx_ana_selparam_find(pparam->name, nparam, params);
+        }
+        else if (i >= 0)
+        {
+            contextStr = gmx::formatString("In value %d", i + 1);
+            oparam = &params[i];
+            if (oparam->name != NULL)
+            {
+                oparam = NULL;
+                _gmx_selparser_error(scanner, "too many NULL parameters provided");
+                bOk = FALSE;
+                pparam = pparam->next;
+                continue;
+            }
+            ++i;
+        }
+        else
+        {
+            _gmx_selparser_error(scanner, "all NULL parameters should appear in the beginning of the list");
+            bOk = FALSE;
+            pparam = pparam->next;
+            continue;
+        }
+        gmx::MessageStringContext  context(errors, contextStr);
+        if (!oparam)
+        {
+            _gmx_selparser_error(scanner, "unknown parameter skipped");
+            bOk = FALSE;
+            goto next_param;
+        }
+        if (oparam->flags & SPAR_SET)
+        {
+            _gmx_selparser_error(scanner, "parameter set multiple times, extra values skipped");
+            bOk = FALSE;
+            goto next_param;
+        }
+        oparam->flags |= SPAR_SET;
+        /* Process the values for the parameter */
+        convert_const_values(pparam->value);
+        if (convert_values(pparam->value, oparam->val.type, scanner) != 0)
+        {
+            _gmx_selparser_error(scanner, "invalid value");
+            bOk = FALSE;
+            goto next_param;
+        }
+        if (oparam->val.type == NO_VALUE)
+        {
+            rc = parse_values_bool(pparam->name, pparam->nval, pparam->value, oparam, scanner);
+        }
+        else if (oparam->flags & SPAR_RANGES)
+        {
+            rc = parse_values_range(pparam->nval, pparam->value, oparam, scanner);
+        }
+        else if (oparam->flags & SPAR_VARNUM)
+        {
+            if (pparam->nval == 1 && pparam->value->bExpr)
+            {
+                rc = parse_values_varnum_expr(pparam->nval, pparam->value, oparam, root, scanner);
+            }
+            else
+            {
+                rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root, scanner);
+            }
+        }
+        else if (oparam->flags & SPAR_ENUMVAL)
+        {
+            rc = parse_values_enum(pparam->nval, pparam->value, oparam, scanner);
+        }
+        else
+        {
+            rc = parse_values_std(pparam->nval, pparam->value, oparam, root, scanner);
+        }
+        if (!rc)
+        {
+            bOk = FALSE;
+        }
+        /* Advance to the next parameter */
+next_param:
+        pparam = pparam->next;
+    }
+    /* Check that all required parameters are present */
+    for (i = 0; i < nparam; ++i)
+    {
+        if (!(params[i].flags & SPAR_OPTIONAL) && !(params[i].flags & SPAR_SET))
+        {
+            _gmx_selparser_error(scanner, "required parameter '%s' not specified", params[i].name);
+            bOk = FALSE;
+        }
+    }
+
+    _gmx_selexpr_free_params(pparams);
+    return bOk;
+}
diff --git a/src/gromacs/selection/parser.cpp b/src/gromacs/selection/parser.cpp
new file mode 100644 (file)
index 0000000..cdc51e6
--- /dev/null
@@ -0,0 +1,2584 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, 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.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names.  */
+#define yyparse _gmx_sel_yybparse
+#define yylex   _gmx_sel_yyblex
+#define yyerror _gmx_sel_yyberror
+#define yylval  _gmx_sel_yyblval
+#define yychar  _gmx_sel_yybchar
+#define yydebug _gmx_sel_yybdebug
+#define yynerrs _gmx_sel_yybnerrs
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVALID = 258,
+     HELP = 259,
+     HELP_TOPIC = 260,
+     TOK_INT = 261,
+     TOK_REAL = 262,
+     STR = 263,
+     IDENTIFIER = 264,
+     CMD_SEP = 265,
+     GROUP = 266,
+     TO = 267,
+     VARIABLE_NUMERIC = 268,
+     VARIABLE_GROUP = 269,
+     VARIABLE_POS = 270,
+     KEYWORD_NUMERIC = 271,
+     KEYWORD_STR = 272,
+     KEYWORD_POS = 273,
+     KEYWORD_GROUP = 274,
+     METHOD_NUMERIC = 275,
+     METHOD_GROUP = 276,
+     METHOD_POS = 277,
+     MODIFIER = 278,
+     EMPTY_POSMOD = 279,
+     PARAM = 280,
+     END_OF_METHOD = 281,
+     OF = 282,
+     CMP_OP = 283,
+     PARAM_REDUCT = 284,
+     XOR = 285,
+     OR = 286,
+     AND = 287,
+     NOT = 288,
+     UNARY_NEG = 289,
+     NUM_REDUCT = 290
+   };
+#endif
+/* Tokens.  */
+#define INVALID 258
+#define HELP 259
+#define HELP_TOPIC 260
+#define TOK_INT 261
+#define TOK_REAL 262
+#define STR 263
+#define IDENTIFIER 264
+#define CMD_SEP 265
+#define GROUP 266
+#define TO 267
+#define VARIABLE_NUMERIC 268
+#define VARIABLE_GROUP 269
+#define VARIABLE_POS 270
+#define KEYWORD_NUMERIC 271
+#define KEYWORD_STR 272
+#define KEYWORD_POS 273
+#define KEYWORD_GROUP 274
+#define METHOD_NUMERIC 275
+#define METHOD_GROUP 276
+#define METHOD_POS 277
+#define MODIFIER 278
+#define EMPTY_POSMOD 279
+#define PARAM 280
+#define END_OF_METHOD 281
+#define OF 282
+#define CMP_OP 283
+#define PARAM_REDUCT 284
+#define XOR 285
+#define OR 286
+#define AND 287
+#define NOT 288
+#define UNARY_NEG 289
+#define NUM_REDUCT 290
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 37 "parser.y"
+
+/*! \internal \file parser.cpp
+ * \brief Generated (from parser.y by Bison) parser for the selection language.
+ *
+ * \ingroup module_selection
+ */
+/*! \internal \file parser.h
+ * \brief Generated (from parser.y by Bison) parser include file.
+ *
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <string2.h>
+
+#include "parsetree.h"
+#include "selelem.h"
+
+#include "scanner.h"
+
+static t_selexpr_value *
+process_value_list(t_selexpr_value *values, int *nr);
+static t_selexpr_param *
+process_param_list(t_selexpr_param *params);
+
+static void
+yyerror(yyscan_t, char const *s);
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 69 "parser.y"
+{
+    int                         i;
+    real                        r;
+    char                       *str;
+    struct gmx_ana_selmethod_t *meth;
+
+    struct t_selelem           *sel;
+
+    struct t_selexpr_value     *val;
+    struct t_selexpr_param     *param;
+}
+/* Line 187 of yacc.c.  */
+#line 218 "parser.cpp"
+       YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 231 "parser.cpp"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+            && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   417
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  49
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  26
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  91
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  150
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   290
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      42,    43,    36,    34,    45,    35,     2,    37,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    41,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    44,     2,    46,    39,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    47,     2,    48,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    38,
+      40
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     7,    10,    13,    14,    16,    18,
+      20,    22,    25,    29,    33,    37,    39,    41,    44,    47,
+      49,    51,    55,    59,    61,    64,    66,    69,    71,    73,
+      75,    77,    80,    84,    88,    92,    96,    99,   102,   104,
+     106,   109,   113,   117,   121,   123,   125,   128,   132,   136,
+     140,   144,   148,   151,   155,   159,   161,   164,   172,   176,
+     179,   183,   185,   187,   189,   191,   194,   195,   198,   201,
+     202,   204,   208,   210,   213,   217,   219,   223,   225,   228,
+     232,   234,   236,   238,   240,   242,   244,   246,   248,   250,
+     254,   258
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      50,     0,    -1,    -1,    50,    51,    -1,    52,    10,    -1,
+       1,    10,    -1,    -1,    53,    -1,     6,    -1,    59,    -1,
+      55,    -1,    59,    55,    -1,     9,    41,    60,    -1,     9,
+      41,    62,    -1,     9,    41,    64,    -1,     4,    -1,    54,
+      -1,     4,     5,    -1,    54,     5,    -1,    64,    -1,    60,
+      -1,    42,    55,    43,    -1,    55,    23,    65,    -1,     6,
+      -1,    35,     6,    -1,     7,    -1,    35,     7,    -1,    56,
+      -1,    57,    -1,     8,    -1,     9,    -1,    33,    60,    -1,
+      60,    32,    60,    -1,    60,    31,    60,    -1,    42,    60,
+      43,    -1,    62,    28,    62,    -1,    11,    59,    -1,    11,
+       6,    -1,    24,    -1,    18,    -1,    61,    19,    -1,    61,
+      17,    70,    -1,    61,    16,    70,    -1,    61,    21,    65,
+      -1,     6,    -1,     7,    -1,    61,    16,    -1,    61,    20,
+      65,    -1,    62,    34,    62,    -1,    62,    35,    62,    -1,
+      62,    36,    62,    -1,    62,    37,    62,    -1,    35,    62,
+      -1,    62,    39,    62,    -1,    42,    62,    43,    -1,    59,
+      -1,    61,    17,    -1,    44,    58,    45,    58,    45,    58,
+      46,    -1,    42,    64,    43,    -1,    22,    65,    -1,    18,
+      27,    60,    -1,    14,    -1,    13,    -1,    15,    -1,    66,
+      -1,    66,    26,    -1,    -1,    66,    67,    -1,    25,    68,
+      -1,    -1,    69,    -1,    47,    69,    48,    -1,    72,    -1,
+      69,    72,    -1,    69,    45,    72,    -1,    71,    -1,    47,
+      71,    48,    -1,    73,    -1,    71,    73,    -1,    71,    45,
+      73,    -1,    60,    -1,    64,    -1,    62,    -1,    63,    -1,
+      74,    -1,    56,    -1,    57,    -1,    59,    -1,    74,    -1,
+      56,    12,    56,    -1,    56,    12,    57,    -1,    57,    12,
+      58,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   189,   189,   190,   199,   200,   220,   224,   225,   234,
+     244,   246,   248,   250,   252,   258,   259,   262,   263,   267,
+     268,   273,   274,   286,   287,   291,   292,   295,   296,   299,
+     300,   308,   314,   320,   332,   336,   344,   350,   358,   359,
+     363,   368,   373,   381,   393,   400,   410,   415,   423,   425,
+     427,   429,   431,   433,   435,   442,   449,   461,   466,   470,
+     478,   489,   493,   497,   506,   508,   513,   514,   519,   526,
+     527,   528,   532,   533,   535,   540,   541,   545,   546,   548,
+     552,   554,   556,   558,   560,   564,   569,   574,   579,   583,
+     588,   593
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "INVALID", "HELP", "HELP_TOPIC",
+  "TOK_INT", "TOK_REAL", "STR", "IDENTIFIER", "CMD_SEP", "GROUP", "TO",
+  "VARIABLE_NUMERIC", "VARIABLE_GROUP", "VARIABLE_POS", "KEYWORD_NUMERIC",
+  "KEYWORD_STR", "KEYWORD_POS", "KEYWORD_GROUP", "METHOD_NUMERIC",
+  "METHOD_GROUP", "METHOD_POS", "MODIFIER", "EMPTY_POSMOD", "PARAM",
+  "END_OF_METHOD", "OF", "CMP_OP", "PARAM_REDUCT", "XOR", "OR", "AND",
+  "NOT", "'+'", "'-'", "'*'", "'/'", "UNARY_NEG", "'^'", "NUM_REDUCT",
+  "'='", "'('", "')'", "'['", "','", "']'", "'{'", "'}'", "$accept",
+  "commands", "command", "cmd_plain", "help_request", "help_topic",
+  "selection", "integer_number", "real_number", "number", "string",
+  "sel_expr", "pos_mod", "num_expr", "str_expr", "pos_expr",
+  "method_params", "method_param_list", "method_param", "value_list",
+  "value_list_contents", "basic_value_list", "basic_value_list_contents",
+  "value_item", "basic_value_item", "value_item_range", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,    43,    45,    42,    47,   289,    94,
+     290,    61,    40,    41,    91,    44,    93,   123,   125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    49,    50,    50,    51,    51,    52,    52,    52,    52,
+      52,    52,    52,    52,    52,    53,    53,    54,    54,    55,
+      55,    55,    55,    56,    56,    57,    57,    58,    58,    59,
+      59,    60,    60,    60,    60,    60,    60,    60,    61,    61,
+      60,    60,    60,    60,    62,    62,    62,    62,    62,    62,
+      62,    62,    62,    62,    62,    63,    63,    64,    64,    64,
+      64,    60,    62,    64,    65,    65,    66,    66,    67,    68,
+      68,    68,    69,    69,    69,    70,    70,    71,    71,    71,
+      72,    72,    72,    72,    72,    73,    73,    73,    73,    74,
+      74,    74
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     2,     2,     0,     1,     1,     1,
+       1,     2,     3,     3,     3,     1,     1,     2,     2,     1,
+       1,     3,     3,     1,     2,     1,     2,     1,     1,     1,
+       1,     2,     3,     3,     3,     3,     2,     2,     1,     1,
+       2,     3,     3,     3,     1,     1,     2,     3,     3,     3,
+       3,     3,     2,     3,     3,     1,     2,     7,     3,     2,
+       3,     1,     1,     1,     1,     2,     0,     2,     2,     0,
+       1,     3,     1,     2,     3,     1,     3,     1,     2,     3,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
+       3,     3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,     0,    15,    44,    45,    29,    30,     0,
+      62,    61,    63,    39,    66,    38,     0,     0,     0,     0,
+       3,     0,     7,    16,    10,     9,    20,     0,     0,    19,
+       5,    17,     0,    37,    30,    36,     0,    59,    64,    44,
+      39,     0,    31,     0,     0,    52,     0,    20,     0,    19,
+      23,    25,     0,    27,    28,     0,     4,    18,    66,    11,
+       0,     0,    46,     0,    40,    66,    66,     0,     0,     0,
+       0,     0,     0,     0,    12,    13,    14,    60,    69,    65,
+      67,     0,     0,    46,    21,    34,    54,    58,    24,    26,
+       0,    22,    33,    32,     0,    85,    86,    87,    42,    75,
+      77,    88,    41,    47,    43,    35,    48,    49,    50,    51,
+      53,     0,    44,    45,     0,     0,     0,     0,    55,    80,
+       0,    82,    83,    81,    68,    70,    72,    84,     0,     0,
+       0,     0,     0,    78,    44,    45,     0,    56,     0,    73,
+       0,    76,    89,    90,    91,    79,    71,    74,     0,    57
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     1,    20,    21,    22,    23,    24,    95,    96,    55,
+      97,   119,    27,    28,   122,   123,    37,    38,    80,   124,
+     125,   102,    99,   126,   100,   101
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -93
+static const yytype_int16 yypact[] =
+{
+     -93,   155,   -93,    10,    19,    26,   -93,   -93,    -3,    73,
+     -93,   -93,   -93,    22,   -93,   -93,   356,   372,   317,    11,
+     -93,    79,   -93,    86,    70,   317,    29,   384,   180,   -93,
+     -93,   -93,   342,   -93,   -93,   -93,   356,   -93,     6,   -93,
+     -93,   356,   -93,   372,   -10,    57,   -20,   -17,   256,    54,
+     -93,   -93,    88,   -93,   -93,    55,   -93,   -93,   -93,    70,
+     356,   356,   197,   174,   -93,   -93,   -93,   372,   372,   372,
+     372,   372,   372,   342,    29,   180,   -93,    29,   221,   -93,
+     -93,   -17,   223,   -93,   -93,   -93,   -93,   -93,   -93,   -93,
+      11,   -93,    69,   -93,    78,    90,    94,   -93,   -93,   244,
+     -93,   -93,   -93,   -93,   -93,   267,    36,    36,    57,    57,
+      57,    54,    95,    96,   375,   303,    90,    94,   -93,    29,
+     392,   267,   -93,   -93,   -93,   263,   -93,   -93,    71,    35,
+      11,    11,    78,   -93,   105,   106,   178,   174,   303,   -93,
+      11,   -93,   -93,   -93,   -93,   -93,   -93,   -93,    80,   -93
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -93,   -93,   -93,   -93,   -93,   -93,   -13,     0,    14,   -81,
+      -1,    87,    -4,   -16,   -93,     3,   -36,   -93,   -93,   -93,
+      12,    81,    39,   -91,   -92,   -67
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -27
+static const yytype_int16 yytable[] =
+{
+      25,    45,    48,    58,    29,    46,    83,   133,    35,   128,
+      65,   127,    59,    44,    60,    61,    75,    50,    51,    53,
+      30,    49,    91,    84,    31,    48,    85,    82,    29,   103,
+     104,    78,    79,    54,   139,    76,    -8,   133,    32,    44,
+     145,    50,    51,     7,    34,   139,    52,   147,   127,    36,
+     144,   105,   106,   107,   108,   109,   110,    48,   127,   148,
+      60,    61,   121,    44,    44,    44,    44,    44,    44,   127,
+      52,   127,    70,    71,   120,    72,   111,   118,   116,    33,
+     132,     7,    34,   141,    50,    51,     7,    34,    26,    56,
+      53,    57,   117,    58,    88,    89,    72,    87,    45,   121,
+      90,    61,   130,    42,    54,    47,   131,   -23,   -25,   121,
+      44,   120,    26,    52,   118,   116,   140,   -24,   -26,    74,
+     121,   120,   121,    77,   118,   116,   149,   136,    81,   117,
+     142,    53,   120,   129,   120,   118,   116,   118,   116,   117,
+      53,     0,     0,    98,   143,    54,     0,    92,    93,     0,
+     117,     0,   117,     0,    54,     2,     3,     0,     0,     4,
+      81,     5,     6,     7,     8,    -6,     9,     0,    10,    11,
+      12,     0,     0,    13,     0,     0,     0,    14,     0,    15,
+      50,    51,     7,    34,   112,   113,     7,    34,    16,     9,
+      17,    10,    11,    12,     0,     0,    13,    18,     0,    19,
+      14,     0,    15,    50,    51,     7,    34,     0,    67,    52,
+       0,    16,     0,   114,    68,    69,    70,    71,     0,    72,
+      73,    94,    19,   138,     0,     0,   146,   112,   113,     7,
+      34,     0,     9,     0,    10,    11,    12,     0,     0,    13,
+       0,     0,     0,    14,    94,    15,     0,     0,     0,     0,
+      50,    51,     7,    34,    16,     0,   114,    68,    69,    70,
+      71,     0,    72,    73,     0,    19,    86,     0,   115,   112,
+     113,     7,    34,     0,     9,     0,    10,    11,    12,    52,
+       0,    13,     0,     0,    67,    14,     0,    15,     0,   132,
+      68,    69,    70,    71,     0,    72,    16,     0,   114,    86,
+       0,    68,    69,    70,    71,    73,    72,    19,   138,   112,
+     113,     7,    34,     0,     9,     0,    10,    11,    12,     0,
+       0,    13,     0,    39,     6,    14,     0,    15,     9,     0,
+      10,    11,    12,     0,     0,    13,    16,     0,   114,    14,
+       0,    15,     0,     0,     0,    73,     0,    19,    39,     6,
+      16,     0,    17,     9,     0,    10,    11,    12,     0,    18,
+      13,    19,    39,     6,    14,     0,    15,     9,     0,    10,
+      11,     0,     0,     0,    40,    16,     0,    17,    39,     6,
+      15,   134,   135,     0,    73,    10,    19,     0,    10,    16,
+      40,    17,     0,    40,     0,     0,    15,     0,    41,    15,
+      62,    63,     0,    64,    65,    66,     0,    17,    62,   137,
+      17,    64,    65,    66,    43,     0,     0,    43
+};
+
+static const yytype_int16 yycheck[] =
+{
+       1,    17,    18,    23,     1,    18,    16,    99,     9,    90,
+      20,    78,    25,    17,    31,    32,    32,     6,     7,    19,
+      10,    18,    58,    43,     5,    41,    43,    43,    25,    65,
+      66,    25,    26,    19,   125,    32,    10,   129,    41,    43,
+     132,     6,     7,     8,     9,   136,    35,   138,   115,    27,
+     131,    67,    68,    69,    70,    71,    72,    73,   125,   140,
+      31,    32,    78,    67,    68,    69,    70,    71,    72,   136,
+      35,   138,    36,    37,    78,    39,    73,    78,    78,     6,
+      45,     8,     9,    48,     6,     7,     8,     9,     1,    10,
+      90,     5,    78,    23,     6,     7,    39,    43,   114,   115,
+      45,    32,    12,    16,    90,    18,    12,    12,    12,   125,
+     114,   115,    25,    35,   115,   115,    45,    12,    12,    32,
+     136,   125,   138,    36,   125,   125,    46,   115,    41,   115,
+     130,   131,   136,    94,   138,   136,   136,   138,   138,   125,
+     140,    -1,    -1,    62,   130,   131,    -1,    60,    61,    -1,
+     136,    -1,   138,    -1,   140,     0,     1,    -1,    -1,     4,
+      73,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
+      15,    -1,    -1,    18,    -1,    -1,    -1,    22,    -1,    24,
+       6,     7,     8,     9,     6,     7,     8,     9,    33,    11,
+      35,    13,    14,    15,    -1,    -1,    18,    42,    -1,    44,
+      22,    -1,    24,     6,     7,     8,     9,    -1,    28,    35,
+      -1,    33,    -1,    35,    34,    35,    36,    37,    -1,    39,
+      42,    47,    44,    45,    -1,    -1,    48,     6,     7,     8,
+       9,    -1,    11,    -1,    13,    14,    15,    -1,    -1,    18,
+      -1,    -1,    -1,    22,    47,    24,    -1,    -1,    -1,    -1,
+       6,     7,     8,     9,    33,    -1,    35,    34,    35,    36,
+      37,    -1,    39,    42,    -1,    44,    43,    -1,    47,     6,
+       7,     8,     9,    -1,    11,    -1,    13,    14,    15,    35,
+      -1,    18,    -1,    -1,    28,    22,    -1,    24,    -1,    45,
+      34,    35,    36,    37,    -1,    39,    33,    -1,    35,    43,
+      -1,    34,    35,    36,    37,    42,    39,    44,    45,     6,
+       7,     8,     9,    -1,    11,    -1,    13,    14,    15,    -1,
+      -1,    18,    -1,     6,     7,    22,    -1,    24,    11,    -1,
+      13,    14,    15,    -1,    -1,    18,    33,    -1,    35,    22,
+      -1,    24,    -1,    -1,    -1,    42,    -1,    44,     6,     7,
+      33,    -1,    35,    11,    -1,    13,    14,    15,    -1,    42,
+      18,    44,     6,     7,    22,    -1,    24,    11,    -1,    13,
+      14,    -1,    -1,    -1,    18,    33,    -1,    35,     6,     7,
+      24,     6,     7,    -1,    42,    13,    44,    -1,    13,    33,
+      18,    35,    -1,    18,    -1,    -1,    24,    -1,    42,    24,
+      16,    17,    -1,    19,    20,    21,    -1,    35,    16,    17,
+      35,    19,    20,    21,    42,    -1,    -1,    42
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    50,     0,     1,     4,     6,     7,     8,     9,    11,
+      13,    14,    15,    18,    22,    24,    33,    35,    42,    44,
+      51,    52,    53,    54,    55,    59,    60,    61,    62,    64,
+      10,     5,    41,     6,     9,    59,    27,    65,    66,     6,
+      18,    42,    60,    42,    61,    62,    55,    60,    62,    64,
+       6,     7,    35,    56,    57,    58,    10,     5,    23,    55,
+      31,    32,    16,    17,    19,    20,    21,    28,    34,    35,
+      36,    37,    39,    42,    60,    62,    64,    60,    25,    26,
+      67,    60,    62,    16,    43,    43,    43,    43,     6,     7,
+      45,    65,    60,    60,    47,    56,    57,    59,    70,    71,
+      73,    74,    70,    65,    65,    62,    62,    62,    62,    62,
+      62,    64,     6,     7,    35,    47,    56,    57,    59,    60,
+      61,    62,    63,    64,    68,    69,    72,    74,    58,    71,
+      12,    12,    45,    73,     6,     7,    69,    17,    45,    72,
+      45,    48,    56,    57,    58,    73,    48,    72,    58,    46
+};
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK (1);                                          \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror (scanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                 \
+    }                                                          \
+while (YYID (0))
+
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+       }                                                               \
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, scanner)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
+do {                                                                     \
+  if (yydebug)                                                           \
+    {                                                                    \
+      YYFPRINTF (stderr, "%s ", Title);                                          \
+      yy_symbol_print (stderr,                                           \
+                 Type, Value, scanner); \
+      YYFPRINTF (stderr, "\n");                                                  \
+    }                                                                    \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t                 scanner)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    yyscan_t                 scanner;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (scanner);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+       break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t                 scanner)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, scanner)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    yyscan_t                 scanner;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, yyscan_t                 scanner)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, scanner)
+    YYSTYPE *yyvsp;
+    int yyrule;
+    yyscan_t                 scanner;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+            yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                      &(yyvsp[(yyi + 1) - (yynrhs)])
+                                      , scanner);
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (yyvsp, Rule, scanner); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+       switch (*++yyp)
+         {
+         case '\'':
+         case ',':
+           goto do_not_strip_quotes;
+
+         case '\\':
+           if (*++yyp != '\\')
+             goto do_not_strip_quotes;
+           /* Fall through.  */
+         default:
+           if (yyres)
+             yyres[yyn] = *yyp;
+           yyn++;
+           break;
+
+         case '"':
+           if (yyres)
+             yyres[yyn] = '\0';
+           return yyn;
+         }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+        constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+                   + sizeof yyexpecting - 1
+                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+                      * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+        YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+         {
+           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+             {
+               yycount = 1;
+               yysize = yysize0;
+               yyformat[sizeof yyunexpected - 1] = '\0';
+               break;
+             }
+           yyarg[yycount++] = yytname[yyx];
+           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+           yysize_overflow |= (yysize1 < yysize);
+           yysize = yysize1;
+           yyfmt = yystpcpy (yyfmt, yyprefix);
+           yyprefix = yyor;
+         }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+       {
+         /* Avoid sprintf, as that infringes on the user's name space.
+            Don't have undefined behavior even if the translation
+            produced a string with the wrong number of "%s"s.  */
+         char *yyp = yyresult;
+         int yyi = 0;
+         while ((*yyp = *yyf) != '\0')
+           {
+             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+               {
+                 yyp += yytnamerr (yyp, yyarg[yyi++]);
+                 yyf += 2;
+               }
+             else
+               {
+                 yyp++;
+                 yyf++;
+               }
+           }
+       }
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t                 scanner)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, scanner)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    yyscan_t                 scanner;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (scanner);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+      case 5: /* "HELP_TOPIC" */
+#line 168 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1321 "parser.cpp"
+       break;
+      case 8: /* "STR" */
+#line 168 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1326 "parser.cpp"
+       break;
+      case 9: /* "IDENTIFIER" */
+#line 168 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1331 "parser.cpp"
+       break;
+      case 25: /* "PARAM" */
+#line 169 "parser.y"
+       { if((yyvaluep->str)) free((yyvaluep->str));              };
+#line 1336 "parser.cpp"
+       break;
+      case 28: /* "CMP_OP" */
+#line 168 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1341 "parser.cpp"
+       break;
+      case 51: /* "command" */
+#line 170 "parser.y"
+       { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
+#line 1346 "parser.cpp"
+       break;
+      case 52: /* "cmd_plain" */
+#line 170 "parser.y"
+       { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
+#line 1351 "parser.cpp"
+       break;
+      case 55: /* "selection" */
+#line 171 "parser.y"
+       { _gmx_selelem_free_chain((yyvaluep->sel));  };
+#line 1356 "parser.cpp"
+       break;
+      case 59: /* "string" */
+#line 168 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1361 "parser.cpp"
+       break;
+      case 60: /* "sel_expr" */
+#line 172 "parser.y"
+       { _gmx_selelem_free((yyvaluep->sel));        };
+#line 1366 "parser.cpp"
+       break;
+      case 62: /* "num_expr" */
+#line 172 "parser.y"
+       { _gmx_selelem_free((yyvaluep->sel));        };
+#line 1371 "parser.cpp"
+       break;
+      case 63: /* "str_expr" */
+#line 172 "parser.y"
+       { _gmx_selelem_free((yyvaluep->sel));        };
+#line 1376 "parser.cpp"
+       break;
+      case 64: /* "pos_expr" */
+#line 172 "parser.y"
+       { _gmx_selelem_free((yyvaluep->sel));        };
+#line 1381 "parser.cpp"
+       break;
+      case 65: /* "method_params" */
+#line 173 "parser.y"
+       { _gmx_selexpr_free_params((yyvaluep->param)); };
+#line 1386 "parser.cpp"
+       break;
+      case 66: /* "method_param_list" */
+#line 173 "parser.y"
+       { _gmx_selexpr_free_params((yyvaluep->param)); };
+#line 1391 "parser.cpp"
+       break;
+      case 67: /* "method_param" */
+#line 173 "parser.y"
+       { _gmx_selexpr_free_params((yyvaluep->param)); };
+#line 1396 "parser.cpp"
+       break;
+      case 68: /* "value_list" */
+#line 174 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1401 "parser.cpp"
+       break;
+      case 69: /* "value_list_contents" */
+#line 174 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1406 "parser.cpp"
+       break;
+      case 70: /* "basic_value_list" */
+#line 175 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1411 "parser.cpp"
+       break;
+      case 71: /* "basic_value_list_contents" */
+#line 175 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1416 "parser.cpp"
+       break;
+      case 72: /* "value_item" */
+#line 174 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1421 "parser.cpp"
+       break;
+      case 73: /* "basic_value_item" */
+#line 175 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1426 "parser.cpp"
+       break;
+      case 74: /* "value_item_range" */
+#line 174 "parser.y"
+       { _gmx_selexpr_free_values((yyvaluep->val)); };
+#line 1431 "parser.cpp"
+       break;
+
+      default:
+       break;
+    }
+}
+\f
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (yyscan_t                 scanner);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (yyscan_t                 scanner)
+#else
+int
+yyparse (scanner)
+    yyscan_t                 scanner;
+#endif
+#endif
+{
+  /* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack.  Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       yytype_int16 *yyss1 = yyss;
+
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow (YY_("memory exhausted"),
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+
+                   &yystacksize);
+
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       yytype_int16 *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyexhaustedlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 189 "parser.y"
+    { (yyval.sel) = NULL ;}
+    break;
+
+  case 3:
+#line 191 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
+                 if (_gmx_sel_parser_should_finish(scanner))
+                     YYACCEPT;
+             ;}
+    break;
+
+  case 4:
+#line 199 "parser.y"
+    { (yyval.sel) = (yyvsp[(1) - (2)].sel); ;}
+    break;
+
+  case 5:
+#line 201 "parser.y"
+    {
+                 (yyval.sel) = NULL;
+                 _gmx_selparser_error(scanner, "invalid selection '%s'",
+                                      _gmx_sel_lexer_pselstr(scanner));
+                 _gmx_sel_lexer_clear_method_stack(scanner);
+                 if (_gmx_sel_is_lexer_interactive(scanner))
+                 {
+                     _gmx_sel_lexer_clear_pselstr(scanner);
+                     yyerrok;
+                 }
+                 else
+                 {
+                     YYABORT;
+                 }
+             ;}
+    break;
+
+  case 6:
+#line 220 "parser.y"
+    {
+                 (yyval.sel) = NULL;
+                 _gmx_sel_handle_empty_cmd(scanner);
+             ;}
+    break;
+
+  case 7:
+#line 224 "parser.y"
+    { (yyval.sel) = NULL; ;}
+    break;
+
+  case 8:
+#line 226 "parser.y"
+    {
+                 t_selelem *s, *p;
+                 s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
+                 if (s == NULL) YYERROR;
+                 p = _gmx_sel_init_position(s, NULL, scanner);
+                 if (p == NULL) YYERROR;
+                 (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+             ;}
+    break;
+
+  case 9:
+#line 235 "parser.y"
+    {
+                 t_selelem *s, *p;
+                 s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
+                 free((yyvsp[(1) - (1)].str));
+                 if (s == NULL) YYERROR;
+                 p = _gmx_sel_init_position(s, NULL, scanner);
+                 if (p == NULL) YYERROR;
+                 (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+             ;}
+    break;
+
+  case 10:
+#line 245 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner); ;}
+    break;
+
+  case 11:
+#line 247 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);   ;}
+    break;
+
+  case 12:
+#line 249 "parser.y"
+    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
+    break;
+
+  case 13:
+#line 251 "parser.y"
+    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
+    break;
+
+  case 14:
+#line 253 "parser.y"
+    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
+    break;
+
+  case 15:
+#line 258 "parser.y"
+    { _gmx_sel_handle_help_cmd(NULL, scanner); ;}
+    break;
+
+  case 17:
+#line 262 "parser.y"
+    { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
+    break;
+
+  case 18:
+#line 263 "parser.y"
+    { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
+    break;
+
+  case 19:
+#line 267 "parser.y"
+    { (yyval.sel) = (yyvsp[(1) - (1)].sel); ;}
+    break;
+
+  case 20:
+#line 269 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 21:
+#line 273 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 22:
+#line 275 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 23:
+#line 286 "parser.y"
+    { (yyval.r) = (yyvsp[(1) - (1)].i); ;}
+    break;
+
+  case 24:
+#line 287 "parser.y"
+    { (yyval.r) = -(yyvsp[(2) - (2)].i); ;}
+    break;
+
+  case 25:
+#line 291 "parser.y"
+    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
+    break;
+
+  case 26:
+#line 292 "parser.y"
+    { (yyval.r) = -(yyvsp[(2) - (2)].r); ;}
+    break;
+
+  case 27:
+#line 295 "parser.y"
+    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
+    break;
+
+  case 28:
+#line 296 "parser.y"
+    { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
+    break;
+
+  case 29:
+#line 299 "parser.y"
+    { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
+    break;
+
+  case 30:
+#line 300 "parser.y"
+    { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
+    break;
+
+  case 31:
+#line 309 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
+                 (yyval.sel)->u.boolt = BOOL_NOT;
+                 (yyval.sel)->child = (yyvsp[(2) - (2)].sel);
+             ;}
+    break;
+
+  case 32:
+#line 315 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
+                 (yyval.sel)->u.boolt = BOOL_AND;
+                 (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+             ;}
+    break;
+
+  case 33:
+#line 321 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
+                 (yyval.sel)->u.boolt = BOOL_OR;
+                 (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+             ;}
+    break;
+
+  case 34:
+#line 332 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 35:
+#line 337 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 36:
+#line 345 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
+                 free((yyvsp[(2) - (2)].str));
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 37:
+#line 351 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 38:
+#line 358 "parser.y"
+    { (yyval.str) = NULL; ;}
+    break;
+
+  case 39:
+#line 359 "parser.y"
+    { (yyval.str) = (yyvsp[(1) - (1)].str);   ;}
+    break;
+
+  case 40:
+#line 364 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 41:
+#line 369 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 42:
+#line 374 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 43:
+#line 382 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 44:
+#line 394 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
+                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
+                 (yyval.sel)->v.u.i[0] = (yyvsp[(1) - (1)].i);
+             ;}
+    break;
+
+  case 45:
+#line 401 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
+                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
+                 (yyval.sel)->v.u.r[0] = (yyvsp[(1) - (1)].r);
+             ;}
+    break;
+
+  case 46:
+#line 411 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 47:
+#line 416 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 48:
+#line 424 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner); ;}
+    break;
+
+  case 49:
+#line 426 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner); ;}
+    break;
+
+  case 50:
+#line 428 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner); ;}
+    break;
+
+  case 51:
+#line 430 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner); ;}
+    break;
+
+  case 52:
+#line 432 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner); ;}
+    break;
+
+  case 53:
+#line 434 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner); ;}
+    break;
+
+  case 54:
+#line 435 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 55:
+#line 443 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
+                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
+                 (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
+             ;}
+    break;
+
+  case 56:
+#line 450 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 57:
+#line 462 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
+    break;
+
+  case 58:
+#line 466 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 59:
+#line 471 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 60:
+#line 479 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 61:
+#line 490 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 62:
+#line 494 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 63:
+#line 498 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 64:
+#line 507 "parser.y"
+    { (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); ;}
+    break;
+
+  case 65:
+#line 509 "parser.y"
+    { (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); ;}
+    break;
+
+  case 66:
+#line 513 "parser.y"
+    { (yyval.param) = NULL;              ;}
+    break;
+
+  case 67:
+#line 515 "parser.y"
+    { (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); ;}
+    break;
+
+  case 68:
+#line 520 "parser.y"
+    {
+                 (yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
+                 (yyval.param)->value = process_value_list((yyvsp[(2) - (2)].val), &(yyval.param)->nval);
+             ;}
+    break;
+
+  case 69:
+#line 526 "parser.y"
+    { (yyval.val) = NULL; ;}
+    break;
+
+  case 70:
+#line 527 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val);   ;}
+    break;
+
+  case 71:
+#line 528 "parser.y"
+    { (yyval.val) = (yyvsp[(2) - (3)].val);   ;}
+    break;
+
+  case 72:
+#line 532 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
+    break;
+
+  case 73:
+#line 534 "parser.y"
+    { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
+    break;
+
+  case 74:
+#line 536 "parser.y"
+    { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
+    break;
+
+  case 75:
+#line 540 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
+    break;
+
+  case 76:
+#line 541 "parser.y"
+    { (yyval.val) = (yyvsp[(2) - (3)].val); ;}
+    break;
+
+  case 77:
+#line 545 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
+    break;
+
+  case 78:
+#line 547 "parser.y"
+    { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
+    break;
+
+  case 79:
+#line 549 "parser.y"
+    { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
+    break;
+
+  case 80:
+#line 553 "parser.y"
+    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 81:
+#line 555 "parser.y"
+    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 82:
+#line 557 "parser.y"
+    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 83:
+#line 559 "parser.y"
+    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 84:
+#line 560 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
+    break;
+
+  case 85:
+#line 565 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
+                 (yyval.val)->u.i.i1 = (yyval.val)->u.i.i2 = (yyvsp[(1) - (1)].r);
+             ;}
+    break;
+
+  case 86:
+#line 570 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
+                 (yyval.val)->u.r.r1 = (yyval.val)->u.r.r2 = (yyvsp[(1) - (1)].r);
+             ;}
+    break;
+
+  case 87:
+#line 575 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
+                 (yyval.val)->u.s = (yyvsp[(1) - (1)].str);
+             ;}
+    break;
+
+  case 88:
+#line 579 "parser.y"
+    { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
+    break;
+
+  case 89:
+#line 584 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
+                 (yyval.val)->u.i.i1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.i.i2 = (yyvsp[(3) - (3)].r);
+             ;}
+    break;
+
+  case 90:
+#line 589 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
+                 (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
+             ;}
+    break;
+
+  case 91:
+#line 594 "parser.y"
+    {
+                 (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
+                 (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
+             ;}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 2313 "parser.cpp"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (scanner, YY_("syntax error"));
+#else
+      {
+       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+         {
+           YYSIZE_T yyalloc = 2 * yysize;
+           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+             yyalloc = YYSTACK_ALLOC_MAXIMUM;
+           if (yymsg != yymsgbuf)
+             YYSTACK_FREE (yymsg);
+           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+           if (yymsg)
+             yymsg_alloc = yyalloc;
+           else
+             {
+               yymsg = yymsgbuf;
+               yymsg_alloc = sizeof yymsgbuf;
+             }
+         }
+
+       if (0 < yysize && yysize <= yymsg_alloc)
+         {
+           (void) yysyntax_error (yymsg, yystate, yychar);
+           yyerror (scanner, yymsg);
+         }
+       else
+         {
+           yyerror (scanner, YY_("syntax error"));
+           if (yysize != 0)
+             goto yyexhaustedlab;
+         }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+       {
+         /* Return failure if at end of input.  */
+         if (yychar == YYEOF)
+           YYABORT;
+       }
+      else
+       {
+         yydestruct ("Error: discarding",
+                     yytoken, &yylval, scanner);
+         yychar = YYEMPTY;
+       }
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+
+      yydestruct ("Error: popping",
+                 yystos[yystate], yyvsp, scanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (scanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+                yytoken, &yylval, scanner);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp, scanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 600 "parser.y"
+
+
+static t_selexpr_value *
+process_value_list(t_selexpr_value *values, int *nr)
+{
+    t_selexpr_value *val, *pval, *nval;
+
+    /* Count values (if needed) and reverse list */
+    if (nr)
+    {
+        *nr  = 0;
+    }
+    pval = NULL;
+    val  = values;
+    while (val)
+    {
+        if (nr)
+        {
+            ++*nr;
+        }
+        nval = val->next;
+        val->next = pval;
+        pval = val;
+        val = nval;
+    }
+    values = pval;
+
+    return values;
+}
+
+static t_selexpr_param *
+process_param_list(t_selexpr_param *params)
+{
+    t_selexpr_param *par, *ppar, *npar;
+
+    /* Reverse list */
+    ppar = NULL;
+    par  = params;
+    while (par)
+    {
+        npar = par->next;
+        par->next = ppar;
+        ppar = par;
+        par = npar;
+    }
+    params = ppar;
+
+    return params;
+}
+
+static void
+yyerror(yyscan_t scanner, char const *s)
+{
+    _gmx_selparser_error(scanner, "%s", s);
+}
+
+
+
diff --git a/src/gromacs/selection/parser.h b/src/gromacs/selection/parser.h
new file mode 100644 (file)
index 0000000..753ddbf
--- /dev/null
@@ -0,0 +1,138 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, 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.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVALID = 258,
+     HELP = 259,
+     HELP_TOPIC = 260,
+     TOK_INT = 261,
+     TOK_REAL = 262,
+     STR = 263,
+     IDENTIFIER = 264,
+     CMD_SEP = 265,
+     GROUP = 266,
+     TO = 267,
+     VARIABLE_NUMERIC = 268,
+     VARIABLE_GROUP = 269,
+     VARIABLE_POS = 270,
+     KEYWORD_NUMERIC = 271,
+     KEYWORD_STR = 272,
+     KEYWORD_POS = 273,
+     KEYWORD_GROUP = 274,
+     METHOD_NUMERIC = 275,
+     METHOD_GROUP = 276,
+     METHOD_POS = 277,
+     MODIFIER = 278,
+     EMPTY_POSMOD = 279,
+     PARAM = 280,
+     END_OF_METHOD = 281,
+     OF = 282,
+     CMP_OP = 283,
+     PARAM_REDUCT = 284,
+     XOR = 285,
+     OR = 286,
+     AND = 287,
+     NOT = 288,
+     UNARY_NEG = 289,
+     NUM_REDUCT = 290
+   };
+#endif
+/* Tokens.  */
+#define INVALID 258
+#define HELP 259
+#define HELP_TOPIC 260
+#define TOK_INT 261
+#define TOK_REAL 262
+#define STR 263
+#define IDENTIFIER 264
+#define CMD_SEP 265
+#define GROUP 266
+#define TO 267
+#define VARIABLE_NUMERIC 268
+#define VARIABLE_GROUP 269
+#define VARIABLE_POS 270
+#define KEYWORD_NUMERIC 271
+#define KEYWORD_STR 272
+#define KEYWORD_POS 273
+#define KEYWORD_GROUP 274
+#define METHOD_NUMERIC 275
+#define METHOD_GROUP 276
+#define METHOD_POS 277
+#define MODIFIER 278
+#define EMPTY_POSMOD 279
+#define PARAM 280
+#define END_OF_METHOD 281
+#define OF 282
+#define CMP_OP 283
+#define PARAM_REDUCT 284
+#define XOR 285
+#define OR 286
+#define AND 287
+#define NOT 288
+#define UNARY_NEG 289
+#define NUM_REDUCT 290
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 69 "parser.y"
+{
+    int                         i;
+    real                        r;
+    char                       *str;
+    struct gmx_ana_selmethod_t *meth;
+
+    struct t_selelem           *sel;
+
+    struct t_selexpr_value     *val;
+    struct t_selexpr_param     *param;
+}
+/* Line 1489 of yacc.c.  */
+#line 131 "parser.h"
+       YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/gromacs/selection/parser.y b/src/gromacs/selection/parser.y
new file mode 100644 (file)
index 0000000..aab69f5
--- /dev/null
@@ -0,0 +1,656 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Grammar description and parser for the selection language.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+%{
+/*! \internal \file parser.cpp
+ * \brief Generated (from parser.y by Bison) parser for the selection language.
+ *
+ * \ingroup module_selection
+ */
+/*! \internal \file parser.h
+ * \brief Generated (from parser.y by Bison) parser include file.
+ *
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <string2.h>
+
+#include "parsetree.h"
+#include "selelem.h"
+
+#include "scanner.h"
+
+static t_selexpr_value *
+process_value_list(t_selexpr_value *values, int *nr);
+static t_selexpr_param *
+process_param_list(t_selexpr_param *params);
+
+static void
+yyerror(yyscan_t, char const *s);
+%}
+
+%union{
+    int                         i;
+    real                        r;
+    char                       *str;
+    struct gmx_ana_selmethod_t *meth;
+
+    struct t_selelem           *sel;
+
+    struct t_selexpr_value     *val;
+    struct t_selexpr_param     *param;
+};
+/* NOTE: The Intel compiler seems to report warnings for the above line about
+ * "definition at end of file not followed by a semicolon or a declarator".
+ * This is due to the compiler misinterpreting #line directives in the
+ * generated files parser.c/.h, and changing them would be more trouble than
+ * it's worth. */
+
+/* Invalid token to report lexer errors */
+%token INVALID
+
+/* Tokens for help requests */
+%token         HELP
+%token <str>   HELP_TOPIC
+
+/* Simple input tokens */
+%token <i>     TOK_INT
+%token <r>     TOK_REAL
+%token <str>   STR
+%token <str>   IDENTIFIER
+%token         CMD_SEP
+
+/* Simple keyword tokens */
+%token         GROUP
+%token         TO
+
+/* Variable tokens */
+%token <sel>   VARIABLE_NUMERIC
+%token <sel>   VARIABLE_GROUP
+%token <sel>   VARIABLE_POS
+
+/* Selection method tokens */
+%token <meth>  KEYWORD_NUMERIC
+%token <meth>  KEYWORD_STR
+%token <str>   KEYWORD_POS
+%token <meth>  KEYWORD_GROUP
+%token <meth>  METHOD_NUMERIC
+%token <meth>  METHOD_GROUP
+%token <meth>  METHOD_POS
+%token <meth>  MODIFIER
+/* Empty token that should precede any non-position KEYWORD/METHOD token that
+ * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
+ * conflicts that appear when a lookahead token would require a reduction of
+ * a rule with empty RHS before shifting, and there is an alternative reduction
+ * available. Replacing the empty RHS with a dummy token makes these conflicts
+ * only shift/reduce conflicts. Another alternative would be to remove the
+ * pos_mod non-terminal completely and split each rule that uses it into two,
+ * but this would require duplicating six rules in the grammar. */
+%token         EMPTY_POSMOD
+
+%token <str>   PARAM
+%token         END_OF_METHOD
+
+%token          OF
+/* Comparison operators have lower precedence than parameter reduction
+ * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
+ * parenthesis. */
+%nonassoc <str> CMP_OP
+/* A dummy token that determines the precedence of parameter reduction */
+%nonassoc       PARAM_REDUCT
+/* Boolean operator tokens */
+%left           OR XOR
+%left           AND
+%left           NOT
+/* Arithmetic operator tokens */
+%left           '+' '-'
+%left           '*' '/'
+%right          UNARY_NEG   /* Dummy token for unary negation precedence */
+%right          '^'
+%nonassoc       NUM_REDUCT  /* Dummy token for numerical keyword reduction precedence */
+
+/* Simple non-terminals */
+%type <r>     integer_number
+%type <r>     real_number number
+%type <str>   string
+%type <str>   pos_mod
+
+/* Expression non-terminals */
+%type <sel>   commands command cmd_plain
+%type <sel>   selection
+%type <sel>   sel_expr
+%type <sel>   num_expr
+%type <sel>   str_expr
+%type <sel>   pos_expr
+
+/* Parameter/value non-terminals */
+%type <param> method_params method_param_list method_param
+%type <val>   value_list value_list_contents value_item value_item_range
+%type <val>   basic_value_list basic_value_list_contents basic_value_item
+
+%destructor { free($$);                     } HELP_TOPIC STR IDENTIFIER CMP_OP string
+%destructor { if($$) free($$);              } PARAM
+%destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
+%destructor { _gmx_selelem_free_chain($$);  } selection
+%destructor { _gmx_selelem_free($$);        } sel_expr num_expr str_expr pos_expr
+%destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
+%destructor { _gmx_selexpr_free_values($$); } value_list value_list_contents value_item value_item_range
+%destructor { _gmx_selexpr_free_values($$); } basic_value_list basic_value_list_contents basic_value_item
+
+%expect 50
+%debug
+%pure-parser
+
+/* If you change these, you also need to update the prototype in parsetree.c. */
+%name-prefix="_gmx_sel_yyb"
+%parse-param { yyscan_t                 scanner }
+%lex-param   { yyscan_t                 scanner }
+
+%%
+
+/* The start rule: allow one or more commands */
+commands:    /* empty */        { $$ = NULL }
+           | commands command
+             {
+                 $$ = _gmx_sel_append_selection($2, $1, scanner);
+                 if (_gmx_sel_parser_should_finish(scanner))
+                     YYACCEPT;
+             }
+;
+
+/* A command is formed from an actual command and a separator */
+command:     cmd_plain CMD_SEP  { $$ = $1; }
+           | error CMD_SEP
+             {
+                 $$ = NULL;
+                 _gmx_selparser_error(scanner, "invalid selection '%s'",
+                                      _gmx_sel_lexer_pselstr(scanner));
+                 _gmx_sel_lexer_clear_method_stack(scanner);
+                 if (_gmx_sel_is_lexer_interactive(scanner))
+                 {
+                     _gmx_sel_lexer_clear_pselstr(scanner);
+                     yyerrok;
+                 }
+                 else
+                 {
+                     YYABORT;
+                 }
+             }
+;
+
+/* Commands can be selections or variable assignments */
+cmd_plain:   /* empty */
+             {
+                 $$ = NULL;
+                 _gmx_sel_handle_empty_cmd(scanner);
+             }
+           | help_request       { $$ = NULL; }
+           | TOK_INT
+             {
+                 t_selelem *s, *p;
+                 s = _gmx_sel_init_group_by_id($1, scanner);
+                 if (s == NULL) YYERROR;
+                 p = _gmx_sel_init_position(s, NULL, scanner);
+                 if (p == NULL) YYERROR;
+                 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+             }
+           | string
+             {
+                 t_selelem *s, *p;
+                 s = _gmx_sel_init_group_by_name($1, scanner);
+                 free($1);
+                 if (s == NULL) YYERROR;
+                 p = _gmx_sel_init_position(s, NULL, scanner);
+                 if (p == NULL) YYERROR;
+                 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+             }
+           | selection
+             { $$ = _gmx_sel_init_selection(NULL, $1, scanner); }
+           | string selection
+             { $$ = _gmx_sel_init_selection($1, $2, scanner);   }
+           | IDENTIFIER '=' sel_expr
+             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+           | IDENTIFIER '=' num_expr
+             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+           | IDENTIFIER '=' pos_expr
+             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+;
+
+/* Help requests */
+help_request:
+             HELP                   { _gmx_sel_handle_help_cmd(NULL, scanner); }
+           | help_topic
+;
+
+help_topic:  HELP HELP_TOPIC        { _gmx_sel_handle_help_cmd($2, scanner); }
+           | help_topic HELP_TOPIC  { _gmx_sel_handle_help_cmd($2, scanner); }
+;
+
+/* Selection is made of an expression and zero or more modifiers */
+selection:   pos_expr           { $$ = $1; }
+           | sel_expr
+             {
+                 $$ = _gmx_sel_init_position($1, NULL, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+           | '(' selection ')'  { $$ = $2; }
+           | selection MODIFIER method_params
+             {
+                 $$ = _gmx_sel_init_modifier($2, $3, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/********************************************************************
+ * BASIC NON-TERMINAL SYMBOLS
+ ********************************************************************/
+
+integer_number:
+             TOK_INT            { $$ = $1; }
+           | '-' TOK_INT        { $$ = -$2; }
+;
+
+real_number:
+             TOK_REAL           { $$ = $1; }
+           | '-' TOK_REAL       { $$ = -$2; }
+;
+
+number:      integer_number     { $$ = $1; }
+           | real_number        { $$ = $1; }
+;
+
+string:      STR                { $$ = $1; }
+           | IDENTIFIER         { $$ = $1; }
+;
+
+/********************************************************************
+ * ATOM SELECTION EXPRESSIONS
+ ********************************************************************/
+
+/* Boolean expressions and grouping */
+sel_expr:    NOT sel_expr
+             {
+                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
+                 $$->u.boolt = BOOL_NOT;
+                 $$->child = $2;
+             }
+           | sel_expr AND sel_expr
+             {
+                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
+                 $$->u.boolt = BOOL_AND;
+                 $$->child = $1; $$->child->next = $3;
+             }
+           | sel_expr OR  sel_expr
+             {
+                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
+                 $$->u.boolt = BOOL_OR;
+                 $$->child = $1; $$->child->next = $3;
+             }
+/*           | sel_expr XOR sel_expr
+             {
+                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
+                 $$->u.boolt = BOOL_XOR;
+                 $$->child = $1; $$->child->next = $3;
+             }*/
+           | '(' sel_expr ')'   { $$ = $2; }
+;
+
+/* Numeric comparisons */
+sel_expr:    num_expr CMP_OP num_expr
+             {
+                 $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/* External groups */
+sel_expr:    GROUP string
+             {
+                 $$ = _gmx_sel_init_group_by_name($2, scanner);
+                 free($2);
+                 if ($$ == NULL) YYERROR;
+             }
+           | GROUP TOK_INT
+             {
+                 $$ = _gmx_sel_init_group_by_id($2, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/* Position modifiers for selection methods */
+pos_mod:     EMPTY_POSMOD       { $$ = NULL; }
+           | KEYWORD_POS        { $$ = $1;   }
+;
+
+/* Keyword selections */
+sel_expr:    pos_mod KEYWORD_GROUP
+             {
+                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+           | pos_mod KEYWORD_STR basic_value_list
+             {
+                 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+           | pos_mod KEYWORD_NUMERIC basic_value_list
+             {
+                 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/* Custom selection methods */
+sel_expr:    pos_mod METHOD_GROUP method_params
+             {
+                 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/********************************************************************
+ * NUMERICAL EXPRESSIONS
+ ********************************************************************/
+
+/* Basic numerical values */
+num_expr:    TOK_INT
+             {
+                 $$ = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype($$, INT_VALUE);
+                 _gmx_selvalue_reserve(&$$->v, 1);
+                 $$->v.u.i[0] = $1;
+             }
+           | TOK_REAL
+             {
+                 $$ = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype($$, REAL_VALUE);
+                 _gmx_selvalue_reserve(&$$->v, 1);
+                 $$->v.u.r[0] = $1;
+             }
+;
+
+/* Numeric selection methods */
+num_expr:    pos_mod KEYWORD_NUMERIC    %prec NUM_REDUCT
+             {
+                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+           | pos_mod METHOD_NUMERIC method_params
+             {
+                 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/* Arithmetic evaluation and grouping */
+num_expr:    num_expr '+' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
+           | num_expr '-' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
+           | num_expr '*' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
+           | num_expr '/' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
+           | '-' num_expr %prec UNARY_NEG
+             { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
+           | num_expr '^' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
+           | '(' num_expr ')'   { $$ = $2; }
+;
+
+/********************************************************************
+ * STRING EXPRESSIONS
+ ********************************************************************/
+
+str_expr:    string
+             {
+                 $$ = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype($$, STR_VALUE);
+                 _gmx_selvalue_reserve(&$$->v, 1);
+                 $$->v.u.s[0] = $1;
+             }
+           | pos_mod KEYWORD_STR
+             {
+                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/********************************************************************
+ * POSITION EXPRESSIONS
+ ********************************************************************/
+
+/* Constant position expressions */
+pos_expr:    '[' number ',' number ',' number ']'
+             { $$ = _gmx_sel_init_const_position($2, $4, $6); }
+;
+
+/* Grouping of position expressions */
+pos_expr:    '(' pos_expr ')'   { $$ = $2; }
+;
+
+/* Expressions with a position value */
+pos_expr:    METHOD_POS method_params
+             {
+                 $$ = _gmx_sel_init_method($1, $2, NULL, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/* Evaluation of positions using a keyword */
+pos_expr:    KEYWORD_POS OF sel_expr    %prec PARAM_REDUCT
+             {
+                 $$ = _gmx_sel_init_position($3, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
+;
+
+/********************************************************************
+ * VARIABLES
+ ********************************************************************/
+
+sel_expr:    VARIABLE_GROUP
+             { $$ = _gmx_sel_init_variable_ref($1); }
+;
+
+num_expr:    VARIABLE_NUMERIC
+             { $$ = _gmx_sel_init_variable_ref($1); }
+;
+
+pos_expr:    VARIABLE_POS
+             { $$ = _gmx_sel_init_variable_ref($1); }
+;
+
+/********************************************************************
+ * METHOD PARAMETERS
+ ********************************************************************/
+
+method_params:
+             method_param_list
+             { $$ = process_param_list($1); }
+           | method_param_list END_OF_METHOD
+             { $$ = process_param_list($1); }
+;
+
+method_param_list:
+             /* empty */        { $$ = NULL;              }
+           | method_param_list method_param
+                                { $2->next = $1; $$ = $2; }
+;
+
+method_param:
+             PARAM value_list
+             {
+                 $$ = _gmx_selexpr_create_param($1);
+                 $$->value = process_value_list($2, &$$->nval);
+             }
+;
+
+value_list:  /* empty */                         { $$ = NULL; }
+           | value_list_contents                 { $$ = $1;   }
+           | '{' value_list_contents '}'         { $$ = $2;   }
+;
+
+value_list_contents:
+             value_item          { $$ = $1; }
+           | value_list_contents value_item
+                                 { $2->next = $1; $$ = $2; }
+           | value_list_contents ',' value_item
+                                 { $3->next = $1; $$ = $3; }
+;
+
+basic_value_list:
+             basic_value_list_contents           { $$ = $1; }
+           | '{' basic_value_list_contents '}'   { $$ = $2; }
+;
+
+basic_value_list_contents:
+             basic_value_item    { $$ = $1; }
+           | basic_value_list_contents basic_value_item
+                                 { $2->next = $1; $$ = $2; }
+           | basic_value_list_contents ',' basic_value_item
+                                 { $3->next = $1; $$ = $3; }
+;
+
+value_item:  sel_expr            %prec PARAM_REDUCT
+             { $$ = _gmx_selexpr_create_value_expr($1); }
+           | pos_expr            %prec PARAM_REDUCT
+             { $$ = _gmx_selexpr_create_value_expr($1); }
+           | num_expr            %prec PARAM_REDUCT
+             { $$ = _gmx_selexpr_create_value_expr($1); }
+           | str_expr            %prec PARAM_REDUCT
+             { $$ = _gmx_selexpr_create_value_expr($1); }
+           | value_item_range    { $$ = $1; }
+;
+
+basic_value_item:
+             integer_number      %prec PARAM_REDUCT
+             {
+                 $$ = _gmx_selexpr_create_value(INT_VALUE);
+                 $$->u.i.i1 = $$->u.i.i2 = $1;
+             }
+           | real_number         %prec PARAM_REDUCT
+             {
+                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
+                 $$->u.r.r1 = $$->u.r.r2 = $1;
+             }
+           | string              %prec PARAM_REDUCT
+             {
+                 $$ = _gmx_selexpr_create_value(STR_VALUE);
+                 $$->u.s = $1;
+             }
+           | value_item_range    { $$ = $1; }
+;
+
+value_item_range:
+             integer_number TO integer_number
+             {
+                 $$ = _gmx_selexpr_create_value(INT_VALUE);
+                 $$->u.i.i1 = $1; $$->u.i.i2 = $3;
+             }
+           | integer_number TO real_number
+             {
+                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
+                 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
+             }
+           | real_number TO number
+             {
+                 $$ = _gmx_selexpr_create_value(REAL_VALUE);
+                 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
+             }
+;
+
+%%
+
+static t_selexpr_value *
+process_value_list(t_selexpr_value *values, int *nr)
+{
+    t_selexpr_value *val, *pval, *nval;
+
+    /* Count values (if needed) and reverse list */
+    if (nr)
+    {
+        *nr  = 0;
+    }
+    pval = NULL;
+    val  = values;
+    while (val)
+    {
+        if (nr)
+        {
+            ++*nr;
+        }
+        nval = val->next;
+        val->next = pval;
+        pval = val;
+        val = nval;
+    }
+    values = pval;
+
+    return values;
+}
+
+static t_selexpr_param *
+process_param_list(t_selexpr_param *params)
+{
+    t_selexpr_param *par, *ppar, *npar;
+
+    /* Reverse list */
+    ppar = NULL;
+    par  = params;
+    while (par)
+    {
+        npar = par->next;
+        par->next = ppar;
+        ppar = par;
+        par = npar;
+    }
+    params = ppar;
+
+    return params;
+}
+
+static void
+yyerror(yyscan_t scanner, char const *s)
+{
+    _gmx_selparser_error(scanner, "%s", s);
+}
+
+
diff --git a/src/gromacs/selection/parsetree.cpp b/src/gromacs/selection/parsetree.cpp
new file mode 100644 (file)
index 0000000..f2929a4
--- /dev/null
@@ -0,0 +1,1371 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in parsetree.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+/*! \internal
+ * \page page_module_selection_parser Selection parsing
+ *
+ * The selection parser is implemented in the following files:
+ *  - scanner.l:
+ *    Tokenizer implemented using Flex, splits the input into tokens
+ *    (scanner.c and scanner_flex.h are generated from this file).
+ *  - scanner.h, scanner_internal.h, scanner_internal.cpp:
+ *    Helper functions for scanner.l and for interfacing between
+ *    scanner.l and parser.y. Functions in scanner_internal.h are only
+ *    used from scanner.l, while scanner.h is used from the parser.
+ *  - symrec.h, symrec.cpp:
+ *    Functions used by the tokenizer to handle the symbol table, i.e.,
+ *    the recognized keywords. Some basic keywords are hardcoded into
+ *    scanner.l, but all method and variable references go through the
+ *    symbol table, as do position evaluation keywords.
+ *  - parser.y:
+ *    Semantic rules for parsing the grammar
+ *    (parser.cpp and parser.h are generated from this file by Bison).
+ *  - parsetree.h, parsetree.cpp:
+ *    Functions called from actions in parser.y to construct the
+ *    evaluation elements corresponding to different grammar elements.
+ *  - params.c:
+ *    Defines a function that processes the parameters of selection
+ *    methods and initializes the children of the method element.
+ *  - selectioncollection.h, selectioncollection.cpp:
+ *    These files define the high-level public interface to the parser
+ *    through SelectionCollection::parseFromStdin(),
+ *    SelectionCollection::parseFromFile() and
+ *    SelectionCollection::parseFromString().
+ *
+ * The basic control flow in the parser is as follows: when a parser function
+ * in SelectionCollection gets called, it performs some
+ * initialization, and then calls the _gmx_sel_yyparse() function generated
+ * by Bison. This function then calls _gmx_sel_yylex() to repeatedly read
+ * tokens from the input (more complex tasks related to token recognition
+ * and bookkeeping are done by functions in scanner_internal.cpp) and uses the
+ * grammar rules to decide what to do with them. Whenever a grammar rule
+ * matches, a corresponding function in parsetree.cpp is called to construct
+ * either a temporary representation for the object or a ::t_selelem object
+ * (some simple rules are handled internally in parser.y).
+ * When a complete selection has been parsed, the functions in parsetree.cpp
+ * also take care of updating the ::gmx_ana_selcollection_t structure
+ * appropriately.
+ *
+ * The rest of this page describes the resulting ::t_selelem object tree.
+ * Before the selections can be evaluated, this tree needs to be passed to
+ * the selection compiler, which is described on a separate page:
+ * \ref page_module_selection_compiler
+ *
+ *
+ * \section selparser_tree Element tree constructed by the parser
+ *
+ * The parser initializes the following fields in all selection elements:
+ * \c t_selelem::name, \c t_selelem::type, \c t_selelem::v\c .type,
+ * \c t_selelem::flags, \c t_selelem::child, \c t_selelem::next, and
+ * \c t_selelem::refcount.
+ * Some other fields are also initialized for particular element types as
+ * discussed below.
+ * Fields that are not initialized are set to zero, NULL, or other similar
+ * value.
+ *
+ *
+ * \subsection selparser_tree_root Root elements
+ *
+ * The parser creates a \ref SEL_ROOT selection element for each variable
+ * assignment and each selection. However, there are two exceptions that do
+ * not result in a \ref SEL_ROOT element (in these cases, only the symbol
+ * table is modified):
+ *  - Variable assignments that assign a variable to another variable.
+ *  - Variable assignments that assign a non-group constant.
+ *  .
+ * The \ref SEL_ROOT elements are linked together in a chain in the same order
+ * as in the input.
+ *
+ * The children of the \ref SEL_ROOT elements can be used to distinguish
+ * the two types of root elements from each other:
+ *  - For variable assignments, the first and only child is always
+ *    a \ref SEL_SUBEXPR element.
+ *  - For selections, the first child is a \ref SEL_EXPRESSION or a
+ *    \ref SEL_MODIFIER element that evaluates the final positions (if the
+ *    selection defines a constant position, the child is a \ref SEL_CONST).
+ *    The rest of the children are \ref SEL_MODIFIER elements with
+ *    \ref NO_VALUE, in the order given by the user.
+ *  .
+ * The name of the selection/variable is stored in \c t_selelem::cgrp\c .name.
+ * It is set to either the name provided by the user or the selection string
+ * for selections not explicitly named by the user.
+ * \ref SEL_ROOT or \ref SEL_SUBEXPR elements do not appear anywhere else.
+ *
+ *
+ * \subsection selparser_tree_const Constant elements
+ *
+ * \ref SEL_CONST elements are created for every constant that is required
+ * for later evaluation.
+ * Currently, \ref SEL_CONST elements can be present for
+ *  - selections that consist of a constant position,
+ *  - \ref GROUP_VALUE method parameters if provided using external index
+ *    groups,
+ *  .
+ * For group-valued elements, the value is stored in \c t_selelem::cgrp;
+ * other types of values are stored in \c t_selelem::v.
+ * Constants that appear as parameters for selection methods are not present
+ * in the selection tree unless they have \ref GROUP_VALUE.
+ * \ref SEL_CONST elements have no children.
+ *
+ *
+ * \subsection selparser_tree_method Method evaluation elements
+ *
+ * \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are treated very
+ * similarly. The \c gmx_ana_selmethod_t structure corresponding to the
+ * evaluation method is in \c t_selelem::method, and the method data in
+ * \c t_selelem::mdata has been allocated using sel_datafunc().
+ * If a non-standard reference position type was set, \c t_selelem::pc has
+ * also been created, but only the type has been set.
+ * All children of these elements are of the type \ref SEL_SUBEXPRREF, and
+ * each describes a selection that needs to be evaluated to obtain a value
+ * for one parameter of the method.
+ * No children are present for parameters that were given a constant
+ * non-\ref GROUP_VALUE value.
+ * The children are sorted in the order in which the parameters appear in the
+ * \ref gmx_ana_selmethod_t structure.
+ *
+ * In addition to actual selection keywords, \ref SEL_EXPRESSION elements
+ * are used internally to implement numerical comparisons (e.g., "x < 5")
+ * and keyword matching (e.g., "resnr 1 to 3" or "name CA").
+ *
+ *
+ * \subsection selparser_tree_subexpr Subexpression elements
+ *
+ * \ref SEL_SUBEXPR elements only appear for variables, as described above.
+ * \c t_selelem::name points to the name of the variable (from the
+ * \ref SEL_ROOT element).
+ * The element always has exactly one child, which represents the value of
+ * the variable.
+ * \ref SEL_SUBEXPR element is the only element type that can have
+ * \c t_selelem::refcount different from 1.
+ *
+ * \ref SEL_SUBEXPRREF elements are used for two purposes:
+ *  - Variable references that need to be evaluated (i.e., there is a
+ *    \ref SEL_SUBEXPR element for the variable) are represented using
+ *    \ref SEL_SUBEXPRREF elements.
+ *    In this case, \c t_selelem::param is NULL, and the first and only
+ *    child of the element is the \ref SEL_SUBEXPR element of the variable.
+ *    Such references can appear anywhere where the variable value
+ *    (the child of the \ref SEL_SUBEXPR element) would be valid.
+ *  - Children of \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are
+ *    always of this type. For these elements, \c t_selelem::param is
+ *    initialized to point to the parameter that receives the value from
+ *    the expression.
+ *    Each such element has exactly one child, which can be of any type;
+ *    the \ref SEL_SUBEXPR element of a variable is used if the value comes
+ *    from a variable, otherwise the child type is not \ref SEL_SUBEXPR.
+ *
+ *
+ * \subsection selparser_tree_gmx_bool Boolean elements
+ *
+ * One \ref SEL_BOOLEAN element is created for each gmx_boolean keyword in the
+ * input, and the tree structure represents the evaluation order.
+ * The \c t_selelem::boolt type gives the type of the operation.
+ * Each element has exactly two children (one for \ref BOOL_NOT elements),
+ * which are in the order given in the input.
+ * The children always have \ref GROUP_VALUE, but different element types
+ * are possible.
+ *
+ *
+ * \subsection selparser_tree_arith Arithmetic elements
+ *
+ * One \ref SEL_ARITHMETIC element is created for each arithmetic operation in
+ * the input, and the tree structure represents the evaluation order.
+ * The \c t_selelem::optype type gives the name of the operation.
+ * Each element has exactly two children (one for unary negation elements),
+ * which are in the order given in the input.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <futil.h>
+#include <smalloc.h>
+#include <string2.h>
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "keywords.h"
+#include "parsetree.h"
+#include "selectioncollection-impl.h"
+#include "selelem.h"
+#include "selhelp.h"
+#include "symrec.h"
+
+#include "scanner.h"
+
+void
+_gmx_selparser_error(yyscan_t scanner, const char *fmt, ...)
+{
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    // FIXME: Use an arbitrary length buffer.
+    char buf[1024];
+    va_list ap;
+    va_start(ap, fmt);
+    vsprintf(buf, fmt, ap);
+    va_end(ap);
+    errors->append(buf);
+}
+
+/*!
+ * \param[in] type  Type for the new value.
+ * \returns   Pointer to the newly allocated value.
+ */
+t_selexpr_value *
+_gmx_selexpr_create_value(e_selvalue_t type)
+{
+    t_selexpr_value *value;
+    snew(value, 1);
+    value->type  = type;
+    value->bExpr = FALSE;
+    value->next  = NULL;
+    return value;
+}
+
+/*!
+ * \param[in] expr  Expression for the value.
+ * \returns   Pointer to the newly allocated value.
+ */
+t_selexpr_value *
+_gmx_selexpr_create_value_expr(t_selelem *expr)
+{
+    t_selexpr_value *value;
+    snew(value, 1);
+    value->type   = expr->v.type;
+    value->bExpr  = TRUE;
+    value->u.expr = expr;
+    value->next   = NULL;
+    return value;
+}
+
+/*!
+ * \param[in] name Name for the new parameter.
+ * \returns   Pointer to the newly allocated parameter.
+ *
+ * No copy of \p name is made.
+ */
+t_selexpr_param *
+_gmx_selexpr_create_param(char *name)
+{
+    t_selexpr_param *param;
+    snew(param, 1);
+    param->name = name;
+    param->next = NULL;
+    return param;
+}
+
+/*!
+ * \param value Pointer to the beginning of the value list to free.
+ *
+ * The expressions referenced by the values are also freed
+ * (to prevent this, set the expression to NULL before calling the function).
+ */
+void
+_gmx_selexpr_free_values(t_selexpr_value *value)
+{
+    t_selexpr_value *old;
+
+    while (value)
+    {
+        if (value->bExpr)
+        {
+            if (value->u.expr)
+            {
+                _gmx_selelem_free(value->u.expr);
+            }
+        }
+        else if (value->type == STR_VALUE)
+        {
+            sfree(value->u.s);
+        }
+        old = value;
+        value = value->next;
+        sfree(old);
+    }
+}
+
+/*!
+ * \param param Pointer the the beginning of the parameter list to free.
+ *
+ * The values of the parameters are freed with free_selexpr_values().
+ */
+void
+_gmx_selexpr_free_params(t_selexpr_param *param)
+{
+    t_selexpr_param *old;
+
+    while (param)
+    {
+        _gmx_selexpr_free_values(param->value);
+        old = param;
+        param = param->next;
+        sfree(old->name);
+        sfree(old);
+    }
+}
+
+/*!
+ * \param[in,out] sel  Root of the selection element tree to initialize.
+ * \param[in]     scanner Scanner data structure.
+ * \returns       0 on success, an error code on error.
+ *
+ * Propagates the \ref SEL_DYNAMIC flag from the children of \p sel to \p sel
+ * (if any child of \p sel is dynamic, \p sel is also marked as such).
+ * The \ref SEL_DYNAMIC flag is also set for \ref SEL_EXPRESSION elements with
+ * a dynamic method.
+ * Also, sets one of the \ref SEL_SINGLEVAL, \ref SEL_ATOMVAL, or
+ * \ref SEL_VARNUMVAL flags, either based on the children or on the type of
+ * the selection method.
+ * If the types of the children conflict, an error is returned.
+ *
+ * The flags of the children of \p sel are also updated if not done earlier.
+ * The flags are initialized only once for any element; if \ref SEL_FLAGSSET
+ * is set for an element, the function returns immediately, and the recursive
+ * operation does not descend beyond such elements.
+ */
+int
+_gmx_selelem_update_flags(t_selelem *sel, yyscan_t scanner)
+{
+    t_selelem          *child;
+    int                 rc;
+    gmx_bool                bUseChildType=FALSE;
+    gmx_bool                bOnlySingleChildren;
+
+    /* Return if the flags have already been set */
+    if (sel->flags & SEL_FLAGSSET)
+    {
+        return 0;
+    }
+    /* Set the flags based on the current element type */
+    switch (sel->type)
+    {
+        case SEL_CONST:
+        case SEL_GROUPREF:
+            sel->flags |= SEL_SINGLEVAL;
+            bUseChildType = FALSE;
+            break;
+
+        case SEL_EXPRESSION:
+            if (sel->u.expr.method->flags & SMETH_DYNAMIC)
+            {
+                sel->flags |= SEL_DYNAMIC;
+            }
+            if (sel->u.expr.method->flags & SMETH_SINGLEVAL)
+            {
+                sel->flags |= SEL_SINGLEVAL;
+            }
+            else if (sel->u.expr.method->flags & SMETH_VARNUMVAL)
+            {
+                sel->flags |= SEL_VARNUMVAL;
+            }
+            else
+            {
+                sel->flags |= SEL_ATOMVAL;
+            }
+            bUseChildType = FALSE;
+            break;
+
+        case SEL_ARITHMETIC:
+            sel->flags |= SEL_ATOMVAL;
+            bUseChildType = FALSE;
+            break;
+
+        case SEL_MODIFIER:
+            if (sel->v.type != NO_VALUE)
+            {
+                sel->flags |= SEL_VARNUMVAL;
+            }
+            bUseChildType = FALSE;
+            break;
+
+        case SEL_ROOT:
+            bUseChildType = FALSE;
+            break;
+
+        case SEL_BOOLEAN:
+        case SEL_SUBEXPR:
+        case SEL_SUBEXPRREF:
+            bUseChildType = TRUE;
+            break;
+    }
+    /* Loop through children to propagate their flags upwards */
+    bOnlySingleChildren = TRUE;
+    child = sel->child;
+    while (child)
+    {
+        /* Update the child */
+        rc = _gmx_selelem_update_flags(child, scanner);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        /* Propagate the dynamic flag */
+        sel->flags |= (child->flags & SEL_DYNAMIC);
+        /* Propagate the type flag if necessary and check for problems */
+        if (bUseChildType)
+        {
+            if ((sel->flags & SEL_VALTYPEMASK)
+                && !(sel->flags & child->flags & SEL_VALTYPEMASK))
+            {
+                _gmx_selparser_error(scanner, "invalid combination of selection expressions");
+                return gmx::eeInvalidInput;
+            }
+            sel->flags |= (child->flags & SEL_VALTYPEMASK);
+        }
+        if (!(child->flags & SEL_SINGLEVAL))
+        {
+            bOnlySingleChildren = FALSE;
+        }
+
+        child = child->next;
+    }
+    /* For arithmetic expressions consisting only of single values,
+     * the result is also a single value. */
+    if (sel->type == SEL_ARITHMETIC && bOnlySingleChildren)
+    {
+        sel->flags = (sel->flags & ~SEL_VALTYPEMASK) | SEL_SINGLEVAL;
+    }
+    /* For root elements, the type should be propagated here, after the
+     * children have been updated. */
+    if (sel->type == SEL_ROOT)
+    {
+        sel->flags |= (sel->child->flags & SEL_VALTYPEMASK);
+    }
+    /* Mark that the flags are set */
+    sel->flags |= SEL_FLAGSSET;
+    return 0;
+}
+
+/*!
+ * \param[in,out] sel    Selection element to initialize.
+ * \param[in]     scanner Scanner data structure.
+ *
+ * A deep copy of the parameters is made to allow several
+ * expressions with the same method to coexist peacefully.
+ * Calls sel_datafunc() if one is specified for the method.
+ */
+void
+_gmx_selelem_init_method_params(t_selelem *sel, yyscan_t scanner)
+{
+    int                 nparams;
+    gmx_ana_selparam_t *orgparam;
+    gmx_ana_selparam_t *param;
+    int                 i;
+    void               *mdata;
+
+    nparams   = sel->u.expr.method->nparams;
+    orgparam  = sel->u.expr.method->param;
+    snew(param, nparams);
+    memcpy(param, orgparam, nparams*sizeof(gmx_ana_selparam_t));
+    for (i = 0; i < nparams; ++i)
+    {
+        param[i].flags &= ~SPAR_SET;
+        _gmx_selvalue_setstore(&param[i].val, NULL);
+        if (param[i].flags & SPAR_VARNUM)
+        {
+            param[i].val.nr = -1;
+        }
+        /* Duplicate the enum value array if it is given statically */
+        if ((param[i].flags & SPAR_ENUMVAL) && orgparam[i].val.u.ptr != NULL)
+        {
+            int n;
+
+            /* Count the values */
+            n = 1;
+            while (orgparam[i].val.u.s[n] != NULL)
+            {
+                ++n;
+            }
+            _gmx_selvalue_reserve(&param[i].val, n+1);
+            memcpy(param[i].val.u.s, orgparam[i].val.u.s,
+                   (n+1)*sizeof(param[i].val.u.s[0]));
+        }
+    }
+    mdata = NULL;
+    if (sel->u.expr.method->init_data)
+    {
+        mdata = sel->u.expr.method->init_data(nparams, param);
+        if (mdata == NULL)
+        {
+            GMX_ERROR_NORET(gmx::eeInvalidValue, "Method data initialization failed");
+        }
+    }
+    if (sel->u.expr.method->set_poscoll)
+    {
+        gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+
+        sel->u.expr.method->set_poscoll(sc->pcc, mdata);
+    }
+    /* Store the values */
+    sel->u.expr.method->param = param;
+    sel->u.expr.mdata         = mdata;
+}
+
+/*!
+ * \param[in,out] sel    Selection element to initialize.
+ * \param[in]     method Selection method to set.
+ * \param[in]     scanner Scanner data structure.
+ *
+ * Makes a copy of \p method and stores it in \p sel->u.expr.method,
+ * and calls _gmx_selelem_init_method_params();
+ */
+void
+_gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
+                        yyscan_t scanner)
+{
+    int      i;
+
+    _gmx_selelem_set_vtype(sel, method->type);
+    sel->name   = method->name;
+    snew(sel->u.expr.method, 1);
+    memcpy(sel->u.expr.method, method, sizeof(gmx_ana_selmethod_t));
+    _gmx_selelem_init_method_params(sel, scanner);
+}
+
+/*! \brief
+ * Initializes the reference position calculation for a \ref SEL_EXPRESSION
+ * element.
+ *
+ * \param[in,out] pcc    Position calculation collection to use.
+ * \param[in,out] sel    Selection element to initialize.
+ * \param[in]     rpost  Reference position type to use (NULL = default).
+ * \param[in]     scanner Scanner data structure.
+ * \returns       0 on success, a non-zero error code on error.
+ */
+static int
+set_refpos_type(gmx_ana_poscalc_coll_t *pcc, t_selelem *sel, const char *rpost,
+                yyscan_t scanner)
+{
+    if (!rpost)
+    {
+        return 0;
+    }
+
+    if (sel->u.expr.method->pupdate)
+    {
+        /* Need to translate exceptions to error codes because the parser still
+         * uses return codes for error handling. */
+        try
+        {
+            /* By default, use whole residues/molecules. */
+            gmx_ana_poscalc_create_enum(&sel->u.expr.pc, pcc, rpost,
+                                        POS_COMPLWHOLE);
+        }
+        catch (gmx::GromacsException &ex)
+        {
+            _gmx_selparser_error(scanner, ex.what());
+            return ex.errorCode();
+        }
+        catch (...)
+        {
+            _gmx_selparser_error(scanner, "Unknown error!");
+            return gmx::eeUnknownError;
+        }
+    }
+    else
+    {
+        _gmx_selparser_error(scanner, "modifier '%s' is not applicable for '%s'",
+                             rpost, sel->u.expr.method->name);
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  left    Selection element for the left hand side.
+ * \param[in]  right   Selection element for the right hand side.
+ * \param[in]  op      String representation of the operator.
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * arithmetic expressions.
+ */
+t_selelem *
+_gmx_sel_init_arithmetic(t_selelem *left, t_selelem *right, char op,
+                         yyscan_t scanner)
+{
+    t_selelem         *sel;
+    char               buf[2];
+
+    buf[0] = op;
+    buf[1] = 0;
+    sel = _gmx_selelem_create(SEL_ARITHMETIC);
+    sel->v.type        = REAL_VALUE;
+    switch(op)
+    {
+        case '+': sel->u.arith.type = ARITH_PLUS; break;
+        case '-': sel->u.arith.type = (right ? ARITH_MINUS : ARITH_NEG); break;
+        case '*': sel->u.arith.type = ARITH_MULT; break;
+        case '/': sel->u.arith.type = ARITH_DIV;  break;
+        case '^': sel->u.arith.type = ARITH_EXP;  break;
+    }
+    sel->u.arith.opstr = strdup(buf);
+    sel->name          = sel->u.arith.opstr;
+    sel->child         = left;
+    sel->child->next   = right;
+    return sel;
+}
+
+/*!
+ * \param[in]  left   Selection element for the left hand side.
+ * \param[in]  right  Selection element for the right hand side.
+ * \param[in]  cmpop  String representation of the comparison operator.
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * comparison expressions.
+ */
+t_selelem *
+_gmx_sel_init_comparison(t_selelem *left, t_selelem *right, char *cmpop,
+                         yyscan_t scanner)
+{
+    t_selelem         *sel;
+    t_selexpr_param   *params, *param;
+    const char        *name;
+    int                rc;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    gmx::MessageStringContext  context(errors, "In comparison initialization");
+
+    sel = _gmx_selelem_create(SEL_EXPRESSION);
+    _gmx_selelem_set_method(sel, &sm_compare, scanner);
+    /* Create the parameter for the left expression */
+    name               = left->v.type == INT_VALUE ? "int1" : "real1";
+    params = param     = _gmx_selexpr_create_param(strdup(name));
+    param->nval        = 1;
+    param->value       = _gmx_selexpr_create_value_expr(left);
+    /* Create the parameter for the right expression */
+    name               = right->v.type == INT_VALUE ? "int2" : "real2";
+    param              = _gmx_selexpr_create_param(strdup(name));
+    param->nval        = 1;
+    param->value       = _gmx_selexpr_create_value_expr(right);
+    params->next       = param;
+    /* Create the parameter for the operator */
+    param              = _gmx_selexpr_create_param(strdup("op"));
+    param->nval        = 1;
+    param->value       = _gmx_selexpr_create_value(STR_VALUE);
+    param->value->u.s  = cmpop;
+    params->next->next = param;
+    if (!_gmx_sel_parse_params(params, sel->u.expr.method->nparams,
+                               sel->u.expr.method->param, sel, scanner))
+    {
+        _gmx_selelem_free(sel);
+        return NULL;
+    }
+
+    return sel;
+}
+
+/*!
+ * \param[in]  method Method to use.
+ * \param[in]  args   Pointer to the first argument.
+ * \param[in]  rpost  Reference position type to use (NULL = default).
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * selection methods that do not take parameters.
+ */
+t_selelem *
+_gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
+                      const char *rpost, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    t_selelem         *root, *child;
+    t_selexpr_param   *params, *param;
+    t_selexpr_value   *arg;
+    int                nargs;
+    int                rc;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[128];
+    sprintf(buf, "In keyword '%s'", method->name);
+    gmx::MessageStringContext  context(errors, buf);
+
+    if (method->nparams > 0)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError,
+                        "Keyword initialization called with non-keyword method");
+        return NULL;
+    }
+
+    root = _gmx_selelem_create(SEL_EXPRESSION);
+    child = root;
+    _gmx_selelem_set_method(child, method, scanner);
+
+    /* Initialize the evaluation of keyword matching if values are provided */
+    if (args)
+    {
+        gmx_ana_selmethod_t *kwmethod;
+        switch (method->type)
+        {
+            case INT_VALUE:  kwmethod = &sm_keyword_int;  break;
+            case REAL_VALUE: kwmethod = &sm_keyword_real; break;
+            case STR_VALUE:  kwmethod = &sm_keyword_str;  break;
+            default:
+                GMX_ERROR_NORET(gmx::eeInternalError,
+                                "Unknown type for keyword selection");
+                _gmx_selexpr_free_values(args);
+                goto on_error;
+        }
+        /* Count the arguments */
+        nargs = 0;
+        arg   = args;
+        while (arg)
+        {
+            ++nargs;
+            arg = arg->next;
+        }
+        /* Initialize the selection element */
+        root = _gmx_selelem_create(SEL_EXPRESSION);
+        _gmx_selelem_set_method(root, kwmethod, scanner);
+        params = param = _gmx_selexpr_create_param(NULL);
+        param->nval    = 1;
+        param->value   = _gmx_selexpr_create_value_expr(child);
+        param          = _gmx_selexpr_create_param(NULL);
+        param->nval    = nargs;
+        param->value   = args;
+        params->next   = param;
+        if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
+                                   root->u.expr.method->param, root, scanner))
+        {
+            goto on_error;
+        }
+    }
+    rc = set_refpos_type(sc->pcc, child, rpost, scanner);
+    if (rc != 0)
+    {
+        goto on_error;
+    }
+
+    return root;
+
+/* On error, free all memory and return NULL. */
+on_error:
+    _gmx_selelem_free(root);
+    return NULL;
+}
+
+/*!
+ * \param[in]  method Method to use for initialization.
+ * \param[in]  params Pointer to the first parameter.
+ * \param[in]  rpost  Reference position type to use (NULL = default).
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * selection methods that take parameters.
+ *
+ * Part of the behavior of the \c same selection keyword is hardcoded into
+ * this function (or rather, into _gmx_selelem_custom_init_same()) to allow the
+ * use of any keyword in \c "same KEYWORD as" without requiring special
+ * handling somewhere else (or sacrificing the simple syntax).
+ */
+t_selelem *
+_gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
+                     const char *rpost, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    t_selelem       *root;
+    int              rc;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[128];
+    sprintf(buf, "In keyword '%s'", method->name);
+    gmx::MessageStringContext  context(errors, buf);
+
+    _gmx_sel_finish_method(scanner);
+    /* The "same" keyword needs some custom massaging of the parameters. */
+    rc = _gmx_selelem_custom_init_same(&method, params, scanner);
+    if (rc != 0)
+    {
+        _gmx_selexpr_free_params(params);
+        return NULL;
+    }
+    root = _gmx_selelem_create(SEL_EXPRESSION);
+    _gmx_selelem_set_method(root, method, scanner);
+    /* Process the parameters */
+    if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
+                               root->u.expr.method->param, root, scanner))
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+    rc = set_refpos_type(sc->pcc, root, rpost, scanner);
+    if (rc != 0)
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+
+    return root;
+}
+
+/*!
+ * \param[in]  method Modifier to use for initialization.
+ * \param[in]  params Pointer to the first parameter.
+ * \param[in]  sel    Selection element that the modifier should act on.
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * selection modifiers.
+ */
+t_selelem *
+_gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
+                       t_selelem *sel, yyscan_t scanner)
+{
+    t_selelem         *root;
+    t_selelem         *mod;
+    t_selexpr_param   *vparam;
+    int                i;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[128];
+    sprintf(buf, "In keyword '%s'", method->name);
+    gmx::MessageStringContext  context(errors, buf);
+
+    _gmx_sel_finish_method(scanner);
+    mod = _gmx_selelem_create(SEL_MODIFIER);
+    _gmx_selelem_set_method(mod, method, scanner);
+    if (method->type == NO_VALUE)
+    {
+        t_selelem *child;
+
+        child = sel;
+        while (child->next)
+        {
+            child = child->next;
+        }
+        child->next = mod;
+        root        = sel;
+    }
+    else
+    {
+        vparam        = _gmx_selexpr_create_param(NULL);
+        vparam->nval  = 1;
+        vparam->value = _gmx_selexpr_create_value_expr(sel);
+        vparam->next  = params;
+        params        = vparam;
+        root          = mod;
+    }
+    /* Process the parameters */
+    if (!_gmx_sel_parse_params(params, mod->u.expr.method->nparams,
+                               mod->u.expr.method->param, mod, scanner))
+    {
+        _gmx_selelem_free(mod);
+        return NULL;
+    }
+
+    return root;
+}
+
+/*!
+ * \param[in]  expr    Input selection element for the position calculation.
+ * \param[in]  type    Reference position type or NULL for default.
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * evaluation of reference positions.
+ */
+t_selelem *
+_gmx_sel_init_position(t_selelem *expr, const char *type, yyscan_t scanner)
+{
+    t_selelem       *root;
+    t_selexpr_param *params;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[128];
+    sprintf(buf, "In position evaluation");
+    gmx::MessageStringContext  context(errors, buf);
+
+    root = _gmx_selelem_create(SEL_EXPRESSION);
+    _gmx_selelem_set_method(root, &sm_keyword_pos, scanner);
+    _gmx_selelem_set_kwpos_type(root, type);
+    /* Create the parameters for the parameter parser. */
+    params        = _gmx_selexpr_create_param(NULL);
+    params->nval  = 1;
+    params->value = _gmx_selexpr_create_value_expr(expr);
+    /* Parse the parameters. */
+    if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
+                               root->u.expr.method->param, root, scanner))
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+
+    return root;
+}
+
+/*!
+ * \param[in] x,y,z  Coordinates for the position.
+ * \returns   The creates selection element.
+ */
+t_selelem *
+_gmx_sel_init_const_position(real x, real y, real z)
+{
+    t_selelem *sel;
+    rvec       pos;
+
+    sel = _gmx_selelem_create(SEL_CONST);
+    _gmx_selelem_set_vtype(sel, POS_VALUE);
+    _gmx_selvalue_reserve(&sel->v, 1);
+    pos[XX] = x;
+    pos[YY] = y;
+    pos[ZZ] = z;
+    gmx_ana_pos_init_const(sel->v.u.p, pos);
+    return sel;
+}
+
+/*!
+ * \param[in] name  Name of an index group to search for.
+ * \param[in] scanner Scanner data structure.
+ * \returns   The created constant selection element, or NULL if no matching
+ *     index group found.
+ *
+ * See gmx_ana_indexgrps_find() for information on how \p name is matched
+ * against the index groups.
+ */
+t_selelem *
+_gmx_sel_init_group_by_name(const char *name, yyscan_t scanner)
+{
+    gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
+    t_selelem *sel;
+
+    if (!_gmx_sel_lexer_has_groups_set(scanner))
+    {
+        sel = _gmx_selelem_create(SEL_GROUPREF);
+        _gmx_selelem_set_vtype(sel, GROUP_VALUE);
+        sel->u.gref.name = strdup(name);
+        sel->u.gref.id = -1;
+        sel->name = name;
+        return sel;
+    }
+    if (!grps)
+    {
+        _gmx_selparser_error(scanner, "No index groups set; cannot match 'group %s'", name);
+        return NULL;
+    }
+    sel = _gmx_selelem_create(SEL_CONST);
+    _gmx_selelem_set_vtype(sel, GROUP_VALUE); 
+    /* FIXME: The constness should not be cast away */
+    if (!gmx_ana_indexgrps_find(&sel->u.cgrp, grps, (char *)name))
+    {
+        _gmx_selparser_error(scanner, "Cannot match 'group %s'", name);
+        _gmx_selelem_free(sel);
+        return NULL;
+    }
+    sel->name = sel->u.cgrp.name;
+    return sel;
+}
+
+/*!
+ * \param[in] id    Zero-based index number of the group to extract.
+ * \param[in] scanner Scanner data structure.
+ * \returns   The created constant selection element, or NULL if no matching
+ *     index group found.
+ */
+t_selelem *
+_gmx_sel_init_group_by_id(int id, yyscan_t scanner)
+{
+    gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
+    t_selelem *sel;
+
+    if (!_gmx_sel_lexer_has_groups_set(scanner))
+    {
+        sel = _gmx_selelem_create(SEL_GROUPREF);
+        _gmx_selelem_set_vtype(sel, GROUP_VALUE);
+        sel->u.gref.name = NULL;
+        sel->u.gref.id = id;
+        return sel;
+    }
+    if (!grps)
+    {
+        _gmx_selparser_error(scanner, "No index groups set; cannot match 'group %d'", id);
+        return NULL;
+    }
+    sel = _gmx_selelem_create(SEL_CONST);
+    _gmx_selelem_set_vtype(sel, GROUP_VALUE);
+    if (!gmx_ana_indexgrps_extract(&sel->u.cgrp, grps, id))
+    {
+        _gmx_selparser_error(scanner, "Cannot match 'group %d'", id);
+        _gmx_selelem_free(sel);
+        return NULL;
+    }
+    sel->name = sel->u.cgrp.name;
+    return sel;
+}
+
+/*!
+ * \param[in,out] sel  Value of the variable.
+ * \returns       The created selection element that references \p sel.
+ *
+ * The reference count of \p sel is updated, but no other modifications are
+ * made.
+ */
+t_selelem *
+_gmx_sel_init_variable_ref(t_selelem *sel)
+{
+    t_selelem *ref;
+
+    if (sel->v.type == POS_VALUE && sel->type == SEL_CONST)
+    {
+        ref = sel;
+    }
+    else
+    {
+        ref = _gmx_selelem_create(SEL_SUBEXPRREF);
+        _gmx_selelem_set_vtype(ref, sel->v.type);
+        ref->name  = sel->name;
+        ref->child = sel;
+    }
+    sel->refcount++;
+    return ref;
+}
+
+/*!
+ * \param[in]  name     Name for the selection
+ *     (if NULL, a default name is constructed).
+ * \param[in]  sel      The selection element that evaluates the selection.
+ * \param      scanner  Scanner data structure.
+ * \returns    The created root selection element.
+ *
+ * This function handles the creation of root (\ref SEL_ROOT) \c t_selelem
+ * objects for selections.
+ */
+t_selelem *
+_gmx_sel_init_selection(char *name, t_selelem *sel, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    t_selelem               *root;
+    int                      rc;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[1024];
+    sprintf(buf, "In selection '%s'", _gmx_sel_lexer_pselstr(scanner));
+    gmx::MessageStringContext  context(errors, buf);
+
+    if (sel->v.type != POS_VALUE)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError,
+                        "Each selection must evaluate to a position");
+        /* FIXME: Better handling of this error */
+        sfree(name);
+        return NULL;
+    }
+
+    root = _gmx_selelem_create(SEL_ROOT);
+    root->child = sel;
+    /* Assign the name (this is done here to free it automatically in the case
+     * of an error below). */
+    if (name)
+    {
+        root->name = root->u.cgrp.name = name;
+    }
+    /* Update the flags */
+    rc = _gmx_selelem_update_flags(root, scanner);
+    if (rc != 0)
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+
+    /* If there is no name provided by the user, check whether the actual
+     * selection given was from an external group, and if so, use the name
+     * of the external group. */
+    if (!root->name)
+    {
+        t_selelem *child = root->child;
+        while (child->type == SEL_MODIFIER)
+        {
+            if (!child->child || child->child->type != SEL_SUBEXPRREF
+                || !child->child->child)
+            {
+                break;
+            }
+            child = child->child->child;
+        }
+        if (child->type == SEL_EXPRESSION
+            && child->child && child->child->type == SEL_SUBEXPRREF
+            && child->child->child
+            && child->child->child->type == SEL_CONST
+            && child->child->child->v.type == GROUP_VALUE)
+        {
+            root->name = root->u.cgrp.name =
+                strdup(child->child->child->u.cgrp.name);
+        }
+    }
+    /* If there still is no name, use the selection string */
+    if (!root->name)
+    {
+        root->name = root->u.cgrp.name
+            = strdup(_gmx_sel_lexer_pselstr(scanner));
+    }
+
+    /* Print out some information if the parser is interactive */
+    if (_gmx_sel_is_lexer_interactive(scanner))
+    {
+        fprintf(stderr, "Selection '%s' parsed\n",
+                _gmx_sel_lexer_pselstr(scanner));
+    }
+
+    return root;
+}
+
+
+/*!
+ * \param[in]  name     Name of the variable (should not be freed after this
+ *   function).
+ * \param[in]  expr     The selection element that evaluates the variable.
+ * \param      scanner  Scanner data structure.
+ * \returns    The created root selection element.
+ *
+ * This function handles the creation of root \c t_selelem objects for
+ * variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
+ * element are both created.
+ */
+t_selelem *
+_gmx_sel_assign_variable(char *name, t_selelem *expr, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    const char              *pselstr = _gmx_sel_lexer_pselstr(scanner);
+    t_selelem               *root = NULL;
+    int                      rc;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[1024];
+    sprintf(buf, "In selection '%s'", pselstr);
+    gmx::MessageStringContext  context(errors, buf);
+
+    rc = _gmx_selelem_update_flags(expr, scanner);
+    if (rc != 0)
+    {
+        sfree(name);
+        _gmx_selelem_free(expr);
+        return NULL;
+    }
+    /* Check if this is a constant non-group value */
+    if (expr->type == SEL_CONST && expr->v.type != GROUP_VALUE)
+    {
+        /* If so, just assign the constant value to the variable */
+        if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr))
+        {
+            _gmx_selelem_free(expr);
+            sfree(name);
+            return NULL;
+        }
+        _gmx_selelem_free(expr);
+        sfree(name);
+        goto finish;
+    }
+    /* Check if we are assigning a variable to another variable */
+    if (expr->type == SEL_SUBEXPRREF)
+    {
+        /* If so, make a simple alias */
+        if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr->child))
+        {
+            _gmx_selelem_free(expr);
+            sfree(name);
+            return NULL;
+        }
+        _gmx_selelem_free(expr);
+        sfree(name);
+        goto finish;
+    }
+    /* Create the root element */
+    root = _gmx_selelem_create(SEL_ROOT);
+    root->name          = name;
+    root->u.cgrp.name   = name;
+    /* Create the subexpression element */
+    root->child = _gmx_selelem_create(SEL_SUBEXPR);
+    _gmx_selelem_set_vtype(root->child, expr->v.type);
+    root->child->name   = name;
+    root->child->child  = expr;
+    /* Update flags */
+    rc = _gmx_selelem_update_flags(root, scanner);
+    if (rc != 0)
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+    /* Add the variable to the symbol table */
+    if (!_gmx_sel_add_var_symbol(sc->symtab, name, root->child))
+    {
+        _gmx_selelem_free(root);
+        return NULL;
+    }
+finish:
+    srenew(sc->varstrs, sc->nvars + 1);
+    sc->varstrs[sc->nvars] = strdup(pselstr);
+    ++sc->nvars;
+    if (_gmx_sel_is_lexer_interactive(scanner))
+    {
+        fprintf(stderr, "Variable '%s' parsed\n", pselstr);
+    }
+    return root;
+}
+
+/*!
+ * \param         sel   Selection to append (can be NULL, in which
+ *   case nothing is done).
+ * \param         last  Last selection, or NULL if not present or not known.
+ * \param         scanner  Scanner data structure.
+ * \returns       The last selection after the append.
+ *
+ * Appends \p sel after the last root element, and returns either \p sel
+ * (if it was non-NULL) or the last element (if \p sel was NULL).
+ */
+t_selelem *
+_gmx_sel_append_selection(t_selelem *sel, t_selelem *last, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+
+    /* Append sel after last, or the last element of sc if last is NULL */
+    if (last)
+    {
+        last->next = sel;
+    }
+    else
+    {
+        if (sc->root)
+        {
+            last = sc->root;
+            while (last->next)
+            {
+                last = last->next;
+            }
+            last->next = sel;
+        }
+        else
+        {
+            sc->root = sel;
+        }
+    }
+    /* Initialize a selection object if necessary */
+    if (sel)
+    {
+        last = sel;
+        /* Add the new selection to the collection if it is not a variable. */
+        if (sel->child->type != SEL_SUBEXPR)
+        {
+            gmx::Selection *newsel
+                = new gmx::Selection(sel, _gmx_sel_lexer_pselstr(scanner));
+            sc->sel.push_back(newsel);
+        }
+    }
+    /* Clear the selection string now that we've saved it */
+    _gmx_sel_lexer_clear_pselstr(scanner);
+    return last;
+}
+
+/*!
+ * \param[in] scanner Scanner data structure.
+ * \returns   TRUE if the parser should finish, FALSE if parsing should
+ *   continue.
+ *
+ * This function is called always after _gmx_sel_append_selection() to
+ * check whether a sufficient number of selections has already been provided.
+ * This is used to terminate interactive parsers when the correct number of
+ * selections has been provided.
+ */
+gmx_bool
+_gmx_sel_parser_should_finish(yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    return (int)sc->sel.size() == _gmx_sel_lexer_exp_selcount(scanner);
+}
+
+/*!
+ * \param[in] scanner Scanner data structure.
+ */
+void
+_gmx_sel_handle_empty_cmd(yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+    gmx_ana_indexgrps_t     *grps = _gmx_sel_lexer_indexgrps(scanner);
+    int                      i;
+
+    if (!_gmx_sel_is_lexer_interactive(scanner))
+        return;
+
+    if (grps)
+    {
+        fprintf(stderr, "Available index groups:\n");
+        gmx_ana_indexgrps_print(stderr, _gmx_sel_lexer_indexgrps(scanner), 0);
+    }
+    if (sc->nvars > 0 || !sc->sel.empty())
+    {
+        fprintf(stderr, "Currently provided selections:\n");
+        for (i = 0; i < sc->nvars; ++i)
+        {
+            fprintf(stderr, "     %s\n", sc->varstrs[i]);
+        }
+        for (i = 0; i < (int)sc->sel.size(); ++i)
+        {
+            fprintf(stderr, " %2d. %s\n", i+1, sc->sel[i]->_sel.selstr);
+        }
+    }
+}
+
+/*!
+ * \param[in] topic   Topic for which help was requested, or NULL for general
+ *                    help.
+ * \param[in] scanner Scanner data structure.
+ *
+ * \p topic is freed by this function.
+ */
+void
+_gmx_sel_handle_help_cmd(char *topic, yyscan_t scanner)
+{
+    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+
+    _gmx_sel_print_help(stderr, sc->symtab, topic);
+    if (topic)
+    {
+        sfree(topic);
+    }
+}
diff --git a/src/gromacs/selection/parsetree.h b/src/gromacs/selection/parsetree.h
new file mode 100644 (file)
index 0000000..452dd2c
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Handling of intermediate selection parser data.
+ *
+ * The data types declared in this header are used by the parser to store
+ * intermediate data when constructing method expressions.
+ * In particular, the parameters for the method are stored.
+ * The intermediate data is freed once a \c t_selelem object can be
+ * constructed.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef SELECTION_PARSETREE_H
+#define SELECTION_PARSETREE_H
+
+#include <types/simple.h>
+
+#include "gromacs/selection/selvalue.h"
+
+struct t_selelem;
+struct gmx_ana_indexgrps_t;
+struct gmx_ana_selmethod_t;
+struct gmx_ana_selparam_t;
+
+/*! \internal \brief
+ * Describes a parsed value, possibly resulting from expression evaluation.
+ */
+typedef struct t_selexpr_value
+{
+    /** Type of the value. */
+    e_selvalue_t            type;
+    /** TRUE if the value is the result of an expression. */
+    gmx_bool                    bExpr;
+    /** The actual value. */
+    union {
+        /** The integer value/range (\p type INT_VALUE); */
+        struct {
+            /** Beginning of the range. */
+            int             i1;
+            /** End of the range; equals \p i1 for a single integer. */
+            int             i2;
+        }                   i;
+        /** The real value/range (\p type REAL_VALUE); */
+        struct {
+            /** Beginning of the range. */
+            real            r1;
+            /** End of the range; equals \p r1 for a single number. */
+            real            r2;
+        }                   r;
+        /** The string value (\p type STR_VALUE); */
+        char               *s;
+        /** The position value (\p type POS_VALUE); */
+        rvec                x;
+        /** The expression if \p bExpr is TRUE. */
+        struct t_selelem   *expr;
+    }                       u;
+    /** Pointer to the next value. */
+    struct t_selexpr_value *next;
+} t_selexpr_value;
+
+/*! \internal \brief
+ * Describes a parsed method parameter.
+ */
+typedef struct t_selexpr_param
+{
+    /** Name of the parameter. */
+    char                   *name;
+    /** Number of values given for this parameter. */
+    int                     nval;
+    /** Pointer to the first value. */
+    struct t_selexpr_value *value;
+    /** Pointer to the next parameter. */
+    struct t_selexpr_param *next;
+} t_selexpr_param;
+
+/** Error reporting function for the selection parser. */
+void
+_gmx_selparser_error(void *scanner, const char *fmt, ...);
+
+/** Allocates and initializes a constant \c t_selexpr_value. */
+t_selexpr_value *
+_gmx_selexpr_create_value(e_selvalue_t type);
+/** Allocates and initializes an expression \c t_selexpr_value. */
+t_selexpr_value *
+_gmx_selexpr_create_value_expr(struct t_selelem *expr);
+/** Allocates and initializes a \c t_selexpr_param. */
+t_selexpr_param *
+_gmx_selexpr_create_param(char *name);
+
+/** Frees the memory allocated for a chain of values. */
+void
+_gmx_selexpr_free_values(t_selexpr_value *value);
+/** Frees the memory allocated for a chain of parameters. */
+void
+_gmx_selexpr_free_params(t_selexpr_param *param);
+
+/** Propagates the flags for selection elements. */
+int
+_gmx_selelem_update_flags(struct t_selelem *sel, void *scanner);
+
+/** Initializes the method parameter data of \ref SEL_EXPRESSION and
+ * \ref SEL_MODIFIER elements. */
+void
+_gmx_selelem_init_method_params(struct t_selelem *sel, void *scanner);
+/** Initializes the method for a \ref SEL_EXPRESSION selection element. */
+void
+_gmx_selelem_set_method(struct t_selelem *sel,
+                        struct gmx_ana_selmethod_t *method, void *scanner);
+
+/** Creates a \c t_selelem for arithmetic expression evaluation. */
+struct t_selelem *
+_gmx_sel_init_arithmetic(struct t_selelem *left, struct t_selelem *right,
+                         char op, void *scanner);
+/** Creates a \c t_selelem for comparsion expression evaluation. */
+struct t_selelem *
+_gmx_sel_init_comparison(struct t_selelem *left, struct t_selelem *right,
+                         char *cmpop, void *scanner);
+/** Creates a \c t_selelem for a keyword expression from the parsed data. */
+struct t_selelem *
+_gmx_sel_init_keyword(struct gmx_ana_selmethod_t *method,
+                      t_selexpr_value *args, const char *rpost, void *scanner);
+/** Creates a \c t_selelem for a method expression from the parsed data. */
+struct t_selelem *
+_gmx_sel_init_method(struct gmx_ana_selmethod_t *method,
+                     t_selexpr_param *params, const char *rpost,
+                     void *scanner);
+/** Creates a \c t_selelem for a modifier expression from the parsed data. */
+struct t_selelem *
+_gmx_sel_init_modifier(struct gmx_ana_selmethod_t *mod, t_selexpr_param *params,
+                       struct t_selelem *sel, void *scanner);
+/** Creates a \c t_selelem for evaluation of reference positions. */
+struct t_selelem *
+_gmx_sel_init_position(struct t_selelem *expr, const char *type, void *scanner);
+
+/** Creates a \c t_selelem for a constant position. */
+struct t_selelem *
+_gmx_sel_init_const_position(real x, real y, real z);
+/** Creates a \c t_selelem for a index group expression using group name. */
+struct t_selelem *
+_gmx_sel_init_group_by_name(const char *name, void *scanner);
+/** Creates a \c t_selelem for a index group expression using group index. */
+struct t_selelem *
+_gmx_sel_init_group_by_id(int id, void *scanner);
+/** Creates a \c t_selelem for a variable reference */
+struct t_selelem *
+_gmx_sel_init_variable_ref(struct t_selelem *sel);
+
+/** Creates a root \c t_selelem for a selection. */
+struct t_selelem *
+_gmx_sel_init_selection(char *name, struct t_selelem *sel, void *scanner);
+/** Creates a root \c t_selelem elements for a variable assignment. */
+struct t_selelem *
+_gmx_sel_assign_variable(char *name, struct t_selelem *expr, void *scanner);
+/** Appends a root \c t_selelem to a selection collection. */
+struct t_selelem *
+_gmx_sel_append_selection(struct t_selelem *sel, struct t_selelem *last,
+                          void *scanner);
+/** Check whether the parser should finish. */
+gmx_bool
+_gmx_sel_parser_should_finish(void *scanner);
+
+/** Handle empty commands. */
+void
+_gmx_sel_handle_empty_cmd(void *scanner);
+/** Process help commands. */
+void
+_gmx_sel_handle_help_cmd(char *topic, void *scanner);
+
+/* In params.c */
+/** Initializes an array of parameters based on input from the selection parser. */
+gmx_bool
+_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam,
+                      struct gmx_ana_selparam_t *param, struct t_selelem *root,
+                      void *scanner);
+
+#endif
diff --git a/src/gromacs/selection/poscalc.cpp b/src/gromacs/selection/poscalc.cpp
new file mode 100644 (file)
index 0000000..e7b9f5c
--- /dev/null
@@ -0,0 +1,1461 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal
+ * \page poscalcengine Position calculation engine
+ *
+ * The header file \ref poscalc.h defines an API for calculating positions
+ * in an automated way. This is useful mostly in the selection engine, in
+ * particular with dynamic selections, because the same COM/COG positions
+ * may be needed in several contexts. The API makes it possible to
+ * optimize the evaluation such that any heavy calculation is only done once,
+ * and the results just copied if needed more than once.
+ * The functions also provide a convenient interface for keeping the whole
+ * \c gmx_ana_pos_t structure up-to-date.
+ *
+ * A new collection of position calculations is allocated with
+ * gmx_ana_poscalc_coll_create().
+ * Calculations within one collection should share the same topology, and
+ * they are optimized. Calculations in different collections do not interact.
+ * The topology for a collection can be set with
+ * gmx_ana_poscalc_coll_set_topology().
+ * This needs to be done before calling gmx_ana_poscalc_set_maxindex() for
+ * any calculation in the collection, unless that calculation does not
+ * require topology information.
+ * All memory allocated for a collection and the calculations in it can be
+ * freed with gmx_ana_poscalc_coll_free().
+ *
+ * A new calculation is created with gmx_ana_poscalc_create().
+ * If flags need to be adjusted later, gmx_ana_poscalc_set_flags() can be
+ * used.
+ * After the flags are final, the largest possible index group for which the
+ * positions are needed has to be set with gmx_ana_poscalc_set_maxindex().
+ * gmx_ana_poscalc_coll_set_topology() should have been called before this
+ * function is called.
+ * After the above calls, gmx_ana_poscalc_init_pos() can be used to initialize
+ * output to a \c gmx_ana_pos_t structure. Several different structures can be
+ * initialized for the same calculation; the only requirement is that the
+ * structure passed later to gmx_ana_poscalc_update() has been initialized
+ * properly.
+ * The memory allocated for a calculation can be freed with
+ * gmx_ana_poscalc_free().
+ *
+ * The position evaluation is simple: gmx_ana_poscalc_init_frame() should be
+ * called once for each frame, and gmx_ana_poscalc_update() can then be called
+ * for each calculation that is needed for that frame.
+ *
+ * It is also possible to initialize the calculations based on a type provided
+ * as a string.
+ * The possible strings are returned by gmx_ana_poscalc_create_type_enum(),
+ * and the string can be converted to the parameters for
+ * gmx_ana_poscalc_create() using gmx_ana_poscalc_type_from_enum().
+ * gmx_ana_poscalc_create_enum() is also provided for convenience.
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in poscalc.h.
+ *
+ * \todo
+ * There is probably some room for optimization in the calculation of
+ * positions with bases.
+ * In particular, the current implementation may do a lot of unnecessary
+ * copying.
+ * The interface would need to be changed to make it possible to use the
+ * same output positions for several calculations.
+ *
+ * \todo
+ * The current algorithm for setting up base calculations could be improved
+ * in cases when there are calculations that cannot use a common base but
+ * still overlap partially (e.g., with three calculations A, B, and C
+ * such that A could use both B and C as a base, but B and C cannot use the
+ * same base).
+ * Setting up the bases in an optimal manner in every possible situation can
+ * be quite difficult unless several bases are allowed for one calculation,
+ * but better heuristics could probably be implemented.
+ * For best results, the setup should probably be postponed (at least
+ * partially) to gmx_ana_poscalc_init_eval().
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <macros.h>
+#include <smalloc.h>
+#include <typedefs.h>
+#include <pbc.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/centerofmass.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/position.h"
+
+/*! \internal \brief
+ * Collection of \c gmx_ana_poscalc_t structures for the same topology.
+ *
+ * Calculations within the same structure are optimized to eliminate duplicate
+ * calculations.
+ */
+struct gmx_ana_poscalc_coll_t
+{
+    /*! \brief
+     * Topology data.
+     *
+     * Can be NULL if none of the calculations require topology data or if
+     * gmx_ana_poscalc_coll_set_topology() has not been called.
+     */
+    t_topology               *top;
+    /** Pointer to the first data structure. */
+    gmx_ana_poscalc_t        *first;
+    /** Pointer to the last data structure. */
+    gmx_ana_poscalc_t        *last;
+    /** Whether the collection has been initialized for evaluation. */
+    gmx_bool                      bInit;
+};
+
+/*! \internal \brief
+ * Data structure for position calculation.
+ */
+struct gmx_ana_poscalc_t
+{
+    /*! \brief
+     * Type of calculation.
+     *
+     * This field may differ from the type requested by the user, because
+     * it is changed internally to the most effective calculation.
+     * For example, if the user requests a COM calculation for residues
+     * consisting of single atoms, it is simply set to POS_ATOM.
+     * To provide a consistent interface to the user, the field \p itype
+     * should be used when information should be given out.
+     */
+    e_poscalc_t               type;
+    /*! \brief
+     * Flags for calculation options.
+     *
+     * See \ref poscalc_flags "documentation of the flags".
+     */
+    int                       flags;
+
+    /*! \brief
+     * Type for the created indices.
+     *
+     * This field always agrees with the type that the user requested, but
+     * may differ from \p type.
+     */
+    e_index_t                 itype;
+    /*! \brief
+     * Block data for the calculation.
+     */
+    t_blocka                  b;
+    /*! \brief
+     * Mapping from the blocks to the blocks of \p sbase.
+     *
+     * If \p sbase is NULL, this field is also.
+     */
+    int                      *baseid;
+    /*! \brief
+     * Maximum evaluation group.
+     */
+    gmx_ana_index_t           gmax;
+
+    /** Position storage for calculations that are used as a base. */
+    gmx_ana_pos_t            *p;
+
+    /** TRUE if the positions have been evaluated for the current frame. */
+    gmx_bool                      bEval;
+    /*! \brief
+     * Base position data for this calculation.
+     *
+     * If not NULL, the centers required by this calculation have
+     * already been calculated in \p sbase.
+     * The structure pointed by \p sbase is always a static calculation.
+     */
+    struct gmx_ana_poscalc_t *sbase;
+    /** Next structure in the linked list of calculations. */
+    struct gmx_ana_poscalc_t *next;
+    /** Previous structure in the linked list of calculations. */
+    struct gmx_ana_poscalc_t *prev;
+    /** Number of references to this structure. */
+    int                       refcount;
+    /** Collection this calculation belongs to. */
+    gmx_ana_poscalc_coll_t   *coll;
+};
+
+//! Strings returned by gmx_ana_poscalc_create_type_enum().
+static const char *const poscalc_enum_strings[] = {
+    "atom",
+    "res_com",       "res_cog",
+    "mol_com",       "mol_cog",
+    "whole_res_com", "whole_res_cog",
+    "whole_mol_com", "whole_mol_cog",
+    "part_res_com",  "part_res_cog",
+    "part_mol_com",  "part_mol_cog",
+    "dyn_res_com",   "dyn_res_cog",
+    "dyn_mol_com",   "dyn_mol_cog",
+    NULL,
+};
+//! Number of elements in ::poscalc_enum_strings.
+#define NENUM asize(poscalc_enum_strings)
+
+/*! \brief
+ * Returns the partition type for a given position type.
+ *
+ * \param [in] type  \c e_poscalc_t value to convert.
+ * \returns    Corresponding \c e_indet_t.
+ */
+static e_index_t
+index_type_for_poscalc(e_poscalc_t type)
+{
+    switch(type)
+    {
+        case POS_ATOM:    return INDEX_ATOM;
+        case POS_RES:     return INDEX_RES;
+        case POS_MOL:     return INDEX_MOL;
+        case POS_ALL:     return INDEX_ALL;
+        case POS_ALL_PBC: return INDEX_ALL;
+    }
+    return INDEX_UNKNOWN;
+}
+
+/*!
+ * \param[in]     post  String (typically an enum command-line argument).
+ *   Allowed values: 'atom', 'res_com', 'res_cog', 'mol_com', 'mol_cog',
+ *   or one of the last four prepended by 'whole_', 'part_', or 'dyn_'.
+ * \param[out]    type  \c e_poscalc_t corresponding to \p post.
+ * \param[in,out] flags Flags corresponding to \p post.
+ *   On input, the flags should contain the default flags.
+ *   On exit, the flags \ref POS_MASS, \ref POS_COMPLMAX and
+ *   \ref POS_COMPLWHOLE have been set according to \p post
+ *   (the completion flags are left at the default values if no completion
+ *   prefix is given).
+ * \throws  InternalError  if post is not recognized.
+ *
+ * \attention
+ * Checking is not complete, and other values than those listed above
+ * may be accepted for \p post, but the results are undefined.
+ */
+void
+gmx_ana_poscalc_type_from_enum(const char *post, e_poscalc_t *type, int *flags)
+{
+    const char *ptr;
+
+    if (post[0] == 'a')
+    {
+        *type   = POS_ATOM;
+        *flags &= ~(POS_MASS | POS_COMPLMAX | POS_COMPLWHOLE);
+        return;
+    }
+
+    /* Process the prefix */
+    ptr = post;
+    if (post[0] == 'w')
+    {
+        *flags &= ~POS_COMPLMAX;
+        *flags |= POS_COMPLWHOLE;
+        ptr = post + 6;
+    }
+    else if (post[0] == 'p')
+    {
+        *flags &= ~POS_COMPLWHOLE;
+        *flags |= POS_COMPLMAX;
+        ptr = post + 5;
+    }
+    else if (post[0] == 'd')
+    {
+        *flags &= ~(POS_COMPLMAX | POS_COMPLWHOLE);
+        ptr = post + 4;
+    }
+
+    if (ptr[0] == 'r')
+    {
+        *type = POS_RES;
+    }
+    else if (ptr[0] == 'm')
+    {
+        *type = POS_MOL;
+    }
+    else
+    {
+        GMX_THROW(gmx::InternalError("Unknown position calculation type"));
+    }
+    if (strlen(ptr) < 7)
+    {
+        GMX_THROW(gmx::InternalError("Unknown position calculation type"));
+    }
+    if (ptr[6] == 'm')
+    {
+        *flags |= POS_MASS;
+    }
+    else if (ptr[6] == 'g')
+    {
+        *flags &= ~POS_MASS;
+    }
+    else
+    {
+        GMX_THROW(gmx::InternalError("Unknown position calculation type"));
+    }
+}
+
+/*!
+ * \param[in]  bAtom    If TRUE, the "atom" value is included.
+ * \returns    NULL-terminated array of strings that contains the string
+ *   values acceptable for gmx_ana_poscalc_type_from_enum().
+ *
+ * The first string in the returned list is always NULL to allow the list to
+ * be used with Gromacs command-line parsing.
+ */
+const char **
+gmx_ana_poscalc_create_type_enum(gmx_bool bAtom)
+{
+    const char **pcenum;
+    size_t       i;
+
+    if (bAtom)
+    {
+        snew(pcenum, NENUM+1);
+        for (i = 0; i < NENUM; ++i)
+        {
+            pcenum[i+1] = poscalc_enum_strings[i];
+        }
+    }
+    else
+    {
+        snew(pcenum, NENUM+1-1);
+        for (i = 1; i < NENUM; ++i)
+        {
+            pcenum[i] = poscalc_enum_strings[i];
+        }
+    }
+    pcenum[0] = NULL;
+    return pcenum;
+}
+
+/*!
+ * \param[out] pccp   Allocated position calculation collection.
+ * \returns    0 for success.
+ */
+int
+gmx_ana_poscalc_coll_create(gmx_ana_poscalc_coll_t **pccp)
+{
+    gmx_ana_poscalc_coll_t *pcc;
+
+    snew(pcc, 1);
+    pcc->top   = NULL;
+    pcc->first = NULL;
+    pcc->last  = NULL;
+    pcc->bInit = FALSE;
+    *pccp = pcc;
+    return 0;
+}
+
+/*!
+ * \param[in,out] pcc   Position calculation collection data structure.
+ * \param[in]     top   Topology data structure.
+ *
+ * This function should be called to set the topology before using
+ * gmx_ana_poscalc_set_maxindex() for any calculation that requires
+ * topology information.
+ */
+void
+gmx_ana_poscalc_coll_set_topology(gmx_ana_poscalc_coll_t *pcc, t_topology *top)
+{
+    pcc->top = top;
+}
+
+/*!
+ * \param[in] pcc   Position calculation collection to free.
+ *
+ * The pointer \p pcc is invalid after the call.
+ * Any calculations in the collection are also freed, no matter how many
+ * references to them are left.
+ */
+void
+gmx_ana_poscalc_coll_free(gmx_ana_poscalc_coll_t *pcc)
+{
+    while (pcc->first)
+    {
+        gmx_ana_poscalc_free(pcc->first);
+    }
+    sfree(pcc);
+}
+
+/*!
+ * \param[in] fp    File handle to receive the output.
+ * \param[in] pcc   Position calculation collection to print.
+ *
+ * The output is very technical, making this function mainly useful for
+ * debugging purposes.
+ */
+void
+gmx_ana_poscalc_coll_print_tree(FILE *fp, gmx_ana_poscalc_coll_t *pcc)
+{
+    gmx_ana_poscalc_t *pc;
+    int                i, j;
+
+    fprintf(fp, "Position calculations:\n");
+    i  = 1;
+    pc = pcc->first;
+    while (pc)
+    {
+        fprintf(fp, "%2d ", i);
+        switch (pc->type)
+        {
+            case POS_ATOM:    fprintf(fp, "ATOM");    break;
+            case POS_RES:     fprintf(fp, "RES");     break;
+            case POS_MOL:     fprintf(fp, "MOL");     break;
+            case POS_ALL:     fprintf(fp, "ALL");     break;
+            case POS_ALL_PBC: fprintf(fp, "ALL_PBC"); break;
+        }
+        if (pc->itype != index_type_for_poscalc(pc->type))
+        {
+            fprintf(fp, " (");
+            switch (pc->itype)
+            {
+                case INDEX_UNKNOWN: fprintf(fp, "???");  break;
+                case INDEX_ATOM:    fprintf(fp, "ATOM"); break;
+                case INDEX_RES:     fprintf(fp, "RES");  break;
+                case INDEX_MOL:     fprintf(fp, "MOL");  break;
+                case INDEX_ALL:     fprintf(fp, "ALL");  break;
+            }
+            fprintf(fp, ")");
+        }
+        fprintf(fp, " flg=");
+        if (pc->flags & POS_MASS)
+        {
+            fprintf(fp, "M");
+        }
+        if (pc->flags & POS_DYNAMIC)
+        {
+            fprintf(fp, "D");
+        }
+        if (pc->flags & POS_MASKONLY)
+        {
+            fprintf(fp, "A");
+        }
+        if (pc->flags & POS_COMPLMAX)
+        {
+            fprintf(fp, "Cm");
+        }
+        if (pc->flags & POS_COMPLWHOLE)
+        {
+            fprintf(fp, "Cw");
+        }
+        if (!pc->flags)
+        {
+            fprintf(fp, "0");
+        }
+        fprintf(fp, " nr=%d nra=%d", pc->b.nr, pc->b.nra);
+        fprintf(fp, " refc=%d", pc->refcount);
+        fprintf(fp, "\n");
+        if (pc->gmax.nalloc_index > 0)
+        {
+            fprintf(fp, "   Group: ");
+            if (pc->gmax.isize > 20)
+            {
+                fprintf(fp, " %d atoms", pc->gmax.isize);
+            }
+            else
+            {
+                for (j = 0; j < pc->gmax.isize; ++j)
+                {
+                    fprintf(fp, " %d", pc->gmax.index[j] + 1);
+                }
+            }
+            fprintf(fp, "\n");
+        }
+        if (pc->b.nalloc_a > 0)
+        {
+            fprintf(fp, "   Atoms: ");
+            if (pc->b.nra > 20)
+            {
+                fprintf(fp, " %d atoms", pc->b.nra);
+            }
+            else
+            {
+                for (j = 0; j < pc->b.nra; ++j)
+                {
+                    fprintf(fp, " %d", pc->b.a[j] + 1);
+                }
+            }
+            fprintf(fp, "\n");
+        }
+        if (pc->b.nalloc_index > 0)
+        {
+            fprintf(fp, "   Blocks:");
+            if (pc->b.nr > 20)
+            {
+                fprintf(fp, " %d pcs", pc->b.nr);
+            }
+            else
+            {
+                for (j = 0; j <= pc->b.nr; ++j)
+                {
+                    fprintf(fp, " %d", pc->b.index[j]);
+                }
+            }
+            fprintf(fp, "\n");
+        }
+        if (pc->sbase)
+        {
+            gmx_ana_poscalc_t *base;
+
+            fprintf(fp, "   Base: ");
+            j = 1;
+            base = pcc->first;
+            while (base && base != pc->sbase)
+            {
+                ++j;
+                base = base->next;
+            }
+            fprintf(fp, "%d", j);
+            if (pc->baseid && pc->b.nr <= 20)
+            {
+                fprintf(fp, " id:");
+                for (j = 0; j < pc->b.nr; ++j)
+                {
+                    fprintf(fp, " %d", pc->baseid[j]+1);
+                }
+            }
+            fprintf(fp, "\n");
+        }
+        ++i;
+        pc = pc->next;
+    }
+}
+
+/*! \brief
+ * Inserts a position calculation structure into its collection.
+ *
+ * \param pc     Data structure to insert.
+ * \param before Data structure before which to insert
+ *   (NULL = insert at end).
+ *
+ * Inserts \p pc to its collection before \p before.
+ * If \p before is NULL, \p pc is appended to the list.
+ */
+static void
+insert_poscalc(gmx_ana_poscalc_t *pc, gmx_ana_poscalc_t *before)
+{
+    if (before == NULL)
+    {
+        pc->next = NULL;
+        pc->prev = pc->coll->last;
+        if (pc->coll->last)
+        {
+            pc->coll->last->next = pc;
+        }
+        pc->coll->last = pc;
+    }
+    else
+    {
+        pc->prev     = before->prev;
+        pc->next     = before;
+        if (before->prev)
+        {
+            before->prev->next = pc;
+        }
+        before->prev = pc;
+    }
+    if (!pc->prev)
+    {
+        pc->coll->first = pc;
+    }
+}
+
+/*! \brief
+ * Removes a position calculation structure from its collection.
+ *
+ * \param pc    Data structure to remove.
+ *
+ * Removes \p pc from its collection.
+ */
+static void
+remove_poscalc(gmx_ana_poscalc_t *pc)
+{
+    if (pc->prev)
+    {
+        pc->prev->next = pc->next;
+    }
+    else if (pc == pc->coll->first)
+    {
+        pc->coll->first = pc->next;
+    }
+    if (pc->next)
+    {
+        pc->next->prev = pc->prev;
+    }
+    else if (pc == pc->coll->last)
+    {
+        pc->coll->last = pc->prev;
+    }
+    pc->prev = pc->next = NULL;
+}
+
+/*! \brief
+ * Initializes position calculation using the maximum possible input index.
+ *
+ * \param[in,out] pc  Position calculation data structure.
+ * \param[in]     g   Maximum index group for the calculation.
+ * \param[in]     bBase Whether \p pc will be used as a base or not.
+ *
+ * \p bBase affects on how the \p pc->gmax field is initialized.
+ */
+static void
+set_poscalc_maxindex(gmx_ana_poscalc_t *pc, gmx_ana_index_t *g, gmx_bool bBase)
+{
+    gmx_ana_index_make_block(&pc->b, pc->coll->top, g, pc->itype, pc->flags & POS_COMPLWHOLE);
+    /* Set the type to POS_ATOM if the calculation in fact is such. */
+    if (pc->b.nr == pc->b.nra)
+    {
+        pc->type   = POS_ATOM; 
+        pc->flags &= ~(POS_MASS | POS_COMPLMAX | POS_COMPLWHOLE);
+    }
+    /* Set the POS_COMPLWHOLE flag if the calculation in fact always uses
+     * complete residues and molecules. */
+    if (!(pc->flags & POS_COMPLWHOLE)
+        && (!(pc->flags & POS_DYNAMIC) || (pc->flags & POS_COMPLMAX))
+        && (pc->type == POS_RES || pc->type == POS_MOL)
+        && gmx_ana_index_has_complete_elems(g, pc->itype, pc->coll->top))
+    {
+        pc->flags &= ~POS_COMPLMAX;
+        pc->flags |= POS_COMPLWHOLE;
+    }
+    /* Setup the gmax field */
+    if ((pc->flags & POS_COMPLWHOLE) && !bBase && pc->b.nra > g->isize)
+    {
+        gmx_ana_index_copy(&pc->gmax, g, TRUE);
+        sfree(pc->gmax.name);
+        pc->gmax.name  = NULL;
+    }
+    else
+    {
+        gmx_ana_index_set(&pc->gmax, pc->b.nra, pc->b.a, NULL, 0);
+    }
+}
+
+/*! \brief
+ * Checks whether a position calculation should use a base at all.
+ *
+ * \param[in] pc   Position calculation data to check.
+ * \returns   TRUE if \p pc can use a base and gets some benefit out of it,
+ *   FALSE otherwise.
+ */
+static gmx_bool
+can_use_base(gmx_ana_poscalc_t *pc)
+{
+    /* For atoms, it should be faster to do a simple copy, so don't use a
+     * base. */
+    if (pc->type == POS_ATOM)
+    {
+        return FALSE;
+    }
+    /* For dynamic selections that do not use completion, it is not possible
+     * to use a base. */
+    if ((pc->type == POS_RES || pc->type == POS_MOL)
+        && (pc->flags & POS_DYNAMIC) && !(pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
+    {
+        return FALSE;
+    }
+    /* Dynamic calculations for a single position cannot use a base. */
+    if ((pc->type == POS_ALL || pc->type == POS_ALL_PBC)
+        && (pc->flags & POS_DYNAMIC))
+    {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/*! \brief
+ * Checks whether two position calculations should use a common base.
+ *
+ * \param[in]     pc1 Calculation 1 to check for.
+ * \param[in]     pc2 Calculation 2 to check for.
+ * \param[in]     g1  Index group structure that contains the atoms from
+ *   \p pc1.
+ * \param[in,out] g   Working space, should have enough allocated memory to
+ *   contain the intersection of the atoms in \p pc1 and \p pc2.
+ * \returns   TRUE if the two calculations should be merged to use a common
+ *   base, FALSE otherwise.
+ */
+static gmx_bool
+should_merge(gmx_ana_poscalc_t *pc1, gmx_ana_poscalc_t *pc2,
+             gmx_ana_index_t *g1, gmx_ana_index_t *g)
+{
+    gmx_ana_index_t  g2;
+
+    /* Do not merge calculations with different mass weighting. */
+    if ((pc1->flags & POS_MASS) != (pc2->flags & POS_MASS))
+    {
+        return FALSE;
+    }
+    /* Avoid messing up complete calculations. */
+    if ((pc1->flags & POS_COMPLWHOLE) != (pc2->flags & POS_COMPLWHOLE))
+    {
+        return FALSE;
+    }
+    /* Find the overlap between the calculations. */
+    gmx_ana_index_set(&g2, pc2->b.nra, pc2->b.a, NULL, 0);
+    gmx_ana_index_intersection(g, g1, &g2);
+    /* Do not merge if there is no overlap. */
+    if (g->isize == 0)
+    {
+        return FALSE;
+    }
+    /* Full completion calculations always match if the type is correct. */
+    if ((pc1->flags & POS_COMPLWHOLE) && (pc2->flags & POS_COMPLWHOLE)
+        && pc1->type == pc2->type)
+    {
+        return TRUE;
+    }
+    /* The calculations also match if the intersection consists of full
+     * blocks. */
+    if (gmx_ana_index_has_full_ablocks(g, &pc1->b)
+        && gmx_ana_index_has_full_ablocks(g, &pc2->b))
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*! \brief
+ * Creates a static base for position calculation.
+ *
+ * \param     pc  Data structure to copy.
+ * \returns   Pointer to a newly allocated base for \p pc.
+ *
+ * Creates and returns a deep copy of \p pc, but clears the
+ * \ref POS_DYNAMIC and \ref POS_MASKONLY flags.
+ * The newly created structure is set as the base (\c gmx_ana_poscalc_t::sbase)
+ * of \p pc and inserted in the collection before \p pc.
+ */
+static gmx_ana_poscalc_t *
+create_simple_base(gmx_ana_poscalc_t *pc)
+{
+    gmx_ana_poscalc_t *base;
+    int                flags;
+
+    flags = pc->flags & ~(POS_DYNAMIC | POS_MASKONLY);
+    gmx_ana_poscalc_create(&base, pc->coll, pc->type, flags);
+    set_poscalc_maxindex(base, &pc->gmax, TRUE);
+
+    snew(base->p, 1);
+
+    pc->sbase = base;
+    remove_poscalc(base);
+    insert_poscalc(base, pc);
+
+    return base;
+}
+
+/*! \brief
+ * Merges a calculation into another calculation such that the new calculation
+ * can be used as a base.
+ *
+ * \param[in,out] base Base calculation to merge to.
+ * \param[in,out] pc   Position calculation to merge to \p base.
+ *
+ * After the call, \p base can be used as a base for \p pc (or any calculation
+ * that used it as a base).
+ * It is assumed that any overlap between \p base and \p pc is in complete
+ * blocks, i.e., that the merge is possible.
+ */
+static void
+merge_to_base(gmx_ana_poscalc_t *base, gmx_ana_poscalc_t *pc)
+{
+    gmx_ana_index_t  gp, gb, g;
+    int              isize, bnr;
+    int              i, j, bi, bj, bo;
+
+    base->flags |= pc->flags & (POS_VELOCITIES | POS_FORCES);
+    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
+    gmx_ana_index_set(&gb, base->b.nra, base->b.a, NULL, 0);
+    isize = gmx_ana_index_difference_size(&gp, &gb);
+    if (isize > 0)
+    {
+        gmx_ana_index_clear(&g);
+        gmx_ana_index_reserve(&g, base->b.nra + isize);
+        /* Find the new blocks */
+        gmx_ana_index_difference(&g, &gp, &gb);
+        /* Count the blocks in g */
+        i = bi = bnr = 0;
+        while (i < g.isize)
+        {
+            while (pc->b.a[pc->b.index[bi]] != g.index[i])
+            {
+                ++bi;
+            }
+            i += pc->b.index[bi+1] - pc->b.index[bi];
+            ++bnr;
+            ++bi;
+        }
+        /* Merge the atoms into a temporary structure */
+        gmx_ana_index_merge(&g, &gb, &g);
+        /* Merge the blocks */
+        srenew(base->b.index, base->b.nr + bnr + 1);
+        i  = g.isize - 1;
+        bi = base->b.nr - 1;
+        bj = pc->b.nr - 1;
+        bo = base->b.nr + bnr - 1;
+        base->b.index[bo+1] = i + 1;
+        while (bo >= 0)
+        {
+            if (bi < 0 || base->b.a[base->b.index[bi+1]-1] != g.index[i])
+            {
+                i -= pc->b.index[bj+1] - pc->b.index[bj];
+                --bj;
+            }
+            else
+            {
+                if (bj >= 0 && pc->b.a[pc->b.index[bj+1]-1] == g.index[i])
+                {
+                    --bj;
+                }
+                i -= base->b.index[bi+1] - base->b.index[bi];
+                --bi;
+            }
+            base->b.index[bo] = i + 1;
+            --bo;
+        }
+        base->b.nr           += bnr;
+        base->b.nalloc_index += bnr;
+        sfree(base->b.a);
+        base->b.nra      = g.isize;
+        base->b.a        = g.index;
+        base->b.nalloc_a = g.isize;
+        /* Refresh the gmax field */
+        gmx_ana_index_set(&base->gmax, base->b.nra, base->b.a, NULL, 0);
+    }
+}
+
+/*! \brief
+ * Merges two bases into one.
+ *
+ * \param[in,out] tbase Base calculation to merge to.
+ * \param[in]     mbase Base calculation to merge to \p tbase.
+ *
+ * After the call, \p mbase has been freed and \p tbase is used as the base
+ * for all calculations that previously had \p mbase as their base.
+ * It is assumed that any overlap between \p tbase and \p mbase is in complete
+ * blocks, i.e., that the merge is possible.
+ */
+static void
+merge_bases(gmx_ana_poscalc_t *tbase, gmx_ana_poscalc_t *mbase)
+{
+    gmx_ana_poscalc_t *pc;
+
+    merge_to_base(tbase, mbase);
+    remove_poscalc(mbase);
+    /* Set tbase as the base for all calculations that had mbase */
+    pc = tbase->coll->first;
+    while (pc)
+    {
+        if (pc->sbase == mbase)
+        {
+            pc->sbase = tbase;
+            tbase->refcount++;
+        }
+        pc = pc->next;
+    }
+    /* Free mbase */
+    mbase->refcount = 0;
+    gmx_ana_poscalc_free(mbase);
+}
+
+/*! \brief
+ * Setups the static base calculation for a position calculation.
+ *
+ * \param[in,out] pc   Position calculation to setup the base for.
+ */
+static void
+setup_base(gmx_ana_poscalc_t *pc)
+{
+    gmx_ana_poscalc_t *base, *pbase, *next;
+    gmx_ana_index_t    gp, g;
+
+    /* Exit immediately if pc should not have a base. */
+    if (!can_use_base(pc))
+    {
+        return;
+    }
+
+    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
+    gmx_ana_index_clear(&g);
+    gmx_ana_index_reserve(&g, pc->b.nra);
+    pbase = pc;
+    base = pc->coll->first;
+    while (base)
+    {
+        /* Save the next calculation so that we can safely delete base */
+        next = base->next;
+        /* Skip pc, calculations that already have a base (we should match the
+         * base instead), as well as calculations that should not have a base.
+         * If the above conditions are met, check whether we should do a
+         * merge.
+         */
+        if (base != pc && !base->sbase && can_use_base(base)
+            && should_merge(pbase, base, &gp, &g))
+        {
+            /* Check whether this is the first base found */
+            if (pbase == pc)
+            {
+                /* Create a real base if one is not present */
+                if (!base->p)
+                {
+                    pbase = create_simple_base(base);
+                }
+                else
+                {
+                    pbase = base;
+                }
+                /* Make it a base for pc as well */
+                merge_to_base(pbase, pc);
+                pc->sbase = pbase;
+                pbase->refcount++;
+            }
+            else /* This was not the first base */
+            {
+                if (!base->p)
+                {
+                    /* If it is not a real base, just make the new base as
+                     * the base for it as well. */
+                    merge_to_base(pbase, base);
+                    base->sbase = pbase;
+                    pbase->refcount++;
+                }
+                else
+                {
+                    /* If base is a real base, merge it with the new base
+                     * and delete it. */
+                    merge_bases(pbase, base);
+                }
+            }
+            gmx_ana_index_set(&gp, pbase->b.nra, pbase->b.a, NULL, 0);
+            gmx_ana_index_reserve(&g, pc->b.nra);
+        }
+        /* Proceed to the next unchecked calculation */
+        base = next;
+    }
+
+    gmx_ana_index_deinit(&g);
+
+    /* If no base was found, create one if one is required */
+    if (!pc->sbase && (pc->flags & POS_DYNAMIC)
+        && (pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
+    {
+        create_simple_base(pc);
+    }
+}
+
+/*!
+ * \param[out] pcp   Position calculation data structure pointer to initialize.
+ * \param[in,out] pcc   Position calculation collection.
+ * \param[in]  type  Type of calculation.
+ * \param[in]  flags Flags for setting calculation options
+ *   (see \ref poscalc_flags "documentation of the flags").
+ */
+void
+gmx_ana_poscalc_create(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
+                       e_poscalc_t type, int flags)
+{
+    gmx_ana_poscalc_t *pc;
+
+    snew(pc, 1);
+    pc->type     = type;
+    pc->itype    = index_type_for_poscalc(type);
+    gmx_ana_poscalc_set_flags(pc, flags);
+    pc->refcount = 1;
+    pc->coll     = pcc;
+    insert_poscalc(pc, NULL);
+    *pcp = pc;
+}
+
+/*!
+ * \param[out] pcp   Position calculation data structure pointer to initialize.
+ * \param[in,out] pcc   Position calculation collection.
+ * \param[in]  post  One of the strings acceptable for
+ *   gmx_ana_poscalc_type_from_enum().
+ * \param[in]  flags Flags for setting calculation options
+ *   (see \ref poscalc_flags "documentation of the flags").
+ * \returns    0 on success, a non-zero error value on error.
+ *
+ * This is a convenience wrapper for gmx_ana_poscalc_create().
+ * \p flags sets the default calculation options if not overridden by \p post;
+ * see gmx_ana_poscalc_type_from_enum().
+ *
+ * \see gmx_ana_poscalc_create(), gmx_ana_poscalc_type_from_enum()
+ */
+void
+gmx_ana_poscalc_create_enum(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
+                            const char *post, int flags)
+{
+    e_poscalc_t  type;
+    int          cflags;
+    int          rc;
+
+    cflags = flags;
+    *pcp = NULL;
+    gmx_ana_poscalc_type_from_enum(post, &type, &cflags);
+    gmx_ana_poscalc_create(pcp, pcc, type, cflags);
+}
+
+/*!
+ * \param[in,out] pc    Position calculation data structure.
+ * \param[in]     flags New flags.
+ *
+ * \p flags are added to the old flags.
+ * If calculation type is \ref POS_ATOM, \ref POS_MASS is automatically
+ * cleared.
+ * If both \ref POS_DYNAMIC and \ref POS_MASKONLY are provided,
+ * \ref POS_DYNAMIC is cleared.
+ * If calculation type is not \ref POS_RES or \ref POS_MOL,
+ * \ref POS_COMPLMAX and \ref POS_COMPLWHOLE are automatically cleared.
+ */
+void
+gmx_ana_poscalc_set_flags(gmx_ana_poscalc_t *pc, int flags)
+{
+    if (pc->type == POS_ATOM)
+    {
+        flags &= ~POS_MASS;
+    }
+    if (flags & POS_MASKONLY)
+    {
+        flags &= ~POS_DYNAMIC;
+    }
+    if (pc->type != POS_RES && pc->type != POS_MOL)
+    {
+        flags &= ~(POS_COMPLMAX | POS_COMPLWHOLE);
+    }
+    pc->flags |= flags;
+}
+
+/*!
+ * \param[in,out] pc  Position calculation data structure.
+ * \param[in]     g   Maximum index group for the calculation.
+ *
+ * Subsequent calls to gmx_ana_poscalc_update() should use only subsets of
+ * \p g for evaluation.
+ *
+ * The topology should have been set for the collection of which \p pc is
+ * a member.
+ */
+void
+gmx_ana_poscalc_set_maxindex(gmx_ana_poscalc_t *pc, gmx_ana_index_t *g)
+{
+    set_poscalc_maxindex(pc, g, FALSE);
+    setup_base(pc);
+}
+
+/*!
+ * \param[in]  pc  Position calculation data structure.
+ * \param[out] p   Output positions.
+ *
+ * Calls to gmx_ana_poscalc_update() using \p pc should use only positions
+ * initialized with this function.
+ * The \c p->g pointer is initialized to point to an internal group that
+ * contains the maximum index group set with gmx_ana_poscalc_set_maxindex().
+ */
+void
+gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p)
+{
+    gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, pc->itype);
+    /* Only do the static optimization when there is no completion */
+    if (!(pc->flags & POS_DYNAMIC) && pc->b.nra == pc->gmax.isize)
+    {
+        gmx_ana_indexmap_set_static(&p->m, &pc->b);
+    }
+    gmx_ana_pos_reserve(p, p->m.nr, 0);
+    if (pc->flags & POS_VELOCITIES)
+    {
+        gmx_ana_pos_reserve_velocities(p);
+    }
+    if (pc->flags & POS_FORCES)
+    {
+        gmx_ana_pos_reserve_forces(p);
+    }
+    gmx_ana_pos_set_nr(p, p->m.nr);
+    gmx_ana_pos_set_evalgrp(p, &pc->gmax);
+}
+
+/*!
+ * \param  pc  Position calculation data to be freed.
+ *
+ * The \p pc pointer is invalid after the call.
+ */
+void
+gmx_ana_poscalc_free(gmx_ana_poscalc_t *pc)
+{
+    if (!pc)
+    {
+        return;
+    }
+
+    pc->refcount--;
+    if (pc->refcount > 0)
+    {
+        return;
+    }
+
+    remove_poscalc(pc);
+    if (pc->b.nalloc_index > 0)
+    {
+        sfree(pc->b.index);
+    }
+    if (pc->b.nalloc_a > 0)
+    {
+        sfree(pc->b.a);
+    }
+    if (pc->flags & POS_COMPLWHOLE)
+    {
+        gmx_ana_index_deinit(&pc->gmax);
+    }
+    if (pc->p)
+    {
+        gmx_ana_pos_free(pc->p);
+    }
+    if (pc->sbase)
+    {
+        gmx_ana_poscalc_free(pc->sbase);
+        sfree(pc->baseid);
+    }
+    sfree(pc);
+}
+
+/*!
+ * \param[in] pc  Position calculation data to query.
+ * \returns   TRUE if \p pc requires topology for initialization and/or
+ *   evaluation, FALSE otherwise.
+ */
+gmx_bool
+gmx_ana_poscalc_requires_top(gmx_ana_poscalc_t *pc)
+{
+    if ((pc->flags & POS_MASS) || pc->type == POS_RES || pc->type == POS_MOL)
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*!
+ * \param[in,out] pcc Position calculation collection to initialize.
+ *
+ * This function does some final initialization of the data structures in the
+ * collection to prepare them for evaluation.
+ * After this function has been called, it is no longer possible to add new
+ * calculations to the collection.
+ *
+ * This function is automatically called by gmx_ana_poscalc_init_frame() 
+ * if not called by the user earlier.
+ * Multiple calls to the function are ignored.
+ */
+void
+gmx_ana_poscalc_init_eval(gmx_ana_poscalc_coll_t *pcc)
+{
+    gmx_ana_poscalc_t      *pc;
+    int                     bi, bj;
+
+    if (pcc->bInit)
+    {
+        return;
+    }
+    pc = pcc->first;
+    while (pc)
+    {
+        /* Initialize position storage for base calculations */
+        if (pc->p)
+        {
+            gmx_ana_poscalc_init_pos(pc, pc->p);
+        }
+        /* Construct the mapping of the base positions */
+        if (pc->sbase)
+        {
+            snew(pc->baseid, pc->b.nr);
+            for (bi = bj = 0; bi < pc->b.nr; ++bi, ++bj)
+            {
+                while (pc->sbase->b.a[pc->sbase->b.index[bj]] != pc->b.a[pc->b.index[bi]])
+                {
+                    ++bj;
+                }
+                pc->baseid[bi] = bj;
+            }
+        }
+        /* Free the block data for dynamic calculations */
+        if (pc->flags & POS_DYNAMIC)
+        {
+            if (pc->b.nalloc_index > 0)
+            {
+                sfree(pc->b.index);
+                pc->b.nalloc_index = 0;
+            }
+            if (pc->b.nalloc_a > 0)
+            {
+                sfree(pc->b.a);
+                pc->b.nalloc_a = 0;
+            }
+        }
+        pc = pc->next;
+    }
+    pcc->bInit = TRUE;
+}
+
+/*!
+ * \param[in,out] pcc Position calculation collection to initialize.
+ *
+ * Clears the evaluation flag for all calculations.
+ * Should be called for each frame before calling gmx_ana_poscalc_update().
+ *
+ * This function is automatically called by gmx_ana_do() for each
+ * frame, and should not be called by the user unless gmx_ana_do() is
+ * not being used.
+ *
+ * This function calls gmx_ana_poscalc_init_eval() automatically if it has
+ * not been called earlier.
+ */
+void
+gmx_ana_poscalc_init_frame(gmx_ana_poscalc_coll_t *pcc)
+{
+    gmx_ana_poscalc_t      *pc;
+
+    if (!pcc->bInit)
+    {
+        gmx_ana_poscalc_init_eval(pcc);
+    }
+    /* Clear the evaluation flags */
+    pc = pcc->first;
+    while (pc)
+    {
+        pc->bEval = FALSE;
+        pc = pc->next;
+    }
+}
+
+/*!
+ * \param[in]     pc   Position calculation data.
+ * \param[in,out] p    Output positions, initialized previously with
+ *   gmx_ana_poscalc_init_pos() using \p pc.
+ * \param[in]     g    Index group to use for the update.
+ * \param[in]     fr   Current frame.
+ * \param[in]     pbc  PBC data, or NULL if no PBC should be used.
+ *
+ * gmx_ana_poscalc_init_frame() should be called for each frame before calling
+ * this function.
+ */
+void
+gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p,
+                       gmx_ana_index_t *g, t_trxframe *fr, t_pbc *pbc)
+{
+    int  i, j, bi, bj;
+    
+    if (pc->bEval == TRUE && !(pc->flags & POS_MASKONLY))
+    {
+        return;
+    }
+    if (pc->sbase)
+    {
+        gmx_ana_poscalc_update(pc->sbase, NULL, NULL, fr, pbc);
+    }
+    if (!p)
+    {
+        p = pc->p;
+    }
+    if (!g)
+    {
+        g = &pc->gmax;
+    }
+    gmx_ana_pos_set_evalgrp(p, g);
+
+    /* Update the index map */
+    if (pc->flags & POS_DYNAMIC)
+    {
+        gmx_ana_indexmap_update(&p->m, g, FALSE);
+        p->nr = p->m.nr;
+    }
+    else if (pc->flags & POS_MASKONLY)
+    {
+        gmx_ana_indexmap_update(&p->m, g, TRUE);
+        if (pc->bEval)
+            return;
+    }
+    if (!(pc->flags & POS_DYNAMIC))
+    {
+        pc->bEval = TRUE;
+    }
+
+    /* Evaluate the positions */
+    if (pc->sbase)
+    {
+        /* TODO: It might be faster to evaluate the positions within this
+         * loop instead of in the beginning. */
+        if (pc->flags & POS_DYNAMIC)
+        {
+            for (bi = 0; bi < p->nr; ++bi)
+            {
+                bj = pc->baseid[p->m.refid[bi]];
+                copy_rvec(pc->sbase->p->x[bj], p->x[bi]);
+            }
+            if (p->v)
+            {
+                for (bi = 0; bi < p->nr; ++bi)
+                {
+                    bj = pc->baseid[p->m.refid[bi]];
+                    copy_rvec(pc->sbase->p->v[bj], p->v[bi]);
+                }
+            }
+            if (p->f)
+            {
+                for (bi = 0; bi < p->nr; ++bi)
+                {
+                    bj = pc->baseid[p->m.refid[bi]];
+                    copy_rvec(pc->sbase->p->f[bj], p->f[bi]);
+                }
+            }
+        }
+        else
+        {
+            for (bi = 0; bi < p->nr; ++bi)
+            {
+                bj = pc->baseid[bi];
+                copy_rvec(pc->sbase->p->x[bj], p->x[bi]);
+            }
+            if (p->v)
+            {
+                for (bi = 0; bi < p->nr; ++bi)
+                {
+                    bj = pc->baseid[bi];
+                    copy_rvec(pc->sbase->p->v[bj], p->v[bi]);
+                }
+            }
+            if (p->f)
+            {
+                for (bi = 0; bi < p->nr; ++bi)
+                {
+                    bj = pc->baseid[bi];
+                    copy_rvec(pc->sbase->p->f[bj], p->f[bi]);
+                }
+            }
+        }
+    }
+    else /* pc->sbase is NULL */
+    {
+        if (pc->flags & POS_DYNAMIC)
+        {
+            pc->b.nr    = p->m.mapb.nr;
+            pc->b.index = p->m.mapb.index;
+            pc->b.nra   = g->isize;
+            pc->b.a     = g->index;
+        }
+        if (p->v && !fr->bV)
+        {
+            for (i = 0; i < pc->b.nra; ++i)
+            {
+                clear_rvec(p->v[i]);
+            }
+        }
+        if (p->f && !fr->bF)
+        {
+            for (i = 0; i < pc->b.nra; ++i)
+            {
+                clear_rvec(p->f[i]);
+            }
+        }
+        /* Here, we assume that the topology has been properly initialized,
+         * and do not check the return values of gmx_calc_comg*(). */
+        switch (pc->type)
+        {
+        case POS_ATOM:
+            for (i = 0; i < pc->b.nra; ++i)
+            {
+                copy_rvec(fr->x[pc->b.a[i]], p->x[i]);
+            }
+            if (p->v && fr->bV)
+            {
+                for (i = 0; i < pc->b.nra; ++i)
+                {
+                    copy_rvec(fr->v[pc->b.a[i]], p->v[i]);
+                }
+            }
+            if (p->f && fr->bF)
+            {
+                for (i = 0; i < pc->b.nra; ++i)
+                {
+                    copy_rvec(fr->f[pc->b.a[i]], p->f[i]);
+                }
+            }
+            break;
+        case POS_ALL:
+            gmx_calc_comg(pc->coll->top, fr->x, pc->b.nra, pc->b.a,
+                          pc->flags & POS_MASS, p->x[0]);
+            if (p->v && fr->bV)
+            {
+                gmx_calc_comg(pc->coll->top, fr->v, pc->b.nra, pc->b.a,
+                              pc->flags & POS_MASS, p->v[0]);
+            }
+            if (p->f && fr->bF)
+            {
+                gmx_calc_comg_f(pc->coll->top, fr->f, pc->b.nra, pc->b.a,
+                                pc->flags & POS_MASS, p->f[0]);
+            }
+            break;
+        case POS_ALL_PBC:
+            gmx_calc_comg_pbc(pc->coll->top, fr->x, pbc, pc->b.nra, pc->b.a,
+                              pc->flags & POS_MASS, p->x[0]);
+            if (p->v && fr->bV)
+            {
+                gmx_calc_comg(pc->coll->top, fr->v, pc->b.nra, pc->b.a,
+                              pc->flags & POS_MASS, p->v[0]);
+            }
+            if (p->f && fr->bF)
+            {
+                gmx_calc_comg_f(pc->coll->top, fr->f, pc->b.nra, pc->b.a,
+                                pc->flags & POS_MASS, p->f[0]);
+            }
+            break;
+        default:
+            gmx_calc_comg_blocka(pc->coll->top, fr->x, &pc->b,
+                                 pc->flags & POS_MASS, p->x);
+            if (p->v && fr->bV)
+            {
+                gmx_calc_comg_blocka(pc->coll->top, fr->v, &pc->b,
+                                     pc->flags & POS_MASS, p->v);
+            }
+            if (p->f && fr->bF)
+            {
+                gmx_calc_comg_blocka(pc->coll->top, fr->f, &pc->b,
+                                     pc->flags & POS_MASS, p->f);
+            }
+            break;
+        }
+    }
+}
diff --git a/src/gromacs/selection/poscalc.h b/src/gromacs/selection/poscalc.h
new file mode 100644 (file)
index 0000000..d57d3cb
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief API for structured and optimized calculation of positions.
+ *
+ * The functions in this header are used internally by the analysis library
+ * to calculate positions.
+ * They can also be used in user code, but in most cases there should be no
+ * need. Instead, one should write an analysis tool such that it gets all
+ * positions through selections.
+ *
+ * The API is documented in more detail on a separate page:
+ * \ref poscalcengine.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_POSCALC_H
+#define GMX_SELECTION_POSCALC_H
+
+#include "../legacyheaders/typedefs.h"
+
+/*! \name Flags for position calculation.
+ * \anchor poscalc_flags
+ */
+/*@{*/
+/*! \brief
+ * Use mass weighting.
+ *
+ * If this flag is set, the positions will be calculated using mass weighting,
+ * i.e., one gets center-of-mass positions.
+ * Without the flag, center-of-geometry positions are calculated.
+ * Does not have any effect if the calculation type is \ref POS_ATOM.
+ */
+#define POS_MASS        1
+/*! \brief
+ * Calculate positions for the same atoms in residues/molecules.
+ *
+ * If this flag is set, the positions are always calculated using the same
+ * atoms for each residue/molecule, even if the evaluation group contains only
+ * some of the atoms for some frames.
+ * The group passed to gmx_ana_poscalc_set_maxindex() is used to determine
+ * the atoms to use for the calculation.
+ *
+ * Has no effect unless \ref POS_DYNAMIC is set or if the calculation type
+ * is not \ref POS_RES of \ref POS_MOL.
+ */
+#define POS_COMPLMAX    2
+/*! \brief
+ * Calculate positions for whole residues/molecules.
+ *
+ * If this flag is set, the positions will be calculated for whole
+ * residues/molecules, even if the group contains only some of the atoms in
+ * the residue/molecule.
+ *
+ * Has no effect unless the calculation type is \ref POS_RES or \ref POS_MOL.
+ */
+#define POS_COMPLWHOLE  4
+/*! \brief
+ * Enable handling of changing calculation groups.
+ *
+ * Can be used for static calculations as well, but implies a small
+ * performance penalty.
+ */
+#define POS_DYNAMIC     16
+/*! \brief
+ * Update \c gmx_ana_pos_t::m dynamically for an otherwise static
+ * calculation.
+ *
+ * Has effect only if \ref POS_DYNAMIC is not set.
+ */
+#define POS_MASKONLY    32
+/*! \brief
+ * Calculate velocities of the positions.
+ */
+#define POS_VELOCITIES  64
+/*! \brief
+ * Calculate forces on the positions.
+ */
+#define POS_FORCES      128
+/*@}*/
+
+/** Specifies the type of positions to be calculated. */
+typedef enum
+{
+    POS_ATOM,    /**< Copy atomic coordinates. */
+    POS_RES,     /**< Calculate center for each residue. */
+    POS_MOL,     /**< Calculate center for each molecule. */
+    POS_ALL,     /**< Calculate center for the whole group. */
+    POS_ALL_PBC  /**< Calculate center for the whole group with PBC. */
+} e_poscalc_t;
+
+/** Collection of \c gmx_ana_poscalc_t structures for the same topology. */
+typedef struct gmx_ana_poscalc_coll_t gmx_ana_poscalc_coll_t;
+/** Data structure for position calculation. */
+typedef struct gmx_ana_poscalc_t gmx_ana_poscalc_t;
+
+struct gmx_ana_index_t;
+struct gmx_ana_pos_t;
+
+/** Converts a string to parameters for gmx_ana_poscalc_create(). */
+void
+gmx_ana_poscalc_type_from_enum(const char *post, e_poscalc_t *type, int *flags);
+/** Creates a list of strings for position enum parameter handling. */
+const char **
+gmx_ana_poscalc_create_type_enum(gmx_bool bAtom);
+
+/** Creates a new position calculation collection object. */
+int
+gmx_ana_poscalc_coll_create(gmx_ana_poscalc_coll_t **pccp);
+/** Sets the topology for a position calculation collection. */
+void
+gmx_ana_poscalc_coll_set_topology(gmx_ana_poscalc_coll_t *pcc, t_topology *top);
+/** Frees memory allocated for a position calculation collection. */
+void
+gmx_ana_poscalc_coll_free(gmx_ana_poscalc_coll_t *pcc);
+/** Prints information about calculations in a position calculation collection. */
+void
+gmx_ana_poscalc_coll_print_tree(FILE *fp, gmx_ana_poscalc_coll_t *pcc);
+
+/** Creates a new position calculation. */
+void
+gmx_ana_poscalc_create(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
+                       e_poscalc_t type, int flags);
+/** Creates a new position calculation based on an enum value. */
+void
+gmx_ana_poscalc_create_enum(gmx_ana_poscalc_t **pcp, gmx_ana_poscalc_coll_t *pcc,
+                            const char *post, int flags);
+/** Sets the flags for position calculation. */
+void
+gmx_ana_poscalc_set_flags(gmx_ana_poscalc_t *pc, int flags);
+/** Sets the maximum possible input index group for position calculation. */
+void
+gmx_ana_poscalc_set_maxindex(gmx_ana_poscalc_t *pc, struct gmx_ana_index_t *g);
+/** Initializes positions for position calculation output. */
+void
+gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, struct gmx_ana_pos_t *p);
+/** Frees the memory allocated for position calculation. */
+void
+gmx_ana_poscalc_free(gmx_ana_poscalc_t *pc);
+/** Returns TRUE if the position calculation requires topology information. */
+gmx_bool
+gmx_ana_poscalc_requires_top(gmx_ana_poscalc_t *pc);
+
+/** Initializes evaluation for a position calculation collection. */
+void
+gmx_ana_poscalc_init_eval(gmx_ana_poscalc_coll_t *pcc);
+/** Initializes a position calculation collection for a new frame. */
+void
+gmx_ana_poscalc_init_frame(gmx_ana_poscalc_coll_t *pcc);
+/** Updates a single COM/COG structure for a frame. */
+void
+gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc,
+                       struct gmx_ana_pos_t *p, struct gmx_ana_index_t *g,
+                       t_trxframe *fr, t_pbc *pbc);
+
+#endif
diff --git a/src/gromacs/selection/position.cpp b/src/gromacs/selection/position.cpp
new file mode 100644 (file)
index 0000000..f7dabf2
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in position.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#include <smalloc.h>
+#include <typedefs.h>
+#include <vec.h>
+
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/position.h"
+
+/*!
+ * \param[out] pos      Output structure.
+ *
+ * Any contents of \p pos are discarded without freeing.
+ */
+void
+gmx_ana_pos_clear(gmx_ana_pos_t *pos)
+{
+    pos->nr = 0;
+    pos->x  = NULL;
+    pos->v  = NULL;
+    pos->f  = NULL;
+    gmx_ana_indexmap_clear(&pos->m);
+    pos->g  = NULL;
+    pos->nalloc_x = 0;
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ * \param[in]     n     Maximum number of positions.
+ * \param[in]     isize Maximum number of atoms.
+ *
+ * Ensures that enough memory is allocated in \p pos to calculate \p n
+ * positions from \p isize atoms.
+ */
+void
+gmx_ana_pos_reserve(gmx_ana_pos_t *pos, int n, int isize)
+{
+    if (pos->nalloc_x < n)
+    {
+        pos->nalloc_x = n;
+        srenew(pos->x, n);
+        if (pos->v)
+        {
+            srenew(pos->v, n);
+        }
+        if (pos->f)
+        {
+            srenew(pos->f, n);
+        }
+    }
+    if (isize > 0)
+    {
+        gmx_ana_indexmap_reserve(&pos->m, n, isize);
+    }
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Currently, this function can only be called after gmx_ana_pos_reserve()
+ * has been called at least once with a \p n > 0.
+ */
+void
+gmx_ana_pos_reserve_velocities(gmx_ana_pos_t *pos)
+{
+    assert(pos->nalloc_x > 0);
+    if (!pos->v)
+    {
+        snew(pos->v, pos->nalloc_x);
+    }
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Currently, this function can only be called after gmx_ana_pos_reserve()
+ * has been called at least once with a \p n > 0.
+ */
+void
+gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos)
+{
+    assert(pos->nalloc_x > 0);
+    if (!pos->f)
+    {
+        snew(pos->f, pos->nalloc_x);
+    }
+}
+
+/*!
+ * \param[out]    pos  Position data structure to initialize.
+ * \param[in]     x    Position vector to use.
+ */
+void
+gmx_ana_pos_init_const(gmx_ana_pos_t *pos, rvec x)
+{
+    gmx_ana_pos_clear(pos);
+    pos->nr = 1;
+    snew(pos->x, 1);
+    snew(pos->v, 1);
+    snew(pos->f, 1);
+    pos->nalloc_x = 1;
+    copy_rvec(x, pos->x[0]);
+    clear_rvec(pos->v[0]);
+    clear_rvec(pos->f[0]);
+    gmx_ana_indexmap_init(&pos->m, NULL, NULL, INDEX_UNKNOWN);
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Frees any memory allocated within \p pos.
+ * The pointer \p pos itself is not freed.
+ *
+ * \see gmx_ana_pos_free()
+ */
+void
+gmx_ana_pos_deinit(gmx_ana_pos_t *pos)
+{
+    pos->nr = 0;
+    sfree(pos->x); pos->x = NULL;
+    sfree(pos->v); pos->v = NULL;
+    sfree(pos->f); pos->f = NULL;
+    pos->nalloc_x = 0;
+    gmx_ana_indexmap_deinit(&pos->m);
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Frees any memory allocated for \p pos.
+ * The pointer \p pos is also freed, and is invalid after the call.
+ *
+ * \see gmx_ana_pos_deinit()
+ */
+void
+gmx_ana_pos_free(gmx_ana_pos_t *pos)
+{
+    gmx_ana_pos_deinit(pos);
+    sfree(pos);
+}
+
+/*!
+ * \param[in,out] dest   Destination positions.
+ * \param[in]     src    Source positions.
+ * \param[in]     bFirst If TRUE, memory is allocated for \p dest and a full
+ *   copy is made; otherwise, only variable parts are copied, and no memory
+ *   is allocated.
+ *
+ * \p dest should have been initialized somehow (calloc() is enough).
+ */
+void
+gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, gmx_bool bFirst)
+{
+    if (bFirst)
+    {
+        gmx_ana_pos_reserve(dest, src->nr, 0);
+        if (src->v)
+        {
+            gmx_ana_pos_reserve_velocities(dest);
+        }
+        if (src->f)
+        {
+            gmx_ana_pos_reserve_forces(dest);
+        }
+    }
+    dest->nr = src->nr;
+    memcpy(dest->x, src->x, dest->nr*sizeof(*dest->x));
+    if (dest->v)
+    {
+        memcpy(dest->v, src->v, dest->nr*sizeof(*dest->v));
+    }
+    if (dest->f)
+    {
+        memcpy(dest->f, src->f, dest->nr*sizeof(*dest->f));
+    }
+    gmx_ana_indexmap_copy(&dest->m, &src->m, bFirst);
+    dest->g = src->g;
+}
+
+/*!
+ * \param[in,out] pos  Position data structure.
+ * \param[in]     nr   Number of positions.
+ */
+void
+gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int nr)
+{
+    pos->nr = nr;
+}
+
+/*!
+ * \param[in,out] pos  Position data structure.
+ * \param         g    Evaluation group.
+ *
+ * The old group, if any, is discarded.
+ * Note that only a pointer to \p g is stored; it is the responsibility of
+ * the caller to ensure that \p g is not freed while it can be accessed
+ * through \p pos.
+ */
+void
+gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g)
+{
+    pos->g = g;
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Sets the number of positions to 0.
+ */
+void
+gmx_ana_pos_empty_init(gmx_ana_pos_t *pos)
+{
+    pos->nr = 0;
+    pos->m.nr = 0;
+    pos->m.mapb.nr = 0;
+    pos->m.b.nr = 0;
+    pos->m.b.nra = 0;
+    /* This should not really be necessary, but do it for safety... */
+    pos->m.mapb.index[0] = 0;
+    pos->m.b.index[0] = 0;
+    /* This function should only be used to construct all the possible
+     * positions, so the result should always be static. */
+    pos->m.bStatic = TRUE;
+    pos->m.bMapStatic = TRUE;
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * Sets the number of positions to 0.
+ */
+void
+gmx_ana_pos_empty(gmx_ana_pos_t *pos)
+{
+    pos->nr = 0;
+    pos->m.nr = 0;
+    pos->m.mapb.nr = 0;
+    /* This should not really be necessary, but do it for safety... */
+    pos->m.mapb.index[0] = 0;
+    /* We set the flags to TRUE, although really in the empty state they
+     * should be FALSE. This makes it possible to update the flags in
+     * gmx_ana_pos_append(), and just make a simple check in
+     * gmx_ana_pos_append_finish(). */
+    pos->m.bStatic = TRUE;
+    pos->m.bMapStatic = TRUE;
+}
+
+/*!
+ * \param[in,out] dest  Data structure to which the new position is appended.
+ * \param[in,out] g     Data structure to which the new atoms are appended.
+ * \param[in]     src   Data structure from which the position is copied.
+ * \param[in]     i     Index in \p from to copy.
+ */
+void
+gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
+                        gmx_ana_pos_t *src, int i)
+{
+    int  j, k;
+
+    j = dest->nr;
+    copy_rvec(src->x[i], dest->x[j]);
+    if (dest->v)
+    {
+        if (src->v)
+        {
+            copy_rvec(src->v[i], dest->v[j]);
+        }
+        else
+        {
+            clear_rvec(dest->v[j]);
+        }
+    }
+    if (dest->f)
+    {
+        if (src->f)
+        {
+            copy_rvec(src->f[i], dest->f[j]);
+        }
+        else
+        {
+            clear_rvec(dest->f[j]);
+        }
+    }
+    dest->m.refid[j] = j;
+    dest->m.mapid[j] = src->m.mapid[i];
+    dest->m.orgid[j] = src->m.orgid[i];
+    for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
+    {
+        g->index[g->isize++]         = src->g->index[k];
+        dest->m.b.a[dest->m.b.nra++] = src->m.b.a[k];
+    }
+    dest->m.mapb.index[j+1] = g->isize;
+    dest->m.b.index[j+1]    = g->isize;
+    dest->nr++;
+    dest->m.nr = dest->nr;
+    dest->m.mapb.nr = dest->nr;
+    dest->m.b.nr = dest->nr;
+}
+
+/*!
+ * \param[in,out] dest  Data structure to which the new position is appended
+ *      (can be NULL, in which case only \p g is updated).
+ * \param[in,out] g     Data structure to which the new atoms are appended.
+ * \param[in]     src   Data structure from which the position is copied.
+ * \param[in]     i     Index in \p src to copy.
+ * \param[in]     refid Reference ID in \p out
+ *   (all negative values are treated as -1).
+ *
+ * If \p dest is NULL, the value of \p refid is not used.
+ */
+void
+gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
+                   gmx_ana_pos_t *src, int i, int refid)
+{
+    int  j, k;
+
+    for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
+    {
+        g->index[g->isize++] = src->g->index[k];
+    }
+    if (dest)
+    {
+        j = dest->nr;
+        if (dest->v)
+        {
+            if (src->v)
+            {
+                copy_rvec(src->v[i], dest->v[j]);
+            }
+            else
+            {
+                clear_rvec(dest->v[j]);
+            }
+        }
+        if (dest->f)
+        {
+            if (src->f)
+            {
+                copy_rvec(src->f[i], dest->f[j]);
+            }
+            else
+            {
+                clear_rvec(dest->f[j]);
+            }
+        }
+        copy_rvec(src->x[i], dest->x[j]);
+        if (refid < 0)
+        {
+            dest->m.refid[j] = -1;
+            dest->m.bStatic = FALSE;
+            /* If we are using masks, there is no need to alter the
+             * mapid field. */
+        }
+        else
+        {
+            if (refid != j)
+            {
+                dest->m.bStatic = FALSE;
+                dest->m.bMapStatic = FALSE;
+            }
+            dest->m.refid[j] = refid;
+            /* Use the original IDs from the output structure to correctly
+             * handle user customization. */
+            dest->m.mapid[j] = dest->m.orgid[refid];
+        }
+        dest->m.mapb.index[j+1] = g->isize;
+        dest->nr++;
+        dest->m.nr = dest->nr;
+        dest->m.mapb.nr = dest->nr;
+    }
+}
+
+/*!
+ * \param[in,out] pos   Position data structure.
+ *
+ * After gmx_ana_pos_empty(), internal state of the position data structure
+ * is not consistent before this function is called. This function should be
+ * called after any gmx_ana_pos_append() calls have been made.
+ */
+void
+gmx_ana_pos_append_finish(gmx_ana_pos_t *pos)
+{
+    if (pos->m.nr != pos->m.b.nr)
+    {
+        pos->m.bStatic = FALSE;
+        pos->m.bMapStatic = FALSE;
+    }
+}
diff --git a/src/gromacs/selection/position.h b/src/gromacs/selection/position.h
new file mode 100644 (file)
index 0000000..8b5adca
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief API for handling positions.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_POSITION_H
+#define GMX_SELECTION_POSITION_H
+
+#include "../legacyheaders/types/simple.h"
+
+#include "indexutil.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief
+ * Stores a set of positions together with their origins.
+ */
+typedef struct gmx_ana_pos_t
+{
+    /*! \brief
+     * Number of positions.
+     */
+    int                 nr;
+    /*! \brief
+     * Array of positions.
+     */
+    rvec               *x;
+    /*! \brief
+     * Velocities (can be NULL).
+     */
+    rvec               *v;
+    /*! \brief
+     * Forces (can be NULL).
+     */
+    rvec               *f;
+    /*! \brief
+     * Mapping of the current positions to the original group.
+     *
+     * \see gmx_ana_indexmap_t
+     */
+    gmx_ana_indexmap_t  m;
+    /*! \brief
+     * Pointer to the current evaluation group.
+     */
+    gmx_ana_index_t    *g;
+    /*! \brief
+     * Number of elements allocated for \c x.
+     */
+    int                 nalloc_x;
+} gmx_ana_pos_t;
+
+/** Initializes an empty position structure. */
+void
+gmx_ana_pos_clear(gmx_ana_pos_t *pos);
+/** Ensures that enough memory has been allocated to store positions. */
+void
+gmx_ana_pos_reserve(gmx_ana_pos_t *pos, int n, int isize);
+/** Request memory allocation for velocities. */
+void
+gmx_ana_pos_reserve_velocities(gmx_ana_pos_t *pos);
+/** Request memory allocation for forces. */
+void
+gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos);
+/** Initializes a \c gmx_ana_pos_t to represent a constant position. */
+void
+gmx_ana_pos_init_const(gmx_ana_pos_t *pos, rvec x);
+/** Frees the memory allocated for position storage. */
+void
+gmx_ana_pos_deinit(gmx_ana_pos_t *pos);
+/** Frees the memory allocated for positions. */
+void
+gmx_ana_pos_free(gmx_ana_pos_t *pos);
+/** Copies the evaluated positions to a preallocated data structure. */
+void
+gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, gmx_bool bFirst);
+
+/** Sets the number of positions in a position structure. */
+void
+gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int n);
+/** Sets the evaluation group of a position data structure. */
+void
+gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g);
+/** Empties a position data structure with full initialization. */
+void
+gmx_ana_pos_empty_init(gmx_ana_pos_t *pos);
+/** Empties a position data structure. */
+void
+gmx_ana_pos_empty(gmx_ana_pos_t *pos);
+/** Appends a position to a preallocated data structure with full
+ * initialization. */
+void
+gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
+                        gmx_ana_pos_t *src, int i);
+/** Appends a position to a preallocated data structure. */
+void
+gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
+                   gmx_ana_pos_t *src, int i, int refid);
+/** Updates position data structure state after appends. */
+void
+gmx_ana_pos_append_finish(gmx_ana_pos_t *pos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/selection/regenerate_parser.sh b/src/gromacs/selection/regenerate_parser.sh
new file mode 100755 (executable)
index 0000000..e8af512
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# This script runs Bison and/or Flex to regenerate the files as follows:
+#   parser.y  -> parser.c, parser.h
+#   scanner.l -> scanner.c, scanner_flex.h
+# The commands are run only if the generated files are older than the
+# Bison/Flex input files, or if a '-f' flag is provided.
+
+FORCE=
+if [ "x$1" == "x-f" ] ; then
+    FORCE=1
+fi
+
+# For convenience, change to the directory where the files are located
+# if the script is run from the root of the source tree.
+dirname=src/gromacs/selection
+if [[ -f $dirname/parser.y && -f $dirname/scanner.l ]] ; then
+    cd $dirname
+fi
+
+[[ $FORCE || parser.y  -nt parser.cpp ]]  && bison -t -o parser.cpp --defines=parser.h parser.y
+[[ $FORCE || scanner.l -nt scanner.cpp ]] && flex -o scanner.cpp scanner.l
diff --git a/src/gromacs/selection/scanner.cpp b/src/gromacs/selection/scanner.cpp
new file mode 100644 (file)
index 0000000..8f1c439
--- /dev/null
@@ -0,0 +1,2220 @@
+#line 2 "scanner.cpp"
+
+#line 4 "scanner.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE _gmx_sel_yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = yyg->yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via _gmx_sel_yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void _gmx_sel_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void _gmx_sel_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner );
+
+static void _gmx_sel_yyensure_buffer_stack (yyscan_t yyscanner );
+static void _gmx_sel_yy_load_buffer_state (yyscan_t yyscanner );
+static void _gmx_sel_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER _gmx_sel_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE _gmx_sel_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *_gmx_sel_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *_gmx_sel_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void _gmx_sel_yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer _gmx_sel_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        _gmx_sel_yyensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        _gmx_sel_yyensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+#define _gmx_sel_yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yyg->yytext_ptr = yy_bp; \
+       yyleng = (size_t) (yy_cp - yy_bp); \
+       yyg->yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 26
+#define YY_END_OF_BUFFER 27
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static yyconst flex_int16_t yy_accept[89] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       27,   25,   23,    6,   20,   25,    1,   25,   25,    2,
+        6,   21,   25,   22,   25,   24,   22,   22,   22,   22,
+       22,   22,   25,   22,   22,   22,   22,   22,   11,    8,
+       10,   10,    9,   23,   21,    0,    4,    0,    1,   17,
+        3,    3,    2,   24,   24,   22,    5,   22,   22,   22,
+       18,   15,   22,   18,   16,   13,   22,   12,   22,   22,
+        8,    9,    0,    0,    3,   17,   22,   20,   19,   13,
+       22,    0,    3,    3,   22,    7,   14,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    5,    6,    1,    1,    7,    1,    1,
+        1,    1,    8,    1,    8,    9,    1,   10,   10,   10,
+       10,   10,   10,   10,   10,   10,   10,    1,   11,   12,
+       13,   12,    1,    1,   14,   14,   14,   14,   15,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+        1,   16,    1,    1,   17,    1,   18,   14,   14,   19,
+
+       20,   21,   22,   23,   14,   14,   14,   24,   14,   25,
+       26,   27,   14,   28,   29,   30,   31,   14,   14,   32,
+       33,   14,    1,   34,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[35] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    3,    4,
+        1,    1,    1,    4,    4,    1,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[94] =
+    {   0,
+        0,    0,  131,  130,   10,   12,  132,  131,   45,    0,
+      153,  158,  150,  158,  138,   75,    0,  143,  139,   72,
+      158,  135,  134,    0,  143,  136,  119,  115,  116,  113,
+      114,  113,  104,   62,  111,   68,  116,  115,  158,  132,
+      158,  158,    0,  131,  158,   79,  158,  127,    0,  158,
+       84,   87,   91,  122,   31,    0,  158,  111,  103,   98,
+        0,    0,   99,  158,    0,   96,  104,    0,   95,   99,
+      120,    0,   34,  107,   76,    0,   82,    0,    0,    0,
+       83,   99,   98,   95,   76,    0,    0,  158,  111,  115,
+      117,   94,   84
+
+    } ;
+
+static yyconst flex_int16_t yy_def[94] =
+    {   0,
+       88,    1,    1,    1,    1,    1,    1,    1,   88,    9,
+       88,   88,   88,   88,   88,   89,   90,   88,   88,   91,
+       88,   88,   88,   92,   88,   91,   92,   92,   92,   92,
+       92,   92,   88,   92,   92,   92,   92,   92,   88,   88,
+       88,   88,   93,   88,   88,   89,   88,   88,   90,   88,
+       88,   88,   91,   91,   91,   92,   88,   92,   92,   92,
+       92,   92,   92,   88,   92,   92,   92,   92,   92,   92,
+       88,   93,   88,   88,   91,   92,   92,   92,   92,   92,
+       92,   88,   88,   88,   92,   92,   92,    0,   88,   88,
+       88,   88,   88
+
+    } ;
+
+static yyconst flex_int16_t yy_nxt[193] =
+    {   0,
+       12,   13,   14,   15,   16,   17,   18,   12,   19,   20,
+       21,   22,   23,   24,   24,   25,   26,   27,   24,   24,
+       24,   28,   24,   24,   29,   30,   24,   24,   24,   31,
+       24,   32,   24,   33,   35,   36,   35,   36,   74,   88,
+       75,   82,   37,   83,   37,   39,   40,   41,   39,   39,
+       39,   39,   39,   39,   39,   42,   39,   39,   43,   43,
+       39,   39,   43,   43,   43,   43,   43,   43,   43,   43,
+       43,   43,   43,   43,   43,   43,   43,   43,   39,   47,
+       52,   53,   65,   47,   88,   75,   55,   72,   67,   61,
+       48,   55,   68,   51,   48,   61,   51,   56,   73,   52,
+
+       53,   73,   87,   73,   84,   55,   73,   83,   83,   86,
+       55,   46,   85,   46,   46,   49,   84,   49,   49,   54,
+       54,   71,   81,   68,   80,   78,   79,   78,   77,   76,
+       88,   46,   44,   71,   70,   69,   66,   64,   63,   62,
+       61,   60,   59,   58,   88,   57,   45,   45,   51,   50,
+       45,   44,   88,   38,   38,   34,   34,   11,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88
+
+    } ;
+
+static yyconst flex_int16_t yy_chk[193] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    5,    5,    6,    6,   55,   55,
+       55,   73,    5,   73,    6,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,   16,
+       20,   20,   34,   46,   75,   75,   20,   93,   36,   34,
+       16,   20,   36,   51,   46,   36,   52,   92,   51,   53,
+
+       53,   52,   85,   51,   84,   53,   52,   83,   82,   81,
+       53,   89,   77,   89,   89,   90,   74,   90,   90,   91,
+       91,   71,   70,   69,   67,   66,   63,   60,   59,   58,
+       54,   48,   44,   40,   38,   37,   35,   33,   32,   31,
+       30,   29,   28,   27,   26,   25,   23,   22,   19,   18,
+       15,   13,   11,    8,    7,    4,    3,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88
+
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "scanner.l"
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \cond \internal \file scanner.l
+ * \brief
+ * Tokenizer for the selection language.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ * \endcond
+ */
+/*! \internal \file scanner.cpp
+ * \brief
+ * Generated (from scanner.l by Flex) tokenizer for the selection language.
+ *
+ * \ingroup module_selection
+ */
+#line 46 "scanner.l"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string2.h>
+
+#include "parser.h"
+#include "scanner.h"
+#include "scanner_internal.h"
+
+/* This macro is here to make the actions a bit shorter, since nearly every
+ * action needs this call. */
+#define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
+
+#define YY_NO_UNISTD_H 1
+
+
+
+
+#line 576 "scanner.cpp"
+
+#define INITIAL 0
+#define matchof 1
+#define matchbool 2
+#define cmdstart 3
+#define help 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+int _gmx_sel_yylex_init (yyscan_t* scanner);
+
+int _gmx_sel_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int _gmx_sel_yylex_destroy (yyscan_t yyscanner );
+
+int _gmx_sel_yyget_debug (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE _gmx_sel_yyget_extra (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *_gmx_sel_yyget_in (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *_gmx_sel_yyget_out (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int _gmx_sel_yyget_leng (yyscan_t yyscanner );
+
+char *_gmx_sel_yyget_text (yyscan_t yyscanner );
+
+int _gmx_sel_yyget_lineno (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int _gmx_sel_yywrap (yyscan_t yyscanner );
+#else
+extern int _gmx_sel_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               size_t n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int _gmx_sel_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int _gmx_sel_yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 85 "scanner.l"
+
+
+
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(yyscanner);
+    int              retval;
+    /* Return a token if one is pending */
+    retval = _gmx_sel_lexer_process_pending(yylval, state);
+    if (retval != 0)
+    {
+        return retval;
+    }
+    /* Handle the start conditions for 'of' matching */
+    if (state->bMatchOf)
+    {
+        BEGIN(matchof);
+        state->bMatchOf = FALSE;
+    }
+    else if (state->bMatchBool)
+    {
+        BEGIN(matchbool);
+        state->bMatchBool = FALSE;
+    }
+    else if (state->bCmdStart)
+    {
+        BEGIN(cmdstart);
+    }
+    else if (YYSTATE != help)
+    {
+        BEGIN(0);
+    }
+
+
+#line 839 "scanner.cpp"
+
+       if ( !yyg->yy_init )
+               {
+               yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yyg->yy_start )
+                       yyg->yy_start = 1;      /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       _gmx_sel_yyensure_buffer_stack (yyscanner);
+                       YY_CURRENT_BUFFER_LVALUE =
+                               _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+               }
+
+               _gmx_sel_yy_load_buffer_state(yyscanner );
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yyg->yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yyg->yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yyg->yy_start;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yyg->yy_last_accepting_state = yy_current_state;
+                               yyg->yy_last_accepting_cpos = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 89 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_current_state != 88 );
+               yy_cp = yyg->yy_last_accepting_cpos;
+               yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+
+               YY_DO_BEFORE_ACTION;
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yyg->yy_hold_char;
+                       yy_cp = yyg->yy_last_accepting_cpos;
+                       yy_current_state = yyg->yy_last_accepting_state;
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 117 "scanner.l"
+
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 118 "scanner.l"
+{ yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 119 "scanner.l"
+{ yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 120 "scanner.l"
+{ yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
+       YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+#line 122 "scanner.l"
+{ _gmx_sel_lexer_add_token(" ", 1, state); }
+       YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 123 "scanner.l"
+{
+                    if (yytext[0] == ';' || state->bInteractive)
+                    {
+                        rtrim(state->pselstr);
+                        return CMD_SEP;
+                    }
+                    else
+                    {
+                        _gmx_sel_lexer_add_token(" ", 1, state);
+                    }
+                }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 135 "scanner.l"
+{ BEGIN(help); return HELP; }
+       YY_BREAK
+
+case 8:
+YY_RULE_SETUP
+#line 137 "scanner.l"
+
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 138 "scanner.l"
+{ yylval->str = gmx_strndup(yytext, yyleng); return HELP_TOPIC; }
+       YY_BREAK
+case 10:
+/* rule 10 can match eol */
+YY_RULE_SETUP
+#line 139 "scanner.l"
+{ return CMD_SEP; }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 140 "scanner.l"
+{ return INVALID; }
+       YY_BREAK
+
+
+case 12:
+YY_RULE_SETUP
+#line 144 "scanner.l"
+{ ADD_TOKEN; yylval->i = 1; return TOK_INT; }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 145 "scanner.l"
+{ ADD_TOKEN; yylval->i = 0; return TOK_INT; }
+       YY_BREAK
+
+case 14:
+YY_RULE_SETUP
+#line 147 "scanner.l"
+{ ADD_TOKEN; return GROUP; }
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 148 "scanner.l"
+{ ADD_TOKEN; return TO; }
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 149 "scanner.l"
+{ ADD_TOKEN; BEGIN(0); return OF; }
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 150 "scanner.l"
+{ ADD_TOKEN; return AND; }
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 151 "scanner.l"
+{ ADD_TOKEN; return OR; }
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 152 "scanner.l"
+{ ADD_TOKEN; return XOR; }
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 153 "scanner.l"
+{ ADD_TOKEN; return NOT; }
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 154 "scanner.l"
+{ yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return CMP_OP; }
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 156 "scanner.l"
+{ return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 158 "scanner.l"
+{ _gmx_sel_lexer_add_token(" ", 1, state); }
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 159 "scanner.l"
+{ yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 160 "scanner.l"
+{ ADD_TOKEN; return yytext[0]; }
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 161 "scanner.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+       YY_BREAK
+#line 1065 "scanner.cpp"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(matchof):
+case YY_STATE_EOF(matchbool):
+case YY_STATE_EOF(cmdstart):
+case YY_STATE_EOF(help):
+       yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yyg->yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * _gmx_sel_yylex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state( yyscanner );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+                       yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yyg->yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yyg->yy_last_accepting_cpos;
+                               yy_current_state = yyg->yy_last_accepting_state;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer( yyscanner ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yyg->yy_did_buffer_switch_on_eof = 0;
+
+                               if ( _gmx_sel_yywrap(yyscanner ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yyg->yy_c_buf_p =
+                                       yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yyg->yy_c_buf_p =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+} /* end of _gmx_sel_yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       register char *source = yyg->yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+       else
+               {
+                       int num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       _gmx_sel_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+                                               number_to_move - 1;
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       yyg->yy_n_chars, (size_t) num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       if ( yyg->yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       _gmx_sel_yyrestart(yyin  ,yyscanner);
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _gmx_sel_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+       }
+
+       yyg->yy_n_chars += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       yy_current_state = yyg->yy_start;
+
+       for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yyg->yy_last_accepting_state = yy_current_state;
+                       yyg->yy_last_accepting_cpos = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 89 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+       register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+       register char *yy_cp = yyg->yy_c_buf_p;
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               yyg->yy_last_accepting_state = yy_current_state;
+               yyg->yy_last_accepting_cpos = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 89 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 88);
+
+       return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+       register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yyg->yy_hold_char;
+
+       if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yyg->yy_n_chars + 2;
+               register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+                                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+               register char *source =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+               while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+               if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+       yyg->yytext_ptr = yy_bp;
+       yyg->yy_hold_char = *yy_cp;
+       yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+       int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+       if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yyg->yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+                       ++yyg->yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer( yyscanner ) )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       _gmx_sel_yyrestart(yyin ,yyscanner);
+
+                                       /*FALLTHROUGH*/
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( _gmx_sel_yywrap(yyscanner ) )
+                                               return EOF;
+
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput(yyscanner);
+#else
+                                       return input(yyscanner);
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+       *yyg->yy_c_buf_p = '\0';        /* preserve yytext */
+       yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+       return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void _gmx_sel_yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! YY_CURRENT_BUFFER ){
+        _gmx_sel_yyensure_buffer_stack (yyscanner);
+               YY_CURRENT_BUFFER_LVALUE =
+            _gmx_sel_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+       }
+
+       _gmx_sel_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+       _gmx_sel_yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void _gmx_sel_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       /* TODO. We should be able to replace this entire function body
+        * with
+        *              _gmx_sel_yypop_buffer_state();
+        *              _gmx_sel_yypush_buffer_state(new_buffer);
+     */
+       _gmx_sel_yyensure_buffer_stack (yyscanner);
+       if ( YY_CURRENT_BUFFER == new_buffer )
+               return;
+
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+       _gmx_sel_yy_load_buffer_state(yyscanner );
+
+       /* We don't actually know whether we did this switch during
+        * EOF (_gmx_sel_yywrap()) processing, but the only time this flag
+        * is looked at is after _gmx_sel_yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void _gmx_sel_yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+       yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+       yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE _gmx_sel_yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       b = (YY_BUFFER_STATE) _gmx_sel_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) _gmx_sel_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       _gmx_sel_yy_init_buffer(b,file ,yyscanner);
+
+       return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with _gmx_sel_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! b )
+               return;
+
+       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               _gmx_sel_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+       _gmx_sel_yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a _gmx_sel_yyrestart() or at EOF.
+ */
+    static void _gmx_sel_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+       int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       _gmx_sel_yy_flush_buffer(b ,yyscanner);
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then _gmx_sel_yy_init_buffer was _probably_
+     * called from _gmx_sel_yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+       errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == YY_CURRENT_BUFFER )
+               _gmx_sel_yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (new_buffer == NULL)
+               return;
+
+       _gmx_sel_yyensure_buffer_stack(yyscanner);
+
+       /* This block is copied from _gmx_sel_yy_switch_to_buffer. */
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       /* Only push if top exists. Otherwise, replace top. */
+       if (YY_CURRENT_BUFFER)
+               yyg->yy_buffer_stack_top++;
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+       /* copied from _gmx_sel_yy_switch_to_buffer. */
+       _gmx_sel_yy_load_buffer_state(yyscanner );
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (!YY_CURRENT_BUFFER)
+               return;
+
+       _gmx_sel_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+       YY_CURRENT_BUFFER_LVALUE = NULL;
+       if (yyg->yy_buffer_stack_top > 0)
+               --yyg->yy_buffer_stack_top;
+
+       if (YY_CURRENT_BUFFER) {
+               _gmx_sel_yy_load_buffer_state(yyscanner );
+               yyg->yy_did_buffer_switch_on_eof = 1;
+       }
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void _gmx_sel_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+       int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if (!yyg->yy_buffer_stack) {
+
+               /* First allocation is just for 2 elements, since we don't know if this
+                * scanner will even need a stack. We use 2 instead of 1 to avoid an
+                * immediate realloc on the next call.
+         */
+               num_to_alloc = 1;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)_gmx_sel_yyalloc
+                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yyensure_buffer_stack()" );
+                                                                 
+               memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+                               
+               yyg->yy_buffer_stack_max = num_to_alloc;
+               yyg->yy_buffer_stack_top = 0;
+               return;
+       }
+
+       if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+               /* Increase the buffer to prepare for a possible push. */
+               int grow_size = 8 /* arbitrary grow size */;
+
+               num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)_gmx_sel_yyrealloc
+                                                               (yyg->yy_buffer_stack,
+                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yyensure_buffer_stack()" );
+
+               /* zero only the new slots.*/
+               memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+               yyg->yy_buffer_stack_max = num_to_alloc;
+       }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE _gmx_sel_yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) _gmx_sel_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       _gmx_sel_yy_switch_to_buffer(b ,yyscanner );
+
+       return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to _gmx_sel_yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       _gmx_sel_yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+       return _gmx_sel_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to _gmx_sel_yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _gmx_sel_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+    
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = _yybytes_len + 2;
+       buf = (char *) _gmx_sel_yyalloc(n ,yyscanner );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in _gmx_sel_yy_scan_bytes()" );
+
+       for ( i = 0; i < _yybytes_len; ++i )
+               buf[i] = yybytes[i];
+
+       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = _gmx_sel_yy_scan_buffer(buf,n ,yyscanner);
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in _gmx_sel_yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               yytext[yyleng] = yyg->yy_hold_char; \
+               yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+               yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+               *yyg->yy_c_buf_p = '\0'; \
+               yyleng = yyless_macro_arg; \
+               } \
+       while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE _gmx_sel_yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int _gmx_sel_yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int _gmx_sel_yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_gmx_sel_yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_gmx_sel_yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int _gmx_sel_yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *_gmx_sel_yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void _gmx_sel_yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _gmx_sel_yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "_gmx_sel_yyset_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _gmx_sel_yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "_gmx_sel_yyset_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see _gmx_sel_yy_switch_to_buffer
+ */
+void _gmx_sel_yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void _gmx_sel_yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int _gmx_sel_yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void _gmx_sel_yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* _gmx_sel_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int _gmx_sel_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) _gmx_sel_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* _gmx_sel_yylex_init_extra has the same functionality as _gmx_sel_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to _gmx_sel_yyalloc in
+ * the yyextra field.
+ */
+
+int _gmx_sel_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    _gmx_sel_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+       
+    *ptr_yy_globals = (yyscan_t) _gmx_sel_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+       
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    _gmx_sel_yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from _gmx_sel_yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * _gmx_sel_yylex_init()
+     */
+    return 0;
+}
+
+/* _gmx_sel_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int _gmx_sel_yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+       while(YY_CURRENT_BUFFER){
+               _gmx_sel_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+               YY_CURRENT_BUFFER_LVALUE = NULL;
+               _gmx_sel_yypop_buffer_state(yyscanner);
+       }
+
+       /* Destroy the stack itself. */
+       _gmx_sel_yyfree(yyg->yy_buffer_stack ,yyscanner);
+       yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        _gmx_sel_yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * _gmx_sel_yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    _gmx_sel_yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+}
+#endif
+
+void *_gmx_sel_yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+       return (void *) malloc( size );
+}
+
+void *_gmx_sel_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+}
+
+void _gmx_sel_yyfree (void * ptr , yyscan_t yyscanner)
+{
+       free( (char *) ptr );   /* see _gmx_sel_yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 161 "scanner.l"
diff --git a/src/gromacs/selection/scanner.h b/src/gromacs/selection/scanner.h
new file mode 100644 (file)
index 0000000..af6c56b
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Parser/scanner interaction functions.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ */
+#ifndef SELECTION_SCANNER_H
+#define SELECTION_SCANNER_H
+
+namespace gmx
+{
+class MessageStringCollector;
+}
+
+#include "parser.h"
+
+struct gmx_ana_indexgrps_t;
+struct gmx_ana_selcollection_t;
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+#endif
+
+/** Initializes the selection scanner. */
+void
+_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
+                    bool bInteractive, int maxnr, bool bGroups,
+                    struct gmx_ana_indexgrps_t *grps);
+/** Frees memory allocated for the selection scanner. */
+void
+_gmx_sel_free_lexer(yyscan_t scanner);
+
+/** Returns TRUE if the scanner is interactive. */
+gmx_bool
+_gmx_sel_is_lexer_interactive(yyscan_t scanner);
+/** Returns the selection collection for the scanner. */
+struct gmx_ana_selcollection_t *
+_gmx_sel_lexer_selcollection(yyscan_t scanner);
+/** Returns the error reporter for the scanner. */
+gmx::MessageStringCollector *
+_gmx_sel_lexer_error_reporter(yyscan_t scanner);
+/** Returns true if the external index groups for the scanner are set. */
+bool
+_gmx_sel_lexer_has_groups_set(yyscan_t scanner);
+/** Returns the external index groups for the scanner. */
+struct gmx_ana_indexgrps_t *
+_gmx_sel_lexer_indexgrps(yyscan_t scanner);
+/** Returns the number of selections after which the parser should stop. */
+int
+_gmx_sel_lexer_exp_selcount(yyscan_t scanner);
+
+/** Returns a pretty string of the current selection.  */
+const char *
+_gmx_sel_lexer_pselstr(yyscan_t scanner);
+/** Clears the current selection string.  */
+void
+_gmx_sel_lexer_clear_pselstr(yyscan_t scanner);
+/** Clears the method stack in the scanner in error situations. */
+void
+_gmx_sel_lexer_clear_method_stack(yyscan_t scanner);
+/** Notifies the scanner that a complete method expression has been parsed. */
+void
+_gmx_sel_finish_method(yyscan_t scanner);
+/** Initializes the scanner to scan a file. */
+void
+_gmx_sel_set_lex_input_file(yyscan_t scanner, FILE *fp);
+/** Initializes the scanner to scan a string. */
+void
+_gmx_sel_set_lex_input_str(yyscan_t scanner, const char *str);
+
+/** A wrapper for the actual scanner, used by the Bison parser. */
+int
+_gmx_sel_yyblex(YYSTYPE *yylval, yyscan_t yyscanner);
+
+#endif
diff --git a/src/gromacs/selection/scanner.l b/src/gromacs/selection/scanner.l
new file mode 100644 (file)
index 0000000..1acebe1
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \cond \internal \file scanner.l
+ * \brief
+ * Tokenizer for the selection language.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ * \endcond
+ */
+/*! \internal \file scanner.cpp
+ * \brief
+ * Generated (from scanner.l by Flex) tokenizer for the selection language.
+ *
+ * \ingroup module_selection
+ */
+%{
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string2.h>
+
+#include "parser.h"
+#include "scanner.h"
+#include "scanner_internal.h"
+
+/* This macro is here to make the actions a bit shorter, since nearly every
+ * action needs this call. */
+#define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
+
+%}
+
+INTEGER    [[:digit:]]+
+DSEQ       ([[:digit:]]+)
+FRAC       (([[:digit:]]*"."{DSEQ})|{DSEQ}".")
+EXP        ([eE][+-]?{DSEQ})
+REAL       (({FRAC}{EXP}?)|({DSEQ}{EXP}))
+STRING     (\"([^\"\\\n]|(\\\"))*\")
+IDENTIFIER ([[:alpha:]][_[:alnum:]]*)
+CMPOP      (([<>]=?)|([!=]=))
+COMMENT    (#.*)
+
+%option nodefault
+%option noyywrap
+%option reentrant
+%option prefix="_gmx_sel_yy"
+%option header-file="scanner_flex.h"
+%option nounistd
+%option never-interactive
+
+%s matchof
+%s matchbool
+%s cmdstart
+%x help
+
+%%
+
+%{
+    gmx_sel_lexer_t *state = yyget_extra(yyscanner);
+    int              retval;
+    /* Return a token if one is pending */
+    retval = _gmx_sel_lexer_process_pending(yylval, state);
+    if (retval != 0)
+    {
+        return retval;
+    }
+    /* Handle the start conditions for 'of' matching */
+    if (state->bMatchOf)
+    {
+        BEGIN(matchof);
+        state->bMatchOf = FALSE;
+    }
+    else if (state->bMatchBool)
+    {
+        BEGIN(matchbool);
+        state->bMatchBool = FALSE;
+    }
+    else if (state->bCmdStart)
+    {
+        BEGIN(cmdstart);
+    }
+    else if (YYSTATE != help)
+    {
+        BEGIN(0);
+    }
+%}
+
+{COMMENT}
+{INTEGER}       { yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
+{REAL}          { yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
+{STRING}        { yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
+
+\\\n            { _gmx_sel_lexer_add_token(" ", 1, state); }
+";"|\n          {
+                    if (yytext[0] == ';' || state->bInteractive)
+                    {
+                        rtrim(state->pselstr);
+                        return CMD_SEP;
+                    }
+                    else
+                    {
+                        _gmx_sel_lexer_add_token(" ", 1, state);
+                    }
+                }
+
+<cmdstart>help  { BEGIN(help); return HELP; }
+<help>{
+[[:blank:]]+
+{IDENTIFIER}    { yylval->str = gmx_strndup(yytext, yyleng); return HELP_TOPIC; }
+";"|\n          { return CMD_SEP; }
+.               { return INVALID; }
+}
+
+<matchbool>{
+yes|on          { ADD_TOKEN; yylval->i = 1; return TOK_INT; }
+no|off          { ADD_TOKEN; yylval->i = 0; return TOK_INT; }
+}
+group           { ADD_TOKEN; return GROUP; }
+to              { ADD_TOKEN; return TO; }
+<matchof>of     { ADD_TOKEN; BEGIN(0); return OF; }
+and|"&&"        { ADD_TOKEN; return AND; }
+or|"||"         { ADD_TOKEN; return OR; }
+xor             { ADD_TOKEN; return XOR; }
+not|"!"         { ADD_TOKEN; return NOT; }
+{CMPOP}         { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return CMP_OP; }
+
+{IDENTIFIER}    { return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
+
+[[:blank:]]+    { _gmx_sel_lexer_add_token(" ", 1, state); }
+[_[:alnum:]]+   { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
+.               { ADD_TOKEN; return yytext[0]; }
diff --git a/src/gromacs/selection/scanner_flex.h b/src/gromacs/selection/scanner_flex.h
new file mode 100644 (file)
index 0000000..abb400c
--- /dev/null
@@ -0,0 +1,350 @@
+#ifndef _gmx_sel_yyHEADER_H
+#define _gmx_sel_yyHEADER_H 1
+#define _gmx_sel_yyIN_HEADER 1
+
+#line 6 "scanner_flex.h"
+
+#line 8 "scanner_flex.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void _gmx_sel_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void _gmx_sel_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void _gmx_sel_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _gmx_sel_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _gmx_sel_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void _gmx_sel_yypop_buffer_state (yyscan_t yyscanner );
+
+YY_BUFFER_STATE _gmx_sel_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE _gmx_sel_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *_gmx_sel_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *_gmx_sel_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void _gmx_sel_yyfree (void * ,yyscan_t yyscanner );
+
+#define _gmx_sel_yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define matchof 1
+#define matchbool 2
+#define cmdstart 3
+#define help 4
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+int _gmx_sel_yylex_init (yyscan_t* scanner);
+
+int _gmx_sel_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int _gmx_sel_yylex_destroy (yyscan_t yyscanner );
+
+int _gmx_sel_yyget_debug (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE _gmx_sel_yyget_extra (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *_gmx_sel_yyget_in (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *_gmx_sel_yyget_out (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int _gmx_sel_yyget_leng (yyscan_t yyscanner );
+
+char *_gmx_sel_yyget_text (yyscan_t yyscanner );
+
+int _gmx_sel_yyget_lineno (yyscan_t yyscanner );
+
+void _gmx_sel_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int _gmx_sel_yywrap (yyscan_t yyscanner );
+#else
+extern int _gmx_sel_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int _gmx_sel_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int _gmx_sel_yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 161 "scanner.l"
+
+#line 349 "scanner_flex.h"
+#undef _gmx_sel_yyIN_HEADER
+#endif /* _gmx_sel_yyHEADER_H */
diff --git a/src/gromacs/selection/scanner_internal.cpp b/src/gromacs/selection/scanner_internal.cpp
new file mode 100644 (file)
index 0000000..346fc7e
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Helper functions for the selection tokenizer.
+ *
+ * This file implements the functions in the headers scanner.h and
+ * scanner_internal.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+/*! \internal \file scanner_flex.h
+ * \brief Generated (from scanner.l) header file by Flex.
+ *
+ * This file contains definitions of functions that are needed in
+ * scanner_internal.cpp.
+ *
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <typedefs.h>
+#include <smalloc.h>
+#include <string.h>
+
+#include "string2.h"
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+
+#include "gromacs/selection/selmethod.h"
+
+#include "parsetree.h"
+#include "selectioncollection-impl.h"
+#include "selelem.h"
+#include "symrec.h"
+
+#include "parser.h"
+#include "scanner.h"
+#include "scanner_internal.h"
+
+//! Step in which the allocated memory for pretty-printed input is incremented.
+#define STRSTORE_ALLOCSTEP 1000
+
+/* These are defined as macros in the generated scanner_flex.h.
+ * We undefine them here to have them as variable names in the subroutines.
+ * There are other ways of doing this, but this is probably the easiest. */
+#undef yylval
+#undef yytext
+#undef yyleng
+
+static gmx_bool
+read_stdin_line(gmx_sel_lexer_t *state)
+{
+    char *ptr     = state->inputstr;
+    int   max_len = state->nalloc_input;
+    int   totlen = 0;
+
+    if (feof(stdin))
+    {
+        return FALSE;
+    }
+    if (state->bInteractive)
+    {
+        if (!state->errors->isEmpty())
+        {
+            fprintf(stderr, "%s", state->errors->toString().c_str());
+            state->errors->clear();
+        }
+        fprintf(stderr, "> ");
+    }
+    /* For some reason (at least on my Linux), fgets() doesn't return until
+     * the user presses Ctrl-D _twice_ at the end of a non-empty line.
+     * This can be a bit confusing for users, but there's not much we can
+     * do, and the chances of a normal user noticing this are not very big. */
+    while (fgets(ptr, max_len, stdin) != NULL)
+    {
+        int len = strlen(ptr);
+
+        totlen += len;
+        if (len >= 2 && ptr[len - 1] == '\n' && ptr[len - 2] == '\\')
+        {
+            if (state->bInteractive)
+            {
+                fprintf(stderr, "... ");
+            }
+        }
+        else if ((len >= 1 && ptr[len - 1] == '\n') || len < max_len - 1)
+        {
+            break;
+        }
+        ptr     += len;
+        max_len -= len;
+        if (max_len <= 2)
+        {
+            max_len += state->nalloc_input;
+            state->nalloc_input *= 2;
+            len = ptr - state->inputstr;
+            srenew(state->inputstr, state->nalloc_input);
+            ptr = state->inputstr + len;
+        }
+    }
+    if (state->bInteractive && (totlen == 0 || ptr[totlen - 1] != '\n'))
+    {
+        fprintf(stderr, "\n");
+    }
+    if (ferror(stdin))
+    {
+        GMX_ERROR_NORET(gmx::eeInvalidInput, "Selection reading failed");
+    }
+    return totlen > 0;
+}
+
+int
+_gmx_sel_yyblex(YYSTYPE *yylval, yyscan_t yyscanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(yyscanner);
+    gmx_bool bCmdStart;
+    int token;
+
+    if (!state->bBuffer && !state->inputstr)
+    {
+        state->nalloc_input = 1024;
+        snew(state->inputstr, state->nalloc_input);
+        read_stdin_line(state);
+        _gmx_sel_set_lex_input_str(yyscanner, state->inputstr);
+    }
+    bCmdStart = state->bCmdStart;
+    token = _gmx_sel_yylex(yylval, yyscanner);
+    while (state->inputstr && token == 0 && read_stdin_line(state))
+    {
+        _gmx_sel_set_lex_input_str(yyscanner, state->inputstr);
+        token = _gmx_sel_yylex(yylval, yyscanner);
+    }
+    if (token == 0 && !bCmdStart)
+    {
+        token = CMD_SEP;
+        rtrim(state->pselstr);
+    }
+    state->bCmdStart = (token == CMD_SEP);
+    return token;
+}
+
+static int
+init_param_token(YYSTYPE *yylval, gmx_ana_selparam_t *param, gmx_bool bBoolNo)
+{
+    if (bBoolNo)
+    {
+        snew(yylval->str, strlen(param->name) + 3);
+        yylval->str[0] = 'n';
+        yylval->str[1] = 'o';
+        strcpy(yylval->str+2, param->name);
+    }
+    else
+    {
+        yylval->str = param->name ? strdup(param->name) : NULL;
+    }
+    return PARAM;
+}
+
+static int
+init_method_token(YYSTYPE *yylval, gmx_ana_selmethod_t *method, gmx_bool bPosMod,
+                  gmx_sel_lexer_t *state)
+{
+    /* If the previous token was not KEYWORD_POS, return EMPTY_POSMOD
+     * before the actual method to work around a limitation in Bison. */
+    if (!bPosMod && method->type != POS_VALUE)
+    {
+        state->nextmethod = method;
+        return EMPTY_POSMOD;
+    }
+    yylval->meth = method;
+    if (!(method->flags & SMETH_MODIFIER) && method->nparams == 0)
+    {
+        /* Keyword */
+        switch (method->type)
+        {
+            case INT_VALUE:   return KEYWORD_NUMERIC;
+            case REAL_VALUE:  return KEYWORD_NUMERIC;
+            case STR_VALUE:   return KEYWORD_STR;
+            case GROUP_VALUE: return KEYWORD_GROUP;
+            default:
+                GMX_ERROR_NORET(gmx::eeInternalError, "Unsupported keyword type");
+                return INVALID;
+        }
+    } else {
+        /* Method with parameters or a modifier */
+        if (method->flags & SMETH_MODIFIER)
+        {
+            /* Remove all methods from the stack */
+            state->msp = -1;
+            if (method->param[1].name == NULL)
+            {
+                state->nextparam = &method->param[1];
+            }
+        }
+        else
+        {
+            if (method->param[0].name == NULL)
+            {
+                state->nextparam = &method->param[0];
+            }
+        }
+        ++state->msp;
+        if (state->msp >= state->mstack_alloc)
+        {
+            state->mstack_alloc += 10;
+            srenew(state->mstack, state->mstack_alloc);
+        }
+        state->mstack[state->msp] = method;
+        if (method->flags & SMETH_MODIFIER)
+        {
+            return MODIFIER;
+        }
+        switch (method->type)
+        {
+            case INT_VALUE:   return METHOD_NUMERIC;
+            case REAL_VALUE:  return METHOD_NUMERIC;
+            case POS_VALUE:   return METHOD_POS;
+            case GROUP_VALUE: return METHOD_GROUP;
+            default:
+                --state->msp;
+                GMX_ERROR_NORET(gmx::eeInternalError, "Unsupported method type");
+                return INVALID;
+        }
+    }
+    return INVALID; /* Should not be reached */
+}
+
+int
+_gmx_sel_lexer_process_pending(YYSTYPE *yylval, gmx_sel_lexer_t *state)
+{
+    if (state->nextparam)
+    {
+        gmx_ana_selparam_t *param = state->nextparam;
+        gmx_bool                bBoolNo = state->bBoolNo;
+
+        if (state->neom > 0)
+        {
+            --state->neom;
+            return END_OF_METHOD;
+        }
+        state->nextparam = NULL;
+        state->bBoolNo   = FALSE;
+        _gmx_sel_lexer_add_token(param->name, -1, state);
+        return init_param_token(yylval, param, bBoolNo);
+    }
+    if (state->prev_pos_kw > 0)
+    {
+        --state->prev_pos_kw;
+    }
+    if (state->nextmethod)
+    {
+        gmx_ana_selmethod_t *method = state->nextmethod;
+
+        state->nextmethod = NULL;
+        return init_method_token(yylval, method, TRUE, state);
+    }
+    return 0;
+}
+
+int
+_gmx_sel_lexer_process_identifier(YYSTYPE *yylval, char *yytext, size_t yyleng,
+                                  gmx_sel_lexer_t *state)
+{
+    gmx_sel_symrec_t *symbol;
+    e_symbol_t        symtype;
+
+    /* Check if the identifier matches with a parameter name */
+    if (state->msp >= 0)
+    {
+        gmx_ana_selparam_t *param = NULL;
+        gmx_bool                bBoolNo = FALSE;
+        int                 sp = state->msp;
+        while (!param && sp >= 0)
+        {
+            int             i;
+            for (i = 0; i < state->mstack[sp]->nparams; ++i)
+            {
+                /* Skip NULL parameters and too long parameters */
+                if (state->mstack[sp]->param[i].name == NULL
+                    || strlen(state->mstack[sp]->param[i].name) > yyleng)
+                {
+                    continue;
+                }
+                if (!strncmp(state->mstack[sp]->param[i].name, yytext, yyleng))
+                {
+                    param = &state->mstack[sp]->param[i];
+                    break;
+                }
+                /* Check separately for a 'no' prefix on gmx_boolean parameters */
+                if (state->mstack[sp]->param[i].val.type == NO_VALUE
+                    && yyleng > 2 && yytext[0] == 'n' && yytext[1] == 'o'
+                    && !strncmp(state->mstack[sp]->param[i].name, yytext+2, yyleng-2))
+                {
+                    param = &state->mstack[sp]->param[i];
+                    bBoolNo = TRUE;
+                    break;
+                }
+            }
+            if (!param)
+            {
+                --sp;
+            }
+        }
+        if (param)
+        {
+            if (param->val.type == NO_VALUE && !bBoolNo)
+            {
+                state->bMatchBool = TRUE;
+            }
+            if (sp < state->msp)
+            {
+                state->neom = state->msp - sp - 1;
+                state->nextparam = param;
+                state->bBoolNo   = bBoolNo;
+                return END_OF_METHOD;
+            }
+            _gmx_sel_lexer_add_token(param->name, -1, state);
+            return init_param_token(yylval, param, bBoolNo);
+        }
+    }
+
+    /* Check if the identifier matches with a symbol */
+    symbol = _gmx_sel_find_symbol_len(state->sc->symtab, yytext, yyleng, FALSE);
+    /* If there is no match, return the token as a string */
+    if (!symbol)
+    {
+        yylval->str = gmx_strndup(yytext, yyleng);
+        _gmx_sel_lexer_add_token(yytext, yyleng, state);
+        return IDENTIFIER;
+    }
+    _gmx_sel_lexer_add_token(_gmx_sel_sym_name(symbol), -1, state);
+    symtype = _gmx_sel_sym_type(symbol);
+    /* Reserved symbols should have been caught earlier */
+    if (symtype == SYMBOL_RESERVED)
+    {
+        GMX_ERROR_NORET(gmx::eeInternalError,
+                        "Mismatch between tokenizer and reserved symbol table");
+        return INVALID;
+    }
+    /* For variable symbols, return the type of the variable value */
+    if (symtype == SYMBOL_VARIABLE)
+    {
+        t_selelem *var;
+
+        var = _gmx_sel_sym_value_var(symbol);
+        /* Return simple tokens for constant variables */
+        if (var->type == SEL_CONST)
+        {
+            switch (var->v.type)
+            {
+                case INT_VALUE:
+                    yylval->i = var->v.u.i[0];
+                    return TOK_INT;
+                case REAL_VALUE:
+                    yylval->r = var->v.u.r[0];
+                    return TOK_REAL;
+                case POS_VALUE:
+                    break;
+                default:
+                    GMX_ERROR_NORET(gmx::eeInternalError,
+                                    "Unsupported variable type");
+                    return INVALID;
+            }
+        }
+        yylval->sel = var;
+        switch (var->v.type)
+        {
+            case INT_VALUE:   return VARIABLE_NUMERIC;
+            case REAL_VALUE:  return VARIABLE_NUMERIC;
+            case POS_VALUE:   return VARIABLE_POS;
+            case GROUP_VALUE: return VARIABLE_GROUP;
+            default:
+                GMX_ERROR_NORET(gmx::eeInternalError,
+                                "Unsupported variable type");
+                return INVALID;
+        }
+        return INVALID; /* Should not be reached. */
+    }
+    /* For method symbols, return the correct type */
+    if (symtype == SYMBOL_METHOD)
+    {
+        gmx_ana_selmethod_t *method;
+
+        method = _gmx_sel_sym_value_method(symbol);
+        return init_method_token(yylval, method, state->prev_pos_kw > 0, state);
+    }
+    /* For position symbols, we need to return KEYWORD_POS, but we also need
+     * some additional handling. */
+    if (symtype == SYMBOL_POS)
+    {
+        state->bMatchOf = TRUE;
+        yylval->str = _gmx_sel_sym_name(symbol);
+        state->prev_pos_kw = 2;
+        return KEYWORD_POS;
+    }
+    /* Should not be reached */
+    return INVALID;
+}
+
+void
+_gmx_sel_lexer_add_token(const char *str, int len, gmx_sel_lexer_t *state)
+{
+    /* Do nothing if the string is empty, or if it is a space and there is
+     * no other text yet, or if there already is a space. */
+    if (!str || len == 0 || strlen(str) == 0
+        || (str[0] == ' ' && str[1] == 0
+            && (state->pslen == 0 || state->pselstr[state->pslen - 1] == ' ')))
+    {
+        return;
+    }
+    if (len < 0)
+    {
+        len = strlen(str);
+    }
+    /* Allocate more memory if necessary */
+    if (state->nalloc_psel - state->pslen < len)
+    {
+        int incr = STRSTORE_ALLOCSTEP < len ? len : STRSTORE_ALLOCSTEP;
+        state->nalloc_psel += incr;
+        srenew(state->pselstr, state->nalloc_psel);
+    }
+    /* Append the token to the stored string */
+    strncpy(state->pselstr + state->pslen, str, len);
+    state->pslen += len;
+    state->pselstr[state->pslen] = 0;
+}
+
+void
+_gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
+                    bool bInteractive, int maxnr, bool bGroups,
+                    struct gmx_ana_indexgrps_t *grps)
+{
+    gmx_sel_lexer_t *state;
+
+    int rc = _gmx_sel_yylex_init(scannerp);
+    if (rc != 0)
+    {
+        // TODO: Throw a more representative exception.
+        GMX_THROW(gmx::InternalError("Lexer initialization failed"));
+    }
+
+    gmx::MessageStringCollector *errors = new gmx::MessageStringCollector;
+
+    snew(state, 1);
+    state->sc        = sc;
+    state->errors    = errors;
+    state->bGroups   = bGroups;
+    state->grps      = grps;
+    state->nexpsel   = (maxnr > 0 ? sc->sel.size() + maxnr : -1);
+
+    state->bInteractive = bInteractive;
+    state->nalloc_input = 0;
+    state->inputstr     = NULL;
+
+    snew(state->pselstr, STRSTORE_ALLOCSTEP);
+    state->pselstr[0]   = 0;
+    state->pslen        = 0;
+    state->nalloc_psel  = STRSTORE_ALLOCSTEP;
+
+    snew(state->mstack, 20);
+    state->mstack_alloc = 20;
+    state->msp          = -1;
+    state->neom         = 0;
+    state->nextparam    = NULL;
+    state->nextmethod   = NULL;
+    state->prev_pos_kw  = 0;
+    state->bBoolNo      = FALSE;
+    state->bMatchOf     = FALSE;
+    state->bMatchBool   = FALSE;
+    state->bCmdStart    = TRUE;
+    state->bBuffer      = FALSE;
+
+    _gmx_sel_yyset_extra(state, *scannerp);
+}
+
+void
+_gmx_sel_free_lexer(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+
+    sfree(state->inputstr);
+    sfree(state->pselstr);
+    sfree(state->mstack);
+    if (state->bBuffer)
+    {
+        _gmx_sel_yy_delete_buffer(state->buffer, scanner);
+    }
+    sfree(state);
+    _gmx_sel_yylex_destroy(scanner);
+}
+
+gmx_bool
+_gmx_sel_is_lexer_interactive(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->bInteractive;
+}
+
+struct gmx_ana_selcollection_t *
+_gmx_sel_lexer_selcollection(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->sc;
+}
+
+gmx::MessageStringCollector *
+_gmx_sel_lexer_error_reporter(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->errors;
+}
+
+bool
+_gmx_sel_lexer_has_groups_set(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->bGroups;
+}
+
+struct gmx_ana_indexgrps_t *
+_gmx_sel_lexer_indexgrps(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->grps;
+}
+
+int
+_gmx_sel_lexer_exp_selcount(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->nexpsel;
+}
+
+const char *
+_gmx_sel_lexer_pselstr(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    return state->pselstr;
+}
+
+void
+_gmx_sel_lexer_clear_pselstr(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    state->pselstr[0] = 0;
+    state->pslen      = 0;
+}
+
+void
+_gmx_sel_lexer_clear_method_stack(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+
+    state->msp = -1;
+}
+
+void
+_gmx_sel_finish_method(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+
+    if (state->msp >= 0)
+    {
+        --state->msp;
+    }
+}
+
+void
+_gmx_sel_set_lex_input_file(yyscan_t scanner, FILE *fp)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+
+    state->bBuffer = TRUE;
+    state->buffer  = _gmx_sel_yy_create_buffer(fp, YY_BUF_SIZE, scanner);
+    _gmx_sel_yy_switch_to_buffer(state->buffer, scanner);
+}
+
+void
+_gmx_sel_set_lex_input_str(yyscan_t scanner, const char *str)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+
+    if (state->bBuffer)
+    {
+        _gmx_sel_yy_delete_buffer(state->buffer, scanner);
+    }
+    state->bBuffer = TRUE;
+    state->buffer  = _gmx_sel_yy_scan_string(str, scanner);
+}
diff --git a/src/gromacs/selection/scanner_internal.h b/src/gromacs/selection/scanner_internal.h
new file mode 100644 (file)
index 0000000..ef0b247
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Internal header file used by the selection tokenizer.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef SELECTION_SCANNER_INTERNAL_H
+#define SELECTION_SCANNER_INTERNAL_H
+
+namespace gmx
+{
+class MessageStringCollector;
+}
+
+#include "parser.h"
+
+/** The scanning function generated by Flex. */
+#define YY_DECL int _gmx_sel_yylex(YYSTYPE *yylval, yyscan_t yyscanner)
+YY_DECL;
+
+/* These need to be defined before including scanner_flex.h, because it
+ * uses YY_EXTRA_TYPE. But we also need to include it before defining
+ * gmx_sel_lexer_t; hence the forward declaration. */
+struct gmx_sel_lexer_t;
+#define YY_EXTRA_TYPE struct gmx_sel_lexer_t *
+
+/* We cannot include scanner_flex.h from the scanner itself, because it
+ * seems to break everything. */
+/* And we need to define YY_NO_UNISTD_H here as well, otherwise unistd.h
+ * gets included in other files than scanner.cpp... */
+#ifndef FLEX_SCANNER
+#define YY_NO_UNISTD_H
+#include "scanner_flex.h"
+#endif
+
+/*! \internal \brief
+ * Internal data structure for the selection tokenizer state.
+ */
+typedef struct gmx_sel_lexer_t
+{
+    //! Selection collection to put parsed selections in.
+    struct gmx_ana_selcollection_t  *sc;
+    //! Error reporter object.
+    gmx::MessageStringCollector     *errors;
+    //! Whether external index groups have been set.
+    bool                             bGroups;
+    //! External index groups for resolving \c group keywords.
+    struct gmx_ana_indexgrps_t      *grps;
+    //! Number of selections at which the parser should stop.
+    int                              nexpsel;
+
+    //! Whether the parser is interactive.
+    gmx_bool                             bInteractive;
+    //! Current input string (line) for an interactive scanner.
+    char                            *inputstr;
+    //! Number of bytes allocated for \a inputstr.
+    int                              nalloc_input;
+
+    //! Pretty-printed version of the string parsed since last clear.
+    char                            *pselstr;
+    //! Length of the string in \a pselstr.
+    int                              pslen;
+    //! Number of bytes allocated for \a pselstr.
+    int                              nalloc_psel;
+
+    //! Stack of methods in which parameters should be looked up.
+    struct gmx_ana_selmethod_t     **mstack;
+    //! Index of the top of the stack in \a mstack.
+    int                              msp;
+    //! Number of elements allocated for \a mstack.
+    int                              mstack_alloc;
+
+    //! Number of END_OF_METHOD tokens to return before \a nextparam.
+    int                              neom;
+    //! Parameter symbol to return before resuming scanning.
+    struct gmx_ana_selparam_t       *nextparam;
+    //! Whether \a nextparam was a boolean parameter with a 'no' prefix.
+    gmx_bool                             bBoolNo;
+    /*! \brief
+     * Method symbol to return before resuming scanning
+     *
+     * Only used when \p nextparam is NULL.
+     */
+    struct gmx_ana_selmethod_t      *nextmethod;
+    //! Used to track whether the previous token was a position modifier.
+    int                              prev_pos_kw;
+
+    //! Whether the 'of' keyword is acceptable as the next token.
+    gmx_bool                             bMatchOf;
+    //! Whether boolean values (yes/no/on/off) are acceptable as the next token.
+    gmx_bool                             bMatchBool;
+    //! Whether the next token starts a new selection.
+    gmx_bool                             bCmdStart;
+
+    //! Whether an external buffer is set for the scanner.
+    gmx_bool                             bBuffer;
+    //! The current buffer for the scanner.
+    YY_BUFFER_STATE                  buffer;
+} gmx_sel_lexer_t;
+
+/* Because Flex defines yylval, yytext, and yyleng as macros,
+ * and this file is included from scanner.l,
+ * we cannot have them here as parameter names... */
+/** Internal function for cases where several tokens need to be returned. */
+int
+_gmx_sel_lexer_process_pending(YYSTYPE *, gmx_sel_lexer_t *state);
+/** Internal function that processes identifier tokens. */
+int
+_gmx_sel_lexer_process_identifier(YYSTYPE *, char *, size_t,
+                                  gmx_sel_lexer_t *state);
+/** Internal function to add a token to the pretty-printed selection text. */
+void
+_gmx_sel_lexer_add_token(const char *str, int len, gmx_sel_lexer_t *state);
+
+#endif
diff --git a/src/gromacs/selection/selection.cpp b/src/gromacs/selection/selection.cpp
new file mode 100644 (file)
index 0000000..d09f886
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::Selection.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <smalloc.h>
+#include <statutil.h>
+#include <string2.h>
+#include <xvgr.h>
+
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selvalue.h"
+
+#include "selelem.h"
+
+namespace gmx
+{
+
+Selection::Selection(t_selelem *elem, const char *selstr)
+{
+    // TODO: This is not exception-safe if any called function throws.
+    _sel.name = strdup(elem->name);
+    _sel.selstr = strdup(selstr);
+    gmx_ana_pos_clear(&_sel.p);
+
+    if (elem->child->type == SEL_CONST)
+    {
+        gmx_ana_pos_copy(&_sel.p, elem->child->v.u.p, TRUE);
+        _sel.bDynamic = FALSE;
+    }
+    else
+    {
+        t_selelem *child;
+
+        child = elem->child;
+        child->flags     &= ~SEL_ALLOCVAL;
+        _gmx_selvalue_setstore(&child->v, &_sel.p);
+        /* We should also skip any modifiers to determine the dynamic
+         * status. */
+        while (child->type == SEL_MODIFIER)
+        {
+            child = child->child;
+            if (child->type == SEL_SUBEXPRREF)
+            {
+                child = child->child;
+                /* Because most subexpression elements are created
+                 * during compilation, we need to check for them
+                 * explicitly here.
+                 */
+                if (child->type == SEL_SUBEXPR)
+                {
+                    child = child->child;
+                }
+            }
+        }
+        /* For variable references, we should skip the
+         * SEL_SUBEXPRREF and SEL_SUBEXPR elements. */
+        if (child->type == SEL_SUBEXPRREF)
+        {
+            child = child->child->child;
+        }
+        _sel.bDynamic = (child->child->flags & SEL_DYNAMIC);
+    }
+    /* The group will be set after compilation */
+    _sel.m        = NULL;
+    _sel.q        = NULL;
+    _sel.g        = NULL;
+    _sel.orgm     = NULL;
+    _sel.orgq     = NULL;
+    _sel.selelem  = elem;
+    initCoveredFraction(CFRAC_NONE);
+}
+
+
+Selection::~Selection()
+{
+    sfree(_sel.name);
+    sfree(_sel.selstr);
+    gmx_ana_pos_deinit(&_sel.p);
+    if (_sel.m != _sel.orgm)
+    {
+        sfree(_sel.m);
+    }
+    if (_sel.q != _sel.orgq)
+    {
+        sfree(_sel.q);
+    }
+    sfree(_sel.orgm);
+    sfree(_sel.orgq);
+}
+
+
+void
+Selection::printInfo(FILE *fp) const
+{
+    fprintf(fp, "\"%s\" (%d position%s, %d atom%s%s)", _sel.name,
+            _sel.p.nr,     _sel.p.nr     == 1 ? "" : "s",
+            _sel.g->isize, _sel.g->isize == 1 ? "" : "s",
+            _sel.bDynamic ? ", dynamic" : "");
+    fprintf(fp, "\n");
+}
+
+
+bool
+Selection::initCoveredFraction(e_coverfrac_t type)
+{
+    gmx_ana_selection_t *sel = &_sel;
+
+    sel->cfractype = type;
+    if (type == CFRAC_NONE || !sel->selelem)
+    {
+        sel->bCFracDyn = FALSE;
+    }
+    else if (!_gmx_selelem_can_estimate_cover(sel->selelem))
+    {
+        sel->cfractype = CFRAC_NONE;
+        sel->bCFracDyn = FALSE;
+    }
+    else
+    {
+        sel->bCFracDyn = TRUE;
+    }
+    sel->cfrac     = sel->bCFracDyn ? 0.0 : 1.0;
+    sel->avecfrac  = sel->cfrac;
+    return type == CFRAC_NONE || sel->cfractype != CFRAC_NONE;
+}
+
+
+void
+Selection::printDebugInfo(FILE *fp, int nmaxind) const
+{
+    fprintf(fp, "  ");
+    printInfo(fp);
+    fprintf(fp, "    ");
+    gmx_ana_index_dump(fp, _sel.g, -1, nmaxind);
+
+    fprintf(fp, "    Block (size=%d):", _sel.p.m.mapb.nr);
+    if (!_sel.p.m.mapb.index)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        int n = _sel.p.m.mapb.nr;
+        if (nmaxind >= 0 && n > nmaxind)
+            n = nmaxind;
+        for (int i = 0; i <= n; ++i)
+            fprintf(fp, " %d", _sel.p.m.mapb.index[i]);
+        if (n < _sel.p.m.mapb.nr)
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+
+    int n = _sel.p.m.nr;
+    if (nmaxind >= 0 && n > nmaxind)
+        n = nmaxind;
+    fprintf(fp, "    RefId:");
+    if (!_sel.p.m.refid)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+            fprintf(fp, " %d", _sel.p.m.refid[i]);
+        if (n < _sel.p.m.nr)
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+
+    fprintf(fp, "    MapId:");
+    if (!_sel.p.m.mapid)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+            fprintf(fp, " %d", _sel.p.m.mapid[i]);
+        if (n < _sel.p.m.nr)
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+}
+
+} // namespace gmx
diff --git a/src/gromacs/selection/selection.h b/src/gromacs/selection/selection.h
new file mode 100644 (file)
index 0000000..f8cfdb3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::Selection.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTION_H
+#define GMX_SELECTION_SELECTION_H
+
+#include "position.h"
+#include "indexutil.h"
+#include "selectionenums.h"
+
+struct t_selelem;
+
+/*! \internal \brief
+ * Describes a single selection.
+ *
+ * \ingroup module_selection
+ */
+typedef struct gmx_ana_selection_t
+{
+    /** Name of the selection. */
+    char                   *name;
+    /** The actual selection string. */
+    char                   *selstr;
+    /** Selected positions. */
+    gmx_ana_pos_t           p;
+    /** Masses associated with the positions. */
+    real                   *m;
+    /** Charges associated with the positions. */
+    real                   *q;
+    /** Pointer to the index group that holds the selected atoms. */
+    struct gmx_ana_index_t *g;
+    /** TRUE if the value can change as a function of time. */
+    gmx_bool                    bDynamic;
+    /** Type of the covered fraction. */
+    e_coverfrac_t           cfractype;
+    /** TRUE if the covered fraction depends on the frame. */
+    gmx_bool                    bCFracDyn;
+    /** Covered fraction of the selection for the current frame. */
+    real                    cfrac;
+    /** The average covered fraction (over the trajectory). */
+    real                    avecfrac;
+
+    /*! \brief
+     * Pointer to the root of the selection element tree (internal use only).
+     *
+     * \internal
+     * This field is NULL if the selection has been loaded directly from an
+     * index file.
+     */
+    struct t_selelem       *selelem;
+    /** Original masses of all possible positions (internal use only). */
+    real                   *orgm;
+    /** Original charges of all possible positions (internal use only). */
+    real                   *orgq;
+} gmx_ana_selection_t;
+
+namespace gmx
+{
+
+class SelectionCollection;
+
+/*! \brief
+ * Provides access to a single selection.
+ *
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+class Selection
+{
+    public:
+        /*! \brief
+         * Creates a new selection object.
+         *
+         * \param[in] elem   Root of the evaluation tree for this selection.
+         * \param[in] selstr String that was parsed to produce this selection.
+         */
+        Selection(t_selelem *elem, const char *selstr);
+
+        //! Returns the name of the selection.
+        const char *name() const  { return _sel.name; }
+        //! Returns the string that was parsed to produce this selection.
+        const char *selectionText() const { return _sel.selstr; }
+        //! Returns true if the size of the selection (posCount()) is dynamic.
+        bool isDynamic() const { return _sel.bDynamic; }
+        //! Returns the type of positions in the selection.
+        e_index_t type() const { return _sel.p.m.type; }
+        //! Number of positions in the selection.
+        int posCount() const { return _sel.p.nr; }
+        //! Returns the \p i'th position for the selection.
+        const rvec &x(int i) const { return _sel.p.x[i]; }
+        //! Returns the velocity for the \p i'th position.
+        const rvec &v(int i) const { return _sel.p.v[i]; }
+        //! Returns the force for the \p i'th position.
+        const rvec &f(int i) const { return _sel.p.f[i]; }
+        /*! \brief
+         * Returns the reference ID for the \p i'th position.
+         */
+        int refId(int i) const { return _sel.p.m.refid[i]; }
+        /*! \brief
+         * Returns the mapped ID for the \p i'th position.
+         */
+        int mapId(int i) const { return _sel.p.m.mapid[i]; }
+        //! Returns the mass for the \p i'th position.
+        real mass(int i) const { return _sel.m[i]; }
+        //! Returns the charge for the \p i'th position.
+        real charge(int i) const { return _sel.q[i]; }
+        //! Returns the number of atoms contributing to the \p i'th position.
+        int atomCount(int i) const
+            { return _sel.p.m.mapb.index[i+1] - _sel.p.m.mapb.index[i]; }
+        //! Returns the atom indices contributing to the \p i'th position.
+        const int *atomIndices(int i) const
+            { return _sel.g ? _sel.g->index + _sel.p.m.mapb.index[i] : NULL; }
+        //! Returns the covered fraction for the current frame.
+        real cfrac() const { return _sel.cfrac; }
+        //! Deprecated method for direct access to position data.
+        const gmx_ana_pos_t *positions() const { return &_sel.p; }
+        //! Deprecated method for direct access to atom index data.
+        gmx_ana_index_t *indexGroup() const { return _sel.g; }
+        //! Deprecated method for direct access to to mapped ID array.
+        int *mapIds() const { return _sel.p.m.mapid; }
+
+        //! Returns true if the given flag is set.
+        bool hasFlag(SelectionFlag flag) const { return _flags.test(flag); }
+        //! Sets the flags for this selection.
+        void setFlags(SelectionFlags flags) { _flags = flags; }
+        /*! \brief
+         * Sets the ID for the \p i'th position for use with mapId().
+         */
+        void setOriginalId(int i, int id) { _sel.p.m.orgid[i] = id; }
+        /*! \brief
+         * Initializes information about covered fractions.
+         *
+         * \param[in] type Type of covered fraction required.
+         * \returns   True if the covered fraction can be calculated for the
+         *      selection.
+         */
+        bool initCoveredFraction(e_coverfrac_t type);
+
+        /*! \brief
+         * Prints out one-line description of the selection.
+         *
+         * \param[in] fp      Where to print the information.
+         */
+        void printInfo(FILE *fp) const;
+        /*! \brief
+         * Prints out extended information about the selection for debugging.
+         *
+         * \param[in] fp      Where to print the information.
+         * \param[in] nmaxind Maximum number of values to print in lists
+         *      (-1 = print all).
+         */
+        void printDebugInfo(FILE *fp, int nmaxind) const;
+
+        gmx_ana_selection_t     _sel;
+
+    private:
+        ~Selection();
+
+        SelectionFlags          _flags;
+
+        friend class SelectionCollection;
+
+        // Disallow copy and assign.
+        Selection(const Selection &);
+        void operator =(const Selection &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/selection/selectioncollection-impl.h b/src/gromacs/selection/selectioncollection-impl.h
new file mode 100644 (file)
index 0000000..acf7d91
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::SelectionCollection.
+ *
+ * This header also defines ::gmx_ana_selcollection_t, which is used in the old
+ * C code for handling selection collections.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONCOLLECTION_IMPL_H
+#define GMX_SELECTION_SELECTIONCOLLECTION_IMPL_H
+
+#include <string>
+#include <vector>
+
+#include <typedefs.h>
+
+#include "../options/options.h"
+#include "../utility/flags.h"
+#include "indexutil.h"
+#include "selectioncollection.h"
+
+namespace gmx
+{
+class Selection;
+}
+
+/*! \internal \brief
+ * Information for a collection of selections.
+ *
+ * \ingroup module_selection
+ */
+struct gmx_ana_selcollection_t
+{
+    /** Root of the selection element tree. */
+    struct t_selelem           *root;
+    /** Array of compiled selections. */
+    std::vector<gmx::Selection *>  sel;
+    /** Number of variables defined. */
+    int                            nvars;
+    /** Selection strings for variables. */
+    char                         **varstrs;
+
+    /** Topology for the collection. */
+    t_topology                    *top;
+    /** Index group that contains all the atoms. */
+    struct gmx_ana_index_t         gall;
+    /** Position calculation collection used for selection position evaluation. */
+    struct gmx_ana_poscalc_coll_t *pcc;
+    /** Memory pool used for selection evaluation. */
+    struct gmx_sel_mempool_t      *mempool;
+    /** Parser symbol table. */
+    struct gmx_sel_symtab_t     *symtab;
+};
+
+namespace gmx
+{
+
+class MessageStringCollector;
+class SelectionOptionStorage;
+
+/*! \internal \brief
+ * Private implemention class for SelectionCollection.
+ *
+ * \ingroup module_selection
+ */
+class SelectionCollection::Impl
+{
+    public:
+        struct SelectionRequest
+        {
+            SelectionRequest(const std::string &name, const std::string &descr,
+                             SelectionOptionStorage *storage)
+                : name(name), descr(descr), storage(storage)
+            { }
+
+            int count() const;
+
+            std::string                 name;
+            std::string                 descr;
+            SelectionOptionStorage     *storage;
+        };
+
+        //! Shorthand for a list of selections stored internally.
+        typedef std::vector<Selection *> SelectionList;
+        //! Shorthand for a list of selection requests.
+        typedef std::vector<SelectionRequest> RequestList;
+
+        //! Possible flags for the selection collection.
+        enum Flag
+        {
+            efOwnPositionCollection = 1<<0,
+            efExternalGroupsSet     = 1<<1
+        };
+        //! Holds a collection of Flag values.
+        typedef FlagsTemplate<Flag> Flags;
+
+        //! Creates a new selection collection.
+        explicit Impl(gmx_ana_poscalc_coll_t *pcc);
+        ~Impl();
+
+        //! Returns true if the given flag has been set.
+        bool hasFlag(Flag flag) const { return _flags.test(flag); }
+        //! Clears the symbol table of the selection collection.
+        void clearSymbolTable();
+        /*! \brief
+         * Helper function that runs the parser once the tokenizer has been
+         * initialized.
+         *
+         * \param[in,out] scanner Scanner data structure.
+         * \param[in]     maxnr   Maximum number of selections to parse
+         *      (if -1, parse as many as provided by the user).
+         * \param[out]    output  Vector to which parsed selections are
+         *      appended.
+         *
+         * Does not clear \p output.
+         */
+        void runParser(void *scanner, int maxnr,
+                       std::vector<Selection *> *output);
+        void requestSelections(const std::string &name,
+                               const std::string &descr,
+                               SelectionOptionStorage *storage);
+        void resolveExternalGroups(struct t_selelem *root,
+                                   MessageStringCollector *errors);
+
+        //! Internal data, used for interfacing with old C code.
+        gmx_ana_selcollection_t _sc;
+        //! Options object for setting global properties on the collection.
+        Options                 _options;
+        //! Default reference position type for selections.
+        std::string             _rpost;
+        //! Default output position type for selections.
+        std::string             _spost;
+        /*! \brief
+         * Debugging level for the collection.
+         *
+         * Possible values:
+         *  - 0: no debugging
+         *  - 1: print selection trees after parsing and compilation
+         *  - 2: like 1, also print intermediate compilation trees
+         *  - 3: like 1, also print the tree after evaluation
+         *  - 4: combine 2 and 3
+         */
+        int                     _debugLevel;
+        //! Flags for various properties of the collection.
+        Flags                   _flags;
+        //! External index groups (can be NULL).
+        gmx_ana_indexgrps_t    *_grps;
+        //! List of selections requested for later parsing.
+        RequestList             _requests;
+};
+
+} // namespace gmx
+
+/*! \addtogroup module_selection
+ * \{
+ */
+
+/* In compiler.cpp */
+/*! \internal \brief
+ * Prepares the selections for evaluation and performs some optimizations.
+ */
+void
+gmx_ana_selcollection_compile(gmx::SelectionCollection *coll);
+
+/* In evaluate.cpp */
+/*! \internal \brief
+ * Evaluates the selection.
+ */
+void
+gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
+                               t_trxframe *fr, t_pbc *pbc);
+/*! \internal \brief
+ * Evaluates the largest possible index groups from dynamic selections.
+ */
+void
+gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes);
+
+/*!\}*/
+
+#endif
diff --git a/src/gromacs/selection/selectioncollection.cpp b/src/gromacs/selection/selectioncollection.cpp
new file mode 100644 (file)
index 0000000..085279b
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::SelectionCollection.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstdio>
+
+#include <smalloc.h>
+#include <statutil.h>
+#include <string2.h>
+#include <xvgr.h>
+
+#include "poscalc.h"
+#include "selmethod.h"
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectioncollection.h"
+
+#include "mempool.h"
+#include "scanner.h"
+#include "selectioncollection-impl.h"
+#include "selectionoptionstorage.h"
+#include "selelem.h"
+#include "selmethod.h"
+#include "symrec.h"
+
+/* In parser.y */
+/*! \brief
+ * Parser function generated by Bison.
+ */
+int
+_gmx_sel_yybparse(void *scanner);
+
+namespace gmx
+{
+
+/********************************************************************
+ * SelectionCollection::Impl
+ */
+
+int SelectionCollection::Impl::SelectionRequest::count() const
+{
+    return storage->maxValueCount();
+}
+
+SelectionCollection::Impl::Impl(gmx_ana_poscalc_coll_t *pcc)
+    : _options("selection", "Common selection control"),
+      _debugLevel(0), _grps(NULL)
+{
+    _sc.root      = NULL;
+    _sc.nvars     = 0;
+    _sc.varstrs   = NULL;
+    _sc.top       = NULL;
+    gmx_ana_index_clear(&_sc.gall);
+    _sc.pcc       = pcc;
+    _sc.mempool   = NULL;
+    _sc.symtab    = NULL;
+
+    // TODO: This is not exception-safe if any called function throws.
+    if (_sc.pcc == NULL)
+    {
+        int rc = gmx_ana_poscalc_coll_create(&_sc.pcc);
+        if (rc != 0)
+        {
+            // TODO: A more reasonable error
+            GMX_THROW(InternalError("Failed to create position calculation collection"));
+        }
+        _flags.set(Impl::efOwnPositionCollection);
+    }
+    _gmx_sel_symtab_create(&_sc.symtab);
+    gmx_ana_selmethod_register_defaults(_sc.symtab);
+}
+
+
+SelectionCollection::Impl::~Impl()
+{
+    _gmx_selelem_free_chain(_sc.root);
+    SelectionList::const_iterator isel;
+    for (isel = _sc.sel.begin(); isel != _sc.sel.end(); ++isel)
+    {
+        delete *isel;
+    }
+    for (int i = 0; i < _sc.nvars; ++i)
+    {
+        sfree(_sc.varstrs[i]);
+    }
+    sfree(_sc.varstrs);
+    gmx_ana_index_deinit(&_sc.gall);
+    if (_sc.mempool)
+    {
+        _gmx_sel_mempool_destroy(_sc.mempool);
+    }
+    if (hasFlag(efOwnPositionCollection))
+    {
+        gmx_ana_poscalc_coll_free(_sc.pcc);
+    }
+    clearSymbolTable();
+}
+
+
+void
+SelectionCollection::Impl::clearSymbolTable()
+{
+    if (_sc.symtab)
+    {
+        _gmx_sel_symtab_free(_sc.symtab);
+        _sc.symtab = NULL;
+    }
+}
+
+
+void
+SelectionCollection::Impl::runParser(yyscan_t scanner, int maxnr,
+                                     std::vector<Selection *> *output)
+{
+    gmx_ana_selcollection_t *sc = &_sc;
+    MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    GMX_ASSERT(sc == _gmx_sel_lexer_selcollection(scanner),
+               "Incorrectly initialized lexer");
+
+    int oldCount = sc->sel.size();
+    int bOk = !_gmx_sel_yybparse(scanner);
+    _gmx_sel_free_lexer(scanner);
+    int nr = sc->sel.size() - oldCount;
+    if (maxnr > 0 && nr != maxnr)
+    {
+        bOk = false;
+        errors->append("Too few selections provided");
+    }
+
+    if (bOk)
+    {
+        SelectionList::const_iterator i;
+        for (i = _sc.sel.begin() + oldCount; i != _sc.sel.end(); ++i)
+        {
+            output->push_back(*i);
+        }
+    }
+
+    if (!bOk || !errors->isEmpty())
+    {
+        GMX_ASSERT(!bOk && !errors->isEmpty(), "Inconsistent error reporting");
+        GMX_THROW(InvalidInputError(errors->toString()));
+    }
+}
+
+
+void SelectionCollection::Impl::requestSelections(
+        const std::string &name, const std::string &descr,
+        SelectionOptionStorage *storage)
+{
+    _requests.push_back(SelectionRequest(name, descr, storage));
+}
+
+
+void SelectionCollection::Impl::resolveExternalGroups(
+        t_selelem *root, MessageStringCollector *errors)
+{
+
+    if (root->type == SEL_GROUPREF)
+    {
+        bool bOk = true;
+        if (_grps == NULL)
+        {
+            // TODO: Improve error messages
+            errors->append("Unknown group referenced in a selection");
+            bOk = false;
+        }
+        else if (root->u.gref.name != NULL)
+        {
+            char *name = root->u.gref.name;
+            if (!gmx_ana_indexgrps_find(&root->u.cgrp, _grps, name))
+            {
+                // TODO: Improve error messages
+                errors->append("Unknown group referenced in a selection");
+                bOk = false;
+            }
+            else
+            {
+                sfree(name);
+            }
+        }
+        else
+        {
+            if (!gmx_ana_indexgrps_extract(&root->u.cgrp, _grps,
+                                           root->u.gref.id))
+            {
+                // TODO: Improve error messages
+                errors->append("Unknown group referenced in a selection");
+                bOk = false;
+            }
+        }
+        if (bOk)
+        {
+            root->type = SEL_CONST;
+            root->name = root->u.cgrp.name;
+        }
+    }
+
+    t_selelem *child = root->child;
+    while (child != NULL)
+    {
+        resolveExternalGroups(child, errors);
+        child = child->next;
+    }
+}
+
+
+/********************************************************************
+ * SelectionCollection
+ */
+
+SelectionCollection::SelectionCollection(gmx_ana_poscalc_coll_t *pcc)
+    : _impl(new Impl(pcc))
+{
+}
+
+
+SelectionCollection::~SelectionCollection()
+{
+    delete _impl;
+}
+
+
+Options *
+SelectionCollection::initOptions()
+{
+    static const char * const debug_levels[]
+        = {"no", "basic", "compile", "eval", "full", NULL};
+    /*
+    static const char * const desc[] = {
+        "This program supports selections in addition to traditional",
+        "index files. Use [TT]-select help[tt] for additional information,",
+        "or type 'help' in the selection prompt.",
+        NULL,
+    };
+    options.setDescription(desc);
+    */
+
+    Options &options = _impl->_options;
+    const char **postypes = gmx_ana_poscalc_create_type_enum(TRUE);
+    if (postypes == NULL)
+    {
+        // TODO: Use an out-of-memory exception here
+        GMX_THROW(InternalError("Could not create position calculation enum"));
+    }
+    options.addOption(StringOption("selrpos").enumValue(postypes + 1)
+                          .store(&_impl->_rpost).defaultValue(postypes[1])
+                          .description("Selection reference positions"));
+    options.addOption(StringOption("seltype").enumValue(postypes + 1)
+                          .store(&_impl->_spost).defaultValue(postypes[1])
+                          .description("Default selection output positions"));
+    GMX_RELEASE_ASSERT(_impl->_debugLevel >= 0 && _impl->_debugLevel <= 4,
+                       "Debug level out of range");
+    options.addOption(StringOption("seldebug").hidden(_impl->_debugLevel == 0)
+                          .enumValue(debug_levels)
+                          .defaultValue(debug_levels[_impl->_debugLevel])
+                          .storeEnumIndex(&_impl->_debugLevel)
+                          .description("Print out selection trees for debugging"));
+    sfree(postypes);
+
+    return &_impl->_options;
+}
+
+
+void
+SelectionCollection::setReferencePosType(const char *type)
+{
+    GMX_RELEASE_ASSERT(type != NULL, "Cannot assign NULL position type");
+    //! Check that the type is valid.
+    e_poscalc_t  dummytype;
+    int          dummyflags;
+    gmx_ana_poscalc_type_from_enum(type, &dummytype, &dummyflags);
+    _impl->_rpost = type;
+}
+
+
+void
+SelectionCollection::setOutputPosType(const char *type)
+{
+    GMX_RELEASE_ASSERT(type != NULL, "Cannot assign NULL position type");
+    //! Check that the type is valid.
+    e_poscalc_t  dummytype;
+    int          dummyflags;
+    gmx_ana_poscalc_type_from_enum(type, &dummytype, &dummyflags);
+    _impl->_spost = type;
+}
+
+
+void
+SelectionCollection::setDebugLevel(int debuglevel)
+{
+    _impl->_debugLevel = debuglevel;
+}
+
+
+void
+SelectionCollection::setTopology(t_topology *top, int natoms)
+{
+    gmx_ana_selcollection_t *sc = &_impl->_sc;
+    gmx_ana_poscalc_coll_set_topology(sc->pcc, top);
+    sc->top = top;
+
+    /* Get the number of atoms from the topology if it is not given */
+    if (natoms <= 0)
+    {
+        if (sc->top == NULL)
+        {
+            GMX_THROW(APIError("Selections need either the topology or the number of atoms"));
+        }
+        natoms = sc->top->atoms.nr;
+    }
+
+    gmx_ana_index_init_simple(&sc->gall, natoms, NULL);
+}
+
+
+void
+SelectionCollection::setIndexGroups(gmx_ana_indexgrps_t *grps)
+{
+    GMX_RELEASE_ASSERT(grps == NULL || !_impl->hasFlag(Impl::efExternalGroupsSet),
+                       "Can only set external groups once or clear them afterwards");
+    _impl->_grps = grps;
+    _impl->_flags.set(Impl::efExternalGroupsSet);
+
+    MessageStringCollector errors;
+    t_selelem *root = _impl->_sc.root;
+    while (root != NULL)
+    {
+        _impl->resolveExternalGroups(root, &errors);
+        root = root->next;
+    }
+    if (!errors.isEmpty())
+    {
+        GMX_THROW(InvalidInputError(errors.toString()));
+    }
+}
+
+
+bool
+SelectionCollection::requiresTopology() const
+{
+    t_selelem   *sel;
+    e_poscalc_t  type;
+    int          flags;
+
+    if (!_impl->_rpost.empty())
+    {
+        flags = 0;
+        // Should not throw, because has been checked earlier.
+        gmx_ana_poscalc_type_from_enum(_impl->_rpost.c_str(), &type, &flags);
+        if (type != POS_ATOM)
+        {
+            return TRUE;
+        }
+    }
+    if (!_impl->_spost.empty())
+    {
+        flags = 0;
+        // Should not throw, because has been checked earlier.
+        gmx_ana_poscalc_type_from_enum(_impl->_spost.c_str(), &type, &flags);
+        if (type != POS_ATOM)
+        {
+            return TRUE;
+        }
+    }
+
+    sel = _impl->_sc.root;
+    while (sel)
+    {
+        if (_gmx_selelem_requires_top(sel))
+        {
+            return TRUE;
+        }
+        sel = sel->next;
+    }
+    return FALSE;
+}
+
+
+class RequestsClearer
+{
+    public:
+        RequestsClearer(SelectionCollection::Impl::RequestList *requests)
+            : _requests(requests)
+        {
+        }
+        ~RequestsClearer()
+        {
+            _requests->clear();
+        }
+
+    private:
+        SelectionCollection::Impl::RequestList *_requests;
+};
+
+
+void
+SelectionCollection::parseRequestedFromStdin(bool bInteractive)
+{
+    RequestsClearer clearRequestsOnExit(&_impl->_requests);
+
+    Impl::RequestList::const_iterator i;
+    for (i = _impl->_requests.begin(); i != _impl->_requests.end(); ++i)
+    {
+        const Impl::SelectionRequest &request = *i;
+        if (bInteractive)
+        {
+            std::fprintf(stderr, "\nSpecify ");
+            if (request.count() < 0)
+            {
+                std::fprintf(stderr, "any number of selections");
+            }
+            else if (request.count() == 1)
+            {
+                std::fprintf(stderr, "a selection");
+            }
+            else
+            {
+                std::fprintf(stderr, "%d selections", request.count());
+            }
+            std::fprintf(stderr, " for option '%s' (%s):\n",
+                         request.name.c_str(), request.descr.c_str());
+            std::fprintf(stderr, "(one selection per line, 'help' for help%s)\n",
+                         request.count() < 0 ? ", Ctrl-D to end" : "");
+        }
+        std::vector<Selection *> selections;
+        parseFromStdin(request.count(), bInteractive, &selections);
+        request.storage->addSelections(selections, true);
+    }
+}
+
+
+void
+SelectionCollection::parseRequestedFromString(const std::string &str)
+{
+    RequestsClearer clearRequestsOnExit(&_impl->_requests);
+
+    std::vector<Selection *> selections;
+    parseFromString(str, &selections);
+
+    std::vector<Selection *>::const_iterator first = selections.begin();
+    std::vector<Selection *>::const_iterator last = first;
+    Impl::RequestList::const_iterator i;
+    for (i = _impl->_requests.begin(); i != _impl->_requests.end(); ++i)
+    {
+        const Impl::SelectionRequest &request = *i;
+        if (request.count() > 0)
+        {
+            if (selections.end() - first < request.count())
+            {
+                GMX_THROW(InvalidInputError("Too few selections provided"));
+            }
+            last = first + request.count();
+        }
+        else
+        {
+            if (i != _impl->_requests.end() - 1)
+            {
+                GMX_THROW(APIError("Request for all selections not the last option"));
+            }
+            last = selections.end();
+        }
+        std::vector<Selection *> curr(first, last);
+        request.storage->addSelections(curr, true);
+        first = last;
+    }
+    if (last != selections.end())
+    {
+        GMX_THROW(InvalidInputError("Too many selections provided"));
+    }
+}
+
+
+void
+SelectionCollection::parseFromStdin(int nr, bool bInteractive,
+                                    std::vector<Selection *> *output)
+{
+    yyscan_t scanner;
+
+    _gmx_sel_init_lexer(&scanner, &_impl->_sc, bInteractive, nr,
+                        _impl->hasFlag(Impl::efExternalGroupsSet),
+                        _impl->_grps);
+    /* We don't set the lexer input here, which causes it to use a special
+     * internal implementation for reading from stdin. */
+    _impl->runParser(scanner, nr, output);
+}
+
+
+void
+SelectionCollection::parseFromFile(const std::string &filename,
+                                   std::vector<Selection *> *output)
+{
+    yyscan_t scanner;
+    FILE *fp;
+
+    _gmx_sel_init_lexer(&scanner, &_impl->_sc, false, -1,
+                        _impl->hasFlag(Impl::efExternalGroupsSet),
+                        _impl->_grps);
+    fp = ffopen(filename.c_str(), "r");
+    _gmx_sel_set_lex_input_file(scanner, fp);
+    // TODO: Use RAII
+    try
+    {
+        _impl->runParser(scanner, -1, output);
+    }
+    catch (std::exception &)
+    {
+        ffclose(fp);
+        throw;
+    }
+    ffclose(fp);
+}
+
+
+void
+SelectionCollection::parseFromString(const std::string &str,
+                                     std::vector<Selection *> *output)
+{
+    yyscan_t scanner;
+
+    _gmx_sel_init_lexer(&scanner, &_impl->_sc, false, -1,
+                        _impl->hasFlag(Impl::efExternalGroupsSet),
+                        _impl->_grps);
+    _gmx_sel_set_lex_input_str(scanner, str.c_str());
+    _impl->runParser(scanner, -1, output);
+}
+
+
+void
+SelectionCollection::compile()
+{
+    if (_impl->_sc.top == NULL && requiresTopology())
+    {
+        GMX_THROW(InconsistentInputError("Selection requires topology information, but none provided"));
+    }
+    if (!_impl->hasFlag(Impl::efExternalGroupsSet))
+    {
+        setIndexGroups(NULL);
+    }
+    if (_impl->_debugLevel >= 1)
+    {
+        printTree(stderr, false);
+    }
+    gmx_ana_selcollection_compile(this);
+    if (_impl->hasFlag(Impl::efOwnPositionCollection))
+    {
+        if (_impl->_debugLevel >= 1)
+        {
+            std::fprintf(stderr, "\n");
+            printTree(stderr, false);
+            std::fprintf(stderr, "\n");
+            gmx_ana_poscalc_coll_print_tree(stderr, _impl->_sc.pcc);
+            std::fprintf(stderr, "\n");
+        }
+        gmx_ana_poscalc_init_eval(_impl->_sc.pcc);
+        if (_impl->_debugLevel >= 1)
+        {
+            gmx_ana_poscalc_coll_print_tree(stderr, _impl->_sc.pcc);
+            std::fprintf(stderr, "\n");
+        }
+    }
+}
+
+
+void
+SelectionCollection::evaluate(t_trxframe *fr, t_pbc *pbc)
+{
+    if (_impl->hasFlag(Impl::efOwnPositionCollection))
+    {
+        gmx_ana_poscalc_init_frame(_impl->_sc.pcc);
+    }
+    gmx_ana_selcollection_evaluate(&_impl->_sc, fr, pbc);
+    if (_impl->_debugLevel >= 3)
+    {
+        std::fprintf(stderr, "\n");
+        printTree(stderr, true);
+    }
+}
+
+
+void
+SelectionCollection::evaluateFinal(int nframes)
+{
+    gmx_ana_selcollection_evaluate_fin(&_impl->_sc, nframes);
+}
+
+
+void
+SelectionCollection::printTree(FILE *fp, bool bValues) const
+{
+    t_selelem *sel;
+
+    sel = _impl->_sc.root;
+    while (sel)
+    {
+        _gmx_selelem_print_tree(fp, sel, bValues, 0);
+        sel = sel->next;
+    }
+}
+
+
+void
+SelectionCollection::printXvgrInfo(FILE *out, output_env_t oenv) const
+{
+    int  i;
+
+    if (output_env_get_xvg_format(oenv) != exvgNONE)
+    {
+        gmx_ana_selcollection_t *sc = &_impl->_sc;
+        std::fprintf(out, "# Selections:\n");
+        for (i = 0; i < sc->nvars; ++i)
+        {
+            std::fprintf(out, "#   %s\n", sc->varstrs[i]);
+        }
+        for (i = 0; i < (int)sc->sel.size(); ++i)
+        {
+            std::fprintf(out, "#   %s\n", sc->sel[i]->_sel.selstr);
+        }
+        std::fprintf(out, "#\n");
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/selection/selectioncollection.h b/src/gromacs/selection/selectioncollection.h
new file mode 100644 (file)
index 0000000..e1d67d2
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::SelectionCollection.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONCOLLECTION_H
+#define GMX_SELECTION_SELECTIONCOLLECTION_H
+
+#include <string>
+#include <vector>
+
+#include <typedefs.h>
+
+struct gmx_ana_indexgrps_t;
+struct gmx_ana_poscalc_coll_t;
+
+namespace gmx
+{
+
+class Options;
+class Selection;
+class SelectionOptionStorage;
+
+/*! \libinternal \brief
+ * Collection of selections.
+ *
+ * Some default values must then be set with
+ * gmx_ana_selcollection_set_refpostype() and
+ * gmx_ana_selcollection_set_outpostype().
+ *
+ * After setting the default values, one or more selections can be parsed
+ * with one or more calls to parseFromStdin(), parseFromFile(), and/or
+ * parseFromString().  After all selections are parsed, the topology must be
+ * set with setTopology() unless requiresTopology() returns false (the topology
+ * can also be set earlier).  Once all selections are parsed, they must be
+ * compiled all at once using compile().
+ * After compilation, dynamic selections have the maximum number of atoms they
+ * can evaluate to, but positions have undefined values.  evaluate() can be
+ * used to update the selections for a new frame.
+ * evaluateFinal() can be called after all the frames have been processed to
+ * restore the selection values back to the ones they were after compile().
+ *
+ * At any point, requiresTopology() can be called to see whether the
+ * information provided so far requires loading the topology.
+ * printTree() can be used to print the internal representation of the
+ * selections (mostly useful for debugging).
+ *
+ * \inlibraryapi
+ * \ingroup module_selection
+ */
+class SelectionCollection
+{
+    public:
+        /*! \brief
+         * Creates an empty selection collection.
+         *
+         * \param[in] pcc  Position calculation collection to use for selection
+         *      evaluation.
+         *
+         * If \p pcc is NULL, an internal collection is created and managed by
+         * the object.
+         */
+        explicit SelectionCollection(gmx_ana_poscalc_coll_t *pcc);
+        ~SelectionCollection();
+
+        /*! \brief
+         * Initializes options for setting global properties on the collection.
+         *
+         * The return value should not be deleted by the caller.
+         */
+        Options *initOptions();
+
+        /*! \brief
+         * Sets the default reference position handling for a selection
+         * collection.
+         *
+         * \param[in]     type      Default selection reference position type
+         *   (one of the strings acceptable for gmx_ana_poscalc_type_from_enum()).
+         *
+         * Should be called before calling the parser functions, unless
+         * initOptions() has been called.  In the latter case, can still be
+         * used to override the default value and/or the value provided through
+         * the Options object.
+         */
+        void setReferencePosType(const char *type);
+        /*! \brief
+         * Sets the default reference position handling for a selection
+         * collection.
+         *
+         * \param[in]     type      Default selection output position type
+         *   (one of the strings acceptable for gmx_ana_poscalc_type_from_enum()).
+         *
+         * Should be called before calling the parser functions, unless
+         * initOptions() has been called.  In the latter case, can still be
+         * used to override the default value and/or the value provided through
+         * the Options object.
+         */
+        void setOutputPosType(const char *type);
+        /*! \brief
+         * Sets the debugging level for the selection collection.
+         */
+        void setDebugLevel(int debuglevel);
+
+        /*! \brief
+         * Returns true if the collection requires topology information for
+         * evaluation.
+         *
+         * \returns true if any selection in the collection requires topology
+         *      information.
+         *
+         * Before the parser functions have been called, the return value is
+         * based just on the position types set.
+         * After parser functions have been called, the return value also takes
+         * into account the selection keywords used.
+         */
+        bool requiresTopology() const;
+        /*! \brief
+         * Sets the topology for the collection.
+         *
+         * \param[in]     top       Topology data.
+         * \param[in]     natoms    Number of atoms. If <=0, the number of
+         *      atoms in the topology is used.
+         * \retval  0 on success.
+         * \retval  ::eeInvalidValue if \p top is NULL and \p natoms <= 0.
+         *
+         * The topology is also set for the position calculation collection
+         * associated with the collection.
+         *
+         * \p natoms determines the largest atom index that can be selected by
+         * the selection: even if the topology contains more atoms, they will
+         * not be selected.
+         */
+        void setTopology(t_topology *top, int natoms);
+        /*! \brief
+         * Sets the external index groups to use for the selections.
+         *
+         * Can be called only once with non-NULL \p grps.
+         */
+        void setIndexGroups(gmx_ana_indexgrps_t *grps);
+        /*! \brief
+         * Parses selection(s) from standard input for options not yet
+         * provided.
+         *
+         * \param[in]  bInteractive Whether the parser should behave
+         *      interactively.
+         *
+         * This method cooperates with SelectionOption to allow interactive
+         * input of missing selections after all options have been processed.
+         * It should be called after the Options::finish() method has been
+         * called on all options that add selections to this collection.
+         */
+        void parseRequestedFromStdin(bool bInteractive);
+        /*! \brief
+         * Parses selection(s) from a string for options not yet provided.
+         *
+         * \param[in]  str     String to parse.
+         *
+         * \see parseRequestedFromStdin()
+         */
+        void parseRequestedFromString(const std::string &str);
+        /*! \brief
+         * Parses selection(s) from standard input.
+         *
+         * \param[in]  count    Number of selections to parse
+         *      (if -1, parse as many as provided by the user).
+         * \param[in]  bInteractive Whether the parser should behave
+         *      interactively.
+         * \param[out] output   Vector to which parsed selections are appended.
+         * \retval     0 on success.
+         * \retval     ::eeInvalidInput on syntax error (an interactive parser
+         *      only returns this if an incorrect number of selections is
+         *      provided).
+         *
+         * Parsed selections are appended to \p output without clearing it
+         * first.  If parsing fails, \p output is not modified.
+         *
+         * The objects returned in \p output remain valid for the lifetime of
+         * the selection collection, and should not be freed by the user.
+         * Some information about the selections only becomes available once
+         * compile() has been called.
+         */
+        void parseFromStdin(int count, bool bInteractive,
+                            std::vector<Selection *> *output);
+        /*! \brief
+         * Parses selection(s) from a file.
+         *
+         * \param[in]  filename Name of the file to parse selections from.
+         * \param[out] output   Vector to which parsed selections are appended.
+         * \retval     0 on success.
+         * \retval     ::eeInvalidInput on syntax error.
+         *
+         * Parsed selections are appended to \p output without clearing it
+         * first.  If parsing fails, \p output is not modified.
+         *
+         * The objects returned in \p output remain valid for the lifetime of
+         * the selection collection, and should not be freed by the user.
+         * Some information about the selections only becomes available once
+         * compile() has been called.
+         */
+        void parseFromFile(const std::string &filename,
+                           std::vector<Selection *> *output);
+        /*! \brief
+         * Parses selection(s) from a string.
+         *
+         * \param[in]  str      String to parse selections from.
+         * \param[out] output   Vector to which parsed selections are appended.
+         * \retval     0 on success.
+         * \retval     ::eeInvalidInput on syntax error.
+         *
+         * Parsed selections are appended to \p output without clearing it
+         * first.  If parsing fails, \p output is not modified.
+         *
+         * The objects returned in \p output remain valid for the lifetime of
+         * the selection collection, and should not be freed by the user.
+         * Some information about the selections only becomes available once
+         * compile() has been called.
+         */
+        void parseFromString(const std::string &str,
+                             std::vector<Selection *> *output);
+        /*! \brief
+         * Prepares the selections for evaluation and performs optimizations.
+         *
+         * \retval  0 on successful compilation, a non-zero error code on error.
+         *
+         * Before compilation, selections should have been added to the
+         * collection using the parseFrom*() functions.
+         * The compiled selection collection can be passed to evaluate() to
+         * evaluate the selection for a frame.
+         * If an error occurs, the collection is cleared.
+         *
+         * The covered fraction information is initialized to ::CFRAC_NONE for
+         * all selections.
+         */
+        void compile();
+        /*! \brief
+         * Evaluates selections in the collection.
+         *
+         * \param[in] fr  Frame for which the evaluation should be carried out.
+         * \param[in] pbc PBC data, or NULL if no PBC should be used.
+         * \returns   0 on successful evaluation, a non-zero error code on error.
+         */
+        void evaluate(t_trxframe *fr, t_pbc *pbc);
+        /*! \brief
+         * Evaluates the largest possible index groups from dynamic selections.
+         *
+         * \param[in] nframes Total number of frames.
+         *
+         * This function does not throw.
+         */
+        void evaluateFinal(int nframes);
+
+        /*! \brief
+         * Prints a human-readable version of the internal selection element
+         * tree.
+         *
+         * \param[in] fp      File handle to receive the output.
+         * \param[in] bValues If true, the evaluated values of selection
+         *      elements are printed as well.
+         */
+        void printTree(FILE *fp, bool bValues) const;
+        /*! \brief
+         * Prints the selection strings into an XVGR file as comments.
+         *
+         * \param[in] fp   Output file.
+         * \param[in] oenv Output options structure.
+         */
+        void printXvgrInfo(FILE *fp, output_env_t oenv) const;
+
+        class Impl;
+        Impl                   *_impl;
+
+    private:
+        /*! \brief
+         * Needed for handling delayed selection parsing requests.
+         */
+        friend class SelectionOptionStorage;
+
+        // Disallow copy and assign.
+        SelectionCollection(const SelectionCollection &);
+        void operator =(const SelectionCollection &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/selection/selectionenums.h b/src/gromacs/selection/selectionenums.h
new file mode 100644 (file)
index 0000000..cdbd201
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares common types used in selections.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONENUMS_H
+#define GMX_SELECTION_SELECTIONENUMS_H
+
+#include "../utility/flags.h"
+
+/*! \brief
+ * Defines the type of covered fraction.
+ *
+ * \inpublicapi
+ */
+typedef enum
+{
+    CFRAC_NONE,         /**< No covered fraction (everything covered). */
+    CFRAC_SOLIDANGLE    /**< Fraction of a solid (3D) angle covered. */
+} e_coverfrac_t;
+
+namespace gmx
+{
+
+/*! \brief
+ * Flags for options.
+ *
+ * These flags are not part of the public interface, even though they are in an
+ * installed header.  They are needed in the implementation of SelectionOption.
+ */
+enum SelectionFlag
+{
+    efOnlyStatic        = 1<<0,
+    efOnlyAtoms         = 1<<1,
+    //! Whether ::POS_MASKONLY should be used for output position evaluation.
+    efDynamicMask       = 1<<2,
+    efDynamicOnlyWhole  = 1<<3,
+    //! Whether velocities of output positions should be evaluated.
+    efEvaluateVelocities        = 1<<5,
+    //! Whether forces on output positions should be evaluated.
+    efEvaluateForces            = 1<<6,
+};
+
+//! Holds a collection of ::SelectionFlag values.
+typedef FlagsTemplate<SelectionFlag> SelectionFlags;
+
+}
+
+#endif
diff --git a/src/gromacs/selection/selectionoption.cpp b/src/gromacs/selection/selectionoption.cpp
new file mode 100644 (file)
index 0000000..3521b6c
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in selectionoption.h and selectionoptionstorage.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#include "gromacs/selection/selectionoption.h"
+
+#include <string>
+#include <vector>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectioncollection.h"
+
+#include "selectioncollection-impl.h"
+#include "selectionoptionstorage.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * SelectionOptionStorage
+ */
+
+SelectionOptionStorage::SelectionOptionStorage(const SelectionOption &settings,
+                                               Options *options)
+    : MyBase(settings, options,
+             OptionFlags() | efNoDefaultValue | efDontCheckMinimumCount),
+      _selectionFlags(settings._selectionFlags), _adjuster(NULL)
+{
+    options->globalProperties().request(eogpSelectionCollection);
+    if (settings._adjuster != NULL)
+    {
+        _adjuster = new SelectionOptionAdjuster(this);
+        *settings._adjuster = _adjuster;
+    }
+}
+
+
+SelectionOptionStorage::~SelectionOptionStorage()
+{
+    delete _adjuster;
+}
+
+
+std::string SelectionOptionStorage::formatValue(int i) const
+{
+    Selection *sel = values().at(i);
+    return (sel != NULL ? sel->selectionText() : "");
+}
+
+
+void SelectionOptionStorage::addSelections(
+        const std::vector<Selection *> &selections,
+        bool bFullValue)
+{
+    if (bFullValue && selections.size() < static_cast<size_t>(minValueCount()))
+    {
+        GMX_THROW(InvalidInputError("Too few selections provided"));
+    }
+    if (bFullValue)
+    {
+        clearSet();
+    }
+    std::vector<Selection *>::const_iterator i;
+    for (i = selections.begin(); i != selections.end(); ++i)
+    {
+        // TODO: Having this check in the parser would make interactive input
+        // behave better.
+        if (_selectionFlags.test(efOnlyStatic) && (*i)->isDynamic())
+        {
+            GMX_THROW(InvalidInputError("Dynamic selections not supported"));
+        }
+        (*i)->setFlags(_selectionFlags);
+        addValue(*i);
+    }
+    if (bFullValue)
+    {
+        commitValues();
+    }
+}
+
+
+void SelectionOptionStorage::convertValue(const std::string &value)
+{
+    SelectionCollection *sc =
+        hostOptions().globalProperties().selectionCollection();
+    GMX_RELEASE_ASSERT(sc != NULL, "Selection collection is not set");
+
+    std::vector<Selection *> selections;
+    // TODO: Implement reading from a file.
+    sc->parseFromString(value, &selections);
+    addSelections(selections, false);
+}
+
+void SelectionOptionStorage::processSetValues(ValueList *values)
+{
+    if (values->size() > 0 && values->size() < static_cast<size_t>(minValueCount()))
+    {
+        GMX_THROW(InvalidInputError("Too few (valid) values provided"));
+    }
+}
+
+void SelectionOptionStorage::processAll()
+{
+    if ((hasFlag(efRequired) || hasFlag(efSet)) && valueCount() == 0)
+    {
+        SelectionCollection *sc =
+            hostOptions().globalProperties().selectionCollection();
+        GMX_RELEASE_ASSERT(sc != NULL, "Selection collection is not set");
+
+        sc->_impl->requestSelections(name(), description(), this);
+        setFlag(efSet);
+    }
+}
+
+void SelectionOptionStorage::setAllowedValueCount(int count)
+{
+    MessageStringCollector errors;
+    errors.startContext("In option '" + name() + "'");
+    if (count >= 0)
+    {
+        // Should not throw because efDontCheckMinimumCount is set
+        setMinValueCount(count);
+        if (valueCount() > 0 && valueCount() < count)
+        {
+            errors.append("Too few (valid) values provided");
+        }
+    }
+    try
+    {
+        setMaxValueCount(count);
+    }
+    catch (UserInputError &ex)
+    {
+        errors.append(ex.what());
+    }
+    errors.finishContext();
+    if (!errors.isEmpty())
+    {
+        GMX_THROW(InvalidInputError(errors.toString()));
+    }
+}
+
+void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
+{
+    _selectionFlags.set(flag, bSet);
+    ValueList::const_iterator i;
+    for (i = values().begin(); i != values().end(); ++i)
+    {
+        if (_selectionFlags.test(efOnlyStatic) && (*i)->isDynamic())
+        {
+            MessageStringCollector errors;
+            errors.startContext("In option '" + name() + "'");
+            errors.append("Dynamic selections not supported");
+            errors.finishContext();
+            GMX_THROW(InvalidInputError(errors.toString()));
+        }
+        (*i)->setFlags(_selectionFlags);
+    }
+}
+
+
+/********************************************************************
+ * SelectionOptionAdjuster
+ */
+
+SelectionOptionAdjuster::SelectionOptionAdjuster(SelectionOptionStorage *storage)
+    : _storage(*storage)
+{
+}
+
+void SelectionOptionAdjuster::setValueCount(int count)
+{
+    return storage().setAllowedValueCount(count);
+}
+
+void SelectionOptionAdjuster::setEvaluateVelocities(bool bEnabled)
+{
+    return storage().setSelectionFlag(efEvaluateVelocities, bEnabled);
+}
+
+void SelectionOptionAdjuster::setEvaluateForces(bool bEnabled)
+{
+    return storage().setSelectionFlag(efEvaluateForces, bEnabled);
+}
+
+void SelectionOptionAdjuster::setOnlyAtoms(bool bEnabled)
+{
+    return storage().setSelectionFlag(efOnlyAtoms, bEnabled);
+}
+
+void SelectionOptionAdjuster::setOnlyStatic(bool bEnabled)
+{
+    return storage().setSelectionFlag(efOnlyStatic, bEnabled);
+}
+
+void SelectionOptionAdjuster::setDynamicMask(bool bEnabled)
+{
+    return storage().setSelectionFlag(efDynamicMask, bEnabled);
+}
+
+void SelectionOptionAdjuster::setDynamicOnlyWhole(bool bEnabled)
+{
+    return storage().setSelectionFlag(efDynamicOnlyWhole, bEnabled);
+}
+
+
+/********************************************************************
+ * SelectionOption
+ */
+
+AbstractOptionStorage *SelectionOption::createDefaultStorage(Options *options) const
+{
+    return new SelectionOptionStorage(*this, options);
+}
+
+} // namespace gmx
diff --git a/src/gromacs/selection/selectionoption.h b/src/gromacs/selection/selectionoption.h
new file mode 100644 (file)
index 0000000..eff1457
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::SelectionOption.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONOPTION_H
+#define GMX_SELECTION_SELECTIONOPTION_H
+
+#include "../options/abstractoption.h"
+#include "selectionenums.h"
+
+namespace gmx
+{
+
+class Selection;
+class SelectionOptionAdjuster;
+class SelectionOptionStorage;
+
+/*! \brief
+ * Specifies an option that provides selection(s).
+ *
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+class SelectionOption : public OptionTemplate<Selection *, SelectionOption>
+{
+    public:
+        //! Initializes an option with the given name.
+        explicit SelectionOption(const char *name)
+            : MyBase(name), _adjuster(NULL)
+        { }
+
+        /*! \brief
+         * Request velocity evaluation for output positions.
+         */
+        MyClass &evaluateVelocities()
+        { _selectionFlags.set(efEvaluateVelocities); return me(); }
+        /*! \brief
+         * Request force evaluation for output positions.
+         */
+        MyClass &evaluateForces()
+        { _selectionFlags.set(efEvaluateForces); return me(); }
+        /*! \brief
+         * Only accept selections that evaluate to atom positions.
+         *
+         * TODO: This option is not yet implemented.
+         */
+        MyClass &onlyAtoms()
+        { _selectionFlags.set(efOnlyAtoms); return me(); }
+        /*! \brief
+         * Only accept static selections for this option.
+         */
+        MyClass &onlyStatic()
+        { _selectionFlags.set(efOnlyStatic); return me(); }
+        /*! \brief
+         * Handle dynamic selections for this option with position masks.
+         *
+         * Sets ::POS_MASKONLY on the positions for this selection.
+         */
+        MyClass &dynamicMask()
+        { _selectionFlags.set(efDynamicMask); return me(); }
+        /*! \brief
+         * Disallow using atom coordinates as the reference positions.
+         *
+         * TODO: This option is not yet implemented.
+         */
+        MyClass &dynamicOnlyWhole()
+        { _selectionFlags.set(efDynamicOnlyWhole); return me(); }
+
+        /*! \brief
+         * Get an adjuster that can be used to alter the option after creation.
+         *
+         * \see SelectionOptionAdjuster
+         */
+        MyClass &getAdjuster(SelectionOptionAdjuster **adjusterp)
+        { _adjuster = adjusterp; return me(); }
+
+    private:
+        // Disable default value because it is impossible to provide a
+        // Selection object.
+        using MyBase::defaultValue;
+        using MyBase::defaultValueIfSet;
+
+        virtual AbstractOptionStorage *createDefaultStorage(Options *options) const;
+
+        SelectionFlags          _selectionFlags;
+        SelectionOptionAdjuster **_adjuster;
+
+        /*! \brief
+         * Needed to initialize SelectionOptionStorage from this class without
+         * otherwise unnecessary accessors.
+         */
+        friend class SelectionOptionStorage;
+};
+
+
+/*! \brief
+ * Allows changes to a selection option after creation.
+ *
+ * This class provides the necessary interface for changing, e.g., the number
+ * of allowed selections for a selection option after the option has been
+ * created with Options::addOption().  This is needed if the number or other
+ * flags are only known after other options have been parsed.  The main
+ * advantage of this class over custom checks is that if used before
+ * interactive selection prompt, the interactive prompt is updated accordingly.
+ *
+ * When using this class, the option should be initially created with the most
+ * permissive flags, and this class should be used to place restrictions where
+ * appropriate.  Otherwise, values that are provided before adjustments will
+ * need to follow the more strict checks.  In most cases in trajectory analysis
+ * (which is the main use case for selection options), the adjustments should
+ * be done in TrajectoryAnalysisModule::initOptionsDone() for them to take
+ * place before interactive selection prompts.
+ *
+ * An instance of this class for a selection option can be obtained with
+ * SelectionOption::getAdjuster() when the option is created.
+ *
+ * Example use:
+ * \code
+std::vector<Selection *> sel;
+Options options("example", "Example options");
+SelectionOptionAdjuster *adjuster;
+options.addOption(SelectionOption("sel").storeVector(&sel)
+                      .multiValue().getAdjuster(&adjuster));
+// < ... assign values to options ...>
+if ( condition )
+{
+    OptionAdjusterErrorContext context(adjuster, errors);
+    // Put limitations on the selections based on the condition,
+    // which can depend on other option values.
+    int rc = adjuster->setValueCount(2);
+    if (rc == 0)
+    {
+        rc = adjuster->setOnlyStatic(true);
+    }
+    if (rc != 0)
+    {
+        return rc;
+    }
+}
+ * \endcode
+ *
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+class SelectionOptionAdjuster
+{
+    public:
+        /*! \brief
+         * Creates a new adjuster.
+         *
+         * Should only be called internally by the options module.
+         */
+        SelectionOptionAdjuster(SelectionOptionStorage *storage);
+
+        /*! \brief
+         * Sets the number of selections allowed for the option.
+         *
+         * \param[in] count  Number of allowed selections.
+         */
+        void setValueCount(int count);
+
+        //! \copydoc SelectionOption::evaluateVelocities()
+        void setEvaluateVelocities(bool bEnabled);
+        //! \copydoc SelectionOption::evaluateForces()
+        void setEvaluateForces(bool bEnabled);
+        //! \copydoc SelectionOption::onlyAtoms()
+        void setOnlyAtoms(bool bEnabled);
+        //! \copydoc SelectionOption::onlyStatic()
+        void setOnlyStatic(bool bEnabled);
+        //! \copydoc SelectionOption::dynamicMask()
+        void setDynamicMask(bool bEnabled);
+        //! \copydoc SelectionOption::dynamicOnlyWhole()
+        void setDynamicOnlyWhole(bool bEnabled);
+
+    private:
+        //! Returns the storage object associated with this adjuster.
+        SelectionOptionStorage &storage() { return _storage; }
+        //! Returns the storage object associated with this adjuster.
+        const SelectionOptionStorage &storage() const { return _storage; }
+
+        SelectionOptionStorage &_storage;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/selection/selectionoptionstorage.h b/src/gromacs/selection/selectionoptionstorage.h
new file mode 100644 (file)
index 0000000..ed71f84
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares gmx::SelectionOptionStorage.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELECTIONOPTIONSTORAGE_H
+#define GMX_SELECTION_SELECTIONOPTIONSTORAGE_H
+
+#include "../options/optionstoragetemplate.h"
+#include "selectionenums.h"
+
+namespace gmx
+{
+
+class Selection;
+class SelectionOption;
+class SelectionOptionAdjuster;
+
+/*! \internal \brief
+ * Converts, validates, and stores selection values.
+ *
+ * \ingroup module_selection
+ */
+class SelectionOptionStorage : public OptionStorageTemplate<Selection *>
+{
+    public:
+        /*! \brief
+         * Initializes the storage from option settings.
+         *
+         * \param[in] settings   Storage settings.
+         * \param[in] options    Options object.
+         */
+        SelectionOptionStorage(const SelectionOption &settings, Options *options);
+        virtual ~SelectionOptionStorage();
+
+        virtual const char *typeString() const { return "sel"; }
+        virtual std::string formatValue(int i) const;
+
+        /*! \brief
+         * Adds selections to the storage.
+         *
+         * \param[in] selections  List of selections to add.
+         * \param[in] bFullValue  If true, the provided selections are the full
+         *      value of the option, and additional checks are performed.
+         *
+         * This function is used to implement the methods
+         * SelectionCollection::parseRequestedFromStdin() and
+         * SelectionCollection::parseRequestedFromString() (called with
+         * \p bFullValue set to true), as well as internally by the storage
+         * class (called with \p bFullValue set to false).
+         */
+        void addSelections(const std::vector<Selection *> &selections,
+                           bool bFullValue);
+
+        // Required to access the number of values in selection requests.
+        // See SelectionCollection::Impl.
+        using MyBase::maxValueCount;
+        /*! \brief
+         * Sets the number of selections allowed for this selection.
+         *
+         * \param[in] count       Required number of selections for this option.
+         *
+         * If values have already been provided, it is checked that a correct
+         * number has been provided.  If requests have already been made, but
+         * have not yet been processed, they are also affected.
+         */
+        void setAllowedValueCount(int count);
+        /*! \brief
+         * Alters flags for the selections created by this option.
+         *
+         * \param[in] flag        Flag to change.
+         * \param[in] bSet        Whether to set or clear the flag.
+         *
+         * If values have already been provided, it is checked that they match
+         * the limitations enforced by the flags.  If requests have already
+         * been made, but have not yet been processed, they are also affected.
+         */
+        void setSelectionFlag(SelectionFlag flag, bool bSet);
+
+    private:
+        virtual void convertValue(const std::string &value);
+        virtual void processSetValues(ValueList *values);
+        virtual void processAll();
+
+        SelectionFlags          _selectionFlags;
+        //! Pointer to the adjuster (there can be only one, can be NULL).
+        SelectionOptionAdjuster *_adjuster;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/selection/selelem.cpp b/src/gromacs/selection/selelem.cpp
new file mode 100644 (file)
index 0000000..d675711
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in selelem.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <smalloc.h>
+#include <gmx_fatal.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "keywords.h"
+#include "mempool.h"
+#include "selelem.h"
+
+/*!
+ * \param[in] sel Selection for which the string is requested
+ * \returns   Pointer to a string that corresponds to \p sel->type.
+ *
+ * The return value points to a string constant and should not be \p free'd.
+ * 
+ * The function returns NULL if \p sel->type is not one of the valid values.
+ */
+const char *
+_gmx_selelem_type_str(t_selelem *sel)
+{
+    switch (sel->type)
+    {
+        case SEL_CONST:      return "CONST";
+        case SEL_EXPRESSION: return "EXPR";
+        case SEL_BOOLEAN:    return "BOOL";
+        case SEL_ARITHMETIC: return "ARITH";
+        case SEL_ROOT:       return "ROOT";
+        case SEL_SUBEXPR:    return "SUBEXPR";
+        case SEL_SUBEXPRREF: return "REF";
+        case SEL_GROUPREF:   return "GROUPREF";
+        case SEL_MODIFIER:   return "MODIFIER";
+    }
+    return NULL;
+}
+
+/*!
+ * \param[in] val Value structore for which the string is requested.
+ * \returns   Pointer to a string that corresponds to \p val->type,
+ *   NULL if the type value is invalid.
+ *
+ * The return value points to a string constant and should not be \p free'd.
+ */
+const char *
+_gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
+{
+    switch (val->type)
+    {
+        case NO_VALUE:       return "NONE";
+        case INT_VALUE:      return "INT";
+        case REAL_VALUE:     return "REAL";
+        case STR_VALUE:      return "STR";
+        case POS_VALUE:      return "VEC";
+        case GROUP_VALUE:    return "GROUP";
+    }
+    return NULL;
+}
+
+/*! \copydoc _gmx_selelem_type_str() */
+const char *
+_gmx_selelem_gmx_boolean_type_str(t_selelem *sel)
+{
+    switch (sel->u.boolt)
+    {
+        case BOOL_NOT:  return "NOT"; break;
+        case BOOL_AND:  return "AND"; break;
+        case BOOL_OR:   return "OR";  break;
+        case BOOL_XOR:  return "XOR"; break;
+    }
+    return NULL;
+}
+
+/*!
+ * \param[in] type Type of selection element to allocate.
+ * \returns   Pointer to the newly allocated and initialized element.
+ *
+ * \c t_selelem::type is set to \p type,
+ * \c t_selelem::v::type is set to \ref GROUP_VALUE for gmx_boolean and comparison
+ * expressions and \ref NO_VALUE for others,
+ * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
+ * set for \ref SEL_BOOLEAN elements),
+ * and \c t_selelem::refcount is set to one.
+ * All the pointers are set to NULL.
+ */
+t_selelem *
+_gmx_selelem_create(e_selelem_t type)
+{
+    t_selelem *sel;
+
+    snew(sel, 1);
+    sel->name       = NULL;
+    sel->type       = type;
+    sel->flags      = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
+    if (type == SEL_BOOLEAN)
+    {
+        sel->v.type = GROUP_VALUE;
+        sel->flags |= SEL_ALLOCDATA;
+    }
+    else
+    {
+        sel->v.type = NO_VALUE;
+    }
+    _gmx_selvalue_clear(&sel->v);
+    sel->evaluate   = NULL;
+    sel->mempool    = NULL;
+    sel->child      = NULL;
+    sel->next       = NULL;
+    sel->refcount   = 1;
+
+    return sel;
+}
+
+/*!
+ * \param[in,out] sel   Selection element to set the type for.
+ * \param[in]     vtype Value type for the selection element.
+ * \returns       0 on success, EINVAL if the value type is invalid.
+ *
+ * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
+ * \ref SEL_ALLOCDATA flag is also set.
+ *
+ * This function should only be called at most once for each element,
+ * preferably right after calling _gmx_selelem_create().
+ */
+int
+_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
+{
+    if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
+    {
+        gmx_bug("internal error");
+        return EINVAL;
+    }
+    if (sel->v.type != NO_VALUE && vtype != sel->v.type)
+    {
+        gmx_call("_gmx_selelem_set_vtype() called more than once");
+        return EINVAL;
+    }
+    sel->v.type = vtype;
+    if (vtype == GROUP_VALUE || vtype == POS_VALUE)
+    {
+        sel->flags |= SEL_ALLOCDATA;
+    }
+    return 0;
+}
+
+/*!
+ * \param[in,out] sel   Selection element to reserve.
+ * \param[in]     count Number of values to reserve memory for.
+ * \returns       0 on success or if no memory pool, non-zero on error.
+ *
+ * Reserves memory for the values of \p sel from the \p sel->mempool
+ * memory pool. If no memory pool is set, nothing is done.
+ */
+void
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count)
+{
+    if (!sel->mempool)
+    {
+        return;
+    }
+    switch (sel->v.type)
+    {
+        case INT_VALUE:
+            sel->v.u.i = static_cast<int *>(
+                    _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.i)*count));
+            break;
+
+        case REAL_VALUE:
+            sel->v.u.r = static_cast<real *>(
+                    _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.r)*count));
+            break;
+
+        case GROUP_VALUE:
+            _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
+            break;
+
+        default:
+            GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
+    }
+}
+
+/*!
+ * \param[in,out] sel   Selection element to release.
+ *
+ * Releases the memory allocated for the values of \p sel from the
+ * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
+ */
+void
+_gmx_selelem_mempool_release(t_selelem *sel)
+{
+    if (!sel->mempool)
+    {
+        return;
+    }
+    switch (sel->v.type)
+    {
+        case INT_VALUE:
+        case REAL_VALUE:
+            _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
+            _gmx_selvalue_setstore(&sel->v, NULL);
+            break;
+
+        case GROUP_VALUE:
+            if (sel->v.u.g)
+            {
+                _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
+            }
+            break;
+
+        default:
+            GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
+    }
+}
+
+/*!
+ * \param[in] sel Selection to free.
+ */
+void
+_gmx_selelem_free_values(t_selelem *sel)
+{
+    int   i, n;
+
+    _gmx_selelem_mempool_release(sel);
+    if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
+    {
+        /* The number of position/group structures is constant, so the
+         * backup of using sel->v.nr should work for them.
+         * For strings, we report an error if we don't know the allocation
+         * size here. */
+        n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
+        switch (sel->v.type)
+        {
+            case STR_VALUE:
+                if (sel->v.nalloc == 0)
+                {
+                    gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
+                    break;
+                }
+                for (i = 0; i < n; ++i)
+                {
+                    sfree(sel->v.u.s[i]);
+                }
+                break;
+            case POS_VALUE:
+                for (i = 0; i < n; ++i)
+                {
+                    gmx_ana_pos_deinit(&sel->v.u.p[i]);
+                }
+                break;
+            case GROUP_VALUE:
+                for (i = 0; i < n; ++i)
+                {
+                    gmx_ana_index_deinit(&sel->v.u.g[i]);
+                }
+                break;
+            default: /* No special handling for other types */
+                break;
+        }
+    }
+    if (sel->flags & SEL_ALLOCVAL)
+    {
+        sfree(sel->v.u.ptr);
+    }
+    _gmx_selvalue_setstore(&sel->v, NULL);
+    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+    {
+        sel->u.param->val.u.ptr = NULL;
+    }
+}
+
+/*!
+ * \param[in] method Method to free.
+ * \param[in] mdata  Method data to free.
+ */
+void
+_gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
+{
+    sel_freefunc free_func = NULL;
+
+    /* Save the pointer to the free function. */
+    if (method && method->free)
+    {
+        free_func = method->free;
+    }
+
+    /* Free the method itself.
+     * Has to be done before freeing the method data, because parameter
+     * values are typically stored in the method data, and here we may
+     * access them. */
+    if (method)
+    {
+        int  i, j;
+
+        /* Free the memory allocated for the parameters that are not managed
+         * by the selection method itself. */
+        for (i = 0; i < method->nparams; ++i)
+        {
+            gmx_ana_selparam_t *param = &method->param[i];
+
+            if (param->val.u.ptr)
+            {
+                if (param->val.type == GROUP_VALUE)
+                {
+                    for (j = 0; j < param->val.nr; ++j)
+                    {
+                        gmx_ana_index_deinit(&param->val.u.g[j]);
+                    }
+                }
+                else if (param->val.type == POS_VALUE)
+                {
+                    for (j = 0; j < param->val.nr; ++j)
+                    {
+                        gmx_ana_pos_deinit(&param->val.u.p[j]);
+                    }
+                }
+
+                if (param->val.nalloc > 0)
+                {
+                    sfree(param->val.u.ptr);
+                }
+            }
+        }
+        sfree(method->param);
+        sfree(method);
+    }
+    /* Free method data. */
+    if (mdata)
+    {
+        if (free_func)
+        {
+            free_func(mdata);
+        }
+        sfree(mdata);
+    }
+}
+
+/*!
+ * \param[in] sel Selection to free.
+ */
+void
+_gmx_selelem_free_exprdata(t_selelem *sel)
+{
+    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+    {
+        _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
+        sel->u.expr.mdata = NULL;
+        sel->u.expr.method = NULL;
+        /* Free position data */
+        if (sel->u.expr.pos)
+        {
+            gmx_ana_pos_free(sel->u.expr.pos);
+            sel->u.expr.pos = NULL;
+        }
+        /* Free position calculation data */
+        if (sel->u.expr.pc)
+        {
+            gmx_ana_poscalc_free(sel->u.expr.pc);
+            sel->u.expr.pc = NULL;
+        }
+    }
+    if (sel->type == SEL_ARITHMETIC)
+    {
+        sfree(sel->u.arith.opstr);
+        sel->u.arith.opstr = NULL;
+    }
+    if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
+        || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
+    {
+        gmx_ana_index_deinit(&sel->u.cgrp);
+    }
+    if (sel->type == SEL_GROUPREF)
+    {
+        sfree(sel->u.gref.name);
+    }
+}
+
+/*!
+ * \param[in] sel Selection to free.
+ *
+ * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
+ * memory allocated for \p sel and all its children if the reference count
+ * reaches zero.
+ */
+void
+_gmx_selelem_free(t_selelem *sel)
+{
+    /* Decrement the reference counter and do nothing if references remain */
+    sel->refcount--;
+    if (sel->refcount > 0)
+    {
+        return;
+    }
+
+    /* Free the children.
+     * Must be done before freeing other data, because the children may hold
+     * references to data in this element. */
+    _gmx_selelem_free_chain(sel->child);
+
+    /* Free value storage */
+    _gmx_selelem_free_values(sel);
+
+    /* Free other storage */
+    _gmx_selelem_free_exprdata(sel);
+
+    /* Free temporary compiler data if present */
+    _gmx_selelem_free_compiler_data(sel);
+
+    sfree(sel);
+}
+
+/*!
+ * \param[in] first First selection to free.
+ *
+ * Frees \p first and all selections accessible through the
+ * \ref t_selelem::next "first->next" pointer.
+ */
+void
+_gmx_selelem_free_chain(t_selelem *first)
+{
+    t_selelem *child, *prev;
+
+    child = first;
+    while (child)
+    {
+        prev = child;
+        child = child->next;
+        _gmx_selelem_free(prev);
+    }
+}
+
+/*!
+ * \param[in] fp      File handle to receive the output.
+ * \param[in] sel     Root of the selection subtree to print.
+ * \param[in] bValues If TRUE, the evaluated values of selection elements
+ *   are printed as well.
+ * \param[in] level   Indentation level, starting from zero.
+ */
+void
+_gmx_selelem_print_tree(FILE *fp, t_selelem *sel, gmx_bool bValues, int level)
+{
+    t_selelem *child;
+    int          i;
+
+    fprintf(fp, "%*c %s %s", level*2+1, '*',
+            _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
+    if (sel->name)
+    {
+        fprintf(fp, " \"%s\"", sel->name);
+    }
+    fprintf(fp, " flg=");
+    if (sel->flags & SEL_FLAGSSET)
+    {
+        fprintf(fp, "s");
+    }
+    if (sel->flags & SEL_SINGLEVAL)
+    {
+        fprintf(fp, "S");
+    }
+    if (sel->flags & SEL_ATOMVAL)
+    {
+        fprintf(fp, "A");
+    }
+    if (sel->flags & SEL_VARNUMVAL)
+    {
+        fprintf(fp, "V");
+    }
+    if (sel->flags & SEL_DYNAMIC)
+    {
+        fprintf(fp, "D");
+    }
+    if (!(sel->flags & SEL_VALFLAGMASK))
+    {
+        fprintf(fp, "0");
+    }
+    if (sel->mempool)
+    {
+        fprintf(fp, "P");
+    }
+    if (sel->type == SEL_CONST)
+    {
+        if (sel->v.type == INT_VALUE)
+        {
+            fprintf(fp, " %d", sel->v.u.i[0]);
+        }
+        else if (sel->v.type == REAL_VALUE)
+        {
+            fprintf(fp, " %f", sel->v.u.r[0]);
+        }
+        else if (sel->v.type == GROUP_VALUE)
+        {
+            gmx_ana_index_t *g = sel->v.u.g;
+            if (!g || g->isize == 0)
+                g = &sel->u.cgrp;
+            fprintf(fp, " (%d atoms)", g->isize);
+        }
+    }
+    else if (sel->type == SEL_BOOLEAN)
+    {
+        fprintf(fp, " %s", _gmx_selelem_gmx_boolean_type_str(sel));
+    }
+    else if (sel->type == SEL_EXPRESSION
+             && sel->u.expr.method->name == sm_compare.name)
+    {
+        _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
+    }
+    if (sel->evaluate)
+    {
+        fprintf(fp, " eval=");
+        _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
+    }
+    if (sel->refcount > 1)
+    {
+        fprintf(fp, " refc=%d", sel->refcount);
+    }
+    if (!(sel->flags & SEL_ALLOCVAL))
+    {
+        fprintf(fp, " (ext. output)");
+    }
+    fprintf(fp, "\n");
+
+    if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
+    {
+        gmx_ana_index_t *g = sel->v.u.g;
+        if (!g || g->isize == 0 || sel->evaluate != NULL)
+        {
+            g = &sel->u.cgrp;
+        }
+        if (g->isize < 0)
+        {
+            fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
+        }
+        else if (g->isize > 0)
+        {
+            fprintf(fp, "%*c group:", level*2+1, ' ');
+            if (g->isize <= 20)
+            {
+                for (i = 0; i < g->isize; ++i)
+                {
+                    fprintf(fp, " %d", g->index[i] + 1);
+                }
+            }
+            else
+            {
+                fprintf(fp, " %d atoms", g->isize);
+            }
+            fprintf(fp, "\n");
+        }
+    }
+    else if (sel->type == SEL_EXPRESSION)
+    {
+        if (sel->u.expr.pc)
+        {
+            fprintf(fp, "%*c COM", level*2+3, '*');
+            fprintf(fp, "\n");
+        }
+    }
+
+    if (sel->cdata)
+    {
+        _gmx_selelem_print_compiler_info(fp, sel, level);
+    }
+
+    if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
+    {
+        fprintf(fp, "%*c value: ", level*2+1, ' ');
+        switch (sel->v.type)
+        {
+            case POS_VALUE:
+                /* In normal use, the pointer should never be NULL, but it's
+                 * useful to have the check for debugging to avoid accidental
+                 * segfaults when printing the selection tree. */
+                if (sel->v.u.p->x)
+                {
+                    fprintf(fp, "(%f, %f, %f)",
+                            sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
+                            sel->v.u.p->x[0][ZZ]);
+                }
+                else
+                {
+                    fprintf(fp, "(null)");
+                }
+                break;
+            case GROUP_VALUE:
+                fprintf(fp, "%d atoms", sel->v.u.g->isize);
+                if (sel->v.u.g->isize < 20)
+                {
+                    if (sel->v.u.g->isize > 0)
+                    {
+                        fprintf(fp, ":");
+                    }
+                    for (i = 0; i < sel->v.u.g->isize; ++i)
+                    {
+                        fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
+                    }
+                }
+                break;
+            default:
+                fprintf(fp, "???");
+                break;
+        }
+        fprintf(fp, "\n");
+    }
+
+    /* Print the subexpressions with one more level of indentation */
+    child = sel->child;
+    while (child)
+    {
+        if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
+        {
+            _gmx_selelem_print_tree(fp, child, bValues, level+1);
+        }
+        child = child->next;
+    }
+}
+
+/*!
+ * \param[in] root Root of the subtree to query.
+ * \returns TRUE if \p root or any any of its elements require topology
+ *   information, FALSE otherwise.
+ */
+gmx_bool
+_gmx_selelem_requires_top(t_selelem *root)
+{
+    t_selelem *child;
+
+    if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
+    {
+        if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
+        {
+            return TRUE;
+        }
+        if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
+        {
+            return TRUE;
+        }
+    }
+    child = root->child;
+    while (child)
+    {
+        if (_gmx_selelem_requires_top(child))
+        {
+            return TRUE;
+        }
+        child = child->next;
+    }
+    return FALSE;
+}
diff --git a/src/gromacs/selection/selelem.h b/src/gromacs/selection/selelem.h
new file mode 100644 (file)
index 0000000..bc30cfd
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares ::t_selelem and related things.
+ *
+ * The selection element trees constructed by the parser and the compiler
+ * are described on the respective pages:
+ * \ref page_module_selection_parser and \ref page_module_selection_compiler.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef SELECTION_ELEMENT_H
+#define SELECTION_ELEMENT_H
+
+#include <types/simple.h>
+
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/selvalue.h"
+
+struct gmx_ana_poscalc_t;
+struct gmx_ana_selparam_t;
+struct gmx_ana_selmethod_t;
+
+struct gmx_sel_evaluate_t;
+struct gmx_sel_mempool_t;
+struct t_selelem;
+
+/********************************************************************/
+/*! \name Enumerations for expression types
+ ********************************************************************/
+/*@{*/
+
+/** Defines the type of a \c t_selelem object. */
+typedef enum
+{
+    /** Constant-valued expression. */
+    SEL_CONST,
+    /** Method expression that requires evaluation. */
+    SEL_EXPRESSION,
+    /** Boolean expression. */
+    SEL_BOOLEAN,
+    /** Arithmetic expression. */
+    SEL_ARITHMETIC,
+    /** Root node of the evaluation tree. */
+    SEL_ROOT,
+    /** Subexpression that may be referenced several times. */
+    SEL_SUBEXPR,
+    /** Reference to a subexpression. */
+    SEL_SUBEXPRREF,
+    /** Unresolved reference to an external group. */
+    SEL_GROUPREF,
+    /** Post-processing of selection value. */
+    SEL_MODIFIER
+} e_selelem_t;
+
+/** Defines the gmx_boolean operation of \c t_selelem objects with type \ref SEL_BOOLEAN. */
+typedef enum
+{
+    BOOL_NOT,           /**< Not */
+    BOOL_AND,           /**< And */
+    BOOL_OR,            /**< Or */
+    BOOL_XOR            /**< Xor (not implemented). */
+} e_boolean_t;
+
+/** Defines the arithmetic operation of \c t_selelem objects with type \ref SEL_ARITHMETIC. */
+typedef enum
+{
+    ARITH_PLUS,         /**< + */
+    ARITH_MINUS,        /**< - */
+    ARITH_NEG,          /**< Unary - */
+    ARITH_MULT,         /**< * */
+    ARITH_DIV,          /**< / */
+    ARITH_EXP           /**< ^ (to power) */
+} e_arithmetic_t;
+
+/** Returns a string representation of the type of a \c t_selelem. */
+extern const char *
+_gmx_selelem_type_str(struct t_selelem *sel);
+/** Returns a string representation of the gmx_boolean type of a \ref SEL_BOOLEAN \c t_selelem. */
+extern const char *
+_gmx_selelem_gmx_boolean_type_str(struct t_selelem *sel);
+/** Returns a string representation of the type of a \c gmx_ana_selvalue_t. */
+extern const char *
+_gmx_sel_value_type_str(gmx_ana_selvalue_t *val);
+
+/*@}*/
+
+
+/********************************************************************/
+/*! \name Selection expression flags
+ * \anchor selelem_flags
+ ********************************************************************/
+/*@{*/
+/*! \brief
+ * Selection value flags are set.
+ *
+ * If this flag is set, the flags covered by \ref SEL_VALFLAGMASK
+ * have been set properly for the element.
+ */
+#define SEL_FLAGSSET    1
+/*! \brief
+ * The element evaluates to a single value.
+ *
+ * This flag is always set for \ref GROUP_VALUE elements.
+ */
+#define SEL_SINGLEVAL   2
+/*! \brief
+ * The element evaluates to one value for each input atom.
+ */
+#define SEL_ATOMVAL     4
+/*! \brief
+ * The element evaluates to an arbitrary number of values.
+ */
+#define SEL_VARNUMVAL   8
+/*! \brief
+ * The element (or one of its children) is dynamic.
+ */
+#define SEL_DYNAMIC     16
+/*! \brief
+ * Mask that covers the flags that describe the number of values.
+ */
+#define SEL_VALTYPEMASK (SEL_SINGLEVAL | SEL_ATOMVAL | SEL_VARNUMVAL)
+/*! \brief
+ * Mask that covers the flags that describe the value type.
+ */
+#define SEL_VALFLAGMASK (SEL_FLAGSSET | SEL_VALTYPEMASK | SEL_DYNAMIC)
+/*! \brief
+ * Data has been allocated for the \p v.u union.
+ *
+ * If not set, the \p v.u.ptr points to data allocated externally.
+ * This is the case if the value of the element is used as a parameter
+ * for a selection method or if the element evaluates the final value of
+ * a selection.
+ *
+ * Even if the flag is set, \p v.u.ptr can be NULL during initialization.
+ *
+ * \todo
+ * This flag overlaps with the function of \p v.nalloc field, and could
+ * probably be removed, making memory management simpler. Currently, the
+ * \p v.nalloc field is not kept up-to-date in all cases when this flag
+ * is changed and is used in places where this flag is not, so this would
+ * require a careful investigation of the selection code.
+ */
+#define SEL_ALLOCVAL    (1<<8)
+/*! \brief
+ * Data has been allocated for the group/position structure.
+ *
+ * If not set, the memory allocated for fields in \p v.u.g or \p v.u.p is
+ * managed externally.
+ *
+ * This field has no effect if the value type is not \ref GROUP_VALUE or
+ * \ref POS_VALUE, but should not be set.
+ */
+#define SEL_ALLOCDATA   (1<<9)
+/*! \brief
+ * \p method->init_frame should be called for the frame.
+ */
+#define SEL_INITFRAME   (1<<10)
+/*! \brief
+ * Parameter has been evaluated for the current frame.
+ *
+ * This flag is set for children of \ref SEL_EXPRESSION elements (which
+ * describe method parameters) after the element has been evaluated for the
+ * current frame.
+ * It is not set for \ref SEL_ATOMVAL elements, because they may need to
+ * be evaluated multiple times.
+ */
+#define SEL_EVALFRAME   (1<<11)
+/*! \brief
+ * \p method->init has been called.
+ */
+#define SEL_METHODINIT  (1<<12)
+/*! \brief
+ * \p method->outinit has been called.
+ *
+ * This flag is also used for \ref SEL_SUBEXPRREF elements.
+ */
+#define SEL_OUTINIT     (1<<13)
+/*@}*/
+
+
+/********************************************************************/
+/*! \name Selection expression data structures and functions
+ ********************************************************************/
+/*@{*/
+
+struct t_selelem;
+
+/*! \brief
+ * Function pointer for evaluating a \c t_selelem.
+ */
+typedef void (*sel_evalfunc)(struct gmx_sel_evaluate_t *data,
+                             struct t_selelem *sel, gmx_ana_index_t *g);
+
+/*! \internal \brief
+ * Represents an element of a selection expression.
+ */
+typedef struct t_selelem
+{
+    /*! \brief Name of the element.
+     *
+     * This field is only used for informative purposes.
+     * It is always either NULL or a pointer to a string.
+     * Memory is never allocated for it directly.
+     */
+    const char                         *name;
+    /** Type of the element. */
+    e_selelem_t                         type;
+    /*! \brief
+     * Value storage of the element.
+     *
+     * This field contains the evaluated value of the element, as well as
+     * the output value type.
+     */
+    gmx_ana_selvalue_t                  v;
+    /*! \brief
+     * Evaluation function for the element.
+     *
+     * Can be either NULL (if the expression is a constant and does not require
+     * evaluation) or point to one of the functions defined in evaluate.h.
+     */
+    sel_evalfunc                        evaluate;
+    /*! \brief
+     * Information flags about the element.
+     *
+     * Allowed flags are listed here:
+     * \ref selelem_flags "flags for \c t_selelem".
+     */
+    int                                 flags;
+    /** Data required by the evaluation function. */
+    union {
+        /*! \brief Index group data for several element types.
+         *
+         *  - \ref SEL_CONST : if the value type is \ref GROUP_VALUE,
+         *    this field holds the unprocessed group value.
+         *  - \ref SEL_ROOT : holds the group value for which the
+         *    selection subtree should be evaluated.
+         *  - \ref SEL_SUBEXPR : holds the group for which the subexpression
+         *    has been evaluated.
+         */
+        gmx_ana_index_t                 cgrp;
+        /** Data for \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements. */
+        struct {
+            /** Pointer the the method used in this expression. */
+            struct gmx_ana_selmethod_t *method;
+            /** Pointer to the data allocated by the method's \p init_data (see sel_datafunc()). */
+            void                       *mdata;
+            /** Pointer to the position data passed to the method. */
+            struct gmx_ana_pos_t       *pos;
+            /** Pointer to the evaluation data for \p pos. */
+            struct gmx_ana_poscalc_t   *pc;
+        }                               expr;
+        /** Operation type for \ref SEL_BOOLEAN elements. */
+        e_boolean_t                     boolt;
+        /** Operation type for \ref SEL_ARITHMETIC elements. */
+        struct {
+            /** Operation type. */
+            e_arithmetic_t              type;
+            /** String representation. */
+            char                       *opstr;
+        }                               arith;
+        /** Associated selection parameter for \ref SEL_SUBEXPRREF elements. */
+        struct gmx_ana_selparam_t      *param;
+        /** The string/number used to reference the group. */
+        struct {
+            /** Name of the referenced external group. */
+            char                       *name;
+            /** If \a name is NULL, the index number of the referenced group. */
+            int                         id;
+        }                               gref;
+    }                                   u;
+    /** Memory pool to use for values, or NULL if standard memory handling. */
+    struct gmx_sel_mempool_t           *mempool;
+    /** Internal data for the selection compiler. */
+    struct t_compiler_data             *cdata;
+    
+    /*! \brief The first child element.
+     *
+     * Other children can be accessed through the \p next field of \p child.
+     */
+    struct t_selelem                    *child;
+    /** The next sibling element. */
+    struct t_selelem                    *next;
+    /*! \brief Number of references to this element.
+     *
+     * Should be larger than one only for \ref SEL_SUBEXPR elements.
+     */
+    int                                  refcount;
+} t_selelem;
+
+/* In evaluate.c */
+/** Writes out a human-readable name for an evaluation function. */
+extern void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc);
+
+/** Allocates memory and performs some common initialization for a \c t_selelem. */
+extern t_selelem *
+_gmx_selelem_create(e_selelem_t type);
+/** Sets the value type of a \c t_selelem. */
+extern int
+_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype);
+/** Reserves memory for value of a \c t_selelem from a memory pool. */
+extern void
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count);
+/** Releases memory pool used for value of a \c t_selelem. */
+extern void
+_gmx_selelem_mempool_release(t_selelem *sel);
+/** Frees the memory allocated for a \c t_selelem structure and all its children. */
+extern void
+_gmx_selelem_free(t_selelem *sel);
+/** Frees the memory allocated for a \c t_selelem structure, all its children, and also all structures referenced through t_selelem::next fields. */
+extern void
+_gmx_selelem_free_chain(t_selelem *first);
+
+/** Frees the memory allocated for the \c t_selelem::d union. */
+extern void
+_gmx_selelem_free_values(t_selelem *sel);
+/** Frees the memory allocated for a selection method. */
+extern void
+_gmx_selelem_free_method(struct gmx_ana_selmethod_t *method, void *mdata);
+/** Frees the memory allocated for the \c t_selelem::u field. */
+extern void
+_gmx_selelem_free_exprdata(t_selelem *sel);
+/* In compiler.c */
+/** Frees the memory allocated for the selection compiler. */
+extern void
+_gmx_selelem_free_compiler_data(t_selelem *sel);
+
+/** Prints a human-readable version of a selection element subtree. */
+extern void
+_gmx_selelem_print_tree(FILE *fp, t_selelem *root, gmx_bool bValues, int level);
+/* In compile.c */
+/** Prints a human-readable version of the internal compiler data structure. */
+extern void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level);
+
+/** Returns TRUE if the selection element subtree requires topology information for evaluation. */
+extern gmx_bool
+_gmx_selelem_requires_top(t_selelem *root);
+
+/* In sm_insolidangle.c */
+/** Returns TRUE if the covered fraction of the selection can be calculated. */
+extern gmx_bool
+_gmx_selelem_can_estimate_cover(t_selelem *sel);
+/** Returns the covered fraction of the selection for the current frame. */
+extern real
+_gmx_selelem_estimate_coverfrac(t_selelem *sel);
+
+/*@}*/
+
+#endif
diff --git a/src/gromacs/selection/selhelp.cpp b/src/gromacs/selection/selhelp.cpp
new file mode 100644 (file)
index 0000000..a30465d
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in selhelp.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <string2.h>
+#include <wman.h>
+
+#include "gromacs/selection/selmethod.h"
+
+#include "selhelp.h"
+#include "symrec.h"
+
+/*! \internal \brief
+ * Describes a selection help section.
+ */
+typedef struct {
+    //! Topic keyword that produces this help.
+    const char  *topic;
+    //! Number of items in the \a text array.
+    int          nl;
+    //! Help text as a list of strings that will be concatenated.
+    const char **text;
+} t_selection_help_item;
+
+static const char *help_common[] = {
+    "SELECTION HELP[PAR]",
+
+    "This program supports selections in addition to traditional index files.",
+    "Please read the subtopic pages (available through \"help topic\") for",
+    "more information.",
+    "Explanation of command-line arguments for specifying selections can be",
+    "found under the \"cmdline\" subtopic, and general selection syntax is",
+    "described under \"syntax\". Available keywords can be found under",
+    "\"keywords\", and concrete examples under \"examples\".",
+    "Other subtopics give more details on certain aspects.",
+    "\"help all\" prints the help for all subtopics.",
+};
+
+static const char *help_arithmetic[] = {
+    "ARITHMETIC EXPRESSIONS IN SELECTIONS[PAR]",
+
+    "Basic arithmetic evaluation is supported for numeric expressions.",
+    "Supported operations are addition, subtraction, negation, multiplication,",
+    "division, and exponentiation (using ^).",
+    "Result of a division by zero or other illegal operations is undefined.",
+};
+
+static const char *help_cmdline[] = {
+    "SELECTION COMMAND-LINE ARGUMENTS[PAR]",
+
+    "There are two alternative command-line arguments for specifying",
+    "selections:[BR]",
+    "1. [TT]-select[tt] can be used to specify the complete selection as a",
+    "string on the command line.[BR]",
+    "2. [TT]-sf[tt] can be used to specify a file name from which the",
+    "selection is read.[BR]",
+    "If both options are specified, [TT]-select[tt] takes precedence.",
+    "If neither of the above is present, the user is prompted to type the",
+    "selection on the standard input (a pipe can also be used to provide",
+    "the selections in this case).",
+    "This is also done if an empty string is passed to [TT]-select[tt].[PAR]",
+
+    "Option [TT]-n[tt] can be used to provide an index file.",
+    "If no index file is provided, default groups are generated.",
+    "In both cases, the user can also select an index group instead of",
+    "writing a full selection.",
+    "The default groups are generated by reading selections from a file",
+    "[TT]defselection.dat[tt]. If such a file is found in the current",
+    "directory, it is used instead of the one provided by default.[PAR]",
+
+    "Depending on the tool, two additional command-line arguments may be",
+    "available to control the behavior:[BR]",
+    "1. [TT]-seltype[tt] can be used to specify the default type of",
+    "positions to calculate for each selection.[BR]",
+    "2. [TT]-selrpos[tt] can be used to specify the default type of",
+    "positions used in selecting atoms by coordinates.[BR]",
+    "See \"help positions\" for more information on these options.",
+};
+
+static const char *help_eval[] = {
+    "SELECTION EVALUATION AND OPTIMIZATION[PAR]",
+
+    "Boolean evaluation proceeds from left to right and is short-circuiting",
+    "i.e., as soon as it is known whether an atom will be selected, the",
+    "remaining expressions are not evaluated at all.",
+    "This can be used to optimize the selections: you should write the",
+    "most restrictive and/or the most inexpensive expressions first in",
+    "boolean expressions.",
+    "The relative ordering between dynamic and static expressions does not",
+    "matter: all static expressions are evaluated only once, before the first",
+    "frame, and the result becomes the leftmost expression.[PAR]",
+
+    "Another point for optimization is in common subexpressions: they are not",
+    "automatically recognized, but can be manually optimized by the use of",
+    "variables. This can have a big impact on the performance of complex",
+    "selections, in particular if you define several index groups like this:",
+    "  [TT]rdist = distance from com of resnr 1 to 5;[tt][BR]",
+    "  [TT]resname RES and rdist < 2;[tt][BR]",
+    "  [TT]resname RES and rdist < 4;[tt][BR]",
+    "  [TT]resname RES and rdist < 6;[tt][BR]",
+    "Without the variable assignment, the distances would be evaluated three",
+    "times, although they are exactly the same within each selection.",
+    "Anything assigned into a variable becomes a common subexpression that",
+    "is evaluated only once during a frame.",
+    "Currently, in some cases the use of variables can actually lead to a small",
+    "performance loss because of the checks necessary to determine for which",
+    "atoms the expression has already been evaluated, but this should not be",
+    "a major problem.",
+};
+
+static const char *help_examples[] = {
+    "SELECTION EXAMPLES[PAR]",
+
+    "Below, examples of increasingly complex selections are given.[PAR]",
+
+    "Selection of all water oxygens:[BR]",
+    "  resname SOL and name OW",
+    "[PAR]",
+
+    "Centers of mass of residues 1 to 5 and 10:[BR]",
+    "  res_com of resnr 1 to 5 10",
+    "[PAR]",
+
+    "All atoms farther than 1 nm of a fixed position:[BR]",
+    "  not within 1 of (1.2, 3.1, 2.4)",
+    "[PAR]",
+
+    "All atoms of a residue LIG within 0.5 nm of a protein (with a custom name):[BR]",
+    "  \"Close to protein\" resname LIG and within 0.5 of group \"Protein\"",
+    "[PAR]",
+
+    "All protein residues that have at least one atom within 0.5 nm of a residue LIG:[BR]",
+    "  group \"Protein\" and same residue as within 0.5 of resname LIG",
+    "[PAR]",
+
+    "All RES residues whose COM is between 2 and 4 nm from the COM of all of them:[BR]",
+    "  rdist = res_com distance from com of resname RES[BR]",
+    "  resname RES and rdist >= 2 and rdist <= 4",
+    "[PAR]",
+
+    "Selection like C1 C2 C2 C3 C3 C4 ... C8 C9 (e.g., for g_bond):[BR]",
+    "  name \"C[1-8]\" merge name \"C[2-9]\"",
+};
+
+static const char *help_keywords[] = {
+    "SELECTION KEYWORDS[PAR]",
+
+    "The following selection keywords are currently available.",
+    "For keywords marked with a star, additional help is available through",
+    "\"help KEYWORD\", where KEYWORD is the name of the keyword.",
+};
+
+static const char *help_limits[] = {
+    "SELECTION LIMITATIONS[PAR]",
+
+    "Some analysis programs may require a special structure for the input",
+    "selections (e.g., [TT]g_angle[tt] requires the index group to be made",
+    "of groups of three or four atoms).",
+    "For such programs, it is up to the user to provide a proper selection",
+    "expression that always returns such positions.",
+    "[PAR]",
+
+    "Due to technical reasons, having a negative value as the first value in",
+    "expressions like[BR]",
+    "[TT]charge -1 to -0.7[tt][BR]",
+    "result in a syntax error. A workaround is to write[BR]",
+    "[TT]charge {-1 to -0.7}[tt][BR]",
+    "instead.",
+};
+
+static const char *help_positions[] = {
+    "SPECIFYING POSITIONS[PAR]",
+
+    "Possible ways of specifying positions in selections are:[PAR]",
+
+    "1. A constant position can be defined as [TT][XX, YY, ZZ][tt], where",
+    "[TT]XX[tt], [TT]YY[tt] and [TT]ZZ[tt] are real numbers.[PAR]",
+
+    "2. [TT]com of ATOM_EXPR [pbc][tt] or [TT]cog of ATOM_EXPR [pbc][tt]",
+    "calculate the center of mass/geometry of [TT]ATOM_EXPR[tt]. If",
+    "[TT]pbc[tt] is specified, the center is calculated iteratively to try",
+    "to deal with cases where [TT]ATOM_EXPR[tt] wraps around periodic",
+    "boundary conditions.[PAR]",
+
+    "3. [TT]POSTYPE of ATOM_EXPR[tt] calculates the specified positions for",
+    "the atoms in [TT]ATOM_EXPR[tt].",
+    "[TT]POSTYPE[tt] can be [TT]atom[tt], [TT]res_com[tt], [TT]res_cog[tt],",
+    "[TT]mol_com[tt] or [TT]mol_cog[tt], with an optional prefix [TT]whole_[tt]",
+    "[TT]part_[tt] or [TT]dyn_[tt].",
+    "[TT]whole_[tt] calculates the centers for the whole residue/molecule,",
+    "even if only part of it is selected.",
+    "[TT]part_[tt] prefix calculates the centers for the selected atoms, but",
+    "uses always the same atoms for the same residue/molecule. The used atoms",
+    "are determined from the the largest group allowed by the selection.",
+    "[TT]dyn_[tt] calculates the centers strictly only for the selected atoms.",
+    "If no prefix is specified, whole selections default to [TT]part_[tt] and",
+    "other places default to [TT]whole_[tt].",
+    "The latter is often desirable to select the same molecules in different",
+    "tools, while the first is a compromise between speed ([TT]dyn_[tt]",
+    "positions can be slower to evaluate than [TT]part_[tt]) and intuitive",
+    "behavior.[PAR]",
+
+    "4. [TT]ATOM_EXPR[tt], when given for whole selections, is handled as 3.",
+    "above, using the position type from the command-line argument",
+    "[TT]-seltype[tt].[PAR]",
+
+    "Selection keywords that select atoms based on their positions, such as",
+    "[TT]dist from[tt], use by default the positions defined by the",
+    "[TT]-selrpos[tt] command-line option.",
+    "This can be overridden by prepending a [TT]POSTYPE[tt] specifier to the",
+    "keyword. For example, [TT]res_com dist from POS[tt] evaluates the",
+    "residue center of mass distances. In the example, all atoms of a residue",
+    "are either selected or not, based on the single distance calculated.",
+};
+
+static const char *help_syntax[] = {
+    "SELECTION SYNTAX[PAR]",
+
+    "A set of selections consists of one or more selections, separated by",
+    "semicolons. Each selection defines a set of positions for the analysis.",
+    "Each selection can also be preceded by a string that gives a name for",
+    "the selection for use in, e.g., graph legends.",
+    "If no name is provided, the string used for the selection is used",
+    "automatically as the name.[PAR]",
+
+    "For interactive input, the syntax is slightly altered: line breaks can",
+    "also be used to separate selections. \\ followed by a line break can",
+    "be used to continue a line if necessary.",
+    "Notice that the above only applies to real interactive input,",
+    "not if you provide the selections, e.g., from a pipe.[PAR]",
+
+    "It is possible to use variables to store selection expressions.",
+    "A variable is defined with the following syntax:[BR]",
+    "[TT]VARNAME = EXPR ;[tt][BR]",
+    "where [TT]EXPR[tt] is any valid selection expression.",
+    "After this, [TT]VARNAME[tt] can be used anywhere where [TT]EXPR[tt]",
+    "would be valid.[PAR]",
+
+    "Selections are composed of three main types of expressions, those that",
+    "define atoms ([TT]ATOM_EXPR[tt]s), those that define positions",
+    "([TT]POS_EXPR[tt]s), and those that evaluate to numeric values",
+    "([TT]NUM_EXPR[tt]s). Each selection should be a [TT]POS_EXPR[tt]",
+    "or a [TT]ATOM_EXPR[tt] (the latter is automatically converted to",
+    "positions). The basic rules are as follows:[BR]",
+    "1. An expression like [TT]NUM_EXPR1 < NUM_EXPR2[tt] evaluates to an",
+    "[TT]ATOM_EXPR[tt] that selects all the atoms for which the comparison",
+    "is true.[BR]",
+    "2. Atom expressions can be combined with gmx_boolean operations such as",
+    "[TT]not ATOM_EXPR[tt], [TT]ATOM_EXPR and ATOM_EXPR[tt], or",
+    "[TT]ATOM_EXPR or ATOM_EXPR[tt]. Parentheses can be used to alter the",
+    "evaluation order.[BR]",
+    "3. [TT]ATOM_EXPR[tt] expressions can be converted into [TT]POS_EXPR[tt]",
+    "expressions in various ways, see \"help positions\" for more details.[PAR]",
+
+    "Some keywords select atoms based on string values such as the atom name.",
+    "For these keywords, it is possible to use wildcards ([TT]name \"C*\"[tt])",
+    "or regular expressions (e.g., [TT]resname \"R[AB]\"[tt]).",
+    "The match type is automatically guessed from the string: if it contains",
+    "other characters than letters, numbers, '*', or '?', it is interpreted",
+    "as a regular expression.",
+    "Strings that contain non-alphanumeric characters should be enclosed in",
+    "double quotes as in the examples. For other strings, the quotes are",
+    "optional, but if the value conflicts with a reserved keyword, a syntax",
+    "error will occur. If your strings contain uppercase letters, this should",
+    "not happen.[PAR]",
+
+    "Index groups provided with the [TT]-n[tt] command-line option or",
+    "generated by default can be accessed with [TT]group NR[tt] or",
+    "[TT]group NAME[tt], where [TT]NR[tt] is a zero-based index of the group",
+    "and [TT]NAME[tt] is part of the name of the desired group.",
+    "The keyword [TT]group[tt] is optional if the whole selection is",
+    "provided from an index group.",
+    "To see a list of available groups in the interactive mode, press enter",
+    "in the beginning of a line.",
+};
+
+static const t_selection_help_item helpitems[] = {
+    {NULL,          asize(help_common),     help_common},
+    {"cmdline",     asize(help_cmdline),    help_cmdline},
+    {"syntax",      asize(help_syntax),     help_syntax},
+    {"positions",   asize(help_positions),  help_positions},
+    {"arithmetic",  asize(help_arithmetic), help_arithmetic},
+    {"keywords",    asize(help_keywords),   help_keywords},
+    {"evaluation",  asize(help_eval),       help_eval},
+    {"limitations", asize(help_limits),     help_limits},
+    {"examples",    asize(help_examples),   help_examples},
+};
+
+/*! \brief
+ * Prints a brief list of keywords (selection methods) available.
+ *
+ * \param[in] fp    Where to write the list.
+ * \param[in] symtab  Symbol table to use to find available keywords.
+ * \param[in] type  Only methods that return this type are printed.
+ * \param[in] bMod  If FALSE, \ref SMETH_MODIFIER methods are excluded, otherwise
+ *     only them are printed.
+ */
+static void
+print_keyword_list(FILE *fp, gmx_sel_symtab_t *symtab, e_selvalue_t type,
+                   gmx_bool bMod)
+{
+    gmx_sel_symrec_t *symbol;
+
+    symbol = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
+    while (symbol)
+    {
+        gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
+        gmx_bool                 bShow;
+        bShow = (method->type == type)
+            && ((bMod && (method->flags & SMETH_MODIFIER))
+                || (!bMod && !(method->flags & SMETH_MODIFIER)));
+        if (bShow)
+        {
+            fprintf(fp, " %c ",
+                    (method->help.nlhelp > 0 && method->help.help) ? '*' : ' ');
+            if (method->help.syntax)
+            {
+                fprintf(fp, "%s\n", method->help.syntax);
+            }
+            else
+            {
+                const char *symname = _gmx_sel_sym_name(symbol);
+
+                fprintf(fp, "%s", symname);
+                if (strcmp(symname, method->name) != 0)
+                {
+                    fprintf(fp, " (synonym for %s)", method->name);
+                }
+                fprintf(fp, "\n");
+            }
+        }
+        symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
+    }
+}
+
+/*!
+ * \param[in]  fp      Where to write the help.
+ * \param[in]  symtab  Symbol table to use to find available keywords.
+ * \param[in]  topic Topic to print help on, or NULL for general help.
+ *
+ * \p symtab is used to get information on which keywords are available in the
+ * present context.
+ */
+void
+_gmx_sel_print_help(FILE *fp, gmx_sel_symtab_t *symtab, const char *topic)
+{
+    const t_selection_help_item *item = NULL;
+    size_t i;
+
+    /* Find the item for the topic */
+    if (!topic)
+    {
+        item = &helpitems[0];
+    }
+    else if (strcmp(topic, "all") == 0)
+    {
+        for (i = 0; i < asize(helpitems); ++i)
+        {
+            item = &helpitems[i];
+            _gmx_sel_print_help(fp, symtab, item->topic);
+            if (i != asize(helpitems) - 1)
+            {
+                fprintf(fp, "\n\n");
+            }
+        }
+        return;
+    }
+    else
+    {
+        for (i = 1; i < asize(helpitems); ++i)
+        {
+            if (strncmp(helpitems[i].topic, topic, strlen(topic)) == 0)
+            {
+                item = &helpitems[i];
+                break;
+            }
+        }
+    }
+    /* If the topic is not found, check the available methods.
+     * If they don't provide any help either, tell the user and exit. */
+    if (!item)
+    {
+        gmx_sel_symrec_t *symbol;
+
+        symbol = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
+        while (symbol)
+        {
+            gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
+            if (method->help.nlhelp > 0 && method->help.help
+                && strncmp(method->name, topic, strlen(topic)) == 0)
+            {
+                print_tty_formatted(fp, method->help.nlhelp,
+                        method->help.help, 0, NULL, NULL, FALSE);
+                return;
+            }
+            symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
+        }
+
+        fprintf(fp, "No help available for '%s'.\n", topic);
+        return;
+    }
+    /* Print the help */
+    print_tty_formatted(fp, item->nl, item->text, 0, NULL, NULL, FALSE);
+    /* Special handling of certain pages */
+    if (!topic)
+    {
+        int len = 0;
+
+        /* Print the subtopics on the main page */
+        fprintf(fp, "\nAvailable subtopics:\n");
+        for (i = 1; i < asize(helpitems); ++i)
+        {
+            int len1 = strlen(helpitems[i].topic) + 2;
+
+            len += len1;
+            if (len > 79)
+            {
+                fprintf(fp, "\n");
+                len = len1;
+            }
+            fprintf(fp, "  %s", helpitems[i].topic);
+        }
+        fprintf(fp, "\n");
+    }
+    else if (strcmp(item->topic, "keywords") == 0)
+    {
+        /* Print the list of keywords */
+        fprintf(fp, "\nKeywords that select atoms by an integer property:\n");
+        fprintf(fp, "(use in expressions or like \"atomnr 1 to 5 7 9\")\n");
+        print_keyword_list(fp, symtab, INT_VALUE, FALSE);
+
+        fprintf(fp, "\nKeywords that select atoms by a numeric property:\n");
+        fprintf(fp, "(use in expressions or like \"occupancy 0.5 to 1\")\n");
+        print_keyword_list(fp, symtab, REAL_VALUE, FALSE);
+
+        fprintf(fp, "\nKeywords that select atoms by a string property:\n");
+        fprintf(fp, "(use like \"name PATTERN [PATTERN] ...\")\n");
+        print_keyword_list(fp, symtab, STR_VALUE, FALSE);
+
+        fprintf(fp, "\nAdditional keywords that directly select atoms:\n");
+        print_keyword_list(fp, symtab, GROUP_VALUE, FALSE);
+
+        fprintf(fp, "\nKeywords that directly evaluate to positions:\n");
+        fprintf(fp, "(see also \"help positions\")\n");
+        print_keyword_list(fp, symtab, POS_VALUE, FALSE);
+
+        fprintf(fp, "\nAdditional keywords:\n");
+        print_keyword_list(fp, symtab, POS_VALUE, TRUE);
+        print_keyword_list(fp, symtab, NO_VALUE, TRUE);
+    }
+}
diff --git a/src/gromacs/selection/selhelp.h b/src/gromacs/selection/selhelp.h
new file mode 100644 (file)
index 0000000..a032c83
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Functions for printing help for selections.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_HELP_H
+#define GMX_SELECTION_HELP_H
+
+#include <stdio.h>
+
+struct gmx_sel_symtab_t;
+
+/** Prints help for writing selections. */
+void
+_gmx_sel_print_help(FILE *fp, struct gmx_sel_symtab_t *symtab, const char *topic);
+
+#endif
diff --git a/src/gromacs/selection/selmethod.cpp b/src/gromacs/selection/selmethod.cpp
new file mode 100644 (file)
index 0000000..6e10315
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in selmethod.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdarg.h>
+
+#include <macros.h>
+#include <string2.h>
+
+#include "gromacs/selection/selmethod.h"
+
+#include "symrec.h"
+
+/*
+ * These global variables cannot be const because gmx_ana_selmethod_register()
+ * modifies them to set some defaults. This is a small price to pay for the
+ * convenience of not having to remember exactly how the selection compiler
+ * expects the structures to be filled, and even more so if the expectations
+ * change. Also, even if the gmx_ana_selmethod_t structures were made const,
+ * the parameters could not be without typecasts somewhere, because the param
+ * field in gmx_ana_selmethod_t cannot be declared const.
+ *
+ * Even though the variables may be modified, this should be thread-safe as
+ * modifications are done only in gmx_ana_selmethod_register(), and it should
+ * work even if called more than once for the same structure, and even if
+ * called concurrently from multiple threads (as long as the selection
+ * collection is not the same).
+ *
+ * All of these problems should go away if/when the selection methods are
+ * implemented as C++ classes.
+ */
+
+/* From sm_com.c */
+extern gmx_ana_selmethod_t sm_cog;
+extern gmx_ana_selmethod_t sm_com;
+/* From sm_simple.c */
+extern gmx_ana_selmethod_t sm_all;
+extern gmx_ana_selmethod_t sm_none;
+extern gmx_ana_selmethod_t sm_atomnr;
+extern gmx_ana_selmethod_t sm_resnr;
+extern gmx_ana_selmethod_t sm_resindex;
+extern gmx_ana_selmethod_t sm_molindex;
+extern gmx_ana_selmethod_t sm_atomname;
+extern gmx_ana_selmethod_t sm_atomtype;
+extern gmx_ana_selmethod_t sm_resname;
+extern gmx_ana_selmethod_t sm_insertcode;
+extern gmx_ana_selmethod_t sm_chain;
+extern gmx_ana_selmethod_t sm_mass;
+extern gmx_ana_selmethod_t sm_charge;
+extern gmx_ana_selmethod_t sm_altloc;
+extern gmx_ana_selmethod_t sm_occupancy;
+extern gmx_ana_selmethod_t sm_betafactor;
+extern gmx_ana_selmethod_t sm_x;
+extern gmx_ana_selmethod_t sm_y;
+extern gmx_ana_selmethod_t sm_z;
+/* From sm_distance.c */
+extern gmx_ana_selmethod_t sm_distance;
+extern gmx_ana_selmethod_t sm_mindistance;
+extern gmx_ana_selmethod_t sm_within;
+/* From sm_insolidangle.c */
+extern gmx_ana_selmethod_t sm_insolidangle;
+/* From sm_same.c */
+extern gmx_ana_selmethod_t sm_same;
+
+/* From sm_merge.c */
+extern gmx_ana_selmethod_t sm_merge;
+extern gmx_ana_selmethod_t sm_plus;
+/* From sm_permute.c */
+extern gmx_ana_selmethod_t sm_permute;
+
+/*! \internal \brief
+ * Helper structure for defining selection methods.
+ */
+typedef struct {
+    /*! \brief
+     * Name to register the method under.
+     *
+     * If NULL, use the actual name of the method.
+     * This field is used for defining synonyms.
+     */
+    const char            *name;
+    /** Method data structure to register. */
+    gmx_ana_selmethod_t   *method;
+} t_register_method;
+
+/** Array of selection methods defined in the library. */
+static const t_register_method smtable_def[] = {
+    {NULL,         &sm_cog},
+    {NULL,         &sm_com},
+
+    {NULL,         &sm_all},
+    {NULL,         &sm_none},
+    {NULL,         &sm_atomnr},
+    {NULL,         &sm_resnr},
+    {"resid",      &sm_resnr},
+    {NULL,         &sm_resindex},
+    {"residue",    &sm_resindex},
+    {NULL,         &sm_molindex},
+    {"mol",        &sm_molindex},
+    {"molecule",   &sm_molindex},
+    {NULL,         &sm_atomname},
+    {NULL,         &sm_atomtype},
+    {NULL,         &sm_resname},
+    {NULL,         &sm_insertcode},
+    {NULL,         &sm_chain},
+    {NULL,         &sm_mass},
+    {NULL,         &sm_charge},
+    {NULL,         &sm_altloc},
+    {NULL,         &sm_occupancy},
+    {NULL,         &sm_betafactor},
+    {NULL,         &sm_x},
+    {NULL,         &sm_y},
+    {NULL,         &sm_z},
+
+    {NULL,         &sm_distance},
+    {NULL,         &sm_mindistance},
+    {NULL,         &sm_within},
+    {NULL,         &sm_insolidangle},
+    {NULL,         &sm_same},
+
+    {NULL,         &sm_merge},
+    {NULL,         &sm_plus},
+    {NULL,         &sm_permute},
+};
+
+/*! \brief
+ * Convenience function for reporting errors found in selection methods.
+ */
+static void
+report_error(FILE *fp, const char *name, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    if (fp)
+    {
+        fprintf(fp, "selection method '%s': ", name);
+        vfprintf(fp, fmt, ap);
+        fprintf(fp, "\n");
+    }
+    va_end(ap);
+}
+
+/*! \brief
+ * Convenience function for reporting errors found in selection method parameters.
+ */
+static void
+report_param_error(FILE *fp, const char *mname, const char *pname,
+                   const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    if (fp)
+    {
+        fprintf(fp, "selection method '%s': parameter '%s': ", mname, pname);
+        vfprintf(fp, fmt, ap);
+        fprintf(fp, "\n");
+    }
+    va_end(ap);
+}
+
+/*! \brief
+ * Checks the validity of parameters.
+ *
+ * \param[in]     fp      File handle to use for diagnostic messages
+ *   (can be NULL).
+ * \param[in]     name    Name of the method (used for error messages).
+ * \param[in]     nparams Number of parameters in \p param.
+ * \param[in,out] param   Parameter array
+ *   (only the \c flags field of gmx_boolean parameters may be modified).
+ * \param[in]     symtab  Symbol table (used for checking overlaps).
+ * \returns       TRUE if there are no problems with the parameters,
+ *   FALSE otherwise.
+ *
+ * This function performs some checks common to both check_method() and
+ * check_modifier().
+ * The purpose of these checks is to ensure that the selection parser does not
+ * need to check for the validity of the parameters at each turn, and to
+ * report programming errors as early as possible.
+ * If you remove a check, make sure that the parameter parser can handle the
+ * resulting parameters.
+ */
+static gmx_bool
+check_params(FILE *fp, const char *name, int nparams, gmx_ana_selparam_t param[],
+             gmx_sel_symtab_t *symtab)
+{
+    gmx_bool              bOk = TRUE;
+    gmx_sel_symrec_t *sym;
+    int               i, j;
+
+    if (nparams > 0 && !param)
+    {
+        report_error(fp, name, "error: missing parameter data");
+        bOk = FALSE;
+        return FALSE;
+    }
+    if (nparams == 0 && param)
+    {
+        report_error(fp, name, "warning: parameter data unused because nparams=0");
+    }
+    /* Check each parameter */
+    for (i = 0; i < nparams; ++i)
+    {
+        /* Check that there is at most one NULL name, in the beginning */
+        if (param[i].name == NULL && i > 0)
+        {
+            report_error(fp, name, "error: NULL parameter should be the first one");
+            bOk = FALSE;
+            continue;
+        }
+        /* Check for duplicates */
+        for (j = 0; j < i; ++j)
+        {
+            if (param[j].name == NULL)
+            {
+                continue;
+            }
+            if (!gmx_strcasecmp(param[i].name, param[j].name))
+            {
+                report_error(fp, name, "error: duplicate parameter name '%s'", param[i].name);
+                bOk = FALSE;
+                break;
+            }
+        }
+        /* Check flags */
+        if (param[i].flags & SPAR_SET)
+        {
+            report_param_error(fp, name, param[i].name, "warning: flag SPAR_SET is set");
+            param[i].flags &= ~SPAR_SET;
+        }
+        if (param[i].flags & SPAR_RANGES)
+        {
+            if (param[i].val.type != INT_VALUE && param[i].val.type != REAL_VALUE)
+            {
+                report_param_error(fp, name, param[i].name, "error: SPAR_RANGES cannot be set for a non-numeric parameter");
+                bOk = FALSE;
+            }
+            if (param[i].flags & SPAR_DYNAMIC)
+            {
+                report_param_error(fp, name, param[i].name, "warning: SPAR_DYNAMIC does not have effect with SPAR_RANGES");
+                param[i].flags &= ~SPAR_DYNAMIC;
+            }
+            if (!(param[i].flags & SPAR_VARNUM) && param[i].val.nr != 1)
+            {
+                report_param_error(fp, name, param[i].name, "error: range should take either one or an arbitrary number of values");
+                bOk = FALSE;
+            }
+            if (param[i].flags & SPAR_ATOMVAL)
+            {
+                report_param_error(fp, name, param[i].name, "error: SPAR_RANGES and SPAR_ATOMVAL both set");
+                bOk = FALSE;
+            }
+        }
+        if ((param[i].flags & SPAR_VARNUM) && (param[i].flags & SPAR_ATOMVAL))
+        {
+            report_param_error(fp, name, param[i].name, "error: SPAR_VARNUM and SPAR_ATOMVAL both set");
+            bOk = FALSE;
+        }
+        if (param[i].flags & SPAR_ENUMVAL)
+        {
+            if (param[i].val.type != STR_VALUE)
+            {
+                report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL can only be set for string parameters");
+                bOk = FALSE;
+            }
+            if (param[i].val.nr != 1)
+            {
+                report_param_error(fp, name, param[i].name, "error: SPAR_ENUMVAL parameters should take exactly one value");
+                bOk = FALSE;
+            }
+            if (param[i].flags & (SPAR_DYNAMIC | SPAR_VARNUM | SPAR_ATOMVAL))
+            {
+                report_param_error(fp, name, param[i].name, "error: only SPAR_OPTIONAL supported with SPAR_ENUMVAL");
+                bOk = FALSE;
+            }
+        }
+        /* Check gmx_boolean parameters */
+        if (param[i].val.type == NO_VALUE)
+        {
+            if (param[i].val.nr != 0)
+            {
+                report_param_error(fp, name, param[i].name, "error: number of values should be zero for gmx_boolean parameters");
+                bOk = FALSE;
+            }
+            /* The gmx_boolean parameters should always be optional, so set the
+             * flag for convenience. */
+            param[i].flags |= SPAR_OPTIONAL;
+            /* Any other flags should not be specified */
+            if (param[i].flags & ~SPAR_OPTIONAL)
+            {
+                report_param_error(fp, name, param[i].name, "error: gmx_boolean parameter should not have any flags set");
+                bOk = FALSE;
+            }
+        }
+        /* Check val.nr */
+        if (param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL))
+        {
+            if (param[i].val.nr != -1)
+            {
+                report_param_error(fp, name, param[i].name, "warning: val.nr is not -1 although SPAR_VARNUM/SPAR_ATOMVAL is set");
+            }
+            param[i].val.nr = -1;
+        }
+        else if (param[i].val.type != NO_VALUE)
+        {
+            if (param[i].val.nr <= 0)
+            {
+                report_param_error(fp, name, param[i].name, "error: val.nr <= 0");
+                bOk = FALSE;
+            }
+        }
+        /* Check that the value pointer is NULL */
+        if (param[i].nvalptr != NULL)
+        {
+            report_param_error(fp, name, param[i].name, "warning: nvalptr is set");
+        }
+        if (param[i].val.u.ptr != NULL && !(param[i].flags & SPAR_ENUMVAL))
+        {
+            report_param_error(fp, name, param[i].name, "warning: value pointer is set");
+        }
+        /* Check that the name contains only valid characters */
+        if (param[i].name == NULL)
+        {
+            continue;
+        }
+        if (!isalpha(param[i].name[0]))
+        {
+            report_param_error(fp, name, param[i].name, "error: name does not begin with a letter");
+            bOk = FALSE;
+            continue;
+        }
+        for (j = 1; param[i].name[j] != 0; ++j)
+        {
+            if (param[i].name[j] != '_' && !isalnum(param[i].name[j]))
+            {
+                report_param_error(fp, name, param[i].name, "error: name contains non-alphanumeric characters");
+                bOk = FALSE;
+                break;
+            }
+        }
+        if (param[i].name[j] != 0)
+        {
+            continue;
+        }
+        /* Check that the name does not conflict with a method */
+        if (_gmx_sel_find_symbol(symtab, param[i].name, TRUE))
+        {
+            report_param_error(fp, name, param[i].name, "error: name conflicts with another method or a keyword");
+            bOk = FALSE;
+        }
+    } /* End of parameter loop */
+    /* Check parameters of existing methods */
+    sym = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
+    while (sym)
+    {
+        gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(sym);
+        gmx_ana_selparam_t  *param =
+            gmx_ana_selmethod_find_param(name, method);
+        if (param)
+        {
+            report_param_error(fp, method->name, param->name, "error: name conflicts with another method or a keyword");
+            bOk = FALSE;
+        }
+        sym = _gmx_sel_next_symbol(sym, SYMBOL_METHOD);
+    }
+    return bOk;
+}
+
+/*! \brief
+ * Checks the validity of selection method callback functions.
+ *
+ * \param[in] fp        File handle to use for diagnostic messages
+ *   (can be NULL).
+ * \param[in] method    The method to check.
+ * \returns   TRUE if there are no problems, FALSE otherwise.
+ *
+ * This function performs some checks common to both check_method() and
+ * check_modifier().
+ * This function checks that all the required callbacks are defined, i.e.,
+ * not NULL, to find programming errors.
+ */
+static gmx_bool
+check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
+{
+    gmx_bool         bOk = TRUE;
+    gmx_bool         bNeedInit;
+    int          i;
+
+    /* Make some checks on init_data and free */
+    if (method->nparams > 0 && !method->init_data)
+    {
+        report_error(fp, method->name, "error: init_data should be provided because the method has parameters");
+        bOk = FALSE;
+    }
+    if (method->free && !method->init_data)
+    {
+        report_error(fp, method->name, "warning: free is not used because of missing init_data");
+    }
+    /* Check presence of outinit for position-valued methods */
+    if (method->type == POS_VALUE && !method->outinit)
+    {
+        report_error(fp, method->name, "error: outinit should be provided because the method has POS_VALUE");
+        bOk = FALSE;
+    }
+    /* Warn of dynamic callbacks in static methods */
+    if (!(method->flags & SMETH_MODIFIER))
+    {
+        if (method->pupdate && !(method->flags & SMETH_DYNAMIC))
+        {
+            report_error(fp, method->name, "warning: pupdate not used because the method is static");
+            method->pupdate = NULL;
+        }
+    }
+    /* Check that there is an evaluation function */
+    if (method->type != NO_VALUE && !method->update && !method->pupdate)
+    {
+        report_error(fp, method->name, "error: evaluation function missing");
+        bOk = FALSE;
+    }
+    /* Loop through the parameters to determine if initialization callbacks
+     * are needed. */
+    bNeedInit = FALSE;
+    for (i = 0; i < method->nparams; ++i)
+    {
+        if (method->param[i].val.type != POS_VALUE
+            && (method->param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
+        {
+            bNeedInit = TRUE;
+        }
+    }
+    /* Check that the callbacks required by the parameters are present */
+    if (bNeedInit && !method->init)
+    {
+        report_error(fp, method->name, "error: init should be provided");
+        bOk = FALSE;
+    }
+    return bOk;
+}
+
+/*!
+ * Checks the validity of a selection method.
+ *
+ * \param[in]     fp     File handle to use for diagnostic messages
+ *   (can be NULL).
+ * \param[in,out] method Method to check.
+ * \param[in]     symtab Symbol table (used for checking overlaps).
+ *
+ * Checks the validity of the given selection method data structure
+ * that does not have \ref SMETH_MODIFIER set.
+ * If you remove a check, please make sure that the selection parser,
+ * compiler, and evaluation functions can deal with the method.
+ */
+static gmx_bool
+check_method(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
+{
+    gmx_bool         bOk = TRUE;
+
+    /* Check the type */
+    if (method->type == NO_VALUE)
+    {
+        report_error(fp, method->name, "error: no value type specified");
+        bOk = FALSE;
+    }
+    if (method->type == STR_VALUE && method->nparams > 0)
+    {
+        report_error(fp, method->name, "error: evaluates to a string but is not a keyword");
+        bOk = FALSE;
+    }
+    /* Check flags */
+    if (method->type == GROUP_VALUE)
+    {
+        /* Group methods should always have SMETH_SINGLEVAL,
+         * so set it for convenience. */
+        method->flags |= SMETH_SINGLEVAL;
+        /* Check that conflicting flags are not present. */
+        if (method->flags & SMETH_VARNUMVAL)
+        {
+            report_error(fp, method->name, "error: SMETH_VARNUMVAL cannot be set for group-valued methods");
+            bOk = FALSE;
+        }
+    }
+    else
+    {
+        if ((method->flags & SMETH_SINGLEVAL)
+            && (method->flags & SMETH_VARNUMVAL))
+        {
+            report_error(fp, method->name, "error: SMETH_SINGLEVAL and SMETH_VARNUMVAL both set");
+            bOk = FALSE;
+        }
+    }
+    if ((method->flags & SMETH_CHARVAL) && method->type != STR_VALUE)
+    {
+        report_error(fp, method->name, "error: SMETH_CHARVAL can only be specified for STR_VALUE methods");
+        bOk = FALSE;
+    }
+    /* Check the parameters */
+    if (!check_params(fp, method->name, method->nparams, method->param, symtab))
+    {
+        bOk = FALSE;
+    }
+    /* Check the callback pointers */
+    if (!check_callbacks(fp, method))
+    {
+        bOk = FALSE;
+    }
+
+    return bOk;
+}
+
+/*!
+ * Checks the validity of a selection modifier method.
+ *
+ * \param[in]     fp     File handle to use for diagnostic messages
+ *   (can be NULL).
+ * \param[in,out] method Method to check.
+ * \param[in]     symtab Symbol table (used for checking overlaps).
+ *
+ * Checks the validity of the given selection method data structure
+ * that has \ref SMETH_MODIFIER set.
+ * If you remove a check, please make sure that the selection parser,
+ * compiler, and evaluation functions can deal with the method.
+ */
+static gmx_bool
+check_modifier(FILE *fp, gmx_ana_selmethod_t *method, gmx_sel_symtab_t *symtab)
+{
+    gmx_bool         bOk = TRUE;
+
+    /* Check the type */
+    if (method->type != NO_VALUE && method->type != POS_VALUE)
+    {
+        report_error(fp, method->name, "error: modifier should have type POS_VALUE or NO_VALUE");
+        bOk = FALSE;
+    }
+    /* Check flags */
+    if (method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
+    {
+        report_error(fp, method->name, "error: modifier should not have SMETH_SINGLEVAL or SMETH_VARNUMVAL set");
+        bOk = FALSE;
+    }
+    /* Check the parameters */
+    /* The first parameter is skipped */
+    if (!check_params(fp, method->name, method->nparams-1, method->param+1, symtab))
+    {
+        bOk = FALSE;
+    }
+    /* Check the callback pointers */
+    if (!check_callbacks(fp, method))
+    {
+        bOk = FALSE;
+    }
+    if (method->update)
+    {
+        report_error(fp, method->name, "error: modifier should not have update");
+        bOk = FALSE;
+    }
+    if (method->type == POS_VALUE && !method->pupdate)
+    {
+        report_error(fp, method->name, "error: evaluation function missing");
+        bOk = FALSE;
+    }
+
+    return bOk;
+}
+
+/*!
+ * \param[in,out] symtab Symbol table to register the method to.
+ * \param[in]     name   Name under which the method should be registered.
+ * \param[in]     method Method to register.
+ * \returns       0 on success, EINVAL if there was something wrong with the
+ *   method.
+ *
+ * \p name does not need to match the name of the method, and the same
+ * method can be registered multiple times under different names.
+ * If \p name equals some previously registered name,
+ * an error message is printed and the method is not registered.
+ *
+ * The function also performs some sanity checking on the input method,
+ * and refuses to register it if there are problems.
+ * Some problems only generate warnings.
+ * All problems are described to \p stderr.
+ */
+int
+gmx_ana_selmethod_register(gmx_sel_symtab_t *symtab,
+                           const char *name, gmx_ana_selmethod_t *method)
+{
+    gmx_bool bOk;
+
+    /* Check the method */
+    if (method->flags & SMETH_MODIFIER)
+    {
+        bOk = check_modifier(stderr, method, symtab);
+    }
+    else
+    {
+        bOk = check_method(stderr, method, symtab);
+    }
+    /* Try to register the method if everything is ok */
+    if (bOk) 
+    {
+        if (!_gmx_sel_add_method_symbol(symtab, name, method))
+        {
+            bOk = FALSE;
+        }
+    }
+    if (!bOk)
+    {
+        report_error(stderr, name, "warning: not registered");
+        return EINVAL;
+    }
+    return 0;
+}
+
+/*!
+ * \param[in,out] symtab Symbol table to register the methods to.
+ * \returns       0 on success, -1 if any of the default methods could not be
+ *   registered.
+ */
+int
+gmx_ana_selmethod_register_defaults(gmx_sel_symtab_t *symtab)
+{
+    size_t i;
+    int  rc;
+    gmx_bool bOk;
+
+    bOk = TRUE;
+    for (i = 0; i < asize(smtable_def); ++i)
+    {
+        gmx_ana_selmethod_t *method = smtable_def[i].method;
+
+        if (smtable_def[i].name == NULL)
+        {
+            rc = gmx_ana_selmethod_register(symtab, method->name, method);
+        }
+        else
+        {
+            rc = gmx_ana_selmethod_register(symtab, smtable_def[i].name, method);
+        }
+        if (rc != 0)
+        {
+            bOk = FALSE;
+        }
+    }
+    return bOk ? 0 : -1;
+}
+
+/*!
+ * \param[in] name   Name of the parameter to search.
+ * \param[in] method Method to search for the parameter.
+ * \returns   Pointer to the parameter in the
+ *   \ref gmx_ana_selmethod_t::param "method->param" array,
+ *   or NULL if no parameter with name \p name was found.
+ *
+ * This is a simple wrapper for gmx_ana_selparam_find().
+ */
+gmx_ana_selparam_t *
+gmx_ana_selmethod_find_param(const char *name, gmx_ana_selmethod_t *method)
+{
+    return gmx_ana_selparam_find(name, method->nparams, method->param);
+}
diff --git a/src/gromacs/selection/selmethod.h b/src/gromacs/selection/selmethod.h
new file mode 100644 (file)
index 0000000..f5290a0
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \page page_module_selection_custom Custom selection methods
+ *
+ * Custom selection methods are defined by creating a new instance of 
+ * \c gmx_ana_selmethod_t and filling it with the necessary data for handling
+ * the selection.
+ * The structure contains callback pointers that define the actual behavior
+ * of the method.
+ * The following sections discuss how the structure should be filled and how
+ * to implement the callbacks.
+ *
+ *
+ * \section selmethods_define \c gmx_ana_selmethod_t data structure
+ *
+ * An example \c gmx_ana_selmethod_t definition could look like this:
+ *
+ * \code
+ * gmx_ana_selmethod_t sm_example = {
+ *   "example", GROUP_VALUE, 0,
+ *   asize(sm_params_example), sm_params_example,
+ *   &init_data_example,
+ *    NULL,
+ *   &init_example,
+ *    NULL,
+ *   &free_data_example,
+ *   &init_frame_example,
+ *   &evaluate_example,
+ *    NULL,
+ *   {"example from POS_EXPR [cutoff REAL]", 0, NULL},
+ * };
+ * \endcode
+ *
+ * The first value defines the name of the method.
+ * It is used mostly for informational purposes; the actual name(s) recognized
+ * by the selection parser are defined by the call to
+ * gmx_ana_selmethod_register() (see \ref selmethods_register).
+ *
+ * The second value defines the type of the value the method returns.
+ * Possible values are
+ *  - \ref NO_VALUE : This is allowed only for methods that have the flag
+ *    \ref SMETH_MODIFIER set (see \ref selmethods_modifiers).
+ *  - \ref INT_VALUE : The method returns one or more integer values.
+ *  - \ref REAL_VALUE : The method returns one or more floating-point values.
+ *  - \ref STR_VALUE : The method returns one or more strings.
+ *  - \ref POS_VALUE : The method returns one or more 3D vectors.
+ *  - \ref GROUP_VALUE : The method returns a single index group.
+ *
+ * The third value gives additional information about the method using
+ * a combination of flags.
+ * Possible flags are:
+ *  - \ref SMETH_REQTOP : If set, the topology information is always loaded
+ *    and the \p top pointer passed to the callbacks is guaranteed to be
+ *    non-NULL. Should be set if the method requires topology information
+ *    for evaluation.
+ *  - \ref SMETH_DYNAMIC : If set, the method can only be evaluated dynamically,
+ *    i.e., it requires data from the trajectory frame.
+ *  - \ref SMETH_MODIFIER : If set, the method is a selection modifier and
+ *    not an actual selection method.
+ *    For more details, see \ref selmethods_modifiers.
+ *
+ * There are two additional flags that specify the number of values the
+ * method returns. Only one of them can be set at a time.
+ * If neither is set, the default behavior is to evaluate a value for each
+ * input atom (except for \ref GROUP_VALUE methods, which always return a
+ * single group).
+ * Other behaviors can be specified with these flags:
+ *  - \ref SMETH_SINGLEVAL : If set, the method evaluates to a single value.
+ *    This is automatically set if the type is \ref GROUP_VALUE.
+ *  - \ref SMETH_VARNUMVAL : If set, the method evaluates to an arbitrary
+ *    number of values.
+ *    The number of values is determined based on the values given by the user
+ *    to the method parameters (see \ref selmethods_params).
+ *  .
+ * If either of these flags is specified (and the method type is not
+ * \ref GROUP_VALUE), the group passed to the evaluation callback should not
+ * be used as it can be NULL.
+ * Currently, the above flags only work (have been tested) for \ref POS_VALUE
+ * methods.
+ *
+ * There is one additional flag that can only be specified for \ref STR_VALUE
+ * methods: \ref SMETH_CHARVAL . It is meant for to ease implementation of
+ * methods that evaluate to strings consisting of single characters.
+ *
+ * The next two values determine the number of parameters and a pointer to
+ * the parameter array. The contents of the parameter array are described in
+ * \ref selmethods_params. If the method does not take parameters, the first
+ * value should be 0 and the second can be NULL.
+ * Currently, \ref STR_VALUE methods cannot take parameters, but this limitation
+ * should be easy to lift if required.
+ *
+ * These are followed by function callbacks that determine the
+ * actual behavior of the method. Any of these except the evaluation callback
+ * can be NULL (the evaluation callback can also be NULL if \ref NO_VALUE is
+ * specified for a selection modifier). However, the presence of parameters
+ * can require some of the callbacks to be implemented.
+ * The details are described in \ref selmethods_callbacks.
+ *
+ * Finally, there is a data structure that gives help texts for the method.
+ *
+ * The \c gmx_ana_selmethod_t variable should be declared as a global variable
+ * or it should be otherwise ensured that the structure is not freed: only a
+ * pointer to the structure is stored by the library.
+ *
+ *
+ * \section selmethods_params Defining parameters
+ *
+ * Parameters to selection methods are defined in a separate array of
+ * \c gmx_ana_selparam_t structures.
+ * The order of the parameters does not matter (except possibly for callback
+ * implementation), with one important exception:
+ * If the method evaluates to a \ref POS_VALUE, the first parameter should 
+ * have \ref GROUP_VALUE and be the one that is used to calculate the
+ * positions.
+ *
+ * An example parameter definition:
+ * \code
+ * static gmx_ana_selparam_t sm_params_example[] = {
+ *   {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
+ *   {"from",   {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+ * };
+ * \endcode
+ *
+ * The first value gives the name of the parameter.
+ * The first parameter can have a NULL name, which means that the value should
+ * immediately follow the method name. This can be used to specify methods
+ * of the type 'within 5 of ...'.
+ *
+ * The second value specifies the type of the value that the parameter accepts.
+ * \ref NO_VALUE can be used to specify a boolean parameter, other possibilities
+ * are the same as for the selection method type.
+ *
+ * The third value gives the number of values that the parameter accepts.
+ * For boolean parameters (\ref NO_VALUE), it should be 0.
+ * For parameters with \ref SPAR_VARNUM of \ref SPAR_ATOMVAL, it should be set
+ * to -1 for consistency (it is not used).
+ * If \ref SPAR_RANGES is specified, it should be either 1 (to accept a single
+ * continuous range) or -1 (if combined with \ref SPAR_VARNUM).
+ * In all other cases, it should be a positive integer; in most cases, it
+ * should be 1.
+ *
+ * The nest two pointers should always be NULL (they should be initialized in
+ * the callbacks), except the first pointer in the case of \ref SPAR_ENUMVAL
+ * (see below).
+ *
+ * The final value gives additional information about the acceptable values
+ * for the parameter using a combination of flags.
+ * The possible flags are:
+ *  - \ref SPAR_OPTIONAL : If set, the user does not need to provide a value
+ *    for the parameter. If not set, an error is reported if the parameter
+ *    is not specified by the user.
+ *  - \ref SPAR_DYNAMIC : If set, the method can handle dynamic values for
+ *    the parameter, i.e., the value(s) can be given by an expression that
+ *    evaluates to different values for different frames.
+ *  - \ref SPAR_RANGES : Can be set only for \ref INT_VALUE and
+ *    \ref REAL_VALUE parameters,
+ *    and cannot be combined with \ref SPAR_DYNAMIC.
+ *    If set, the parameter accepts ranges of values.
+ *    The ranges are automatically sorted and compacted such that a minimum
+ *    amount of non-overlapping ranges are given for the method.
+ *  - \ref SPAR_VARNUM : If set, the parameter can have a variable number
+ *    of values. These can be provided by the user as a list of values, or
+ *    using a single \ref SMETH_VARNUMVAL (or a single \ref SMETH_SINGLEVAL)
+ *    method.
+ *  - \ref SPAR_ATOMVAL : If set, the parameter accepts either a single value
+ *    or an expression that evaluates to a value for each input atom.
+ *    The single input value is treated as if the same value was returned for
+ *    each atom.
+ *    Cannot be combined with \ref SPAR_RANGES or \ref SPAR_VARNUM.
+ *  - \ref SPAR_ENUMVAL : Can only be set for \ref STR_VALUE parameters that
+ *    take a single value, and cannot be combined with any other flag than
+ *    \ref SPAR_OPTIONAL. If set, the parameter only accepts one of predefined
+ *    string values. See \ref SPAR_ENUMVAL documentation for details on how
+ *    to specify the acceptable values.
+ *
+ *
+ * \section selmethods_callbacks Implementing callbacks
+ *
+ * There are eight differen callback functions that can be implemented for
+ * selection methods: sel_datafunc(), sel_posfunc(), sel_initfunc(),
+ * sel_outinitfunc(), sel_freefunc(), sel_framefunc(), and two update functions.
+ * They are in this order in the \c gmx_ana_selmethod_t data structure.
+ * In general, any of the callbacks can be NULL, but the presence of
+ * parameters or other callbacks imposes some restrictions:
+ *  - sel_datafunc() should be provided if the method takes parameters.
+ *  - sel_initfunc() should be provided if the method takes
+ *    any parameters with the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flags,
+ *    except if those parameters have a \ref POS_VALUE.
+ *  - sel_outinitfunc() should be provided for \ref POS_VALUE methods
+ *    and \ref SMETH_VARNUMVAL methods.
+ *  - sel_freefunc() should be provided if sel_datafunc() and/or
+ *    sel_initfunc() allocate any dynamic memory in addition to the data
+ *    structure itself.
+ *  - sel_updatefunc_pos() only makes sense for methods with \ref SMETH_DYNAMIC
+ *    set.
+ *  - At least one update function should be provided unless the method type is
+ *    \ref NO_VALUE.
+ *
+ * The documentations for the function pointer types provide more information
+ * about how the callbacks should be implemented.
+ *
+ *
+ * \section selmethods_modifiers Selection modifiers
+ *
+ * Selection modifiers are a special kind of selection methods that can be
+ * appended to the end of a selection. They are specified by adding the
+ * \ref SMETH_MODIFIER flag to the \c gmx_ana_selmethod_t.
+ * They can have two different types:
+ *  - \ref POS_VALUE : These modifiers are given the final positions
+ *    as an input, and they can make modifications to the selection that are
+ *    not possible otherwise (e.g., permute the atoms).
+ *    The modifier should implement sel_updatefunc_pos() and also have
+ *    one NULL parameter in the beginning of the parameter list that takes
+ *    \ref POS_VALUE and is used to give the input positions.
+ *  - \ref NO_VALUE : These modifiers do not modify the final selection, but
+ *    can be used to implement per-selection options for analysis tools
+ *    or to control the default behavior of the selection engine
+ *    (currently, such a framework is not implemented, but should be easy to
+ *    implement if required).
+ *
+ * In addition to restricting the type of the method, selection modifiers
+ * do not allow the flags \ref SMETH_SINGLEVAL and \ref SMETH_VARNUMVAL
+ * (they would not make sense).
+ *
+ * Parameters and callbacks should be implemented as with normal selection
+ * method, but beware that very little of the functionality has been tested.
+ *
+ * \todo
+ * The modifier handling could be made more flexible and more generic;
+ * the current implementation does not allow many things which would be
+ * possible with slight changes in the internals of the library.
+ *
+ *
+ * \section selmethods_register Registering the method
+ *
+ * After defining the method with \c gmx_ana_selmethod_t, it should be
+ * registered with the selection engine.
+ * In analysis programs, this can be done by calling
+ * gmx_ana_selmethod_register().
+ * If adding the method to the library, you should add a pointer to the new
+ * method structure into the \c smtable_def array (in selmethod.cpp), and it is
+ * registered automatically.
+ * In both cases, gmx_ana_selmethod_register() does several checks on the
+ * structure and reports any errors or inconsistencies it finds.
+ */
+/*! \file
+ * \brief API for handling selection methods.
+ *
+ * There should be no need to use the data structures or call the
+ * functions in this file directly unless implementing a custom selection
+ * method.
+ *
+ * Instructions for implementing custom selection methods can be found
+ * on a separate page: \ref page_module_selection_custom
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELMETHOD_H
+#define GMX_SELECTION_SELMETHOD_H
+
+#include "../legacyheaders/typedefs.h"
+
+#include "indexutil.h"
+#include "selparam.h"
+#include "selvalue.h"
+
+struct gmx_ana_pos_t;
+struct gmx_ana_poscalc_coll_t;
+struct gmx_ana_selcollection_t;
+
+/*! \name Selection method flags
+ * \anchor selmethod_flags
+ */
+/*@{*/
+/*! \brief
+ * If set, the method requires topology information.
+ */
+#define SMETH_REQTOP     1
+/*! \brief
+ * If set, the method can only be evaluated dynamically.
+ */
+#define SMETH_DYNAMIC    2
+/*! \brief
+ * If set, the method evaluates to a single value.
+ *
+ * The default is that the method evaluates to a value for each input atom.
+ * Cannot be combined with \ref SMETH_VARNUMVAL.
+ */
+#define SMETH_SINGLEVAL  4
+/*! \brief
+ * If set, the method evaluates to an arbitrary number of values.
+ *
+ * The default is that the method evaluates to a value for each input atom.
+ * Cannot be combined with \ref SMETH_SINGLEVAL or with \ref GROUP_VALUE.
+ */
+#define SMETH_VARNUMVAL  8
+/*! \brief
+ * If set, the method evaluates to single-character strings.
+ *
+ * This flag can only be set for \ref STR_VALUE methods. If it is set, the
+ * selection engine automatically allocates and frees the required strings.
+ * The evaluation function should store the character values as the first
+ * character in the strings in the output data structure and should not change
+ * the string pointers.
+ */
+#define SMETH_CHARVAL    64
+/*! \brief
+ * If set, the method is a selection modifier.
+ *
+ * The method type should be \ref GROUP_VALUE or \ref NO_VALUE .
+ * Cannot be combined with \ref SMETH_SINGLEVAL or \ref SMETH_VARNUMVAL .
+ */
+#define SMETH_MODIFIER   256
+/*@}*/
+
+/*! \brief
+ * Allocates and initializes internal data and parameter values.
+ *
+ * \param[in]     npar  Number of parameters in \p param.
+ * \param[in,out] param Pointer to (a copy of) the method's
+ *   \c gmx_ana_selmethod_t::param.
+ * \returns       Pointer to method-specific data structure.
+ *   This pointer will be passed as the last parameter of all other function
+ *   calls.
+ *   Should return NULL on error (only error that should occur is out of
+ *   memory).
+ *
+ * Should allocate and initialize any internal data required by the method.
+ * Should also initialize the value pointers (\c gmx_ana_selparam_t::val) in
+ * \p param to point to variables within the internal data structure,
+ * with the exception of parameters that specify the \ref SPAR_VARNUM or
+ * the \ref SPAR_ATOMVAL flag (these should be handled in sel_initfunc()).
+ * However, parameters with a position value should be initialized.
+ * It is also possible to initialize \ref SPAR_ENUMVAL statically outside
+ * this function (see \ref SPAR_ENUMVAL).
+ * The \c gmx_ana_selparam_t::nvalptr should also be initialized for
+ * non-position-valued parameters that have both \ref SPAR_VARNUM and
+ * \ref SPAR_DYNAMIC set (it can also be initialized for other parameters if
+ * desired, but the same information will be available through other means).
+ * For optional parameters, the default values can (and should) be initialized
+ * here, as the parameter values are not changed if the parameter is not
+ * provided.
+ *
+ * For boolean parameters (type equals \ref NO_VALUE), the default value
+ * should be set here. The user can override the value by giving the parameter
+ * either as 'NAME'/'noNAME', or as 'NAME on/off/yes/no'.
+ *
+ * If the method takes any parameters, this function must be provided.
+ */
+typedef void *(*sel_datafunc)(int npar, gmx_ana_selparam_t *param);
+/*! \brief
+ * Sets the position calculation collection for the method.
+ *
+ * \param[in]  pcc   Position calculation collection that the method should use
+ *   for position calculations.
+ * \param      data  Internal data structure from sel_datafunc().
+ *
+ * This function should be provided if the method uses the routines from
+ * poscalc.h for calculating positions.
+ * The pointer \p pcc should then be stored and used for initialization for
+ * any position calculation structures.
+ */
+typedef void  (*sel_posfunc)(struct gmx_ana_poscalc_coll_t *pcc, void *data);
+/*! \brief
+ * Does initialization based on topology and/or parameter values.
+ *
+ * \param[in]  top   Topology structure
+ *   (can be NULL if \ref SMETH_REQTOP is not set).
+ * \param[in]  npar  Number of parameters in \p param.
+ * \param[in]  param Pointer to (an initialized copy of) the method's
+ *   \c gmx_ana_selmethod_t::param.
+ * \param      data  Internal data structure from sel_datafunc().
+ * \returns    0 on success, a non-zero error code on failure.
+ *
+ * This function is called after the parameters have been processed:
+ * the values of the parameters are stored at the locations set in
+ * sel_datafunc().
+ * The flags \ref SPAR_DYNAMIC and \ref SPAR_ATOMVAL are cleared before
+ * calling the function if the value is static or single-valued, respectively.
+ * If a parameter had the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flag (and
+ * is not \ref POS_VALUE), a pointer to the memory allocated for the values is
+ * found in \c gmx_ana_selparam_t::val.
+ * The pointer should be stored by this function, otherwise the values
+ * cannot be accessed.
+ * For \ref SPAR_VARNUM parameters, the number of values can be accessed
+ * through \c gmx_ana_selparam_t::val. For parameters with \ref SPAR_DYNAMIC,
+ * the number is the maximum number of values (the actual number can be
+ * accessed in sel_framefunc() and in the update callback through the value
+ * pointed by \c gmx_ana_selparam_t::nvalptr).
+ * For \ref SPAR_ATOMVAL parameters, \c gmx_ana_selparam_t::val::nr is set to
+ * 1 if a single value was provided, otherwise it is set to the maximum number
+ * of values possibly passed to the method.
+ * The value pointed by \c gmx_ana_selparam_t::nvalptr always contains the same
+ * value as \c gmx_ana_selparam_t::val::nr.
+ *
+ * For dynamic \ref GROUP_VALUE parameters (\ref SPAR_DYNAMIC set), the value
+ * will be the largest possible selection that may occur during the
+ * evaluation. For other types of dynamic parameters, the values are
+ * undefined.
+ *
+ * If the method takes any parameters with the \ref SPAR_VARNUM or
+ * \ref SPAR_ATOMVAL flags, this function must be provided, except if these
+ * parameters all have \ref POS_VALUE.
+ *
+ * This function may be called multiple times for the same method if the
+ * method takes parameters with \ref SPAR_ATOMVAL set.
+ */
+typedef void  (*sel_initfunc)(t_topology *top, int npar,
+                              gmx_ana_selparam_t *param, void *data);
+/*! \brief
+ * Initializes output data structure.
+ *
+ * \param[in]     top   Topology structure
+ *   (can be NULL if \ref SMETH_REQTOP is not set).
+ * \param[in,out] out   Output data structure.
+ * \param[in]     data  Internal data structure from sel_datafunc().
+ * \returns       0 on success, an error code on error.
+ *
+ * This function is called immediately after sel_initfunc().
+ *
+ * If the method evaluates to a position (\ref POS_VALUE), this function
+ * should be provided, and it should initialize the \c gmx_ana_pos_t data
+ * structure pointed by \p out.p (the pointer is guaranteed to be non-NULL).
+ * The \p out.p->g pointer should be initialized to the group that is used
+ * to evaluate positions in sel_updatefunc() or sel_updatefunc_pos().
+ *
+ * The function should also be provided for non-position-valued
+ * \ref SMETH_VARNUMVAL methods. For these methods, it suffices to set the
+ * \p out->nr field to reflect the maximum number of values returned by the
+ * method.
+ *
+ * Currently, this function is not needed for other types of methods.
+ *
+ * This function may be called multiple times for the same method if the
+ * method takes parameters with \ref SPAR_ATOMVAL set.
+ */
+typedef void  (*sel_outinitfunc)(t_topology *top, gmx_ana_selvalue_t *out,
+                                 void *data);
+/*! \brief
+ * Frees the internal data.
+ *
+ * \param[in] data Internal data structure from sel_datafunc().
+ *
+ * This function should be provided if the internal data structure contains
+ * dynamically allocated data, and should free any such data.
+ * The data structure itself should not be freed; this is handled automatically.
+ * If there is no dynamically allocated data within the structure,
+ * this function is not needed.
+ * Any memory pointers received as values of parameters are managed externally,
+ * and should not be freed.
+ * Pointers set as the value pointer of \ref SPAR_ENUMVAL parameters should not
+ * be freed.
+ */
+typedef void  (*sel_freefunc)(void *data);
+
+/*! \brief
+ * Initializes the evaluation for a new frame.
+ *
+ * \param[in]  top  Topology structure
+ *   (can be NULL if \ref SMETH_REQTOP is not set).
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  Initialized periodic boundary condition structure,
+ *   or NULL if PBC should not be used.
+ * \param      data Internal data structure from sel_datafunc().
+ * \returns    0 on success, a non-zero error code on failure.
+ *
+ * This function should be implemented if the selection method needs to
+ * do some preprocessing for each frame, and the preprocessing does not
+ * depend on the evaluation group.
+ * Because \p sel_updatefunc_* can be called more than once for a frame,
+ * it is inefficient do the preprocessing there.
+ * It is ensured that this function will be called before
+ * \p sel_updatefunc_* for each frame, and that it will be called at most
+ * once for each frame.
+ * For static methods, it is called once, with \p fr and \p pbc set to
+ * NULL.
+ */
+typedef void  (*sel_framefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                               void *data);
+/*! \brief
+ * Evaluates a selection method.
+ *
+ * \param[in]  top  Topology structure
+ *   (can be NULL if \ref SMETH_REQTOP is not set).
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  Initialized periodic boundary condition structure,
+ *   or NULL if PBC should not be used.
+ * \param[in]  g    Index group for which the method should be evaluated.
+ * \param[out] out  Output data structure.
+ * \param      data Internal data structure from sel_datafunc().
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * This function should evaluate the method for each atom included in \p g,
+ * and write the output to \p out. The pointer in the union \p out->u that
+ * corresponds to the type of the method should be used.
+ * Enough memory has been allocated to store the output values.
+ * The number of values in \p out should also be updated if necessary.
+ * However, \ref POS_VALUE or \ref GROUP_VALUE methods should not touch
+ * \p out->nr (it should be 1 anyways).
+ *
+ * For \ref STR_VALUE methods, the pointers stored in \p out->s are discarded
+ * without freeing; it is the responsibility of this function to provide
+ * pointers that can be discarded without memory leaks.
+ */
+typedef void  (*sel_updatefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                                gmx_ana_index_t *g, gmx_ana_selvalue_t *out,
+                                void *data);
+/*! \brief
+ * Evaluates a selection method using positions.
+ *
+ * \param[in]  top  Topology structure
+ *   (can be NULL if \ref SMETH_REQTOP is not set).
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  Initialized periodic boundary condition structure,
+ *   or NULL if PBC should not be used.
+ * \param[in]  pos  Positions for which the method should be evaluated.
+ * \param[out] out  Output data structure.
+ * \param      data Internal data structure from sel_datafunc().
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * This function should evaluate the method for each position in \p g,
+ * and write the output values to \p out. The pointer in the union \p out->u
+ * that corresponds to the type of the method should be used.
+ * Enough memory has been allocated to store the output values.
+ * The number of values in \p out should also be updated if necessary.
+ * However, \ref POS_VALUE or \ref GROUP_VALUE methods should not touch
+ * \p out->nr (it should be 1 anyways).
+ *
+ * For \ref STR_VALUE methods, the pointers stored in \p out->s are discarded
+ * without freeing; it is the responsibility of this function to provide
+ * pointers that can be discarded without memory leaks.
+ */
+typedef void  (*sel_updatefunc_pos)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                                    struct gmx_ana_pos_t *pos,
+                                    gmx_ana_selvalue_t *out,
+                                    void *data);
+
+/*! \brief
+ * Help information for a selection method.
+ *
+ * If some information is not available, the corresponding field can be set to
+ * 0/NULL.
+ */
+typedef struct gmx_ana_selmethod_help_t
+{
+    /*! \brief
+     * One-line description of the syntax of the method.
+     *
+     * If NULL, the name of the method is used.
+     */
+    const char         *syntax;
+    /*! \brief
+     * Number of strings in \p help.
+     *
+     * Set to 0 if \p help is NULL.
+     */
+    int                 nlhelp;
+    /*! \brief
+     * Detailed help for the method.
+     *
+     * If there is no help available in addition to \p syntax, this can be set
+     * to NULL.
+     */
+    const char        **help;
+} gmx_ana_selmethod_help_t;
+
+/*! \brief
+ * Describes a selection method.
+ *
+ * Any of the function pointers except the update call can be NULL if the
+ * operation is not required or not supported. In this case,
+ * corresponding function calls are skipped.
+ *
+ * See the function pointer type documentation for details of how the
+ * functions should be implemented.
+ * More details on implementing new selection methods can be found on a
+ * separate page: \ref page_module_selection_custom.
+ */
+typedef struct gmx_ana_selmethod_t
+{
+    /** Name of the method. */
+    const char         *name;
+    /** Type which the method returns. */
+    e_selvalue_t        type;
+    /*! \brief
+     * Flags to specify how the method should be handled.
+     *
+     * See \ref selmethod_flags for allowed values.
+     */
+    int                 flags;
+    /** Number of parameters the method takes. */
+    int                 nparams;
+    /** Pointer to the array of parameter descriptions. */
+    gmx_ana_selparam_t *param;
+
+    /** Function for allocating and initializing internal data and parameters. */
+    sel_datafunc        init_data;
+    /** Function to set the position calculation collection. */
+    sel_posfunc         set_poscoll;
+    /** Function to do initialization based on topology and/or parameter values. */
+    sel_initfunc        init;
+    /** Function to initialize output data structure. */
+    sel_outinitfunc     outinit;
+    /** Function to free the internal data. */
+    sel_freefunc        free;
+
+    /** Function to initialize the calculation for a new frame. */
+    sel_framefunc       init_frame;
+    /** Function to evaluate the value. */
+    sel_updatefunc      update;
+    /** Function to evaluate the value using positions. */
+    sel_updatefunc_pos  pupdate;
+
+    /** Help data for the method. */
+    gmx_ana_selmethod_help_t help;
+} gmx_ana_selmethod_t;
+
+/** Registers a selection method. */
+int
+gmx_ana_selmethod_register(struct gmx_sel_symtab_t *symtab,
+                           const char *name, gmx_ana_selmethod_t *method);
+/** Registers all selection methods in the library. */
+int
+gmx_ana_selmethod_register_defaults(struct gmx_sel_symtab_t *symtab);
+
+/** Finds a parameter from a selection method by name. */
+gmx_ana_selparam_t *
+gmx_ana_selmethod_find_param(const char *name, gmx_ana_selmethod_t *method);
+
+#endif
diff --git a/src/gromacs/selection/selparam.h b/src/gromacs/selection/selparam.h
new file mode 100644 (file)
index 0000000..507d0fc
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief API for handling parameters used in selections.
+ *
+ * There should be no need to use the data structures or call the
+ * functions in this file directly unless implementing a custom selection
+ * method.
+ *
+ * More details can be found on the page discussing
+ * \ref page_module_selection_custom "custom selection methods".
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELPARAM_H
+#define GMX_SELECTION_SELPARAM_H
+
+#include "indexutil.h"
+#include "selvalue.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*! \name Parameter flags
+ * \anchor selparam_flags
+ */
+/*@{*/
+/*! \brief
+ * This flag is set if the user has provided the parameter.
+ *
+ * This flag is set automatically, and should not be set by the user.
+ */
+#define SPAR_SET      1
+/*! \brief
+ * If not set, an error is reported if the parameter is not specified by the
+ * user.
+ */
+#define SPAR_OPTIONAL 2
+/*! \brief
+ * If set, the parameter value can be dynamic, i.e., be different for
+ * different frames.
+ *
+ * If set, the parameter value should only be accessed in the update function
+ * of \c gmx_ana_selmethod_t.
+ * The flag is cleared before sel_initfunc() if the value provided is actually
+ * static.
+ */
+#define SPAR_DYNAMIC  4
+/*! \brief
+ * If set, the parameter value is parsed into sorted ranges.
+ *
+ * Can only be specified for integer parameters.
+ * If specified, the value of the parameter (\c gmx_ana_selparam_t::val)
+ * consists of sets of two integers, each specifying a range.
+ * The values give the endpoints of the ranges (inclusive).
+ * The ranges are sorted and overlapping/continuous ranges are merged into
+ * a single range to minimize the number of ranges.
+ *
+ * If this flag is specified, \c gmx_ana_selparam_t::nval gives the number of
+ * ranges. \p gmx_ana_selparam_t::nval should be 1 or \ref SPAR_VARNUM should be
+ * specified; other values would lead to unpredictable behavior.
+ */
+#define SPAR_RANGES   8
+/*! \brief
+ * If set, the parameter can have any number of values.
+ *
+ * If specified, the data pointer in \c gmx_ana_selparam_t::val should be NULL;
+ * the memory is allocated by the parameter parser.
+ * The implementation of the method should ensure that the pointer to the
+ * allocated memory is stored somewhere in sel_initfunc();
+ * otherwise, the memory is lost.
+ *
+ * The initial value of \c gmx_ana_selparam_t::nval is not used with this flag.
+ * Instead, it will give the number of actual values provided by the user
+ * after the parameters have been parsed.
+ * For consistency, it should be initialized to -1.
+ *
+ * Cannot be combined with \ref GROUP_VALUE parameters.
+ */
+#define SPAR_VARNUM   16
+/*! \brief
+ * If set, the parameter can have a separate value for each atom.
+ *
+ * The flag is cleared before sel_initfunc() if the value provided is actually
+ * a single value.
+ *
+ * Cannot be combined with \ref POS_VALUE or \ref GROUP_VALUE parameters.
+ */
+#define SPAR_ATOMVAL  32
+/*! \brief
+ * If set, the parameter takes one of a set of predefined strings.
+ *
+ * Can only be specified for a \ref STR_VALUE parameter that takes a single
+ * string.
+ * The data pointer in \c gmx_ana_selparam_t::val should be initialized into an
+ * array of strings such that the first and last elements are NULL, and the
+ * rest give the possible values. For optional values, the second element in
+ * the array should give the default value. The string given by the user is
+ * matched against the beginnings of the given strings, and if a unique match
+ * is found, the first pointer in the array will be initialized to point to
+ * the matching string.
+ * The data pointer can be initialized as a static array; duplication of the
+ * array for multiple instances of the same method is automatically taken care
+ * of.
+ */
+#define SPAR_ENUMVAL  128
+/*@}*/
+
+/*! \brief
+ * Describes a single parameter for a selection method.
+ */
+typedef struct gmx_ana_selparam_t
+{
+    /** Name of the parameter. */
+    const char         *name;
+    /*! \brief
+     * The parameter value.
+     *
+     * Type \ref NO_VALUE can be used to define a boolean parameter.
+     * The number of values should be 0 for boolean parameters.
+     *
+     * The value pointer be initialized to NULL in the definition of a
+     * \c gmx_ana_selmethod_t and initialized in the
+     * \c gmx_ana_selmethod_t::init_data call
+     * (see sel_datafunc()).
+     * However, if \ref SPAR_VARNUM is provided and the parameter is not
+     * \ref POS_VALUE, this field should not be initialized. Instead,
+     * sufficient memory is allocated automatically and the pointer should be
+     * stored in \c gmx_ana_selmethod_t::init
+     * (see sel_initfunc()).
+     *
+     * The values cannot be accessed outside these two functions: the compiler
+     * makes a copy of the parameter structure for each instance of the
+     * method, and the original parameter array is not changed.
+     */
+    gmx_ana_selvalue_t  val;
+    /*! \brief
+     * Pointer to store the number of values.
+     *
+     * If not NULL, the number of values for the parameter is stored in the
+     * pointed value.
+     * Should be specified if \ref SPAR_VARNUM and \ref SPAR_DYNAMIC are both
+     * set.
+     *
+     * Should be initialized to NULL in the definition a \c gmx_ana_selmethod_t
+     * and initialized in sel_datafunc().
+     */
+    int                *nvalptr;
+    /*! \brief
+     * Flags that alter the way the parameter is parsed/handled.
+     *
+     * See \ref selparam_flags for allowed values.
+     */
+    int                 flags;
+} gmx_ana_selparam_t;
+
+/** Finds a parameter from an array by name. */
+gmx_ana_selparam_t *
+gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/selection/selvalue.cpp b/src/gromacs/selection/selvalue.cpp
new file mode 100644 (file)
index 0000000..5c455ca
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in selvalue.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <smalloc.h>
+
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selvalue.h"
+
+/*!
+ * \param[out] val  Output structure
+ *
+ * The type of \p val is not touched.
+ * Any contents of \p val are discarded without freeing.
+ */
+void
+_gmx_selvalue_clear(gmx_ana_selvalue_t *val)
+{
+    val->nr     = 0;
+    val->u.ptr  = NULL;
+    val->nalloc = 0;
+}
+
+/*!
+ * \param[in,out] val  Value structure to allocate.
+ * \param[in]     n    Maximum number of values needed.
+ * \returns       Zero on success.
+ *
+ * Reserves memory for the values within \p val to store at least \p n values,
+ * of the type specified in the \p val structure.
+ *
+ * If the type is \ref POS_VALUE or \ref GROUP_VALUE, memory is reserved for
+ * the data structures, but no memory is reserved inside these newly allocated
+ * data structures.
+ * Similarly, for \ref STR_VALUE values, the pointers are set to NULL.
+ * For other values, the memory is uninitialized.
+ */
+int
+_gmx_selvalue_reserve(gmx_ana_selvalue_t *val, int n)
+{
+    int  i;
+
+    if (val->nalloc == -1)
+    {
+        return 0;
+    }
+
+    if (!val->u.ptr || val->nalloc < n)
+    {
+        switch (val->type)
+        {
+            case INT_VALUE:   srenew(val->u.i, n); break;
+            case REAL_VALUE:  srenew(val->u.r, n); break;
+            case STR_VALUE:
+                srenew(val->u.s, n);
+                for (i = val->nalloc; i < n; ++i)
+                {
+                    val->u.s[i] = NULL;
+                }
+                break;
+            case POS_VALUE:
+                srenew(val->u.p, n);
+                for (i = val->nalloc; i < n; ++i)
+                {
+                    gmx_ana_pos_clear(&val->u.p[i]);
+                }
+                break;
+            case GROUP_VALUE:
+                srenew(val->u.g, n);
+                for (i = val->nalloc; i < n; ++i)
+                {
+                    gmx_ana_index_clear(&val->u.g[i]);
+                }
+                break;
+            case NO_VALUE:    break;
+        }
+        val->nalloc = n;
+    }
+    return 0;
+}
+
+/*!
+ * \param[in,out] val    Value structure to allocate.
+ * \param[in]     ptr    Pointer where the values should be stored.
+ * \returns       Zero on success.
+ *
+ * Automatic memory management is disabled for \p ptr, unless \p ptr is NULL.
+ */
+int
+_gmx_selvalue_setstore(gmx_ana_selvalue_t *val, void *ptr)
+{
+    val->u.ptr  = ptr;
+    val->nalloc = (ptr ? -1 : 0);
+    return 0;
+}
+
+/*!
+ * \param[in,out] val    Value structure to allocate.
+ * \param[in]     ptr    Pointer where the values should be stored.
+ * \param[in]     nalloc Number of values allocated for \p ptr.
+ * \returns       Zero on success.
+ */
+int
+_gmx_selvalue_setstore_alloc(gmx_ana_selvalue_t *val, void *ptr, int nalloc)
+{
+    val->u.ptr  = ptr;
+    val->nalloc = nalloc;
+    return 0;
+}
diff --git a/src/gromacs/selection/selvalue.h b/src/gromacs/selection/selvalue.h
new file mode 100644 (file)
index 0000000..e789ef5
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares ::gmx_ana_selvalue_t.
+ *
+ * There should be no need to use the data structures in this file directly
+ * unless implementing a custom selection routine.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef GMX_SELECTION_SELVALUE_H
+#define GMX_SELECTION_SELVALUE_H
+
+#include "../legacyheaders/types/simple.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** Defines the value type of a different selection objects. */
+typedef enum
+{
+    NO_VALUE,           /**< No value; either an error condition or an gmx_boolean 
+                             parameter. */
+    INT_VALUE,          /**< One or more integer values. */
+    REAL_VALUE,         /**< One or more real values. */
+    STR_VALUE,          /**< One or more string values. */
+    POS_VALUE,          /**< One or more position values. */
+    GROUP_VALUE         /**< One group of atoms. */
+} e_selvalue_t;
+
+/*! \brief
+ * Describes a value of a selection expression or of a selection method
+ * parameter.
+ *
+ * Which field in the union is used depends on the \p type.
+ */
+typedef struct gmx_ana_selvalue_t
+{
+    /** Type of the value. */
+    e_selvalue_t                type;
+    /*! \brief
+     * Number of values in the array pointed by the union.
+     *
+     * Note that for position and group values, it is the number of
+     * data structures in the array, not the number of positions or
+     * the number of atoms in the group.
+     */
+    int                         nr;
+    /** Pointer to the value. */
+    union {
+        /*! \brief
+         * Generic pointer for operations that do not need type information.
+         *
+         * Needs to be the first member to be able to use initialized arrays.
+         */
+        void                   *ptr;
+        /** Integer value(s) (type \ref INT_VALUE). */
+        int                    *i;
+        /** Real value(s) (type \ref REAL_VALUE). */
+        real                   *r;
+        /** String value(s) (type \ref STR_VALUE). */
+        char                  **s;
+        /** Structure for the position value(s) (type \ref POS_VALUE). */
+        struct gmx_ana_pos_t   *p;
+        /** Group value (type \ref GROUP_VALUE). */
+        struct gmx_ana_index_t *g;
+        /** Boolean value (only parameters of type \ref NO_VALUE); */
+        gmx_bool                   *b;
+    }                           u;
+    /*! \brief
+     * Number of elements allocated for the value array.
+     */
+    int                         nalloc;
+} gmx_ana_selvalue_t;
+
+/** Initializes an empty selection value structure. */
+void
+_gmx_selvalue_clear(gmx_ana_selvalue_t *val);
+/** Reserve memory for storing selection values. */
+int
+_gmx_selvalue_reserve(gmx_ana_selvalue_t *val, int n);
+/** Sets the memory for storing selection values. */
+int
+_gmx_selvalue_setstore(gmx_ana_selvalue_t *val, void *ptr);
+/** Sets the memory for storing selection values and marks it for automatic freeing. */
+int
+_gmx_selvalue_setstore_alloc(gmx_ana_selvalue_t *val, void *ptr, int nalloc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gromacs/selection/sm_compare.cpp b/src/gromacs/selection/sm_compare.cpp
new file mode 100644 (file)
index 0000000..5503a24
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements internal selection method for comparison expressions.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <maths.h>
+#include <macros.h>
+#include <smalloc.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/selmethod.h"
+
+/** Defines the comparison operator for comparison expressions. */
+typedef enum
+{
+    CMP_INVALID,        /**< Indicates an error */
+    CMP_LESS,           /**< '<' */
+    CMP_LEQ,            /**< '<=' */
+    CMP_GTR,            /**< '>' */
+    CMP_GEQ,            /**< '>=' */
+    CMP_EQUAL,          /**< '==' */
+    CMP_NEQ             /**< '!=' */
+} e_comparison_t;
+
+/** The operand has a single value. */
+#define CMP_SINGLEVAL  1
+/** The operand value is dynamic. */
+#define CMP_DYNAMICVAL 2
+/** The value is real. */
+#define CMP_REALVAL    4
+/** The integer array is allocated. */
+#define CMP_ALLOCINT   16
+/** The real array is allocated. */
+#define CMP_ALLOCREAL  32
+
+/*! \internal \brief
+ * Data structure for comparison expression operand values.
+ */
+typedef struct
+{
+    /** Flags that describe the type of the operand. */
+    int             flags;
+    /** (Array of) integer value(s). */
+    int        *i;
+    /** (Array of) real value(s). */
+    real       *r;
+} t_compare_value;
+
+/*! \internal \brief
+ * Data structure for comparison expression evaluation.
+ */
+typedef struct
+{
+    /** Comparison operator as a string. */
+    char            *cmpop;
+    /** Comparison operator type. */
+    e_comparison_t   cmpt;
+    /** Left value. */
+    t_compare_value  left;
+    /** Right value. */
+    t_compare_value  right;
+} t_methoddata_compare;
+
+/** Allocates data for comparison expression evaluation. */
+static void *
+init_data_compare(int npar, gmx_ana_selparam_t *param);
+/** Initializes data for comparison expression evaluation. */
+static void
+init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Frees the memory allocated for comparison expression evaluation. */
+static void
+free_data_compare(void *data);
+/** Evaluates comparison expressions. */
+static void
+evaluate_compare(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for comparison expression evaluation. */
+static gmx_ana_selparam_t smparams_compare[] = {
+    {"int1",  {INT_VALUE,  -1, {NULL}}, NULL,
+     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"real1", {REAL_VALUE, -1, {NULL}}, NULL,
+     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"op",    {STR_VALUE,   1, {NULL}}, NULL, 0},
+    {"int2",  {INT_VALUE,  -1, {NULL}}, NULL,
+     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"real2", {REAL_VALUE, -1, {NULL}}, NULL,
+     SPAR_OPTIONAL | SPAR_DYNAMIC | SPAR_ATOMVAL},
+};
+
+/** \internal Selection method data for comparison expression evaluation. */
+gmx_ana_selmethod_t sm_compare = {
+    "cmp", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_compare), smparams_compare,
+    &init_data_compare,
+    NULL,
+    &init_compare,
+    NULL,
+    &free_data_compare,
+    NULL,
+    &evaluate_compare,
+    NULL,
+    {NULL, 0, NULL},
+};
+
+/*! \brief
+ * Returns a \c e_comparison_t value corresponding to an operator.
+ *
+ * \param[in] str  String to process.
+ * \returns   The comparison type corresponding to the first one or two
+ *   characters of \p str.
+ *
+ * \p str can contain any number of characters; only the first two
+ * are used.
+ * If the beginning of \p str does not match any of the recognized types,
+ * \ref CMP_INVALID is returned.
+ */
+static e_comparison_t
+comparison_type(char *str)
+{
+    switch (str[0])
+    {
+        case '<': return (str[1] == '=') ? CMP_LEQ   : CMP_LESS;
+        case '>': return (str[1] == '=') ? CMP_GEQ   : CMP_GTR;
+        case '=': return (str[1] == '=') ? CMP_EQUAL : CMP_INVALID;
+        case '!': return (str[1] == '=') ? CMP_NEQ   : CMP_INVALID;
+    }
+    return CMP_INVALID;
+}
+
+/*! \brief
+ * Returns a string corresponding to a \c e_comparison_t value.
+ *
+ * \param[in] cmpt  Comparison type to convert.
+ * \returns   Pointer to a string that corresponds to \p cmpt.
+ *
+ * The return value points to a string constant and should not be \p free'd.
+ * 
+ * The function returns NULL if \p cmpt is not one of the valid values.
+ */
+static const char *
+comparison_type_str(e_comparison_t cmpt)
+{
+    switch (cmpt)
+    {
+        case CMP_INVALID: return "INVALID"; break;
+        case CMP_LESS:    return "<";  break;
+        case CMP_LEQ:     return "<="; break;
+        case CMP_GTR:     return ">";  break;
+        case CMP_GEQ:     return ">="; break;
+        case CMP_EQUAL:   return "=="; break;
+        case CMP_NEQ:     return "!="; break;
+    }
+    return NULL;
+}
+
+/*!
+ * \param[in] fp    File to receive the output.
+ * \param[in] data  Should point to a \c t_methoddata_compare.
+ */
+void
+_gmx_selelem_print_compare_info(FILE *fp, void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+
+    fprintf(fp, " \"");
+    /* Print the left value */
+    if ((d->left.flags & CMP_SINGLEVAL) && !(d->left.flags & CMP_DYNAMICVAL))
+    {
+        if (d->left.flags & CMP_REALVAL)
+        {
+            fprintf(fp, "%f ", d->left.r[0]);
+        }
+        else
+        {
+            fprintf(fp, "%d ", d->left.i[0]);
+        }
+    }
+    /* Print the operator */
+    if (d->cmpt != CMP_INVALID)
+    {
+        fprintf(fp, "%s", comparison_type_str(d->cmpt));
+    }
+    else
+    {
+        fprintf(fp, "%s", d->cmpop);
+    }
+    /* Print the right value */
+    if ((d->right.flags & CMP_SINGLEVAL) && !(d->right.flags & CMP_DYNAMICVAL))
+    {
+        if (d->right.flags & CMP_REALVAL)
+        {
+            fprintf(fp, " %f", d->right.r[0]);
+        }
+        else
+        {
+            fprintf(fp, " %d", d->right.i[0]);
+        }
+    }
+    fprintf(fp, "\"");
+}
+
+/*!
+ * \param[in]     npar  Not used (should be 5).
+ * \param[in,out] param Method parameters (should point to a copy of
+ *   \ref smparams_compare).
+ * \returns       Pointer to the allocated data (\c t_methoddata_compare).
+ *
+ * Allocates memory for a \c t_methoddata_compare structure.
+ */
+static void *
+init_data_compare(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_compare *data;
+
+    snew(data, 1);
+    param[2].val.u.s = &data->cmpop;
+    return data;
+}
+
+/* \brief
+ * Reverses a comparison operator.
+ *
+ * \param[in] type  Comparison operator to reverse.
+ * \returns   The correct comparison operator that equals \p type when the
+ *   left and right sides are interchanged.
+ */
+static e_comparison_t
+reverse_comparison_type(e_comparison_t type)
+{
+    switch (type)
+    {
+        case CMP_LESS: return CMP_GTR;
+        case CMP_LEQ:  return CMP_GEQ;
+        case CMP_GTR:  return CMP_LESS;
+        case CMP_GEQ:  return CMP_LEQ;
+        default:       break;
+    }
+    return type;
+}
+
+/*! \brief
+ * Initializes the value storage for comparison expression.
+ *
+ * \param[out] val   Value structure to initialize.
+ * \param[in]  param Parameters to use for initialization.
+ * \returns    The number of values provided for the value, 0 on error.
+ */
+static int
+init_comparison_value(t_compare_value *val, gmx_ana_selparam_t param[2])
+{
+    int  n;
+
+    val->flags = 0;
+    if (param[0].flags & SPAR_SET)
+    {
+        val->flags |=  (param[0].flags & SPAR_DYNAMIC) ? CMP_DYNAMICVAL : 0;
+        val->flags |= !(param[0].flags & SPAR_ATOMVAL) ? CMP_SINGLEVAL  : 0;
+        n           = param[0].val.nr;
+        val->i      = param[0].val.u.i;
+    }
+    else if (param[1].flags & SPAR_SET)
+    {
+        val->flags |=  (param[1].flags & SPAR_DYNAMIC) ? CMP_DYNAMICVAL : 0;
+        val->flags |= !(param[1].flags & SPAR_ATOMVAL) ? CMP_SINGLEVAL  : 0;
+        val->flags |= CMP_REALVAL;
+        n           = param[1].val.nr;
+        val->r      = param[1].val.u.r;
+    }
+    else
+    {
+        n           = 0;
+        val->i      = NULL;
+        val->r      = NULL;
+    }
+    return n;
+}
+
+/* \brief
+ * Converts an integer value to floating point.
+ *
+ * \param[in]     n   Number of values in the \p val->u array.
+ * \param[in,out] val Value to convert.
+ */
+static void
+convert_int_real(int n, t_compare_value *val)
+{
+    int   i;
+    real *rv;
+
+    snew(rv, n);
+    for (i = 0; i < n; ++i)
+    {
+        rv[i] = (real)val->i[i];
+    }
+    /* Free the previous value if one is present. */
+    sfree(val->r);
+    val->r      = rv;
+    val->flags |= CMP_REALVAL | CMP_ALLOCREAL;
+}
+
+/* \brief
+ * Converts a floating point value to integer.
+ *
+ * \param[in]     n      Number of values in the \p val->u array.
+ * \param[in,out] val    Value to convert.
+ * \param[in]     cmpt   Comparison operator type.
+ * \param[in]     bRight TRUE if \p val appears on the right hand size of
+ *   \p cmpt.
+ * \returns       0 on success, EINVAL on error.
+ *
+ * The values are rounded such that the same comparison operator can be used.
+ */
+static void
+convert_real_int(int n, t_compare_value *val, e_comparison_t cmpt, gmx_bool bRight)
+{
+    int   i;
+    int  *iv;
+
+    if (!bRight)
+    {
+        cmpt = reverse_comparison_type(cmpt);
+    }
+    snew(iv, n);
+    /* Round according to the comparison type */
+    for (i = 0; i < n; ++i)
+    {
+        switch (cmpt)
+        {
+            case CMP_LESS:
+            case CMP_GEQ:
+                iv[i] = (int)ceil(val->r[i]);
+                break;
+            case CMP_GTR:
+            case CMP_LEQ:
+                iv[i] = (int)floor(val->r[i]);
+                break;
+            case CMP_EQUAL:
+            case CMP_NEQ:
+                sfree(iv);
+                /* TODO: Implement, although it isn't typically very useful.
+                 * Implementation is only a matter or proper initialization,
+                 * the evaluation function can already handle this case with
+                 * proper preparations. */
+                GMX_THROW(gmx::NotImplementedError("Equality comparison between dynamic integer and static real expressions not implemented"));
+            case CMP_INVALID: /* Should not be reached */
+                sfree(iv);
+                GMX_THROW(gmx::InternalError("Invalid comparison type"));
+        }
+    }
+    /* Free the previous value if one is present. */
+    sfree(val->i);
+    val->i      = iv;
+    val->flags &= ~CMP_REALVAL;
+    val->flags |= CMP_ALLOCINT;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 5).
+ * \param[in] param Method parameters (should point to \ref smparams_compare).
+ * \param[in] data  Should point to a \c t_methoddata_compare.
+ * \returns   0 if the input data is valid, -1 on error.
+ */
+static void
+init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+    int                   n1, n2;
+
+    /* Store the values */
+    n1 = init_comparison_value(&d->left, &param[0]);
+    n2 = init_comparison_value(&d->right, &param[3]);
+    if (n1 == 0 || n2 == 0)
+    {
+        GMX_THROW(gmx::InternalError("One of the values for comparison missing"));
+    }
+    /* Store the comparison type */
+    d->cmpt = comparison_type(d->cmpop);
+    if (d->cmpt == CMP_INVALID)
+    {
+        GMX_THROW(gmx::InternalError("Invalid comparison type"));
+    }
+    /* Convert the values to the same type */
+    if ((d->left.flags & CMP_REALVAL) && !(d->right.flags & CMP_REALVAL))
+    {
+        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
+        {
+            /* Nothing can be done */
+        }
+        else if (!(d->right.flags & CMP_DYNAMICVAL))
+        {
+            convert_int_real(n2, &d->right);
+        }
+        else /* d->left is static */
+        {
+            convert_real_int(n1, &d->left, d->cmpt, FALSE);
+        }
+    }
+    else if (!(d->left.flags & CMP_REALVAL) && (d->right.flags & CMP_REALVAL))
+    {
+        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
+        {
+            /* Reverse the sides to place the integer on the right */
+            int    flags;
+            d->left.r  = d->right.r;
+            d->right.r = NULL;
+            d->right.i = d->left.i;
+            d->left.i  = NULL;
+            flags          = d->left.flags;
+            d->left.flags  = d->right.flags;
+            d->right.flags = flags;
+            d->cmpt = reverse_comparison_type(d->cmpt);
+        }
+        else if (!(d->left.flags & CMP_DYNAMICVAL))
+        {
+            convert_int_real(n1, &d->left);
+        }
+        else /* d->right is static */
+        {
+            convert_real_int(n2, &d->right, d->cmpt, TRUE);
+        }
+    }
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_compare).
+ *
+ * Frees the memory allocated for \c t_methoddata_compare.
+ */
+static void
+free_data_compare(void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+
+    sfree(d->cmpop);
+    if (d->left.flags & CMP_ALLOCINT)
+    {
+        sfree(d->left.i);
+    }
+    if (d->left.flags & CMP_ALLOCREAL)
+    {
+        sfree(d->left.r);
+    }
+    if (d->right.flags & CMP_ALLOCINT)
+    {
+        sfree(d->right.i);
+    }
+    if (d->right.flags & CMP_ALLOCREAL)
+    {
+        sfree(d->right.r);
+    }
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  g     Evaluation index group.
+ * \param[out] out   Output data structure (\p out->u.g is used).
+ * \param[in]  data  Should point to a \c t_methoddata_compare.
+ */
+static void
+evaluate_compare_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+    int                   i, i1, i2, ig;
+    int                   a, b;
+    gmx_bool                  bAccept;
+
+    for (i = i1 = i2 = ig = 0; i < g->isize; ++i)
+    {
+        a = d->left.i[i1];
+        b = d->right.i[i2];
+        bAccept = FALSE;
+        switch (d->cmpt)
+        {
+            case CMP_INVALID: break;
+            case CMP_LESS:    bAccept = a <  b; break;
+            case CMP_LEQ:     bAccept = a <= b; break;
+            case CMP_GTR:     bAccept = a >  b; break;
+            case CMP_GEQ:     bAccept = a >= b; break;
+            case CMP_EQUAL:   bAccept = a == b; break;
+            case CMP_NEQ:     bAccept = a != b; break;
+        }
+        if (bAccept)
+        {
+            out->u.g->index[ig++] = g->index[i];
+        }
+        if (!(d->left.flags & CMP_SINGLEVAL))
+        {
+            ++i1;
+        }
+        if (!(d->right.flags & CMP_SINGLEVAL))
+        {
+            ++i2;
+        }
+    }
+    out->u.g->isize = ig;
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  g     Evaluation index group.
+ * \param[out] out   Output data structure (\p out->u.g is used).
+ * \param[in]  data  Should point to a \c t_methoddata_compare.
+ */
+static void
+evaluate_compare_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+    int                   i, i1, i2, ig;
+    real                  a, b;
+    gmx_bool                  bAccept;
+
+    for (i = i1 = i2 = ig = 0; i < g->isize; ++i)
+    {
+        a = d->left.r[i1];
+        b = (d->right.flags & CMP_REALVAL) ? d->right.r[i2] : d->right.i[i2];
+        bAccept = FALSE;
+        switch (d->cmpt)
+        {
+            case CMP_INVALID: break;
+            case CMP_LESS:    bAccept = a <  b; break;
+            case CMP_LEQ:     bAccept = a <= b; break;
+            case CMP_GTR:     bAccept = a >  b; break;
+            case CMP_GEQ:     bAccept = a >= b; break;
+            case CMP_EQUAL:   bAccept =  gmx_within_tol(a, b, GMX_REAL_EPS); break;
+            case CMP_NEQ:     bAccept = !gmx_within_tol(a, b, GMX_REAL_EPS); break;
+        }
+        if (bAccept)
+        {
+            out->u.g->index[ig++] = g->index[i];
+        }
+        if (!(d->left.flags & CMP_SINGLEVAL))
+        {
+            ++i1;
+        }
+        if (!(d->right.flags & CMP_SINGLEVAL))
+        {
+            ++i2;
+        }
+    }
+    out->u.g->isize = ig;
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  g     Evaluation index group.
+ * \param[out] out   Output data structure (\p out->u.g is used).
+ * \param[in]  data  Should point to a \c t_methoddata_compare.
+ */
+static void
+evaluate_compare(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_compare *d = (t_methoddata_compare *)data;
+
+    if (!((d->left.flags | d->right.flags) & CMP_REALVAL))
+    {
+        evaluate_compare_int(top, fr, pbc, g, out, data);
+    }
+    else
+    {
+        evaluate_compare_real(top, fr, pbc, g, out, data);
+    }
+}
diff --git a/src/gromacs/selection/sm_distance.cpp b/src/gromacs/selection/sm_distance.cpp
new file mode 100644 (file)
index 0000000..8c6da79
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements distance-based selection methods.
+ *
+ * This file implements the \p distance, \p mindistance and \p within
+ * selection methods.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <pbc.h>
+#include <smalloc.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/nbsearch.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+
+/*! \internal \brief
+ * Data structure for distance-based selection method.
+ *
+ * The same data structure is used by all the distance-based methods.
+ */
+typedef struct
+{
+    /** Cutoff distance. */
+    real                cutoff;
+    /** Positions of the reference points. */
+    gmx_ana_pos_t       p;
+    /** Neighborhood search data. */
+    gmx_ana_nbsearch_t *nb;
+} t_methoddata_distance;
+
+/** Allocates data for distance-based selection methods. */
+static void *
+init_data_common(int npar, gmx_ana_selparam_t *param);
+/** Initializes a distance-based selection method. */
+static void
+init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Frees the data allocated for a distance-based selection method. */
+static void
+free_data_common(void *data);
+/** Initializes the evaluation of a distance-based within selection method for a frame. */
+static void
+init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p distance selection method. */
+static void
+evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p within selection method. */
+static void
+evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for the \p distance selection method. */
+static gmx_ana_selparam_t smparams_distance[] = {
+    {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
+    {"from",   {POS_VALUE,  1, {NULL}}, NULL, SPAR_DYNAMIC},
+};
+
+/** Parameters for the \p mindistance selection method. */
+static gmx_ana_selparam_t smparams_mindistance[] = {
+    {"cutoff", {REAL_VALUE, 1, {NULL}}, NULL, SPAR_OPTIONAL},
+    {"from",   {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Parameters for the \p within selection method. */
+static gmx_ana_selparam_t smparams_within[] = {
+    {NULL, {REAL_VALUE,  1, {NULL}}, NULL, 0},
+    {"of", {POS_VALUE,  -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Help text for the distance selection methods. */
+static const char *help_distance[] = {
+    "DISTANCE-BASED SELECTION KEYWORDS[PAR]",
+
+    "[TT]distance from POS [cutoff REAL][tt][BR]",
+    "[TT]mindistance from POS_EXPR [cutoff REAL][tt][BR]",
+    "[TT]within REAL of POS_EXPR[tt][PAR]",
+
+    "[TT]distance[tt] and [TT]mindistance[tt] calculate the distance from the",
+    "given position(s), the only difference being in that [TT]distance[tt]",
+    "only accepts a single position, while any number of positions can be",
+    "given for [TT]mindistance[tt], which then calculates the distance to the",
+    "closest position.",
+    "[TT]within[tt] directly selects atoms that are within [TT]REAL[tt] of",
+    "[TT]POS_EXPR[tt].[PAR]",
+
+    "For the first two keywords, it is possible to specify a cutoff to speed",
+    "up the evaluation: all distances above the specified cutoff are",
+    "returned as equal to the cutoff.",
+    "Currently, this does nothing, but in the future, it allows the use of",
+    "grid-based neighborhood search techniques.",
+};
+
+/** \internal Selection method data for the \p distance method. */
+gmx_ana_selmethod_t sm_distance = {
+    "distance", REAL_VALUE, SMETH_DYNAMIC,
+    asize(smparams_distance), smparams_distance,
+    &init_data_common,
+    NULL,
+    &init_common,
+    NULL,
+    &free_data_common,
+    &init_frame_common,
+    NULL,
+    &evaluate_distance,
+    {"distance from POS [cutoff REAL]", asize(help_distance), help_distance},
+};
+
+/** \internal Selection method data for the \p distance method. */
+gmx_ana_selmethod_t sm_mindistance = {
+    "mindistance", REAL_VALUE, SMETH_DYNAMIC,
+    asize(smparams_mindistance), smparams_mindistance,
+    &init_data_common,
+    NULL,
+    &init_common,
+    NULL,
+    &free_data_common,
+    &init_frame_common,
+    NULL,
+    &evaluate_distance,
+    {"mindistance from POS_EXPR [cutoff REAL]", asize(help_distance), help_distance},
+};
+
+/** \internal Selection method data for the \p within method. */
+gmx_ana_selmethod_t sm_within = {
+    "within", GROUP_VALUE, SMETH_DYNAMIC,
+    asize(smparams_within), smparams_within,
+    &init_data_common,
+    NULL,
+    &init_common,
+    NULL,
+    &free_data_common,
+    &init_frame_common,
+    NULL,
+    &evaluate_within,
+    {"within REAL of POS_EXPR", asize(help_distance), help_distance},
+};
+
+/*!
+ * \param[in]     npar  Not used (should be 2).
+ * \param[in,out] param Method parameters (should point to one of the distance
+ *   parameter arrays).
+ * \returns       Pointer to the allocated data (\c t_methoddata_distance).
+ *
+ * Allocates memory for a \c t_methoddata_distance structure and
+ * initializes the parameter as follows:
+ *  - the first parameter defines the value for
+ *    \c t_methoddata_distance::cutoff.
+ *  - the second parameter defines the reference positions and the value is
+ *    stored in \c t_methoddata_distance::p.
+ */
+static void *
+init_data_common(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_distance *data;
+
+    snew(data, 1);
+    data->cutoff     = -1;
+    param[0].val.u.r = &data->cutoff;
+    param[1].val.u.p = &data->p;
+    return data;
+}
+
+/*!
+ * \param   top   Not used.
+ * \param   npar  Not used (should be 2).
+ * \param   param Method parameters (should point to one of the distance
+ *   parameter arrays).
+ * \param   data  Pointer to \c t_methoddata_distance to initialize.
+ * \returns 0 on success, a non-zero error code on failure.
+ *
+ * Initializes the neighborhood search data structure
+ * (\c t_methoddata_distance::nb).
+ * Also checks that the cutoff is valid.
+ */
+static void
+init_common(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_distance *d = (t_methoddata_distance *)data;
+
+    if ((param[0].flags & SPAR_SET) && d->cutoff <= 0)
+    {
+        GMX_THROW(gmx::InvalidInputError("Distance cutoff should be > 0"));
+    }
+    d->nb = gmx_ana_nbsearch_create(d->cutoff, d->p.nr);
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_distance).
+ *
+ * Frees the memory allocated for \c t_methoddata_distance::xref and
+ * \c t_methoddata_distance::nb.
+ */
+static void
+free_data_common(void *data)
+{
+    t_methoddata_distance *d = (t_methoddata_distance *)data;
+
+    if (d->nb)
+    {
+        gmx_ana_nbsearch_free(d->nb);
+    }
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \c t_methoddata_distance.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Initializes the neighborhood search for the current frame.
+ */
+static void
+init_frame_common(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_distance *d = (t_methoddata_distance *)data;
+
+    gmx_ana_nbsearch_pos_init(d->nb, pbc, &d->p);
+}
+
+/*!
+ * See sel_updatefunc_pos() for description of the parameters.
+ * \p data should point to a \c t_methoddata_distance.
+ *
+ * Calculates the distance of each position from \c t_methoddata_distance::p
+ * and puts them in \p out->u.r.
+ */
+static void
+evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_distance *d = (t_methoddata_distance *)data;
+    int  b, i;
+    real n;
+
+    out->nr = pos->g->isize;
+    for (b = 0; b < pos->nr; ++b)
+    {
+        n = gmx_ana_nbsearch_pos_mindist(d->nb, pos, b);
+        for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
+        {
+            out->u.r[i] = n;
+        }
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_distance.
+ *
+ * Finds the atoms that are closer than the defined cutoff to
+ * \c t_methoddata_distance::xref and puts them in \p out.g.
+ */
+static void
+evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_distance *d = (t_methoddata_distance *)data;
+    int                    b;
+
+    out->u.g->isize = 0;
+    for (b = 0; b < pos->nr; ++b)
+    {
+        if (gmx_ana_nbsearch_pos_is_within(d->nb, pos, b))
+        {
+            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
+        }
+    }
+}
diff --git a/src/gromacs/selection/sm_insolidangle.cpp b/src/gromacs/selection/sm_insolidangle.cpp
new file mode 100644 (file)
index 0000000..75402d8
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \page page_module_selection_insolidangle Selection method: insolidangle
+ *
+ * This method selects a subset of particles that are located in a solid
+ * angle defined by a center and a set of points.
+ * The solid angle is constructed as a union of small cones whose axis
+ * goes through the center and a point.
+ * So there's such a cone for each position, and a
+ * point is in the solid angle if it lies within any of these cones.
+ * The width of the cones can be adjusted.
+ *
+ * \internal
+ *
+ * The method is implemented by partitioning the surface of the unit sphere
+ * into bins using the polar coordinates \f$(\theta, \phi)\f$.
+ * The partitioning is always uniform in the zenith angle \f$\theta\f$,
+ * while the partitioning in the azimuthal angle \f$\phi\f$ varies.
+ * For each reference point, the unit vector from the center to the point
+ * is constructed, and it is stored in all the bins that overlap with the
+ * cone defined by the point.
+ * Bins that are completely covered by a single cone are marked as such.
+ * Checking whether a point is in the solid angle is then straightforward
+ * with this data structure: one finds the bin that corresponds to the point,
+ * and checks whether the bin is completely covered. If it is not, one
+ * additionally needs to check whether it is within the specified cutoff of
+ * any of the stored points.
+ *
+ * The above construction gives quite a lot of flexibility for constructing
+ * the bins without modifying the rest of the code.
+ * The current (quite inefficient) implementation is discussed below, but
+ * it should be optimized to get the most out of the code.
+ *
+ * The current way of constructing the bins constructs the boundaries
+ * statically: the bin size in the zenith direction is set to approximately
+ * half the angle cutoff, and the bins in the azimuthal direction have
+ * sizes such that the shortest edge of the bin is approximately equal to
+ * half the angle cutoff (for the regions close to the poles, a single bin
+ * is used).
+ * Each reference point is then added to the bins as follows:
+ *  -# Find the zenith angle range that is spanned by the cone centered at the
+ *     point (this is simple addition/subtraction).
+ *  -# Calculate the maximal span of the cone in the azimuthal direction using
+ *     the formula
+ *     \f[\sin \Delta \phi_{max} = \frac{\sin \alpha}{\sin \theta}\f]
+ *     (a sine formula in spherical coordinates),
+ *     where \f$\alpha\f$ is the width of the cone and \f$\theta\f$ is the
+ *     zenith angle of the cone center.
+ *     Similarly, the zenith angle at which this extent is achieved is
+ *     calculated using
+ *     \f[\cos \theta_{max} = \frac{\cos \theta}{\cos \alpha}\f]
+ *     (Pythagoras's theorem in spherical coordinates).
+ *  -# For each zenith angle bin that is at least partially covered by the
+ *     cone, calculate the span of the cone at the edges using
+ *     \f[\sin^2 \frac{\Delta \phi}{2} = \frac{\sin^2 \frac{\alpha}{2} - \sin^2 \frac{\theta - \theta'}{2}}{\sin \theta \sin \theta'}\f]
+ *     (distance in spherical geometry),
+ *     where \f$\theta'\f$ is the zenith angle of the bin edge.
+ *  -# Using the values calculated above, loop through the azimuthal bins that
+ *     are partially or completely covered by the cone and update them.
+ *
+ * The total solid angle (for covered fraction calculations) is estimated by
+ * taking the total area of completely covered bins plus
+ * half the area of partially covered bins.
+ * The second one is an approximation, but should give reasonable estimates
+ * for the averages as well as in cases where the bin size is small.
+ */
+/*! \internal \file
+ * \brief
+ * Implements the \ref sm_insolidangle "insolidangle" selection method.
+ *
+ * \todo
+ * The implementation could be optimized quite a bit.
+ *
+ * \todo
+ * Move the covered fraction stuff somewhere else and make it more generic
+ * (along the lines it is handled in selection.h and trajana.h in the old C
+ * API).
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+
+#include <macros.h>
+#include <maths.h>
+#include <pbc.h>
+#include <physics.h>
+#include <smalloc.h>
+#include <vec.h>
+
+// FIXME: Should really be in the beginning, but causes compilation errors
+#include <algorithm>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "selelem.h"
+
+using std::min;
+using std::max;
+
+/*! \internal \brief
+ * Internal data structure for the \p insolidangle selection method.
+ *
+ * \see \c t_partition
+ */
+typedef struct
+{
+    /** Left edge of the partition. */
+    real                left;
+    /** Bin index corresponding to this partition. */
+    int                 bin;
+} t_partition_item;
+
+/*! \internal \brief
+ * Internal data structure for the \p insolidangle selection method.
+ *
+ * Describes the surface partitioning within one slice along the zenith angle.
+ * The slice from azimuthal angle \p p[i].left to \p p[i+1].left belongs to
+ * bin \p p[i].bin.
+ */
+typedef struct
+{
+    /** Number of partition items (\p p contains \p n+1 items). */
+    int                 n;
+    /** Array of partition edges and corresponding bins. */
+    t_partition_item   *p;
+} t_partition;
+
+/*! \internal \brief
+ * Internal data structure for the \p insolidangle selection method.
+ *
+ * Contains the reference points that partially cover a certain region on the
+ * surface of the unit sphere.
+ * If \p n is -1, the whole region described by the bin is covered.
+ */
+typedef struct
+{
+    /** Number of points in the array \p x, -1 if whole bin covered. */
+    int   n;
+    /** Number of elements allocated for \p x. */
+    int   n_alloc;
+    /** Array of points that partially cover the bin. */
+    rvec *x;
+} t_spheresurfacebin;
+
+/*! \internal \brief
+ * Data structure for the \p insolidangle selection method.
+ *
+ * All angle values are in the units of radians.
+ */
+typedef struct
+{
+    /** Center of the solid angle. */
+    gmx_ana_pos_t       center;
+    /** Positions that span the solid angle. */
+    gmx_ana_pos_t       span;
+    /** Cutoff angle. */
+    real                angcut;
+    /** Estimate of the covered fraction. */
+    real                cfrac;
+
+    /** Cutoff for the cosine (equals cos(angcut)). */
+    real                distccut;
+    /** Bin size to be used as the target bin size when constructing the bins. */
+    real                targetbinsize;
+
+    /** Number of bins in the \p tbin array. */
+    int                 ntbins;
+    /** Size of one bin in the zenith angle direction. */
+    real                tbinsize;
+    /** Array of zenith angle slices. */
+    t_partition        *tbin;
+    /** Number of elements allocated for the \p bin array. */
+    int                 maxbins;
+    /** Number of elements used in the \p bin array. */
+    int                 nbins;
+    /** Array of individual bins. */
+    t_spheresurfacebin *bin;
+} t_methoddata_insolidangle;
+
+/** Allocates data for the \p insolidangle selection method. */
+static void *
+init_data_insolidangle(int npar, gmx_ana_selparam_t *param);
+/** Initializes the \p insolidangle selection method. */
+static void
+init_insolidangle(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Frees the data allocated for the \p insolidangle selection method. */
+static void
+free_data_insolidangle(void *data);
+/** Initializes the evaluation of the \p insolidangle selection method for a frame. */
+static void
+init_frame_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Internal helper function for evaluate_insolidangle(). */
+static gmx_bool
+accept_insolidangle(rvec x, t_pbc *pbc, void *data);
+/** Evaluates the \p insolidangle selection method. */
+static void
+evaluate_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                      gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+
+/** Calculates the distance between unit vectors. */
+static real
+sph_distc(rvec x1, rvec x2);
+/** Does a binary search on a \p t_partition to find a bin for a value. */
+static int
+find_partition_bin(t_partition *p, real value);
+/** Finds a bin that corresponds to a location on the unit sphere surface. */
+static int
+find_surface_bin(t_methoddata_insolidangle *surf, rvec x);
+/** Clears/initializes the bins on the unit sphere surface. */
+static void
+clear_surface_points(t_methoddata_insolidangle *surf);
+/** Frees memory allocated for storing the reference points in the surface bins. */
+static void
+free_surface_points(t_methoddata_insolidangle *surf);
+/** Adds a reference point to a given bin. */
+static void
+add_surface_point(t_methoddata_insolidangle *surf, int tbin, int pbin, rvec x);
+/** Marks a bin as completely covered. */
+static void
+mark_surface_covered(t_methoddata_insolidangle *surf, int tbin, int pbin);
+/** Helper function for store_surface_point() to update a single zenith angle bin. */
+static void
+update_surface_bin(t_methoddata_insolidangle *surf, int tbin,
+                   real phi, real pdelta1, real pdelta2, real pdeltamax,
+                   rvec x);
+/** Adds a single reference point and updates the surface bins. */
+static void
+store_surface_point(t_methoddata_insolidangle *surf, rvec x);
+/** Optimizes the surface bins for faster searching. */
+static void
+optimize_surface_points(t_methoddata_insolidangle *surf);
+/** Estimates the area covered by the reference cones. */
+static real
+estimate_covered_fraction(t_methoddata_insolidangle *surf);
+/** Checks whether a point lies within a solid angle. */
+static gmx_bool
+is_surface_covered(t_methoddata_insolidangle *surf, rvec x);
+
+/** Parameters for the \p insolidangle selection method. */
+static gmx_ana_selparam_t smparams_insolidangle[] = {
+    {"center", {POS_VALUE,   1, {NULL}}, NULL, SPAR_DYNAMIC},
+    {"span",   {POS_VALUE,  -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+    {"cutoff", {REAL_VALUE,  1, {NULL}}, NULL, SPAR_OPTIONAL},
+};
+
+/** Help text for the \p insolidangle selection method. */
+static const char *help_insolidangle[] = {
+    "SELECTING ATOMS IN A SOLID ANGLE[PAR]",
+
+    "[TT]insolidangle center POS span POS_EXPR [cutoff REAL][tt][PAR]",
+
+    "This keyword selects atoms that are within [TT]REAL[tt] degrees",
+    "(default=5) of any position in [TT]POS_EXPR[tt] as seen from [TT]POS[tt]",
+    "a position expression that evaluates to a single position), i.e., atoms",
+    "in the solid angle spanned by the positions in [TT]POS_EXPR[tt] and",
+    "centered at [TT]POS[tt].[PAR]"
+
+    "Technically, the solid angle is constructed as a union of small cones",
+    "whose tip is at [TT]POS[tt] and the axis goes through a point in",
+    "[TT]POS_EXPR[tt]. There is such a cone for each position in",
+    "[TT]POS_EXPR[tt], and point is in the solid angle if it lies within any",
+    "of these cones. The cutoff determines the width of the cones.",
+};
+
+/** \internal Selection method data for the \p insolidangle method. */
+gmx_ana_selmethod_t sm_insolidangle = {
+    "insolidangle", GROUP_VALUE, SMETH_DYNAMIC,
+    asize(smparams_insolidangle), smparams_insolidangle,
+    &init_data_insolidangle,
+    NULL,
+    &init_insolidangle,
+    NULL,
+    &free_data_insolidangle,
+    &init_frame_insolidangle,
+    NULL,
+    &evaluate_insolidangle,
+    {"insolidangle center POS span POS_EXPR [cutoff REAL]",
+     asize(help_insolidangle), help_insolidangle},
+};
+
+/*!
+ * \param[in]     npar  Not used (should be 3).
+ * \param[in,out] param Method parameters (should point to 
+ *   \ref smparams_insolidangle).
+ * \returns Pointer to the allocated data (\ref t_methoddata_insolidangle).
+ *
+ * Allocates memory for a \ref t_methoddata_insolidangle structure and
+ * initializes the parameter as follows:
+ *  - \p center defines the value for t_methoddata_insolidangle::center.
+ *  - \p span   defines the value for t_methoddata_insolidangle::span.
+ *  - \p cutoff defines the value for t_methoddata_insolidangle::angcut.
+ */
+static void *
+init_data_insolidangle(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_insolidangle *data;
+
+    snew(data, 1);
+    data->angcut = 5.0;
+    param[0].val.u.p = &data->center;
+    param[1].val.u.p = &data->span;
+    param[2].val.u.r = &data->angcut;
+    return data;
+}
+
+/*!
+ * \param   top  Not used.
+ * \param   npar Not used.
+ * \param   param Not used.
+ * \param   data Pointer to \ref t_methoddata_insolidangle to initialize.
+ * \returns 0 on success, -1 on failure.
+ *
+ * Converts t_methoddata_insolidangle::angcut to radians and allocates
+ * and allocates memory for the bins used during the evaluation.
+ */
+static void
+init_insolidangle(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_insolidangle *surf = (t_methoddata_insolidangle *)data;
+    int                        i, c;
+
+    if (surf->angcut <= 0)
+    {
+        GMX_THROW(gmx::InvalidInputError("Angle cutoff should be > 0"));
+    }
+
+    surf->angcut *= DEG2RAD;
+
+    surf->distccut = -cos(surf->angcut);
+    surf->targetbinsize = surf->angcut / 2;
+    surf->ntbins = (int) (M_PI / surf->targetbinsize);
+    surf->tbinsize = (180.0 / surf->ntbins)*DEG2RAD;
+
+    snew(surf->tbin, (int)(M_PI/surf->tbinsize) + 1);
+    surf->maxbins = 0;
+    for (i = 0; i < surf->ntbins; ++i)
+    {
+        c = max(sin(surf->tbinsize*i), sin(surf->tbinsize*(i+1)))
+              * M_2PI / surf->targetbinsize + 1;
+        snew(surf->tbin[i].p, c+1);
+        surf->maxbins += c;
+    }
+    surf->nbins = 0;
+    snew(surf->bin, surf->maxbins);
+}
+
+/*!
+ * \param data Data to free (should point to a \ref t_methoddata_insolidangle).
+ *
+ * Frees the memory allocated for \c t_methoddata_insolidangle::center and
+ * \c t_methoddata_insolidangle::span, as well as the memory for the internal
+ * bin structure.
+ */
+static void
+free_data_insolidangle(void *data)
+{
+    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
+    int                        i;
+
+    if (d->tbin)
+    {
+        for (i = 0; i < d->ntbins; ++i)
+        {
+            sfree(d->tbin[i].p);
+        }
+        sfree(d->tbin);
+    }
+    free_surface_points(d);
+    sfree(d->bin);
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_insolidangle.
+ *
+ * Creates a lookup structure that enables fast queries of whether a point
+ * is within the solid angle or not.
+ */
+static void
+init_frame_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
+    rvec                       dx;
+    int                        i;
+
+    free_surface_points(d);
+    clear_surface_points(d);
+    for (i = 0; i < d->span.nr; ++i)
+    {
+        if (pbc)
+        {
+            pbc_dx(pbc, d->span.x[i], d->center.x[0], dx);
+        }
+        else
+        {
+            rvec_sub(d->span.x[i], d->center.x[0], dx);
+        }
+        unitv(dx, dx);
+        store_surface_point(d, dx);
+    }
+    optimize_surface_points(d);
+    d->cfrac = -1;
+}
+
+/*!
+ * \param[in] x    Test point.
+ * \param[in] pbc  PBC data (if NULL, no PBC are used).
+ * \param[in] data Pointer to a \c t_methoddata_insolidangle data structure.
+ * \returns   TRUE if \p x is within the solid angle, FALSE otherwise.
+ */
+static gmx_bool
+accept_insolidangle(rvec x, t_pbc *pbc, void *data)
+{
+    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
+    rvec                       dx;
+
+    if (pbc)
+    {
+        pbc_dx(pbc, x, d->center.x[0], dx);
+    }
+    else
+    {
+        rvec_sub(x, d->center.x[0], dx);
+    }
+    unitv(dx, dx);
+    return is_surface_covered(d, dx);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_insolidangle.
+ *
+ * Calculates which atoms in \p g are within the solid angle spanned by
+ * \c t_methoddata_insolidangle::span and centered at
+ * \c t_methoddata_insolidangle::center, and stores the result in \p out->u.g.
+ */
+static void
+evaluate_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                      gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
+    int                        b;
+
+    out->u.g->isize = 0;
+    for (b = 0; b < pos->nr; ++b)
+    {
+        if (accept_insolidangle(pos->x[b], pbc, data))
+        {
+            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
+        }
+    }
+}
+
+/*!
+ * \param[in] sel Selection element to query.
+ * \returns   TRUE if the covered fraction can be estimated for \p sel with
+ *   _gmx_selelem_estimate_coverfrac(), FALSE otherwise.
+ */
+gmx_bool
+_gmx_selelem_can_estimate_cover(t_selelem *sel)
+{
+    t_selelem   *child;
+    gmx_bool         bFound;
+    gmx_bool         bDynFound;
+
+    if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_OR)
+    {
+        return FALSE;
+    }
+    bFound    = FALSE;
+    bDynFound = FALSE;
+    child     = sel->child;
+    while (child)
+    {
+        if (child->type == SEL_EXPRESSION)
+        {
+            if (child->u.expr.method->name == sm_insolidangle.name)
+            {
+                if (bFound || bDynFound)
+                {
+                    return FALSE;
+                }
+                bFound = TRUE;
+            }
+            else if (child->u.expr.method
+                     && (child->u.expr.method->flags & SMETH_DYNAMIC))
+            {
+                if (bFound)
+                {
+                    return FALSE;
+                }
+                bDynFound = TRUE;
+            }
+        }
+        else if (!_gmx_selelem_can_estimate_cover(child))
+        {
+            return FALSE;
+        }
+        child = child->next;
+    }
+    return TRUE;
+}
+
+/*!
+ * \param[in] sel Selection for which the fraction should be calculated.
+ * \returns Fraction of angles covered by the selection (between zero and one).
+ *
+ * The return value is undefined if _gmx_selelem_can_estimate_cover() returns
+ * FALSE.
+ * Should be called after gmx_ana_evaluate_selections() has been called for the
+ * frame.
+ */
+real
+_gmx_selelem_estimate_coverfrac(t_selelem *sel)
+{
+    t_selelem   *child;
+    real         cfrac;
+
+    if (sel->type == SEL_EXPRESSION && sel->u.expr.method->name == sm_insolidangle.name)
+    {
+        t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)sel->u.expr.mdata;
+        if (d->cfrac < 0)
+        {
+            d->cfrac = estimate_covered_fraction(d);        
+        }
+        return d->cfrac;
+    }
+    if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT)
+    {
+        cfrac = _gmx_selelem_estimate_coverfrac(sel->child);
+        if (cfrac < 1.0)
+        {
+            return 1 - cfrac;
+        }
+        return 1;
+    }
+
+    /* Here, we assume that the selection is simple enough */
+    child = sel->child;
+    while (child)
+    {
+        cfrac = _gmx_selelem_estimate_coverfrac(child); 
+        if (cfrac < 1.0)
+        {
+            return cfrac;
+        }
+        child = child->next;
+    }
+    return 1.0;
+}
+
+/*!
+ * \param[in] x1  Unit vector 1.
+ * \param[in] x2  Unit vector 2.
+ * \returns   Minus the dot product of \p x1 and \p x2.
+ *
+ * This function is used internally to calculate the distance between the
+ * unit vectors \p x1 and \p x2 to find out whether \p x2 is within the
+ * cone centered at \p x1. Currently, the cosine of the angle is used
+ * for efficiency, and the minus is there to make it behave like a normal
+ * distance (larger values mean longer distances).
+ */
+static real
+sph_distc(rvec x1, rvec x2)
+{
+    return -iprod(x1, x2);
+}
+
+/*!
+ * \param[in] p     Partition to search.
+ * \param[in] value Value to search for.
+ * \returns   The partition index in \p p that contains \p value.
+ *
+ * If \p value is outside the range of \p p, the first/last index is returned.
+ * Otherwise, the return value \c i satisfies \c p->p[i].left<=value and
+ * \c p->p[i+1].left>value
+ */
+static int
+find_partition_bin(t_partition *p, real value)
+{
+    int pmin, pmax, pbin;
+
+    /* Binary search the partition */
+    pmin = 0; pmax = p->n;
+    while (pmax > pmin + 1)
+    {
+        pbin = pmin + (pmax - pmin) / 2;
+        if (p->p[pbin].left <= value)
+        {
+            pmin = pbin;
+        }
+        else
+        {
+            pmax = pbin;
+        }
+    }
+    pbin = pmin;
+    return pbin;
+}
+
+/*!
+ * \param[in] surf  Surface data structure to search.
+ * \param[in] x     Unit vector to find.
+ * \returns   The bin index that contains \p x.
+ *
+ * The return value is an index to the \p surf->bin array.
+ */
+static int
+find_surface_bin(t_methoddata_insolidangle *surf, rvec x)
+{
+    real theta, phi;
+    int  tbin, pbin;
+    
+    theta = acos(x[ZZ]);
+    phi = atan2(x[YY], x[XX]);
+    tbin = floor(theta / surf->tbinsize);
+    if (tbin >= surf->ntbins)
+    {
+        tbin = surf->ntbins - 1;
+    }
+    pbin = find_partition_bin(&surf->tbin[tbin], phi);
+    return surf->tbin[tbin].p[pbin].bin;
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ *
+ * Clears the reference points from the bins and (re)initializes the edges
+ * of the azimuthal bins.
+ */
+static void
+clear_surface_points(t_methoddata_insolidangle *surf)
+{
+    int i, j, c;
+
+    surf->nbins = 0;
+    for (i = 0; i < surf->ntbins; ++i)
+    {
+        c = min(sin(surf->tbinsize*i), sin(surf->tbinsize*(i+1)))
+              * M_2PI / surf->targetbinsize + 1;
+        if (c <= 0)
+        {
+            c = 1;
+        }
+        surf->tbin[i].n = c;
+        for (j = 0; j < c; ++j)
+        {
+            surf->tbin[i].p[j].left = -M_PI + j*M_2PI/c - 0.0001;
+            surf->tbin[i].p[j].bin = surf->nbins;
+            surf->bin[surf->nbins].n = 0;
+            surf->nbins++;
+        }
+        surf->tbin[i].p[c].left = M_PI + 0.0001;
+        surf->tbin[i].p[c].bin = -1;
+    }
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ */
+static void
+free_surface_points(t_methoddata_insolidangle *surf)
+{
+    int i;
+
+    for (i = 0; i < surf->nbins; ++i)
+    {
+        if (surf->bin[i].x)
+        {
+            sfree(surf->bin[i].x);
+        }
+        surf->bin[i].n_alloc = 0;
+        surf->bin[i].x = NULL;
+    }
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ * \param[in]     tbin Bin number in the zenith angle direction.
+ * \param[in]     pbin Bin number in the azimuthal angle direction.
+ * \param[in]     x    Point to store.
+ */
+static void
+add_surface_point(t_methoddata_insolidangle *surf, int tbin, int pbin, rvec x)
+{
+    int bin;
+
+    bin = surf->tbin[tbin].p[pbin].bin;
+    /* Return if bin is already completely covered */
+    if (surf->bin[bin].n == -1)
+        return;
+    /* Allocate more space if necessary */
+    if (surf->bin[bin].n == surf->bin[bin].n_alloc) {
+        surf->bin[bin].n_alloc += 10;
+        srenew(surf->bin[bin].x, surf->bin[bin].n_alloc);
+    }
+    /* Add the point to the bin */
+    copy_rvec(x, surf->bin[bin].x[surf->bin[bin].n]);
+    ++surf->bin[bin].n;
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ * \param[in]     tbin Bin number in the zenith angle direction.
+ * \param[in]     pbin Bin number in the azimuthal angle direction.
+ */
+static void
+mark_surface_covered(t_methoddata_insolidangle *surf, int tbin, int pbin)
+{
+    int bin;
+
+    bin = surf->tbin[tbin].p[pbin].bin;
+    surf->bin[bin].n = -1;
+}
+
+/*!
+ * \param[in,out] surf      Surface data structure.
+ * \param[in]     tbin      Bin number in the zenith angle direction.
+ * \param[in]     phi       Azimuthal angle of \p x.
+ * \param[in]     pdelta1   Width of the cone at the lower edge of \p tbin.
+ * \param[in]     pdelta2   Width of the cone at the uppper edge of \p tbin.
+ * \param[in]     pdeltamax Max. width of the cone inside \p tbin.
+ * \param[in]     x         Point to store (should have unit length).
+ */
+static void
+update_surface_bin(t_methoddata_insolidangle *surf, int tbin,
+                   real phi, real pdelta1, real pdelta2, real pdeltamax,
+                   rvec x)
+{
+    real pdelta, phi1, phi2;
+    int  pbin1, pbin2, pbin;
+
+    /* Find the edges of the bins affected */
+    pdelta = max(max(pdelta1, pdelta2), pdeltamax);
+    phi1 = phi - pdelta;
+    if (phi1 < -M_PI)
+    {
+        phi1 += M_2PI;
+    }
+    phi2 = phi + pdelta;
+    if (phi2 > M_PI)
+    {
+        phi2 -= M_2PI;
+    }
+    pbin1 = find_partition_bin(&surf->tbin[tbin], phi1);
+    pbin2 = find_partition_bin(&surf->tbin[tbin], phi2);
+    /* Find the edges of completely covered region */
+    pdelta = min(pdelta1, pdelta2);
+    phi1 = phi - pdelta;
+    if (phi1 < -M_PI)
+    {
+        phi1 += M_2PI;
+    }
+    phi2 = phi + pdelta;
+    /* Loop over all affected bins */
+    pbin = pbin1;
+    do
+    {
+        /* Wrap bin around if end reached */
+        if (pbin == surf->tbin[tbin].n)
+        {
+            pbin = 0;
+            phi1 -= M_2PI;
+            phi2 -= M_2PI;
+        }
+        /* Check if bin is completely covered and update */
+        if (surf->tbin[tbin].p[pbin].left >= phi1
+            && surf->tbin[tbin].p[pbin+1].left <= phi2)
+        {
+            mark_surface_covered(surf, tbin, pbin);
+        }
+        else
+        {
+            add_surface_point(surf, tbin, pbin, x);
+        }
+    }
+    while (pbin++ != pbin2); /* Loop including pbin2 */
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ * \param[in]     x    Point to store (should have unit length).
+ *
+ * Finds all the bins covered by the cone centered at \p x and calls
+ * update_surface_bin() to update them.
+ */
+static void
+store_surface_point(t_methoddata_insolidangle *surf, rvec x)
+{
+    real theta, phi;
+    real pdeltamax, tmax;
+    real theta1, theta2, pdelta1, pdelta2;
+    int  tbin, pbin, bin;
+
+    theta = acos(x[ZZ]);
+    phi = atan2(x[YY], x[XX]);
+    /* Find the maximum extent in the phi direction */
+    if (theta <= surf->angcut)
+    {
+        pdeltamax = M_PI;
+        tmax = 0;
+    }
+    else if (theta >= M_PI - surf->angcut)
+    {
+        pdeltamax = M_PI;
+        tmax = M_PI;
+    }
+    else
+    {
+        pdeltamax = asin(sin(surf->angcut) / sin(theta));
+        tmax = acos(cos(theta) / cos(surf->angcut));
+    }
+    /* Find the first affected bin */
+    tbin = max(floor((theta - surf->angcut) / surf->tbinsize), 0.0);
+    theta1 = tbin * surf->tbinsize;
+    if (theta1 < theta - surf->angcut)
+    {
+        pdelta1 = 0;
+    }
+    else
+    {
+        pdelta1 = M_PI;
+    }
+    /* Loop through all affected bins */
+    while (tbin < ceil((theta + surf->angcut) / surf->tbinsize)
+           && tbin < surf->ntbins)
+    {
+        /* Calculate the next boundaries */
+        theta2 = (tbin+1) * surf->tbinsize;
+        if (theta2 > theta + surf->angcut)
+        {
+            pdelta2 = 0;
+        }
+        else if (tbin == surf->ntbins - 1)
+        {
+            pdelta2 = M_PI;
+        }
+        else
+        {
+            pdelta2 = 2*asin(sqrt(
+                    (sqr(sin(surf->angcut/2)) - sqr(sin((theta2-theta)/2))) /
+                    (sin(theta) * sin(theta2))));
+        }
+        /* Update the bin */
+        if (tmax >= theta1 && tmax <= theta2)
+        {
+            update_surface_bin(surf, tbin, phi, pdelta1, pdelta2, pdeltamax, x);
+        }
+        else
+        {
+            update_surface_bin(surf, tbin, phi, pdelta1, pdelta2, 0, x);
+        }
+        /* Next bin */
+        theta1 = theta2;
+        pdelta1 = pdelta2;
+        ++tbin;
+    }
+}
+
+/*!
+ * \param[in,out] surf Surface data structure.
+ *
+ * Currently, this function does nothing.
+ */
+static void
+optimize_surface_points(t_methoddata_insolidangle *surf)
+{
+    /* TODO: Implement */
+}
+
+/*!
+ * \param[in] surf Surface data structure.
+ * \returns   An estimate for the area covered by the reference points.
+ */
+static real
+estimate_covered_fraction(t_methoddata_insolidangle *surf)
+{
+    int  t, p, n;
+    real cfrac, tfrac, pfrac;
+
+    cfrac = 0.0;
+    for (t = 0; t < surf->ntbins; ++t)
+    {
+        tfrac = cos(t * surf->tbinsize) - cos((t+1) * surf->tbinsize);
+        for (p = 0; p < surf->tbin[t].n; ++p)
+        {
+            pfrac = surf->tbin[t].p[p+1].left - surf->tbin[t].p[p].left;
+            n = surf->bin[surf->tbin[t].p[p].bin].n;
+            if (n == -1) /* Bin completely covered */
+            {
+                cfrac += tfrac * pfrac;
+            }
+            else if (n > 0) /* Bin partially covered */
+            {
+                cfrac += tfrac * pfrac / 2; /* A rough estimate */
+            }
+        }
+    }
+    return cfrac / (4*M_PI);
+}
+
+/*!
+ * \param[in] surf  Surface data structure to search.
+ * \param[in] x     Unit vector to check.
+ * \returns   TRUE if \p x is within the solid angle, FALSE otherwise.
+ */
+static gmx_bool
+is_surface_covered(t_methoddata_insolidangle *surf, rvec x)
+{
+    int  bin, i;
+
+    bin = find_surface_bin(surf, x);
+    /* Check for completely covered bin */
+    if (surf->bin[bin].n == -1)
+    {
+        return TRUE;
+    }
+    /* Check each point that partially covers the bin */
+    for (i = 0; i < surf->bin[bin].n; ++i)
+    {
+        if (sph_distc(x, surf->bin[bin].x[i]) < surf->distccut)
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
diff --git a/src/gromacs/selection/sm_keywords.cpp b/src/gromacs/selection/sm_keywords.cpp
new file mode 100644 (file)
index 0000000..fd91e3e
--- /dev/null
@@ -0,0 +1,750 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements internal selection methods for numeric and string keyword
+ * evaluation.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>  /*old Mac needs types before regex.h*/
+#endif
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#define USE_REGEX
+#endif
+
+#include <macros.h>
+#include <smalloc.h>
+#include <string2.h>
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "gromacs/fatalerror/messagestringcollector.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "keywords.h"
+#include "parsetree.h"
+#include "scanner.h"
+#include "selelem.h"
+
+/** Allocates data for integer keyword evaluation. */
+static void *
+init_data_kwint(int npar, gmx_ana_selparam_t *param);
+/** Allocates data for real keyword evaluation. */
+static void *
+init_data_kwreal(int npar, gmx_ana_selparam_t *param);
+/** Allocates data for string keyword evaluation. */
+static void *
+init_data_kwstr(int npar, gmx_ana_selparam_t *param);
+/** Initializes data for integer keyword evaluation. */
+static void
+init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes data for real keyword evaluation. */
+static void
+init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes data for string keyword evaluation. */
+static void
+init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Frees the memory allocated for string keyword evaluation. */
+static void
+free_data_kwstr(void *data);
+/** Evaluates integer selection keywords. */
+static void
+evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates real selection keywords. */
+static void
+evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates string selection keywords. */
+static void
+evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/*! \internal \brief
+ * Data structure for integer keyword expression evaluation.
+ */
+typedef struct t_methoddata_kwint
+{
+    /** Array of values for the keyword. */
+    int               *v;
+    /** Number of ranges in the \p r array. */
+    int                n;
+    /*! \brief
+     * Array of sorted integer ranges to match against.
+     *
+     * Each range is made of two integers, giving the endpoints (inclusive).
+     * This field stores the pointer to the ranges allocated by the
+     * parameter parser; see \ref SPAR_RANGES for more information.
+     */
+    int               *r;
+} t_methoddata_kwint;
+
+/*! \internal \brief
+ * Data structure for real keyword expression evaluation.
+ */
+typedef struct t_methoddata_kwreal
+{
+    /** Array of values for the keyword. */
+    real              *v;
+    /** Number of ranges in the \p r array. */
+    int                n;
+    /*! \brief
+     * Array of sorted ranges to match against.
+     *
+     * Each range is made of two values, giving the endpoints (inclusive).
+     * This field stores the pointer to the ranges allocated by the
+     * parameter parser; see \ref SPAR_RANGES for more information.
+     */
+    real              *r;
+} t_methoddata_kwreal;
+
+/*! \internal \brief
+ * Data structure for string keyword expression evaluation.
+ */
+typedef struct t_methoddata_kwstr
+{
+    /** Array of values for the keyword. */
+    char             **v;
+    /** Number of elements in the \p val array. */
+    int                n;
+    /*! \internal \brief
+     * Array of strings/regular expressions to match against.
+     */
+    struct t_methoddata_kwstr_match {
+        /** TRUE if the expression is a regular expression, FALSE otherwise. */
+        gmx_bool           bRegExp;
+        /** The value to match against. */
+        union {
+#ifdef USE_REGEX
+            /** Compiled regular expression if \p bRegExp is TRUE. */
+            regex_t    r;
+#endif
+            /** The string if \p bRegExp is FALSE; */
+            char      *s;
+        }              u;
+    }                 *m;
+} t_methoddata_kwstr;
+
+/** Parameters for integer keyword evaluation. */
+static gmx_ana_selparam_t smparams_keyword_int[] = {
+    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
+    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
+};
+
+/** Parameters for real keyword evaluation. */
+static gmx_ana_selparam_t smparams_keyword_real[] = {
+    {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL | SPAR_DYNAMIC},
+    {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
+};
+
+/** Parameters for string keyword evaluation. */
+static gmx_ana_selparam_t smparams_keyword_str[] = {
+    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
+    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_VARNUM},
+};
+
+/** \internal Selection method data for integer keyword evaluation. */
+gmx_ana_selmethod_t sm_keyword_int = {
+    "kw_int", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_keyword_int), smparams_keyword_int,
+    &init_data_kwint,
+     NULL,
+    &init_kwint,
+     NULL,
+     NULL,
+     NULL,
+    &evaluate_keyword_int,
+     NULL,
+    {NULL, 0, NULL},
+};
+
+/** \internal Selection method data for real keyword evaluation. */
+gmx_ana_selmethod_t sm_keyword_real = {
+    "kw_real", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_keyword_real), smparams_keyword_real,
+    &init_data_kwreal,
+     NULL,
+    &init_kwreal,
+     NULL,
+     NULL,
+     NULL,
+    &evaluate_keyword_real,
+     NULL,
+    {NULL, 0, NULL},
+};
+
+/** \internal Selection method data for string keyword evaluation. */
+gmx_ana_selmethod_t sm_keyword_str = {
+    "kw_str", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_keyword_str), smparams_keyword_str,
+    &init_data_kwstr,
+     NULL,
+    &init_kwstr,
+     NULL,
+    &free_data_kwstr,
+     NULL,
+    &evaluate_keyword_str,
+     NULL,
+    {NULL, 0, NULL},
+};
+
+/** Initializes keyword evaluation for an arbitrary group. */
+static void
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for keyword evaluation in an arbitrary group. */
+static void
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the data allocated for keyword evaluation in an arbitrary group. */
+static void
+free_data_kweval(void *data);
+/** Initializes frame evaluation for keyword evaluation in an arbitrary group. */
+static void
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates keywords in an arbitrary group. */
+static void
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/*! \internal \brief
+ * Data structure for keyword evaluation in arbitrary groups.
+ */
+typedef struct
+{
+    /** Wrapped keyword method for evaluating the values. */
+    gmx_ana_selmethod_t  *kwmethod;
+    /** Method data for \p kwmethod. */
+    void                 *kwmdata;
+    /** Group in which \p kwmethod should be evaluated. */
+    gmx_ana_index_t       g;
+} t_methoddata_kweval;
+
+/** Parameters for keyword evaluation in an arbitrary group. */
+static gmx_ana_selparam_t smparams_kweval[] = {
+    {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+};
+
+
+/********************************************************************
+ * INTEGER KEYWORD EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] npar  Not used.
+ * \param     param Not used.
+ * \returns   Pointer to the allocated data (\ref t_methoddata_kwint).
+ *
+ * Allocates memory for a \ref t_methoddata_kwint structure.
+ */
+static void *
+init_data_kwint(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_kwint *data;
+
+    snew(data, 1);
+    return data;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 2).
+ * \param[in] param Method parameters (should point to \ref smparams_keyword_int).
+ * \param[in] data  Should point to \ref t_methoddata_kwint.
+ */
+static void
+init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_kwint *d = (t_methoddata_kwint *)data;
+
+    d->v = param[0].val.u.i;
+    d->n = param[1].val.nr;
+    d->r = param[1].val.u.i;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kwint.
+ *
+ * Does a binary search to find which atoms match the ranges in the
+ * \c t_methoddata_kwint structure for this selection.
+ * Matching atoms are stored in \p out->u.g.
+ */
+static void
+evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kwint *d = (t_methoddata_kwint *)data;
+    int                 n, i, j, jmin, jmax;
+    int                 val;
+
+    out->u.g->isize = 0;
+    n    = d->n;
+    for (i = 0; i < g->isize; ++i)
+    {
+        val = d->v[i];
+        if (d->r[0] > val || d->r[2*n-1] < val)
+        {
+            continue;
+        }
+        jmin = 0;
+        jmax = n;
+        while (jmax - jmin > 1)
+        {
+            j = jmin + (jmax - jmin) / 2;
+            if (val < d->r[2*j])
+            {
+                jmax = j;
+            }
+            else
+            {
+                jmin = j;
+                if (val <= d->r[2*j+1])
+                {
+                    break;
+                }
+                /* ++jmin;*/
+            }
+        }
+        if (val <= d->r[2*jmin+1])
+        {
+            out->u.g->index[out->u.g->isize++] = g->index[i];
+        }
+    }
+}
+
+
+/********************************************************************
+ * REAL KEYWORD EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] npar  Not used.
+ * \param     param Not used.
+ * \returns   Pointer to the allocated data (\ref t_methoddata_kwreal).
+ *
+ * Allocates memory for a \ref t_methoddata_kwreal structure.
+ */
+static void *
+init_data_kwreal(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_kwreal *data;
+
+    snew(data, 1);
+    return data;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 2).
+ * \param[in] param Method parameters (should point to \ref smparams_keyword_real).
+ * \param[in] data  Should point to \ref t_methoddata_kwreal.
+ * \returns   0 (the initialization always succeeds).
+ */
+static void
+init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
+
+    d->v = param[0].val.u.r;
+    d->n = param[1].val.nr;
+    d->r = param[1].val.u.r;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kwreal.
+ *
+ * Does a binary search to find which atoms match the ranges in the
+ * \c t_methoddata_kwreal structure for this selection.
+ * Matching atoms are stored in \p out->u.g.
+ */
+static void
+evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
+    int                  n, i, j, jmin, jmax;
+    real                 val;
+
+    out->u.g->isize = 0;
+    n    = d->n;
+    for (i = 0; i < g->isize; ++i)
+    {
+        val = d->v[i];
+        if (d->r[0] > val || d->r[2*n-1] < val)
+        {
+            continue;
+        }
+        jmin = 0;
+        jmax = n;
+        while (jmax - jmin > 1)
+        {
+            j = jmin + (jmax - jmin) / 2;
+            if (val < d->r[2*j])
+            {
+                jmax = j;
+            }
+            else
+            {
+                jmin = j;
+                if (val <= d->r[2*j+1])
+                {
+                    break;
+                }
+                /* ++jmin;*/
+            }
+        }
+        if (val <= d->r[2*jmin+1])
+        {
+            out->u.g->index[out->u.g->isize++] = g->index[i];
+        }
+    }
+}
+
+
+/********************************************************************
+ * STRING KEYWORD EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] npar  Not used.
+ * \param     param Not used.
+ * \returns Pointer to the allocated data (\ref t_methoddata_kwstr).
+ *
+ * Allocates memory for a \ref t_methoddata_kwstr structure.
+ */
+static void *
+init_data_kwstr(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_kwstr *data;
+
+    snew(data, 1);
+    return data;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 2).
+ * \param[in] param Method parameters (should point to \ref smparams_keyword_str).
+ * \param[in] data  Should point to \ref t_methoddata_kwstr.
+ */
+static void
+init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
+    char               *buf;
+    char               *s;
+    int                 i;
+    size_t              j;
+    gmx_bool                bRegExp;
+
+    d->v   = param[0].val.u.s;
+    d->n   = param[1].val.nr;
+    /* Return if this is not the first time */
+    if (d->m)
+    {
+        return;
+    }
+    snew(d->m, d->n);
+    for (i = 0; i < d->n; ++i)
+    {
+        s = param[1].val.u.s[i];
+        bRegExp = FALSE;
+        for (j = 0; j < strlen(s); ++j)
+        {
+            if (ispunct(s[j]) && s[j] != '?' && s[j] != '*')
+            {
+                bRegExp = TRUE;
+                break;
+            }
+        }
+        if (bRegExp)
+        {
+            // TODO: Get rid of these prints to stderr
+#ifdef USE_REGEX
+            snew(buf, strlen(s) + 3);
+            sprintf(buf, "^%s$", s);
+            if (regcomp(&d->m[i].u.r, buf, REG_EXTENDED | REG_NOSUB))
+            {
+                bRegExp = FALSE;
+                fprintf(stderr, "WARNING: error in regular expression,\n"
+                                "         will match '%s' as a simple string\n", s);
+            }
+            sfree(buf);
+#else
+            bRegExp = FALSE;
+            fprintf(stderr, "WARNING: no regular expressions support,\n"
+                            "         will match '%s' as a simple string\n", s);
+#endif
+        }
+        if (!bRegExp)
+        {
+            d->m[i].u.s = s;
+        }
+        d->m[i].bRegExp = bRegExp;
+    }
+}
+
+/*!
+ * \param data Data to free (should point to a \ref t_methoddata_kwstr).
+ *
+ * Frees the memory allocated for t_methoddata_kwstr::val.
+ */
+static void
+free_data_kwstr(void *data)
+{
+    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
+    int                 i;
+
+    for (i = 0; i < d->n; ++i)
+    {
+        if (d->m[i].bRegExp)
+        {
+#ifdef USE_REGEX
+            /* This branch should only be taken if regular expressions
+             * are available, but the ifdef is still needed. */
+            regfree(&d->m[i].u.r);
+#endif
+        }
+    }
+    sfree(d->m);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kwstr.
+ *
+ * Does a linear search to find which atoms match the strings in the
+ * \c t_methoddata_kwstr structure for this selection.
+ * Wildcards are allowed in the strings.
+ * Matching atoms are stored in \p out->u.g.
+ */
+static void
+evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
+    int                 i, j;
+    gmx_bool                bFound;
+
+    out->u.g->isize = 0;
+    for (i = 0; i < g->isize; ++i)
+    {
+        bFound = FALSE;
+        for (j = 0; j < d->n && !bFound; ++j)
+        {
+            if (d->m[j].bRegExp)
+            {
+#ifdef USE_REGEX
+                /* This branch should only be taken if regular expressions
+                 * are available, but the ifdef is still needed. */
+                if (!regexec(&d->m[j].u.r, d->v[i], 0, NULL, 0))
+                {
+                    bFound = TRUE;
+                }
+#endif
+            }
+            else
+            {
+                if (gmx_wcmatch(d->m[j].u.s, d->v[i]) == 0)
+                {
+                    bFound = TRUE;
+                }
+            }
+        }
+        if (bFound)
+        {
+            out->u.g->index[out->u.g->isize++] = g->index[i];
+        }
+    }
+}
+
+
+/********************************************************************
+ * KEYWORD EVALUATION FOR ARBITRARY GROUPS
+ ********************************************************************/
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used.
+ * \param[in] param Not used.
+ * \param[in] data  Should point to \ref t_methoddata_kweval.
+ * \returns   0 on success, a non-zero error code on return.
+ *
+ * Calls the initialization method of the wrapped keyword.
+ */
+static void
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    d->kwmethod->init(top, 0, NULL, d->kwmdata);
+}
+
+/*!
+ * \param[in]     top   Not used.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_kweval.
+ * \returns       0 for success.
+ */
+static void
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    out->nr = d->g.isize;
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_kweval).
+ *
+ * Frees the memory allocated for all the members of \c t_methoddata_kweval.
+ */
+static void
+free_data_kweval(void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    _gmx_selelem_free_method(d->kwmethod, d->kwmdata);
+}
+
+/*!
+ * \param[in]  top  Topology.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_kweval.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Creates a lookup structure that enables fast queries of whether a point
+ * is within the solid angle or not.
+ */
+static void
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    d->kwmethod->init_frame(top, fr, pbc, d->kwmdata);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kweval.
+ *
+ * Calls the evaluation function of the wrapped keyword with the given
+ * parameters, with the exception of using \c t_methoddata_kweval::g for the
+ * evaluation group.
+ */
+static void
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    d->kwmethod->update(top, fr, pbc, &d->g, out, d->kwmdata);
+}
+
+/*!
+ * \param[out]  selp    Pointer to receive a pointer to the created selection
+ *      element (set to NULL on error).
+ * \param[in]   method  Keyword selection method to evaluate.
+ * \param[in]   param   Parameter that gives the group to evaluate \p method in.
+ * \param[in]   scanner Scanner data structure.
+ * \returns     0 on success, non-zero error code on error.
+ *
+ * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
+ * that evaluates the keyword method given by \p method in the group given by
+ * \p param.
+ */
+int
+_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
+                                t_selexpr_param *param, void *scanner)
+{
+    t_selelem            *sel;
+    t_methoddata_kweval  *data;
+
+    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
+    char  buf[1024];
+    sprintf(buf, "In evaluation of '%s'", method->name);
+    gmx::MessageStringContext   context(errors, buf);
+
+    if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
+        || method->outinit || method->pupdate)
+    {
+        _gmx_selexpr_free_params(param);
+        GMX_ERROR(gmx::eeInternalError,
+                  "Unsupported keyword method for arbitrary group evaluation");
+    }
+
+    *selp = NULL;
+    sel = _gmx_selelem_create(SEL_EXPRESSION);
+    _gmx_selelem_set_method(sel, method, scanner);
+
+    snew(data, 1);
+    data->kwmethod = sel->u.expr.method;
+    data->kwmdata  = sel->u.expr.mdata;
+    gmx_ana_index_clear(&data->g);
+
+    snew(sel->u.expr.method, 1);
+    memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
+    sel->u.expr.method->flags       |= SMETH_VARNUMVAL;
+    sel->u.expr.method->init_data    = NULL;
+    sel->u.expr.method->set_poscoll  = NULL;
+    sel->u.expr.method->init         = method->init ? &init_kweval : NULL;
+    sel->u.expr.method->outinit      = &init_output_kweval;
+    sel->u.expr.method->free         = &free_data_kweval;
+    sel->u.expr.method->init_frame   = method->init_frame ? &init_frame_kweval : NULL;
+    sel->u.expr.method->update       = &evaluate_kweval;
+    sel->u.expr.method->pupdate      = NULL;
+    sel->u.expr.method->nparams      = asize(smparams_kweval);
+    sel->u.expr.method->param        = smparams_kweval;
+    _gmx_selelem_init_method_params(sel, scanner);
+    sel->u.expr.mdata = data;
+
+    sel->u.expr.method->param[0].val.u.g = &data->g;
+
+    sfree(param->name);
+    param->name = NULL;
+    if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
+                               sel->u.expr.method->param, sel, scanner))
+    {
+        _gmx_selelem_free(sel);
+        return -1;
+    }
+    *selp = sel;
+    return 0;
+}
diff --git a/src/gromacs/selection/sm_merge.cpp b/src/gromacs/selection/sm_merge.cpp
new file mode 100644 (file)
index 0000000..95073d5
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements the \p merge and \p plus selection modifiers.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <smalloc.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+
+/*! \internal \brief
+ * Data structure for the merging selection modifiers.
+ */
+typedef struct
+{
+    /** Input positions. */
+    gmx_ana_pos_t    p1;
+    /** Other input positions. */
+    gmx_ana_pos_t    p2;
+    /** Group to store the output atom indices. */
+    gmx_ana_index_t  g;
+    /** Stride for merging (\c stride values from \c p1 for each in \c p2). */
+    int              stride;
+} t_methoddata_merge;
+
+/** Allocates data for the merging selection modifiers. */
+static void *
+init_data_merge(int npar, gmx_ana_selparam_t *param);
+/** Initializes data for the merging selection modifiers. */
+static void
+init_merge(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for the \p merge selection modifier. */
+static void
+init_output_merge(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Initializes output for the \p plus selection modifier. */
+static void
+init_output_plus(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the memory allocated for the merging selection modifiers. */
+static void
+free_data_merge(void *data);
+/** Evaluates the \p merge selection modifier. */
+static void
+evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p plus selection modifier. */
+static void
+evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for the merging selection modifiers. */
+static gmx_ana_selparam_t smparams_merge[] = {
+    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+    {"stride",   {INT_VALUE,  1, {NULL}}, NULL, SPAR_OPTIONAL},
+};
+
+/** Help text for the merging selection modifiers. */
+static const char *help_merge[] = {
+    "MERGING SELECTIONS[PAR]",
+
+    "[TT]POSEXPR merge POSEXPR [stride INT][tt][BR]",
+    "[TT]POSEXPR merge POSEXPR [merge POSEXPR ...][tt][BR]",
+    "[TT]POSEXPR plus POSEXPR [plus POSEXPR ...][tt][PAR]",
+
+    "Basic selection keywords can only create selections where each atom",
+    "occurs at most once. The [TT]merge[tt] and [TT]plus[tt] selection",
+    "keywords can be used to work around this limitation. Both create",
+    "a selection that contains the positions from all the given position",
+    "expressions, even if they contain duplicates.",
+    "The difference between the two is that [TT]merge[tt] expects two or more",
+    "selections with the same number of positions, and the output contains",
+    "the input positions selected from each expression in turn, i.e.,",
+    "the output is like A1 B1 A2 B2 and so on. It is also possible to merge",
+    "selections of unequal size as long as the size of the first is a",
+    "multiple of the second one. The [TT]stride[tt] parameter can be used",
+    "to explicitly provide this multiplicity.",
+    "[TT]plus[tt] simply concatenates the positions after each other, and",
+    "can work also with selections of different sizes.",
+    "These keywords are valid only at the selection level, not in any",
+    "subexpressions.[PAR]",
+};
+
+/** \internal Selection method data for the \p plus modifier. */
+gmx_ana_selmethod_t sm_merge = {
+    "merge", POS_VALUE, SMETH_MODIFIER,
+    asize(smparams_merge), smparams_merge,
+    &init_data_merge,
+    NULL,
+    &init_merge,
+    &init_output_merge,
+    &free_data_merge,
+    NULL,
+    NULL,
+    &evaluate_merge,
+    {"merge POSEXPR", asize(help_merge), help_merge},
+};
+
+/** \internal Selection method data for the \p plus modifier. */
+gmx_ana_selmethod_t sm_plus = {
+    "plus", POS_VALUE, SMETH_MODIFIER,
+    asize(smparams_merge)-1, smparams_merge,
+    &init_data_merge,
+    NULL,
+    &init_merge,
+    &init_output_plus,
+    &free_data_merge,
+    NULL,
+    NULL,
+    &evaluate_plus,
+    {"plus POSEXPR", asize(help_merge), help_merge},
+};
+
+/*!
+ * \param[in]     npar  Should be 2 for \c plus and 3 for \c merge.
+ * \param[in,out] param Method parameters (should point to a copy of
+ *   \ref smparams_merge).
+ * \returns Pointer to the allocated data (\p t_methoddata_merge).
+ *
+ * Allocates memory for a \p t_methoddata_merge structure.
+ */
+static void *
+init_data_merge(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_merge *data;
+
+    snew(data, 1);
+    data->stride = 0;
+    param[0].val.u.p = &data->p1;
+    param[1].val.u.p = &data->p2;
+    if (npar > 2)
+    {
+        param[2].val.u.i = &data->stride;
+    }
+    return data;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 2 or 3).
+ * \param[in] param Method parameters (should point to \ref smparams_merge).
+ * \param[in] data  Should point to a \p t_methoddata_merge.
+ * \returns   0 if everything is successful, -1 on error.
+ */
+static void
+init_merge(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+    int                 i;
+
+    if (d->stride < 0)
+    {
+        GMX_THROW(gmx::InvalidInputError("Stride for merging should be positive"));
+    }
+    /* If no stride given, deduce it from the input sizes */
+    if (d->stride == 0)
+    {
+        d->stride = d->p1.nr / d->p2.nr;
+    }
+    if (d->p1.nr != d->stride*d->p2.nr)
+    {
+        GMX_THROW(gmx::InconsistentInputError("The number of positions to be merged are not compatible"));
+    }
+    /* We access the m.b.nra field instead of g->isize in the position
+     * data structures to handle cases where g is NULL
+     * (this occurs with constant positions. */
+    gmx_ana_index_reserve(&d->g, d->p1.m.b.nra + d->p2.m.b.nra);
+    d->g.isize = d->p1.m.b.nra + d->p2.m.b.nra;
+}
+
+/*! \brief
+ * Does common initialization to all merging modifiers.
+ *
+ * \param[in]     top   Topology data structure.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_merge.
+ */
+static void
+init_output_common(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+
+    if (d->p1.m.type != d->p2.m.type)
+    {
+        /* TODO: Maybe we could pick something else here? */
+        out->u.p->m.type = INDEX_UNKNOWN;
+    }
+    else
+    {
+        out->u.p->m.type = d->p1.m.type;
+    }
+    gmx_ana_pos_reserve(out->u.p, d->p1.nr + d->p2.nr, d->g.isize);
+    if (d->p1.v)
+    {
+        gmx_ana_pos_reserve_velocities(out->u.p);
+    }
+    if (d->p1.f)
+    {
+        gmx_ana_pos_reserve_forces(out->u.p);
+    }
+    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
+    gmx_ana_pos_empty_init(out->u.p);
+    d->g.isize = 0;
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_merge.
+ */
+static void
+init_output_merge(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+    int                 i, j;
+
+    init_output_common(top, out, data);
+    for (i = 0; i < d->p2.nr; ++i)
+    {
+        for (j = 0; j < d->stride; ++j)
+        {
+            gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, d->stride*i+j);
+        }
+        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
+    }
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_merge.
+ */
+static void
+init_output_plus(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+    int                 i;
+
+    init_output_common(top, out, data);
+    for (i = 0; i < d->p1.nr; ++i)
+    {
+        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, i);
+    }
+    for (i = 0; i < d->p2.nr; ++i)
+    {
+        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
+    }
+}
+
+/*!
+ * \param data Data to free (should point to a \p t_methoddata_merge).
+ *
+ * Frees the memory allocated for \c t_methoddata_merge.
+ */
+static void
+free_data_merge(void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+
+    gmx_ana_index_deinit(&d->g);
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  p     Positions to merge (should point to \p data->p1).
+ * \param[out] out   Output data structure (\p out->u.p is used).
+ * \param[in]  data  Should point to a \p t_methoddata_merge.
+ */
+static void
+evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+    int                 i, j;
+    int                 refid;
+
+    if (d->p1.nr != d->stride*d->p2.nr)
+    {
+        GMX_THROW(gmx::InconsistentInputError("The number of positions to be merged are not compatible"));
+    }
+    d->g.isize = 0;
+    gmx_ana_pos_empty(out->u.p);
+    for (i = 0; i < d->p2.nr; ++i)
+    {
+        for (j = 0; j < d->stride; ++j)
+        {
+            refid = d->p1.m.refid[d->stride*i+j];
+            if (refid != -1)
+            {
+                refid = (d->stride+1) * (refid / d->stride) + (refid % d->stride);
+            }
+            gmx_ana_pos_append(out->u.p, &d->g, &d->p1, d->stride*i+j, refid);
+        }
+        refid = (d->stride+1)*d->p2.m.refid[i]+d->stride;
+        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
+    }
+    gmx_ana_pos_append_finish(out->u.p);
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  p     Positions to merge (should point to \p data->p1).
+ * \param[out] out   Output data structure (\p out->u.p is used).
+ * \param[in]  data  Should point to a \p t_methoddata_merge.
+ */
+static void
+evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_merge *d = (t_methoddata_merge *)data;
+    int                 i;
+    int                 refid;
+
+    d->g.isize = 0;
+    gmx_ana_pos_empty(out->u.p);
+    for (i = 0; i < d->p1.nr; ++i)
+    {
+        refid = d->p1.m.refid[i];
+        gmx_ana_pos_append(out->u.p, &d->g, &d->p1, i, refid);
+    }
+    for (i = 0; i < d->p2.nr; ++i)
+    {
+        refid = d->p2.m.refid[i];
+        if (refid != -1)
+        {
+            refid += d->p1.m.b.nr;
+        }
+        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
+    }
+    gmx_ana_pos_append_finish(out->u.p);
+}
diff --git a/src/gromacs/selection/sm_permute.cpp b/src/gromacs/selection/sm_permute.cpp
new file mode 100644 (file)
index 0000000..1367086
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements the \p permute selection modifier.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <smalloc.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+#include "gromacs/utility/format.h"
+
+/*! \internal \brief
+ * Data structure for the \p permute selection modifier.
+ */
+typedef struct
+{
+    /** Positions to permute. */
+    gmx_ana_pos_t    p;
+    /** Group to receive the output permutation. */
+    gmx_ana_index_t  g;
+    /** Number of elements in the permutation. */
+    int              n;
+    /** Array describing the permutation. */
+    int             *perm;
+    /** Array that has the permutation reversed. */
+    int             *rperm;
+} t_methoddata_permute;
+
+/** Allocates data for the \p permute selection modifier. */
+static void *
+init_data_permute(int npar, gmx_ana_selparam_t *param);
+/** Initializes data for the \p permute selection modifier. */
+static void
+init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for the \p permute selection modifier. */
+static void
+init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the memory allocated for the \p permute selection modifier. */
+static void
+free_data_permute(void *data);
+/** Evaluates the \p permute selection modifier. */
+static void
+evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for the \p permute selection modifier. */
+static gmx_ana_selparam_t smparams_permute[] = {
+    {NULL,       {POS_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+    {NULL,       {INT_VALUE, -1, {NULL}}, NULL, SPAR_VARNUM},
+};
+
+/** Help text for the \p permute selection modifier. */
+static const char *help_permute[] = {
+    "PERMUTING SELECTIONS[PAR]",
+
+    "[TT]permute P1 ... PN[tt][PAR]",
+
+    "By default, all selections are evaluated such that the atom indices are",
+    "returned in ascending order. This can be changed by appending",
+    "[TT]permute P1 P2 ... PN[tt] to an expression.",
+    "The [TT]Pi[tt] should form a permutation of the numbers 1 to N.",
+    "This keyword permutes each N-position block in the selection such that",
+    "the i'th position in the block becomes Pi'th.",
+    "Note that it is the positions that are permuted, not individual atoms.",
+    "A fatal error occurs if the size of the selection is not a multiple of n.",
+    "It is only possible to permute the whole selection expression, not any",
+    "subexpressions, i.e., the [TT]permute[tt] keyword should appear last in",
+    "a selection.",
+};
+
+/** \internal Selection method data for the \p permute modifier. */
+gmx_ana_selmethod_t sm_permute = {
+    "permute", POS_VALUE, SMETH_MODIFIER,
+    asize(smparams_permute), smparams_permute,
+    &init_data_permute,
+    NULL,
+    &init_permute,
+    &init_output_permute,
+    &free_data_permute,
+    NULL,
+    NULL,
+    &evaluate_permute,
+    {"permute P1 ... PN", asize(help_permute), help_permute},
+};
+
+/*!
+ * \param[in]     npar  Not used (should be 2).
+ * \param[in,out] param Method parameters (should point to a copy of
+ *   \ref smparams_permute).
+ * \returns Pointer to the allocated data (\p t_methoddata_permute).
+ *
+ * Allocates memory for a \p t_methoddata_permute structure.
+ */
+static void *
+init_data_permute(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_permute *data;
+
+    snew(data, 1);
+    param[0].val.u.p = &data->p;
+    return data;
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used (should be 2).
+ * \param[in] param Method parameters (should point to \ref smparams_permute).
+ * \param[in] data  Should point to a \p t_methoddata_permute.
+ * \returns   0 if the input permutation is valid, -1 on error.
+ */
+static void
+init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_permute *d = (t_methoddata_permute *)data;
+    int                   i;
+
+    gmx_ana_index_reserve(&d->g, d->p.g->isize);
+    d->n    = param[1].val.nr;
+    d->perm = param[1].val.u.i;
+    if (d->p.nr % d->n != 0)
+    {
+        GMX_THROW(gmx::InconsistentInputError(
+                    gmx::formatString("The number of positions to be permuted is not divisible by %d", d->n)));
+    }
+    snew(d->rperm, d->n);
+    for (i = 0; i < d->n; ++i)
+    {
+        d->rperm[i] = -1;
+    }
+    for (i = 0; i < d->n; ++i)
+    {
+        d->perm[i]--;
+        if (d->perm[i] < 0 || d->perm[i] >= d->n)
+        {
+            GMX_THROW(gmx::InvalidInputError("Invalid permutation"));
+        }
+        if (d->rperm[d->perm[i]] >= 0)
+        {
+            GMX_THROW(gmx::InvalidInputError("Invalid permutation"));
+        }
+        d->rperm[d->perm[i]] = i;
+    }
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_permute.
+ */
+static void
+init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_permute *d = (t_methoddata_permute *)data;
+    int                   i, j, b, k;
+
+    gmx_ana_pos_copy(out->u.p, &d->p, TRUE);
+    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
+    d->g.isize = 0;
+    gmx_ana_pos_empty_init(out->u.p);
+    for (i = 0; i < d->p.nr; i += d->n)
+    {
+        for (j = 0; j < d->n; ++j)
+        {
+            b = i + d->rperm[j];
+            gmx_ana_pos_append_init(out->u.p, &d->g, &d->p, b);
+        }
+    }
+}
+
+/*!
+ * \param data Data to free (should point to a \p t_methoddata_permute).
+ *
+ * Frees the memory allocated for \c t_methoddata_permute.
+ */
+static void
+free_data_permute(void *data)
+{
+    t_methoddata_permute *d = (t_methoddata_permute *)data;
+
+    gmx_ana_index_deinit(&d->g);
+    sfree(d->rperm);
+}
+
+/*!
+ * \param[in]  top   Not used.
+ * \param[in]  fr    Not used.
+ * \param[in]  pbc   Not used.
+ * \param[in]  p     Positions to permute (should point to \p data->p).
+ * \param[out] out   Output data structure (\p out->u.p is used).
+ * \param[in]  data  Should point to a \p t_methoddata_permute.
+ * \returns    0 if \p p could be permuted, -1 on error.
+ *
+ * Returns -1 if the size of \p p is not divisible by the number of
+ * elements in the permutation.
+ */
+static void
+evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_pos_t *p, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_permute *d = (t_methoddata_permute *)data;
+    int                   i, j, b, k;
+    int                   refid;
+
+    if (d->p.nr % d->n != 0)
+    {
+        GMX_THROW(gmx::InconsistentInputError(
+                    gmx::formatString("The number of positions to be permuted is not divisible by %d", d->n)));
+    }
+    d->g.isize = 0;
+    gmx_ana_pos_empty(out->u.p);
+    for (i = 0; i < d->p.nr; i += d->n)
+    {
+        for (j = 0; j < d->n; ++j)
+        {
+            b = i + d->rperm[j];
+            refid = d->p.m.refid[b];
+            if (refid != -1)
+            {
+                /* De-permute the reference ID */
+                refid = refid - (refid % d->n) + d->perm[refid % d->n];
+            }
+            gmx_ana_pos_append(out->u.p, &d->g, p, b, refid);
+        }
+    }
+    gmx_ana_pos_append_finish(out->u.p);
+}
diff --git a/src/gromacs/selection/sm_position.cpp b/src/gromacs/selection/sm_position.cpp
new file mode 100644 (file)
index 0000000..dba49af
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements position evaluation selection methods.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <smalloc.h>
+#include <string2.h>
+
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "keywords.h"
+#include "selelem.h"
+
+/*! \internal \brief
+ * Data structure for position keyword evaluation.
+ */
+typedef struct
+{
+    /** Position calculation collection to use. */
+    gmx_ana_poscalc_coll_t *pcc;
+    /** Index group for which the center should be evaluated. */
+    gmx_ana_index_t    g;
+    /** Position evaluation data structure. */
+    gmx_ana_poscalc_t *pc;
+    /** TRUE if periodic boundary conditions should be used. */
+    gmx_bool               bPBC;
+    /** Type of positions to calculate. */
+    char              *type;
+    /** Flags for the position calculation. */
+    int                flags;
+} t_methoddata_pos;
+
+/** Allocates data for position evaluation selection methods. */
+static void *
+init_data_pos(int npar, gmx_ana_selparam_t *param);
+/** Sets the position calculation collection for position evaluation selection methods. */
+static void
+set_poscoll_pos(gmx_ana_poscalc_coll_t *pcc, void *data);
+/** Initializes position evaluation keywords. */
+static void
+init_kwpos(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes the \p cog selection method. */
+static void
+init_cog(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes the \p cog selection method. */
+static void
+init_com(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for position evaluation selection methods. */
+static void
+init_output_pos(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the data allocated for position evaluation selection methods. */
+static void
+free_data_pos(void *data);
+/** Evaluates position evaluation selection methods. */
+static void
+evaluate_pos(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for position keyword evaluation. */
+static gmx_ana_selparam_t smparams_keyword_pos[] = {
+    {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+};
+
+/** Parameters for the \p cog and \p com selection methods. */
+static gmx_ana_selparam_t smparams_com[] = {
+    {"of",   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+    {"pbc",  {NO_VALUE,    0, {NULL}}, NULL, 0},
+};
+
+/** \internal Selection method data for position keyword evaluation. */
+gmx_ana_selmethod_t sm_keyword_pos = {
+    "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL,
+    asize(smparams_keyword_pos), smparams_keyword_pos,
+    &init_data_pos,
+    &set_poscoll_pos,
+    &init_kwpos,
+    &init_output_pos,
+    &free_data_pos,
+     NULL,
+    &evaluate_pos,
+     NULL,
+    {NULL, 0, NULL},
+};
+
+/** \internal Selection method data for the \p cog method. */
+gmx_ana_selmethod_t sm_cog = {
+    "cog", POS_VALUE, SMETH_DYNAMIC | SMETH_SINGLEVAL,
+    asize(smparams_com), smparams_com,
+    &init_data_pos,
+    &set_poscoll_pos,
+    &init_cog,
+    &init_output_pos,
+    &free_data_pos,
+     NULL,
+    &evaluate_pos,
+     NULL,
+    {"cog of ATOM_EXPR [pbc]", 0, NULL},
+};
+
+/** \internal Selection method data for the \p com method. */
+gmx_ana_selmethod_t sm_com = {
+    "com", POS_VALUE, SMETH_REQTOP | SMETH_DYNAMIC | SMETH_SINGLEVAL,
+    asize(smparams_com), smparams_com,
+    &init_data_pos,
+    &set_poscoll_pos,
+    &init_com,
+    &init_output_pos,
+    &free_data_pos,
+     NULL,
+    &evaluate_pos,
+     NULL,
+    {"com of ATOM_EXPR [pbc]", 0, NULL},
+};
+
+/*!
+ * \param[in]     npar  Should be 1 or 2.
+ * \param[in,out] param Method parameters (should point to
+ *   \ref smparams_keyword_pos or \ref smparams_com).
+ * \returns       Pointer to the allocated data (\c t_methoddata_pos).
+ *
+ * Allocates memory for a \c t_methoddata_pos structure and initializes
+ * the first parameter to define the value for \c t_methoddata_pos::g.
+ * If a second parameter is present, it is used for setting the
+ * \c t_methoddata_pos::bPBC flag.
+ */
+static void *
+init_data_pos(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_pos *data;
+
+    snew(data, 1);
+    param[0].val.u.g = &data->g;
+    if (npar > 1)
+    {
+        param[1].val.u.b = &data->bPBC;
+    }
+    data->pc       = NULL;
+    data->bPBC     = FALSE;
+    data->type     = NULL;
+    data->flags    = -1;
+    return data;
+}
+
+/*!
+ * \param[in]     pcc   Position calculation collection to use.
+ * \param[in,out] data  Should point to \c t_methoddata_pos.
+ */
+static void
+set_poscoll_pos(gmx_ana_poscalc_coll_t *pcc, void *data)
+{
+    ((t_methoddata_pos *)data)->pcc = pcc;
+}
+
+/*!
+ * \param[in,out] sel   Selection element to initialize.
+ * \param[in]     type  One of the enum values acceptable for
+ *   gmx_ana_poscalc_type_from_enum().
+ *
+ * Initializes the reference position type for position evaluation.
+ * If called multiple times, the first setting takes effect, and later calls
+ * are neglected.
+ */
+void
+_gmx_selelem_set_kwpos_type(t_selelem *sel, const char *type)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
+
+    if (sel->type != SEL_EXPRESSION || !sel->u.expr.method
+        || sel->u.expr.method->name != sm_keyword_pos.name)
+    {
+        return;
+    }
+    if (!d->type && type)
+    {
+        d->type  = strdup(type);
+        /* FIXME: It would be better not to have the string here hardcoded. */
+        if (type[0] != 'a')
+        {
+            sel->u.expr.method->flags |= SMETH_REQTOP;
+        }
+    }
+}
+
+/*!
+ * \param[in,out] sel   Selection element to initialize.
+ * \param[in]     flags Default completion flags
+ *   (see gmx_ana_poscalc_type_from_enum()).
+ *
+ * Initializes the flags for position evaluation.
+ * If called multiple times, the first setting takes effect, and later calls
+ * are neglected.
+ */
+void
+_gmx_selelem_set_kwpos_flags(t_selelem *sel, int flags)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
+
+    if (sel->type != SEL_EXPRESSION || !sel->u.expr.method
+        || sel->u.expr.method->name != sm_keyword_pos.name)
+    {
+        return;
+    }
+    if (d->flags == -1)
+    {
+        d->flags = flags;
+    }
+}
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used.
+ * \param[in] param Not used.
+ * \param[in,out] data  Should point to \c t_methoddata_pos.
+ * \returns       0 on success, a non-zero error code on error.
+ *
+ * The \c t_methoddata_pos::type field should have been initialized
+ * externally using _gmx_selelem_set_kwpos_type().
+ */
+static void
+init_kwpos(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    if (!(param[0].flags & SPAR_DYNAMIC))
+    {
+        d->flags &= ~(POS_DYNAMIC | POS_MASKONLY);
+    }
+    else if (!(d->flags & POS_MASKONLY))
+    {
+        d->flags |= POS_DYNAMIC;
+    }
+    gmx_ana_poscalc_create_enum(&d->pc, d->pcc, d->type, d->flags);
+    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in]     npar  Not used.
+ * \param[in]     param Not used.
+ * \param[in,out] data  Should point to \c t_methoddata_pos.
+ * \returns       0 on success, a non-zero error code on error.
+ */
+static void
+init_cog(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    d->flags = (param[0].flags & SPAR_DYNAMIC) ? POS_DYNAMIC : 0;
+    gmx_ana_poscalc_create(&d->pc, d->pcc, d->bPBC ? POS_ALL_PBC : POS_ALL,
+                           d->flags);
+    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in]     npar  Not used.
+ * \param[in]     param Not used.
+ * \param[in,out] data  Should point to \c t_methoddata_pos.
+ * \returns       0 on success, a non-zero error code on error.
+ */
+static void
+init_com(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    d->flags  = (param[0].flags & SPAR_DYNAMIC) ? POS_DYNAMIC : 0;
+    d->flags |= POS_MASS;
+    gmx_ana_poscalc_create(&d->pc, d->pcc, d->bPBC ? POS_ALL_PBC : POS_ALL,
+                           d->flags);
+    gmx_ana_poscalc_set_maxindex(d->pc, &d->g);
+}
+
+/*!
+ * \param[in]     top   Topology data structure.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_pos.
+ * \returns       0 for success.
+ */
+static void
+init_output_pos(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    gmx_ana_poscalc_init_pos(d->pc, out->u.p);
+    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_pos).
+ *
+ * Frees the memory allocated for \c t_methoddata_pos::g and
+ * \c t_methoddata_pos::pc.
+ */
+static void
+free_data_pos(void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    sfree(d->type);
+    gmx_ana_poscalc_free(d->pc);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_pos.
+ *
+ * Calculates the positions using \c t_methoddata_pos::pc for the index group
+ * in \c t_methoddata_pos::g and stores the results in \p out->u.p.
+ */
+static void
+evaluate_pos(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_pos *d = (t_methoddata_pos *)data;
+
+    gmx_ana_poscalc_update(d->pc, out->u.p, &d->g, fr, pbc);
+}
diff --git a/src/gromacs/selection/sm_same.cpp b/src/gromacs/selection/sm_same.cpp
new file mode 100644 (file)
index 0000000..d8a5c1e
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements the \p same selection method.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <macros.h>
+#include <smalloc.h>
+#include <string2.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/selmethod.h"
+
+#include "keywords.h"
+#include "parsetree.h"
+#include "selelem.h"
+
+/*! \internal \brief
+ * Data structure for the \p same selection method.
+ *
+ * To avoid duplicate initialization code, the same data structure is used
+ * for matching both integer and string keywords; hence the unions.
+ */
+typedef struct
+{
+    /** Value for each atom to match. */
+    union
+    {
+        int                 *i;
+        char               **s;
+        void                *ptr;
+    }                        val;
+    /*! \brief
+     * Number of values in the \p as array.
+     *
+     * For string values, this is actually the number of values in the
+     * \p as_s_sorted array.
+     */
+    int                      nas;
+    /** Values to match against. */
+    union
+    {
+        int                 *i;
+        char               **s;
+        void                *ptr;
+    }                        as;
+    /*! \brief
+     * Separate array for sorted \p as.s array.
+     *
+     * The array of strings returned as the output value of a parameter should
+     * not be messed with to avoid memory corruption (the pointers in the array
+     * may be reused for several evaluations), so we keep our own copy for
+     * modifications.
+     */
+    char                   **as_s_sorted;
+    /** Whether simple matching can be used. */
+    gmx_bool                     bSorted;
+} t_methoddata_same;
+
+/** Allocates data for the \p same selection method. */
+static void *
+init_data_same(int npar, gmx_ana_selparam_t *param);
+/** Initializes the \p same selection method. */
+static void
+init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Frees the data allocated for the \p same selection method. */
+static void
+free_data_same(void *data);
+/** Initializes the evaluation of the \p same selection method for a frame. */
+static void
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
+static void
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Initializes the evaluation of the \p same selection method for a frame. */
+static void
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
+static void
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_int[] = {
+    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"as", {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_str[] = {
+    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"as", {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Help text for the \p same selection method. */
+static const char *help_same[] = {
+    "EXTENDING SELECTIONS[PAR]",
+
+    "[TT]same KEYWORD as ATOM_EXPR[tt][PAR]",
+
+    "The keyword [TT]same[tt] can be used to select all atoms for which",
+    "the given [TT]KEYWORD[tt] matches any of the atoms in [TT]ATOM_EXPR[tt].",
+    "Keywords that evaluate to integer or string values are supported.",
+};
+
+/*! \internal \brief Selection method data for the \p same method. */
+gmx_ana_selmethod_t sm_same = {
+    "same", GROUP_VALUE, 0,
+    asize(smparams_same_int), smparams_same_int,
+    &init_data_same,
+    NULL,
+    &init_same,
+    NULL,
+    &free_data_same,
+    &init_frame_same_int,
+    &evaluate_same_int,
+    NULL,
+    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
+};
+
+/*! \brief
+ * Selection method data for the \p same method.
+ *
+ * This selection method is used for matching string keywords. The parser
+ * never sees this method; _gmx_selelem_custom_init_same() replaces sm_same
+ * with this method in cases where it is required.
+ */
+static gmx_ana_selmethod_t sm_same_str = {
+    "same", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_same_str), smparams_same_str,
+    &init_data_same,
+    NULL,
+    &init_same,
+    NULL,
+    &free_data_same,
+    &init_frame_same_str,
+    &evaluate_same_str,
+    NULL,
+    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
+};
+
+/*!
+ * \param[in]     npar  Not used (should be 2).
+ * \param[in,out] param Method parameters (should point to 
+ *   \ref smparams_same).
+ * \returns Pointer to the allocated data (\ref t_methoddata_same).
+ */
+static void *
+init_data_same(int npar, gmx_ana_selparam_t *param)
+{
+    t_methoddata_same *data;
+
+    snew(data, 1);
+    data->as_s_sorted = NULL;
+    param[1].nvalptr = &data->nas;
+    return data;
+}
+
+/*!
+ * \param[in,out] method  The method to initialize.
+ * \param[in,out] params  Pointer to the first parameter.
+ * \param[in]     scanner Scanner data structure.
+ * \returns       0 on success, a non-zero error code on error.
+ *
+ * If \p *method is not a \c same method, this function returns zero
+ * immediately.
+ */
+int
+_gmx_selelem_custom_init_same(gmx_ana_selmethod_t **method,
+                              t_selexpr_param *params,
+                              void *scanner)
+{
+    gmx_ana_selmethod_t *kwmethod;
+    t_selelem           *kwelem;
+    t_selexpr_param     *param;
+    char                *pname;
+    int                  rc;
+
+    /* Do nothing if this is not a same method. */
+    if (!*method || (*method)->name != sm_same.name)
+    {
+        return 0;
+    }
+
+    if (params->nval != 1 || !params->value->bExpr
+        || params->value->u.expr->type != SEL_EXPRESSION)
+    {
+        _gmx_selparser_error(scanner, "'same' should be followed by a single keyword");
+        return -1;
+    }
+    kwmethod = params->value->u.expr->u.expr.method;
+
+    if (kwmethod->type == STR_VALUE)
+    {
+        *method = &sm_same_str;
+    }
+
+    /* We do custom processing with the second parameter, so remove it from
+     * the params list, but save the name for later. */
+    param        = params->next;
+    params->next = NULL;
+    pname        = param->name;
+    param->name  = NULL;
+    /* Create a second keyword evaluation element for the keyword given as
+     * the first parameter, evaluating the keyword in the group given by the
+     * second parameter. */
+    rc = _gmx_sel_init_keyword_evaluator(&kwelem, kwmethod, param, scanner);
+    if (rc != 0)
+    {
+        sfree(pname);
+        return rc;
+    }
+    /* Replace the second parameter with one with a value from \p kwelem. */
+    param        = _gmx_selexpr_create_param(pname);
+    param->nval  = 1;
+    param->value = _gmx_selexpr_create_value_expr(kwelem);
+    params->next = param;
+    return 0;
+}
+
+/*!
+ * \param   top   Not used.
+ * \param   npar  Not used (should be 2).
+ * \param   param Initialized method parameters (should point to a copy of
+ *      \ref smparams_same).
+ * \param   data  Pointer to \ref t_methoddata_same to initialize.
+ * \returns 0 on success, -1 on failure.
+ */
+static void
+init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+
+    d->val.ptr = param[0].val.u.ptr;
+    d->as.ptr  = param[1].val.u.ptr;
+    if (param[1].val.type == STR_VALUE)
+    {
+        snew(d->as_s_sorted, d->nas);
+    }
+    if (!(param[0].flags & SPAR_ATOMVAL))
+    {
+        GMX_THROW(gmx::InvalidInputError(
+                    "The 'same' selection keyword combined with a "
+                    "non-keyword does not make sense"));
+    }
+}
+
+/*!
+ * \param data Data to free (should point to a \ref t_methoddata_same).
+ */
+static void
+free_data_same(void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+
+    sfree(d->as_s_sorted);
+}
+
+/*! \brief
+ * Helper function for comparison of two integers.
+ */
+static int
+cmp_int(const void *a, const void *b)
+{
+    if (*(int *)a < *(int *)b)
+    {
+        return -1;
+    }
+    if (*(int *)a > *(int *)b)
+    {
+        return 1;
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_same.
+ *
+ * Sorts the \c data->as.i array and removes identical values for faster and
+ * simpler lookup.
+ */
+static void
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                i, j;
+
+    /* Collapse adjacent values, and check whether the array is sorted. */
+    d->bSorted = TRUE;
+    for (i = 1, j = 0; i < d->nas; ++i)
+    {
+        if (d->as.i[i] != d->as.i[j])
+        {
+            if (d->as.i[i] < d->as.i[j])
+            {
+                d->bSorted = FALSE;
+            }
+            ++j;
+            d->as.i[j] = d->as.i[i];
+        }
+    }
+    d->nas = j + 1;
+
+    if (!d->bSorted)
+    {
+        qsort(d->as.i, d->nas, sizeof(d->as.i[0]), &cmp_int);
+        /* More identical values may become adjacent after sorting. */
+        for (i = 1, j = 0; i < d->nas; ++i)
+        {
+            if (d->as.i[i] != d->as.i[j])
+            {
+                ++j;
+                d->as.i[j] = d->as.i[i];
+            }
+        }
+        d->nas = j + 1;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_same.
+ *
+ * Calculates which values in \c data->val.i can be found in \c data->as.i
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * If \c data->val is sorted, uses a linear scan of both arrays, otherwise a
+ * binary search of \c data->as is performed for each block of values in
+ * \c data->val.
+ */
+static void
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                    i, j;
+
+    out->u.g->isize = 0;
+    i = j = 0;
+    while (j < g->isize)
+    {
+        if (d->bSorted)
+        {
+            /* If we are sorted, we can do a simple linear scan. */
+            while (i < d->nas && d->as.i[i] < d->val.i[j]) ++i;
+        }
+        else
+        {
+            /* If not, we must do a binary search of all the values. */
+            int i1, i2;
+
+            i1 = 0;
+            i2 = d->nas;
+            while (i2 - i1 > 1)
+            {
+                int itry = (i1 + i2) / 2;
+                if (d->as.i[itry] <= d->val.i[j])
+                {
+                    i1 = itry;
+                }
+                else
+                {
+                    i2 = itry;
+                }
+            }
+            i = (d->as.i[i1] == d->val.i[j] ? i1 : d->nas);
+        }
+        /* Check whether the value was found in the as list. */
+        if (i == d->nas || d->as.i[i] != d->val.i[j])
+        {
+            /* If not, skip all atoms with the same value. */
+            int tmpval = d->val.i[j];
+            ++j;
+            while (j < g->isize && d->val.i[j] == tmpval) ++j;
+        }
+        else
+        {
+            /* Copy all the atoms with this value to the output. */
+            while (j < g->isize && d->val.i[j] == d->as.i[i])
+            {
+                out->u.g->index[out->u.g->isize++] = g->index[j];
+                ++j;
+            }
+        }
+        if (j < g->isize && d->val.i[j] < d->val.i[j - 1])
+        {
+            d->bSorted = FALSE;
+        }
+    }
+}
+
+/*! \brief
+ * Helper function for comparison of two strings.
+ */
+static int
+cmp_str(const void *a, const void *b)
+{
+    return strcmp(*(char **)a, *(char **)b);
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_same.
+ *
+ * Sorts the \c data->as.s array and removes identical values for faster and
+ * simpler lookup.
+ */
+static void
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                i, j;
+
+    /* Collapse adjacent values.
+     * For strings, it's unlikely that the values would be sorted originally,
+     * so set bSorted always to FALSE. */
+    d->bSorted = FALSE;
+    d->as_s_sorted[0] = d->as.s[0];
+    for (i = 1, j = 0; i < d->nas; ++i)
+    {
+        if (strcmp(d->as.s[i], d->as_s_sorted[j]) != 0)
+        {
+            ++j;
+            d->as_s_sorted[j] = d->as.s[i];
+        }
+    }
+    d->nas = j + 1;
+
+    qsort(d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
+    /* More identical values may become adjacent after sorting. */
+    for (i = 1, j = 0; i < d->nas; ++i)
+    {
+        if (strcmp(d->as_s_sorted[i], d->as_s_sorted[j]) != 0)
+        {
+            ++j;
+            d->as_s_sorted[j] = d->as_s_sorted[i];
+        }
+    }
+    d->nas = j + 1;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_same.
+ *
+ * Calculates which strings in \c data->val.s can be found in \c data->as.s
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * A binary search of \c data->as is performed for each block of values in
+ * \c data->val.
+ */
+static void
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                    i, j;
+
+    out->u.g->isize = 0;
+    j = 0;
+    while (j < g->isize)
+    {
+        /* Do a binary search of the strings. */
+        void *ptr;
+        ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas,
+                      sizeof(d->as_s_sorted[0]), &cmp_str);
+        /* Check whether the value was found in the as list. */
+        if (ptr == NULL)
+        {
+            /* If not, skip all atoms with the same value. */
+            const char *tmpval = d->val.s[j];
+            ++j;
+            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0) ++j;
+        }
+        else
+        {
+            const char *tmpval = d->val.s[j];
+            /* Copy all the atoms with this value to the output. */
+            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0)
+            {
+                out->u.g->index[out->u.g->isize++] = g->index[j];
+                ++j;
+            }
+        }
+    }
+}
diff --git a/src/gromacs/selection/sm_simple.cpp b/src/gromacs/selection/sm_simple.cpp
new file mode 100644 (file)
index 0000000..ecf45ff
--- /dev/null
@@ -0,0 +1,846 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements simple keyword selection methods.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selmethod.h"
+
+/** Evaluates the \p all selection keyword. */
+static void
+evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p none selection keyword. */
+static void
+evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p atomnr selection keyword. */
+static void
+evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p resnr selection keyword. */
+static void
+evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p resindex selection keyword. */
+static void
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Checks whether molecule information is present in the topology. */
+static void
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Evaluates the \p molindex selection keyword. */
+static void
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p name selection keyword. */
+static void
+evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Checks whether atom types are present in the topology. */
+static void
+check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Evaluates the \p type selection keyword. */
+static void
+evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p insertcode selection keyword. */
+static void
+evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p chain selection keyword. */
+static void
+evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p mass selection keyword. */
+static void
+evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p charge selection keyword. */
+static void
+evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Checks whether PDB info is present in the topology. */
+static void
+check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Evaluates the \p altloc selection keyword. */
+static void
+evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p occupancy selection keyword. */
+static void
+evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p betafactor selection keyword. */
+static void
+evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p resname selection keyword. */
+static void
+evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/** Evaluates the \p x selection keyword. */
+static void
+evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p y selection keyword. */
+static void
+evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+/** Evaluates the \p z selection keyword. */
+static void
+evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
+
+/** \internal Selection method data for \p all selection keyword. */
+gmx_ana_selmethod_t sm_all = {
+    "all", GROUP_VALUE, 0,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_all,
+    NULL,
+};
+
+/** \internal Selection method data for \p none selection keyword. */
+gmx_ana_selmethod_t sm_none = {
+    "none", GROUP_VALUE, 0,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_none,
+    NULL,
+};
+
+/** \internal Selection method data for \p atomnr selection keyword. */
+gmx_ana_selmethod_t sm_atomnr = {
+    "atomnr", INT_VALUE, 0,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_atomnr,
+    NULL,
+};
+
+/** \internal Selection method data for \p resnr selection keyword. */
+gmx_ana_selmethod_t sm_resnr = {
+    "resnr", INT_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_resnr,
+    NULL,
+};
+
+/** \internal Selection method data for \p resindex selection keyword. */
+gmx_ana_selmethod_t sm_resindex = {
+    "resindex", INT_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_resindex,
+    NULL,
+};
+
+/** \internal Selection method data for \p molindex selection keyword. */
+gmx_ana_selmethod_t sm_molindex = {
+    "molindex", INT_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_molecules,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_molindex,
+    NULL,
+};
+
+/** \internal Selection method data for \p name selection keyword. */
+gmx_ana_selmethod_t sm_atomname = {
+    "name", STR_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_atomname,
+    NULL,
+};
+
+/** \internal Selection method data for \p type selection keyword. */
+gmx_ana_selmethod_t sm_atomtype = {
+    "type", STR_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_atomtype,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_atomtype,
+    NULL,
+};
+
+/** \internal Selection method data for \p resname selection keyword. */
+gmx_ana_selmethod_t sm_resname = {
+    "resname", STR_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_resname,
+    NULL,
+};
+
+/** \internal Selection method data for \p chain selection keyword. */
+gmx_ana_selmethod_t sm_insertcode = {
+    "insertcode", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_insertcode,
+    NULL,
+};
+
+/** \internal Selection method data for \p chain selection keyword. */
+gmx_ana_selmethod_t sm_chain = {
+    "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_chain,
+    NULL,
+};
+
+/** \internal Selection method data for \p mass selection keyword. */
+gmx_ana_selmethod_t sm_mass = {
+    "mass", REAL_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_mass,
+    NULL,
+};
+
+/** \internal Selection method data for \p charge selection keyword. */
+gmx_ana_selmethod_t sm_charge = {
+    "charge", REAL_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_charge,
+    NULL,
+};
+
+/** \internal Selection method data for \p chain selection keyword. */
+gmx_ana_selmethod_t sm_altloc = {
+    "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_pdbinfo,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_altloc,
+    NULL,
+};
+
+/** \internal Selection method data for \p occupancy selection keyword. */
+gmx_ana_selmethod_t sm_occupancy = {
+    "occupancy", REAL_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_pdbinfo,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_occupancy,
+    NULL,
+};
+
+/** \internal Selection method data for \p betafactor selection keyword. */
+gmx_ana_selmethod_t sm_betafactor = {
+    "betafactor", REAL_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_pdbinfo,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_betafactor,
+    NULL,
+};
+
+/** \internal Selection method data for \p x selection keyword. */
+gmx_ana_selmethod_t sm_x = {
+    "x", REAL_VALUE, SMETH_DYNAMIC,
+    0, NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+    &evaluate_x,
+};
+
+/** \internal Selection method data for \p y selection keyword. */
+gmx_ana_selmethod_t sm_y = {
+    "y", REAL_VALUE, SMETH_DYNAMIC,
+    0, NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+    &evaluate_y,
+};
+
+/** \internal Selection method data for \p z selection keyword. */
+gmx_ana_selmethod_t sm_z = {
+    "z", REAL_VALUE, SMETH_DYNAMIC,
+    0, NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+    &evaluate_z,
+};
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Copies \p g to \p out->u.g.
+ */
+static void
+evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+             gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    gmx_ana_index_copy(out->u.g, g, FALSE);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns an empty \p out->u.g.
+ */
+static void
+evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    out->u.g->isize = 0;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the indices for each atom in \p out->u.i.
+ */
+static void
+evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.i[i] = g->index[i] + 1;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the residue numbers for each atom in \p out->u.i.
+ */
+static void
+evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+    int  resind;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        resind = top->atoms.atom[g->index[i]].resind;
+        out->u.i[i] = top->atoms.resinfo[resind].nr;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the residue indices for each atom in \p out->u.i.
+ */
+static void
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.i[i] = top->atoms.atom[g->index[i]].resind + 1;
+    }
+}
+
+/*!
+ * \param[in] top  Topology structure.
+ * \param     npar Not used.
+ * \param     param Not used.
+ * \param     data Not used.
+ * \returns   0 if molecule info is present in the topology, -1 otherwise.
+ *
+ * If molecule information is not found, also prints an error message.
+ */
+static void
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    gmx_bool bOk;
+
+    bOk = (top != NULL && top->mols.nr > 0);
+    if (!bOk)
+    {
+        GMX_THROW(gmx::InconsistentInputError("Molecule information not available in topology"));
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the molecule indices for each atom in \p out->u.i.
+ */
+static void
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i, j;
+
+    out->nr = g->isize;
+    for (i = j = 0; i < g->isize; ++i)
+    {
+        while (top->mols.index[j + 1] <= g->index[i]) ++j;
+        out->u.i[i] = j + 1;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the atom name for each atom in \p out->u.s.
+ */
+static void
+evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.s[i] = *top->atoms.atomname[g->index[i]];
+    }
+}
+
+/*!
+ * \param[in] top  Topology structure.
+ * \param     npar Not used.
+ * \param     param Not used.
+ * \param     data Not used.
+ * \returns   0 if atom types are present in the topology, -1 otherwise.
+ *
+ * If the atom types are not found, also prints an error message.
+ */
+static void
+check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    gmx_bool bOk;
+
+    bOk = (top != NULL && top->atoms.atomtype != NULL);
+    if (!bOk)
+    {
+        GMX_THROW(gmx::InconsistentInputError("Atom types not available in topology"));
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the atom type for each atom in \p out->u.s.
+ * Segfaults if atom types are not found in the topology.
+ */
+static void
+evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.s[i] = *top->atoms.atomtype[g->index[i]];
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the residue name for each atom in \p out->u.s.
+ */
+static void
+evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+    int  resind;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        resind = top->atoms.atom[g->index[i]].resind;
+        out->u.s[i] = *top->atoms.resinfo[resind].name;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the insertion code for each atom in \p out->u.s.
+ */
+static void
+evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+    int  resind;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        resind = top->atoms.atom[g->index[i]].resind;
+        out->u.s[i][0] = top->atoms.resinfo[resind].ic;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the chain for each atom in \p out->u.s.
+ */
+static void
+evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+    int  resind;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        resind = top->atoms.atom[g->index[i]].resind;
+        out->u.s[i][0] = top->atoms.resinfo[resind].chainid;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the mass for each atom in \p out->u.r.
+ */
+static void
+evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.r[i] = top->atoms.atom[g->index[i]].m;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the charge for each atom in \p out->u.r.
+ */
+static void
+evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.r[i] = top->atoms.atom[g->index[i]].q;
+    }
+}
+
+/*!
+ * \param[in] top  Topology structure.
+ * \param     npar Not used.
+ * \param     param Not used.
+ * \param     data Not used.
+ * \returns   0 if PDB info is present in the topology, -1 otherwise.
+ *
+ * If PDB info is not found, also prints an error message.
+ */
+static void
+check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    gmx_bool bOk;
+
+    bOk = (top != NULL && top->atoms.pdbinfo != NULL);
+    if (!bOk)
+    {
+        GMX_THROW(gmx::InconsistentInputError("PDB info not available in topology"));
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the alternate location identifier for each atom in \p out->u.s.
+ */
+static void
+evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.s[i][0] = top->atoms.pdbinfo[g->index[i]].altloc;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the occupancy numbers for each atom in \p out->u.r.
+ * Segfaults if PDB info is not found in the topology.
+ */
+static void
+evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.r[i] = top->atoms.pdbinfo[g->index[i]].occup;
+    }
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the B-factors for each atom in \p out->u.r.
+ * Segfaults if PDB info is not found in the topology.
+ */
+static void
+evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i;
+
+    out->nr = g->isize;
+    for (i = 0; i < g->isize; ++i)
+    {
+        out->u.r[i] = top->atoms.pdbinfo[g->index[i]].bfac;
+    }
+}
+
+/*! \brief
+ * Internal utility function for position keyword evaluation.
+ *
+ * \param[in]  fr   Current frame.
+ * \param[in]  g    Index group for which the coordinates should be evaluated.
+ * \param[out] out  Output array.
+ * \param[in]  pos  Position data to use instead of atomic coordinates
+ *   (can be NULL).
+ * \param[in]  d    Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
+ *
+ * This function is used internally by evaluate_x(), evaluate_y() and
+ * evaluate_z() to do the actual evaluation.
+ */
+static void
+evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
+               gmx_ana_pos_t *pos, int d)
+{
+    int  b, i;
+    real v;
+
+    if (pos)
+    {
+        for (b = 0; b < pos->nr; ++b)
+        {
+            v = pos->x[b][d];
+            for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
+            {
+                out[i] = v;
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < g->isize; ++i)
+        {
+            out[i] = fr->x[g->index[i]][d];
+        }
+    }
+}
+
+/*!
+ * See sel_updatefunc_pos() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the \p x coordinate for each atom in \p out->u.r.
+ */
+static void
+evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    out->nr = pos->g->isize;
+    evaluate_coord(fr, pos->g, out->u.r, pos, XX);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the \p y coordinate for each atom in \p out->u.r.
+ */
+static void
+evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    out->nr = pos->g->isize;
+    evaluate_coord(fr, pos->g, out->u.r, pos, YY);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the \p z coordinate for each atom in \p out->u.r.
+ */
+static void
+evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+{
+    out->nr = pos->g->isize;
+    evaluate_coord(fr, pos->g, out->u.r, pos, ZZ);
+}
diff --git a/src/gromacs/selection/symrec.cpp b/src/gromacs/selection/symrec.cpp
new file mode 100644 (file)
index 0000000..a2376bf
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in symrec.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <macros.h>
+#include <smalloc.h>
+#include <string2.h>
+#include <typedefs.h>
+#include <gmx_fatal.h>
+
+#include "gromacs/selection/poscalc.h"
+
+#include "selelem.h"
+#include "symrec.h"
+
+/*! \internal \brief
+ * Symbol table for the selection parser.
+ */
+struct gmx_sel_symtab_t
+{
+    /** Pointer to the first symbol in the linked list of symbols. */
+    gmx_sel_symrec_t *first;
+};
+
+/*! \internal \brief
+ * Single symbol for the selection parser.
+ */
+struct gmx_sel_symrec_t
+{
+    /** Name of the symbol. */
+    char                           *name;
+    /** Type of the symbol. */
+    e_symbol_t                      type;
+    /** Value of the symbol. */
+    union {
+        /** Pointer to the method structure (\ref SYMBOL_METHOD). */
+        struct gmx_ana_selmethod_t *meth;
+        /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
+        struct t_selelem           *var;
+    }                               u;
+    /** Pointer to the next symbol. */
+    struct gmx_sel_symrec_t        *next;
+};
+
+/** List of reserved symbols to register in add_reserved_symbols(). */
+static const char *const sym_reserved[] = {
+    "group",
+    "to",
+    "not",
+    "and",
+    "or",
+    "xor",
+    "yes",
+    "no",
+    "on",
+    "off",
+    "help",
+};
+
+/*!
+ * \param[in] sym Symbol to query.
+ * \returns   The name of \p sym.
+ *
+ * The returned pointer should not be free'd.
+ */
+char *
+_gmx_sel_sym_name(gmx_sel_symrec_t *sym)
+{
+    return sym->name;
+}
+
+/*!
+ * \param[in] sym Symbol to query.
+ * \returns   The type of \p sym.
+ */
+e_symbol_t
+_gmx_sel_sym_type(gmx_sel_symrec_t *sym)
+{
+    return sym->type;
+}
+
+/*!
+ * \param[in] sym Symbol to query.
+ * \returns   The method associated with \p sym, or NULL if \p sym is not a
+ *   \ref SYMBOL_METHOD symbol.
+ */
+struct gmx_ana_selmethod_t *
+_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym)
+{
+    if (sym->type != SYMBOL_METHOD)
+    {
+        gmx_call("symbol is not a method symbol");
+        return NULL;
+    }
+    return sym->u.meth;
+}
+
+/*!
+ * \param[in] sym Symbol to query.
+ * \returns   The variable expression associated with \p sym, or NULL if
+ *   \p sym is not a \ref SYMBOL_VARIABLE symbol.
+ */
+struct t_selelem *
+_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym)
+{
+    if (sym->type != SYMBOL_VARIABLE)
+    {
+        gmx_call("symbol is not a variable symbol");
+        return NULL;
+    }
+    return sym->u.var;
+}
+
+/*! \brief
+ * Adds the reserved symbols to a symbol table.
+ * 
+ * \param[in,out] tab  Symbol table to which the symbols are added.
+ *
+ * Assumes that the symbol table is empty.
+ */
+static void
+add_reserved_symbols(gmx_sel_symtab_t *tab)
+{
+    gmx_sel_symrec_t *sym;
+    gmx_sel_symrec_t *last;
+    size_t            i;
+
+    last = NULL;
+    for (i = 0; i < asize(sym_reserved); ++i)
+    {
+        snew(sym, 1);
+        sym->name = strdup(sym_reserved[i]);
+        sym->type = SYMBOL_RESERVED;
+        sym->next = NULL;
+        if (last)
+        {
+            last->next = sym;
+        }
+        else
+        {
+            tab->first = sym;
+        }
+        last = sym;
+    }
+}
+
+/*! \brief
+ * Adds the position symbols to the symbol list.
+ * 
+ * \param[in,out] tab  Symbol table to which the symbols are added.
+ */
+static void
+add_position_symbols(gmx_sel_symtab_t *tab)
+{
+    const char       **postypes;
+    gmx_sel_symrec_t  *sym;
+    gmx_sel_symrec_t  *last;
+    int                i;
+
+    postypes = gmx_ana_poscalc_create_type_enum(TRUE);
+    last = tab->first;
+    while (last && last->next)
+    {
+        last = last->next;
+    }
+    for (i = 1; postypes[i] != NULL; ++i)
+    {
+        snew(sym, 1);
+        sym->name = strdup(postypes[i]);
+        sym->type = SYMBOL_POS;
+        sym->next = NULL;
+        if (last)
+        {
+            last->next = sym;
+        }
+        else
+        {
+            tab->first = sym;
+        }
+        last = sym;
+    }
+    sfree(postypes);
+}
+
+/*!
+ * \param[out] tabp Symbol table pointer to initialize.
+ *
+ * Reserved and position symbols are added to the created table.
+ */
+int
+_gmx_sel_symtab_create(gmx_sel_symtab_t **tabp)
+{
+    gmx_sel_symtab_t *tab;
+
+    snew(tab, 1);
+    add_reserved_symbols(tab);
+    add_position_symbols(tab);
+    *tabp = tab;
+    return 0;
+}
+
+/*!
+ * \param[in] tab Symbol table to free.
+ *
+ * The pointer \p tab is invalid after the call.
+ */
+void
+_gmx_sel_symtab_free(gmx_sel_symtab_t *tab)
+{
+    gmx_sel_symrec_t *sym;
+
+    while (tab->first)
+    {
+        sym = tab->first;
+        tab->first = sym->next;
+        if (sym->type == SYMBOL_VARIABLE)
+        {
+            _gmx_selelem_free(sym->u.var);
+        }
+        sfree(sym->name);
+        sfree(sym);
+    }
+    sfree(tab);
+}
+
+/*!
+ * \param[in] tab    Symbol table to search.
+ * \param[in] name   Symbol name to find.
+ * \param[in] bExact If FALSE, symbols that begin with \p name are also
+ *   considered.
+ * \returns   Pointer to the symbol with name \p name, or NULL if not found.
+ *
+ * If no exact match is found and \p bExact is FALSE, returns a symbol that
+ * begins with \p name if a unique matching symbol is found.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact)
+{
+    return _gmx_sel_find_symbol_len(tab, name, strlen(name), bExact);
+}
+
+/*!
+ * \param[in] tab    Symbol table to search.
+ * \param[in] name   Symbol name to find.
+ * \param[in] len    Only consider the first \p len characters of \p name.
+ * \param[in] bExact If FALSE, symbols that begin with \p name are also
+ *   considered.
+ * \returns   Pointer to the symbol with name \p name, or NULL if not found.
+ *
+ * If no exact match is found and \p bExact is FALSE, returns a symbol that
+ * begins with \p name if a unique matching symbol is found.
+ *
+ * The parameter \p len is there to allow using this function from scanner.l
+ * without modifying the text to be scanned or copying it.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
+                         gmx_bool bExact)
+{
+    gmx_sel_symrec_t *sym;
+    gmx_sel_symrec_t *match;
+    gmx_bool              bUnique;
+    gmx_bool              bMatch;
+
+    match = NULL;
+    bUnique = TRUE;
+    bMatch  = FALSE;
+    sym = tab->first;
+    while (sym)
+    {
+        if (!strncmp(sym->name, name, len))
+        {
+            if (strlen(sym->name) == len)
+            {
+                return sym;
+            }
+            if (bMatch)
+            {
+                bUnique = FALSE;
+            }
+            bMatch = TRUE;
+            if (sym->type == SYMBOL_METHOD)
+            {
+                match = sym;
+            }
+        }
+        sym = sym->next;
+    }
+    if (bExact)
+    {
+        return NULL;
+    }
+
+    if (!bUnique)
+    {
+        fprintf(stderr, "parse error: ambiguous symbol\n");
+        return NULL;
+    }
+    return match;
+}
+
+/*!
+ * \param[in] tab   Symbol table to search.
+ * \param[in] type  Type of symbol to find.
+ * \returns   The first symbol in \p tab with type \p type,
+ *   or NULL if there are no such symbols.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type)
+{
+    gmx_sel_symrec_t *sym;
+
+    sym = tab->first;
+    while (sym)
+    {
+        if (sym->type == type)
+        {
+            return sym;
+        }
+        sym = sym->next;
+    }
+    return NULL;
+}
+
+/*!
+ * \param[in] after Start the search after this symbol.
+ * \param[in] type  Type of symbol to find.
+ * \returns   The next symbol after \p after with type \p type,
+ *   or NULL if there are no more symbols.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type)
+{
+    gmx_sel_symrec_t *sym;
+
+    sym = after->next;
+    while (sym)
+    {
+        if (sym->type == type)
+        {
+            return sym;
+        }
+        sym = sym->next;
+    }
+    return NULL;
+}
+
+/*! \brief
+ * Internal utility function used in adding symbols to a symbol table.
+ *
+ * \param[in,out] tab   Symbol table to add the symbol to.
+ * \param[in]     name  Name of the symbol to add.
+ * \param[out]    ctype On error, the type of the conflicting symbol is
+ *   written to \p *ctype.
+ * \returns       Pointer to the new symbol record, or NULL if \p name
+ *   conflicts with an existing symbol.
+ */
+static gmx_sel_symrec_t *
+add_symbol(gmx_sel_symtab_t *tab, const char *name, e_symbol_t *ctype)
+{
+    gmx_sel_symrec_t *sym, *psym;
+    int               len;
+
+    /* Check if there is a conflicting symbol */
+    psym = NULL;
+    sym  = tab->first;
+    while (sym)
+    {
+        if (!gmx_strcasecmp(sym->name, name))
+        {
+            *ctype = sym->type;
+            return NULL;
+        }
+        psym = sym;
+        sym  = sym->next;
+    }
+
+    /* Create a new symbol record */
+    if (psym == NULL)
+    {
+        snew(tab->first, 1);
+        sym = tab->first;
+    }
+    else
+    {
+        snew(psym->next, 1);
+        sym = psym->next;
+    }
+    sym->name = strdup(name);
+    return sym;
+}
+
+/*!
+ * \param[in,out] tab    Symbol table to add the symbol to.
+ * \param[in]     name   Name of the new symbol.
+ * \param[in]     sel    Value of the variable.
+ * \returns       Pointer to the created symbol record, or NULL if there was a
+ *   symbol with the same name.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
+                        struct t_selelem *sel)
+{
+    gmx_sel_symrec_t *sym;
+    e_symbol_t        ctype;
+
+    sym = add_symbol(tab, name, &ctype);
+    if (!sym)
+    {
+        fprintf(stderr, "parse error: ");
+        switch (ctype)
+        {
+            case SYMBOL_RESERVED:
+            case SYMBOL_POS:
+                fprintf(stderr, "variable name (%s) conflicts with a reserved keyword\n",
+                        name);
+                break;
+            case SYMBOL_VARIABLE:
+                fprintf(stderr, "duplicate variable name (%s)\n", name);
+                break;
+            case SYMBOL_METHOD:
+                fprintf(stderr, "variable name (%s) conflicts with a selection keyword\n",
+                        name);
+                break;
+        }
+        return NULL;
+    }
+
+    sym->type  = SYMBOL_VARIABLE;
+    sym->u.var = sel;
+    sel->refcount++;
+    return sym;
+}
+
+/*!
+ * \param[in,out] tab    Symbol table to add the symbol to.
+ * \param[in]     name   Name of the new symbol.
+ * \param[in]     method Method that this symbol represents.
+ * \returns       Pointer to the created symbol record, or NULL if there was a
+ *   symbol with the same name.
+ */
+gmx_sel_symrec_t *
+_gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
+                           struct gmx_ana_selmethod_t *method)
+{
+    gmx_sel_symrec_t *sym;
+    e_symbol_t        ctype;
+
+    sym = add_symbol(tab, name, &ctype);
+    if (!sym)
+    {
+        fprintf(stderr, "parse error: ");
+        switch (ctype)
+        {
+            case SYMBOL_RESERVED:
+            case SYMBOL_POS:
+                fprintf(stderr, "method name (%s) conflicts with a reserved keyword\n",
+                        name);
+                break;
+            case SYMBOL_VARIABLE:
+                fprintf(stderr, "method name (%s) conflicts with a variable name\n",
+                        name);
+                break;
+            case SYMBOL_METHOD:
+                fprintf(stderr, "duplicate method name (%s)\n", name);
+                break;
+        }
+        return NULL;
+    }
+
+    sym->type   = SYMBOL_METHOD;
+    sym->u.meth = method;
+    return sym;
+}
diff --git a/src/gromacs/selection/symrec.h b/src/gromacs/selection/symrec.h
new file mode 100644 (file)
index 0000000..bab9483
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Handling of selection parser symbol table.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#ifndef SELECTION_SYMREC_H
+#define SELECTION_SYMREC_H
+
+struct t_selelem;
+struct gmx_ana_selmethod_t;
+
+/** Defines the type of the symbol. */
+typedef enum
+{
+    SYMBOL_RESERVED,    /**< The symbol is a reserved keyword. */
+    SYMBOL_VARIABLE,    /**< The symbol is a variable. */
+    SYMBOL_METHOD,      /**< The symbol is a selection method. */
+    SYMBOL_POS          /**< The symbol is a position keyword. */
+} e_symbol_t;
+
+/** Symbol table for the selection parser. */
+typedef struct gmx_sel_symtab_t gmx_sel_symtab_t;
+/** Single symbol for the selection parser. */
+typedef struct gmx_sel_symrec_t gmx_sel_symrec_t;
+
+/** Returns the name of a symbol. */
+char *
+_gmx_sel_sym_name(gmx_sel_symrec_t *sym);
+/** Returns the type of a symbol. */
+e_symbol_t
+_gmx_sel_sym_type(gmx_sel_symrec_t *sym);
+/** Returns the method associated with a \ref SYMBOL_METHOD symbol. */
+struct gmx_ana_selmethod_t *
+_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym);
+/** Returns the method associated with a \ref SYMBOL_VARIABLE symbol. */
+struct t_selelem *
+_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym);
+
+/** Creates a new symbol table. */
+int
+_gmx_sel_symtab_create(gmx_sel_symtab_t **tabp);
+/** Frees all memory allocated for a symbol table. */
+void
+_gmx_sel_symtab_free(gmx_sel_symtab_t *tab);
+/** Finds a symbol by name. */
+gmx_sel_symrec_t *
+_gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact);
+/** Finds a symbol by name. */
+gmx_sel_symrec_t *
+_gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
+                         gmx_bool bExact);
+/** Returns the first symbol of a given type. */
+gmx_sel_symrec_t *
+_gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type);
+/** Returns the next symbol of a given type. */
+gmx_sel_symrec_t *
+_gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type);
+/** Adds a new variable symbol. */
+gmx_sel_symrec_t *
+_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
+                        struct t_selelem *sel);
+/** Adds a new method symbol. */
+gmx_sel_symrec_t *
+_gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
+                           struct gmx_ana_selmethod_t *method);
+
+#endif
diff --git a/src/gromacs/selection/tests/.gitignore b/src/gromacs/selection/tests/.gitignore
new file mode 100644 (file)
index 0000000..8a29fe3
--- /dev/null
@@ -0,0 +1 @@
+selection-test
diff --git a/src/gromacs/selection/tests/CMakeLists.txt b/src/gromacs/selection/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ac952bc
--- /dev/null
@@ -0,0 +1,4 @@
+if (TESTUTILS_HAVE_REFDATA)
+    add_gtest_test(SelectionUnitTests selection-test
+                   selectioncollection.cpp selectionoption.cpp)
+endif ()
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAllNone.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAllNone.xml
new file mode 100644 (file)
index 0000000..bfb7ec3
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">all</String>
+    <String Name="Name">all</String>
+    <String Name="Text">all</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">none</String>
+    <String Name="Name">none</String>
+    <String Name="Text">none</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">0</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesArithmeticExpressions.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesArithmeticExpressions.xml
new file mode 100644 (file)
index 0000000..f2948ac
--- /dev/null
@@ -0,0 +1,197 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">x+1 &gt; 3</String>
+    <String Name="Name">x+1 &gt; 3</String>
+    <String Name="Text">x+1 &gt; 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">(y-1)^2 &lt;= 1</String>
+    <String Name="Name">(y-1)^2 &lt;= 1</String>
+    <String Name="Text">(y-1)^2 &lt;= 1</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">x+--1 &gt; 3</String>
+    <String Name="Name">x+--1 &gt; 3</String>
+    <String Name="Text">x+--1 &gt; 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection4Parse" Subtype="SelectionParse">
+    <String Name="Input">-x+-1 &lt; -3</String>
+    <String Name="Name">-x+-1 &lt; -3</String>
+    <String Name="Text">-x+-1 &lt; -3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection4Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">7</Int>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">8</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">7</Int>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection4Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">7</Int>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomname.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomname.xml
new file mode 100644 (file)
index 0000000..df5cf08
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">name CB</String>
+    <String Name="Name">name CB</String>
+    <String Name="Text">name CB</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">name S1 S2</String>
+    <String Name="Name">name S1 S2</String>
+    <String Name="Text">name S1 S2</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomnr.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesAtomnr.xml
new file mode 100644 (file)
index 0000000..d0b8be0
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 3 6 to 8</String>
+    <String Name="Name">atomnr 1 to 3 6 to 8</String>
+    <String Name="Text">atomnr 1 to 3 6 to 8</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 4 2 5 to 7</String>
+    <String Name="Name">atomnr 4 2 5 to 7</String>
+    <String Name="Text">atomnr 4 2 5 to 7</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr &lt;= 5</String>
+    <String Name="Name">atomnr &lt;= 5</String>
+    <String Name="Text">atomnr &lt;= 5</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>1</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBasicBoolean.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBasicBoolean.xml
new file mode 100644 (file)
index 0000000..a30c669
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and atomnr 2 to 7</String>
+    <String Name="Name">atomnr 1 to 5 and atomnr 2 to 7</String>
+    <String Name="Text">atomnr 1 to 5 and atomnr 2 to 7</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 or not atomnr 3 to 8</String>
+    <String Name="Name">atomnr 1 to 5 or not atomnr 3 to 8</String>
+    <String Name="Text">atomnr 1 to 5 or not atomnr 3 to 8</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7</String>
+    <String Name="Name">atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7</String>
+    <String Name="Text">atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysis.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysis.xml
new file mode 100644 (file)
index 0000000..1a61687
--- /dev/null
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and atomnr 2 to 7 and x &lt; 2</String>
+    <String Name="Name">atomnr 1 to 5 and atomnr 2 to 7 and x &lt; 2</String>
+    <String Name="Text">atomnr 1 to 5 and atomnr 2 to 7 and x &lt; 2</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Name">atomnr 1 to 5 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Text">atomnr 1 to 5 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and y &lt; 3 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Name">atomnr 1 to 5 and y &lt; 3 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Text">atomnr 1 to 5 and y &lt; 3 and (atomnr 4 to 7 or x &lt; 2)</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection4Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 5 and not (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Name">atomnr 1 to 5 and not (atomnr 4 to 7 or x &lt; 2)</String>
+    <String Name="Text">atomnr 1 to 5 and not (atomnr 4 to 7 or x &lt; 2)</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection4Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithMoreVariables.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithMoreVariables.xml
new file mode 100644 (file)
index 0000000..8a319a2
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Variable1Parse" Subtype="VariableParse">
+    <String Name="Input">foo = atomnr 4 to 7</String>
+  </Compound>
+  <Compound Name="Variable2Parse" Subtype="VariableParse">
+    <String Name="Input">bar = foo and x &lt; 2</String>
+  </Compound>
+  <Compound Name="Variable3Parse" Subtype="VariableParse">
+    <String Name="Input">bar2 = foo and y &lt; 2</String>
+  </Compound>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 4 and bar</String>
+    <String Name="Name">atomnr 1 to 4 and bar</String>
+    <String Name="Text">atomnr 1 to 4 and bar</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 2 to 6 and y &lt; 3 and bar2</String>
+    <String Name="Name">atomnr 2 to 6 and y &lt; 3 and bar2</String>
+    <String Name="Text">atomnr 2 to 6 and y &lt; 3 and bar2</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 6 to 10 and not foo</String>
+    <String Name="Name">atomnr 6 to 10 and not foo</String>
+    <String Name="Text">atomnr 6 to 10 and not foo</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">1</Int>
+      <Int>3</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithVariables.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesBooleanStaticAnalysisWithVariables.xml
new file mode 100644 (file)
index 0000000..a3c0f25
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Variable1Parse" Subtype="VariableParse">
+    <String Name="Input">foo = atomnr 4 to 7 or x &lt; 2</String>
+  </Compound>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 1 to 4 and foo</String>
+    <String Name="Name">atomnr 1 to 4 and foo</String>
+    <String Name="Text">atomnr 1 to 4 and foo</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 2 to 6 and y &lt; 3 and foo</String>
+    <String Name="Name">atomnr 2 to 6 and y &lt; 3 and foo</String>
+    <String Name="Text">atomnr 2 to 6 and y &lt; 3 and foo</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">atomnr 6 to 10 and not foo</String>
+    <String Name="Name">atomnr 6 to 10 and not foo</String>
+    <String Name="Text">atomnr 6 to 10 and not foo</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesConstantPositions.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesConstantPositions.xml
new file mode 100644 (file)
index 0000000..407ad00
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">[1, -2, 3.5]</String>
+    <String Name="Name">[1, -2, 3.5]</String>
+    <String Name="Text">[1, -2, 3.5]</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">0</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">0</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">1</Int>
+      <Vector>1.000000 -2.000000 3.500000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesCoordinateKeywords.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesCoordinateKeywords.xml
new file mode 100644 (file)
index 0000000..038528c
--- /dev/null
@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">x &lt; 3</String>
+    <String Name="Name">x &lt; 3</String>
+    <String Name="Text">x &lt; 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">y &gt;= 3</String>
+    <String Name="Name">y &gt;= 3</String>
+    <String Name="Text">y &gt;= 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">x {-1 to 2}</String>
+    <String Name="Name">x {-1 to 2}</String>
+    <String Name="Text">x {-1 to 2}</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">8</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">7</Int>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">8</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesDistanceKeyword.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesDistanceKeyword.xml
new file mode 100644 (file)
index 0000000..0d5d97c
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">distance from cog of resnr 1 &lt; 2</String>
+    <String Name="Name">distance from cog of resnr 1 &lt; 2</String>
+    <String Name="Text">distance from cog of resnr 1 &lt; 2</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">6</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMergeModifier.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMergeModifier.xml
new file mode 100644 (file)
index 0000000..9108a21
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">name S2 merge name S1</String>
+    <String Name="Name">name S2 merge name S1</String>
+    <String Name="Text">name S2 merge name S1</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">name S2 merge name S1 merge name CB</String>
+    <String Name="Name">name S2 merge name S1 merge name CB</String>
+    <String Name="Text">name S2 merge name S1 merge name CB</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>2</Int>
+      <Int>1</Int>
+      <Int>5</Int>
+      <Int>4</Int>
+      <Int>8</Int>
+      <Int>7</Int>
+      <Int>11</Int>
+      <Int>10</Int>
+      <Int>14</Int>
+      <Int>13</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>2</Int>
+      <Int>1</Int>
+      <Int>0</Int>
+      <Int>5</Int>
+      <Int>4</Int>
+      <Int>3</Int>
+      <Int>8</Int>
+      <Int>7</Int>
+      <Int>6</Int>
+      <Int>11</Int>
+      <Int>10</Int>
+      <Int>9</Int>
+      <Int>14</Int>
+      <Int>13</Int>
+      <Int>12</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>2</Int>
+      <Int>1</Int>
+      <Int>5</Int>
+      <Int>4</Int>
+      <Int>8</Int>
+      <Int>7</Int>
+      <Int>11</Int>
+      <Int>10</Int>
+      <Int>14</Int>
+      <Int>13</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">10</Int>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>2</Int>
+      <Int>1</Int>
+      <Int>0</Int>
+      <Int>5</Int>
+      <Int>4</Int>
+      <Int>3</Int>
+      <Int>8</Int>
+      <Int>7</Int>
+      <Int>6</Int>
+      <Int>11</Int>
+      <Int>10</Int>
+      <Int>9</Int>
+      <Int>14</Int>
+      <Int>13</Int>
+      <Int>12</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">15</Int>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMinDistanceKeyword.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesMinDistanceKeyword.xml
new file mode 100644 (file)
index 0000000..eacce2d
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">mindistance from resnr 1 &lt; 2</String>
+    <String Name="Name">mindistance from resnr 1 &lt; 2</String>
+    <String Name="Text">mindistance from resnr 1 &lt; 2</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">8</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPermuteModifier.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPermuteModifier.xml
new file mode 100644 (file)
index 0000000..fb59f63
--- /dev/null
@@ -0,0 +1,233 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">all permute 3 1 2</String>
+    <String Name="Name">all permute 3 1 2</String>
+    <String Name="Text">all permute 3 1 2</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">res_cog of resnr 1 to 4 permute 2 1</String>
+    <String Name="Name">res_cog of resnr 1 to 4 permute 2 1</String>
+    <String Name="Text">res_cog of resnr 1 to 4 permute 2 1</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">name CB S1 and res_cog x &lt; 3 permute 2 1</String>
+    <String Name="Name">name CB S1 and res_cog x &lt; 3 permute 2 1</String>
+    <String Name="Text">name CB S1 and res_cog x &lt; 3 permute 2 1</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>0</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>3</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>6</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>9</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+      <Int>12</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">16</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+      <Int>15</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">12</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>1</Int>
+      <Int>0</Int>
+      <Int>4</Int>
+      <Int>3</Int>
+      <Int>7</Int>
+      <Int>6</Int>
+      <Int>10</Int>
+      <Int>9</Int>
+      <Int>13</Int>
+      <Int>12</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">11</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>0</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>3</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>6</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>9</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+      <Int>12</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">16</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+      <Int>15</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">15</Int>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+      <Vector>4.000000 1.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">12</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">5</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">4</Int>
+      <Vector>1.666667 2.333333 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>2.333333 2.666667 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>1</Int>
+      <Int>0</Int>
+      <Int>4</Int>
+      <Int>3</Int>
+      <Int>7</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">7</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">6</Int>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPlusModifier.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPlusModifier.xml
new file mode 100644 (file)
index 0000000..3c8cee0
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">name S2 plus name S1</String>
+    <String Name="Name">name S2 plus name S1</String>
+    <String Name="Text">name S2 plus name S1</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3</String>
+    <String Name="Name">res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3</String>
+    <String Name="Text">res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>2</Int>
+      <Int>5</Int>
+      <Int>8</Int>
+      <Int>11</Int>
+      <Int>14</Int>
+      <Int>1</Int>
+      <Int>4</Int>
+      <Int>7</Int>
+      <Int>10</Int>
+      <Int>13</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">11</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">9</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>2</Int>
+      <Int>5</Int>
+      <Int>8</Int>
+      <Int>11</Int>
+      <Int>14</Int>
+      <Int>1</Int>
+      <Int>4</Int>
+      <Int>7</Int>
+      <Int>10</Int>
+      <Int>13</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">11</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">10</Int>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 4.000000 0.000000</Vector>
+      <Vector>4.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 3.000000 0.000000</Vector>
+      <Vector>4.000000 2.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">9</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">3</Int>
+      <Vector>1.666667 2.333333 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>2.333333 2.666667 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPositionKeywords.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesPositionKeywords.xml
new file mode 100644 (file)
index 0000000..88572dc
--- /dev/null
@@ -0,0 +1,241 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">cog of resnr 1 3</String>
+    <String Name="Name">cog of resnr 1 3</String>
+    <String Name="Text">cog of resnr 1 3</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">res_cog of name CB and resnr 1 3</String>
+    <String Name="Name">res_cog of name CB and resnr 1 3</String>
+    <String Name="Text">res_cog of name CB and resnr 1 3</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection3Parse" Subtype="SelectionParse">
+    <String Name="Input">whole_res_cog of name CB and resnr 1 3</String>
+    <String Name="Name">whole_res_cog of name CB and resnr 1 3</String>
+    <String Name="Text">whole_res_cog of name CB and resnr 1 3</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection4Parse" Subtype="SelectionParse">
+    <String Name="Input">part_res_cog of x &lt; 3</String>
+    <String Name="Name">part_res_cog of x &lt; 3</String>
+    <String Name="Text">part_res_cog of x &lt; 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection5Parse" Subtype="SelectionParse">
+    <String Name="Input">dyn_res_cog of x &lt; 3</String>
+    <String Name="Name">dyn_res_cog of x &lt; 3</String>
+    <String Name="Text">dyn_res_cog of x &lt; 3</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection4Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+      <Int>15</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection5Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>9</Int>
+      <Int>12</Int>
+      <Int>15</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">1</Int>
+      <Vector>1.666667 2.333333 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">2</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection3Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">2</Int>
+      <Int>0</Int>
+      <Int>6</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">3</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">2</Int>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>2.333333 2.666667 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection4Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">3</Int>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.666667 2.333333 0.000000</Vector>
+      <Vector>2.333333 2.666667 0.000000</Vector>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection5Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">8</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+    </Compound>
+    <Compound Name="PositionBlocks" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>3</Int>
+      <Int>6</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">3</Int>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.666667 2.333333 0.000000</Vector>
+      <Vector>2.000000 3.500000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesRegexMatching.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesRegexMatching.xml
new file mode 100644 (file)
index 0000000..a8a8540
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">resname "R[BD]"</String>
+    <String Name="Name">resname "R[BD]"</String>
+    <String Name="Text">resname "R[BD]"</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResname.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResname.xml
new file mode 100644 (file)
index 0000000..bbaa1f9
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">resname RA</String>
+    <String Name="Name">resname RA</String>
+    <String Name="Text">resname RA</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">resname RB RC</String>
+    <String Name="Name">resname RB RC</String>
+    <String Name="Text">resname RB RC</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResnr.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesResnr.xml
new file mode 100644 (file)
index 0000000..e983090
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">resnr 1 2 5</String>
+    <String Name="Name">resnr 1 2 5</String>
+    <String Name="Text">resnr 1 2 5</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection2Parse" Subtype="SelectionParse">
+    <String Name="Input">resnr 4 to 3</String>
+    <String Name="Name">resnr 4 to 3</String>
+    <String Name="Text">resnr 4 to 3</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">9</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection2Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">6</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidue.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidue.xml
new file mode 100644 (file)
index 0000000..5469fdf
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">same residue as atomnr 1 4 12</String>
+    <String Name="Name">same residue as atomnr 1 4 12</String>
+    <String Name="Text">same residue as atomnr 1 4 12</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">9</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidueName.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesSameResidueName.xml
new file mode 100644 (file)
index 0000000..e3b07c4
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">same resname as atomnr 1 14</String>
+    <String Name="Name">same resname as atomnr 1 14</String>
+    <String Name="Text">same resname as atomnr 1 14</String>
+    <Bool Name="Dynamic">false</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">9</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinConstantPositions.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinConstantPositions.xml
new file mode 100644 (file)
index 0000000..7277310
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">within 1 of [2, 1, 0]</String>
+    <String Name="Name">within 1 of [2, 1, 0]</String>
+    <String Name="Text">within 1 of [2, 1, 0]</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">4</Int>
+      <Int>0</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>8</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">4</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinKeyword.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesWithinKeyword.xml
new file mode 100644 (file)
index 0000000..0b3a3e0
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<ReferenceData>
+  <Compound Name="Selection1Parse" Subtype="SelectionParse">
+    <String Name="Input">within 1 of resnr 2</String>
+    <String Name="Name">within 1 of resnr 2</String>
+    <String Name="Text">within 1 of resnr 2</String>
+    <Bool Name="Dynamic">true</Bool>
+  </Compound>
+  <Compound Name="Selection1Compile" Subtype="SelectionCompile">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">15</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+      <Int>10</Int>
+      <Int>11</Int>
+      <Int>12</Int>
+      <Int>13</Int>
+      <Int>14</Int>
+    </Compound>
+  </Compound>
+  <Compound Name="Selection1Frame1" Subtype="SelectionFrame">
+    <Compound Name="Atoms" Subtype="SequenceInteger">
+      <Int Name="Length">10</Int>
+      <Int>0</Int>
+      <Int>1</Int>
+      <Int>2</Int>
+      <Int>3</Int>
+      <Int>4</Int>
+      <Int>5</Int>
+      <Int>6</Int>
+      <Int>7</Int>
+      <Int>8</Int>
+      <Int>9</Int>
+    </Compound>
+    <Compound Name="Positions" Subtype="SequenceVector">
+      <Int Name="Length">10</Int>
+      <Vector>1.000000 1.000000 0.000000</Vector>
+      <Vector>1.000000 2.000000 0.000000</Vector>
+      <Vector>1.000000 3.000000 0.000000</Vector>
+      <Vector>1.000000 4.000000 0.000000</Vector>
+      <Vector>2.000000 1.000000 0.000000</Vector>
+      <Vector>2.000000 2.000000 0.000000</Vector>
+      <Vector>2.000000 3.000000 0.000000</Vector>
+      <Vector>2.000000 4.000000 0.000000</Vector>
+      <Vector>3.000000 1.000000 0.000000</Vector>
+      <Vector>3.000000 2.000000 0.000000</Vector>
+    </Compound>
+  </Compound>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/selectioncollection.cpp b/src/gromacs/selection/tests/selectioncollection.cpp
new file mode 100644 (file)
index 0000000..4a3416e
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests selection parsing and compilation.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "smalloc.h"
+#include "statutil.h"
+#include "tpxio.h"
+#include "vec.h"
+
+// FIXME: This kind of hackery should not be necessary
+#undef min
+#undef max
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/selection/poscalc.h"
+#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/utility/flags.h"
+
+#include "testutils/datapath.h"
+#include "testutils/refdata.h"
+
+namespace
+{
+
+/********************************************************************
+ * Test fixture for selection testing
+ */
+
+class SelectionCollectionTest : public ::testing::Test
+{
+    public:
+        SelectionCollectionTest();
+        ~SelectionCollectionTest();
+
+        void setAtomCount(int natoms)
+        {
+            ASSERT_NO_THROW(_sc.setTopology(NULL, natoms));
+        }
+        void loadTopology(const char *filename);
+
+        gmx::SelectionCollection _sc;
+        std::vector<gmx::Selection *> _sel;
+        t_topology              *_top;
+        t_trxframe              *_frame;
+};
+
+
+SelectionCollectionTest::SelectionCollectionTest()
+    : _sc(NULL), _top(NULL), _frame(NULL)
+{
+    _sc.setReferencePosType("atom");
+    _sc.setOutputPosType("atom");
+}
+
+
+SelectionCollectionTest::~SelectionCollectionTest()
+{
+    if (_top != NULL)
+    {
+        done_top(_top);
+        sfree(_top);
+    }
+
+    if (_frame != NULL)
+    {
+        sfree(_frame->x);
+        sfree(_frame);
+    }
+}
+
+
+void
+SelectionCollectionTest::loadTopology(const char *filename)
+{
+    char    title[STRLEN];
+    int     ePBC;
+    rvec   *xtop;
+    matrix  box;
+
+    snew(_top, 1);
+    read_tps_conf(gmx::test::getTestFilePath(filename).c_str(),
+                  title, _top, &ePBC, &xtop, NULL, box, FALSE);
+
+    snew(_frame, 1);
+    _frame->flags  = TRX_NEED_X;
+    _frame->natoms = _top->atoms.nr;
+    _frame->bX     = TRUE;
+    snew(_frame->x, _frame->natoms);
+    memcpy(_frame->x, xtop, sizeof(*_frame->x) * _frame->natoms);
+    _frame->bBox   = TRUE;
+    copy_mat(box, _frame->box);
+
+    ASSERT_NO_THROW(_sc.setTopology(_top, -1));
+}
+
+
+/********************************************************************
+ * Test fixture for selection testing with reference data
+ */
+
+class SelectionCollectionDataTest : public SelectionCollectionTest
+{
+    public:
+        enum TestFlag
+        {
+            efTestPositionBlocks = 1<<0,
+            efTestEvaluation     = 1<<1,
+            efTestPositions      = 1<<2
+        };
+        typedef gmx::FlagsTemplate<TestFlag> TestFlags;
+
+        SelectionCollectionDataTest()
+            : _checker(_data.rootChecker()), _count(0), _framenr(0)
+        {
+        }
+
+        void setFlags(TestFlags flags) { _flags = flags; }
+
+        void runTest(int natoms, const char *const *selections);
+        void runTest(const char *filename, const char *const *selections);
+
+    private:
+        void runParser(const char *const *selections);
+        void runCompiler();
+        void checkCompiled();
+        void runEvaluate();
+        void runEvaluateFinal();
+
+        gmx::test::TestReferenceData  _data;
+        gmx::test::TestReferenceChecker _checker;
+        size_t                        _count;
+        int                           _framenr;
+        TestFlags                     _flags;
+};
+
+
+void
+SelectionCollectionDataTest::runParser(const char *const *selections)
+{
+    using gmx::test::TestReferenceChecker;
+
+    size_t varcount = 0;
+    _count = 0;
+    for (size_t i = 0; selections[i] != NULL; ++i)
+    {
+        SCOPED_TRACE(std::string("Parsing selection \"")
+                     + selections[i] + "\"");
+        ASSERT_NO_THROW(_sc.parseFromString(selections[i], &_sel));
+        char buf[50];
+        if (_sel.size() == _count)
+        {
+            snprintf(buf, 50, "Variable%dParse", static_cast<int>(varcount + 1));
+            TestReferenceChecker compound(_checker.checkCompound("VariableParse", buf));
+            compound.checkString(selections[i], "Input");
+            ++varcount;
+        }
+        else
+        {
+            snprintf(buf, 50, "Selection%dParse", static_cast<int>(_count + 1));
+            TestReferenceChecker compound(_checker.checkCompound("SelectionParse", buf));
+            compound.checkString(selections[i], "Input");
+            compound.checkString(_sel[_count]->name(), "Name");
+            compound.checkString(_sel[_count]->selectionText(), "Text");
+            compound.checkBoolean(_sel[_count]->isDynamic(), "Dynamic");
+            ++_count;
+        }
+    }
+}
+
+
+void
+SelectionCollectionDataTest::runCompiler()
+{
+    ASSERT_NO_THROW(_sc.compile());
+    ASSERT_EQ(_count, _sel.size());
+    checkCompiled();
+}
+
+
+void
+SelectionCollectionDataTest::checkCompiled()
+{
+    using gmx::test::TestReferenceChecker;
+
+    for (size_t i = 0; i < _count; ++i)
+    {
+        SCOPED_TRACE(std::string("Checking selection \"") +
+                     _sel[i]->selectionText() + "\"");
+        char buf[50];
+        snprintf(buf, 50, "Selection%dCompile", static_cast<int>(i + 1));
+        TestReferenceChecker compound(_checker.checkCompound("SelectionCompile", buf));
+        if (_sel[i]->indexGroup() != NULL)
+        {
+            compound.checkSequenceArray(_sel[i]->indexGroup()->isize,
+                                        _sel[i]->indexGroup()->index,
+                                        "Atoms");
+        }
+        else
+        {
+            compound.checkSequenceArray(0, (int *)NULL, "Atoms");
+        }
+        if (_flags.test(efTestPositionBlocks))
+        {
+            compound.checkSequenceArray(_sel[i]->posCount() + 1,
+                                        _sel[i]->positions()->m.mapb.index,
+                                        "PositionBlocks");
+        }
+    }
+}
+
+
+void
+SelectionCollectionDataTest::runEvaluate()
+{
+    using gmx::test::TestReferenceChecker;
+
+    ++_framenr;
+    ASSERT_NO_THROW(_sc.evaluate(_frame, NULL));
+    for (size_t i = 0; i < _count; ++i)
+    {
+        SCOPED_TRACE(std::string("Checking selection \"") +
+                     _sel[i]->selectionText() + "\"");
+        char buf[50];
+        snprintf(buf, 50, "Selection%dFrame%d",
+                 static_cast<int>(i + 1), _framenr);
+        TestReferenceChecker compound(_checker.checkCompound("SelectionFrame", buf));
+        if (_sel[i]->indexGroup() != NULL)
+        {
+            compound.checkSequenceArray(_sel[i]->indexGroup()->isize,
+                                        _sel[i]->indexGroup()->index,
+                                        "Atoms");
+        }
+        else
+        {
+            compound.checkSequenceArray(0, (int *)NULL, "Atoms");
+        }
+        if (_flags.test(efTestPositionBlocks))
+        {
+            compound.checkSequenceArray(_sel[i]->posCount() + 1,
+                                        _sel[i]->positions()->m.mapb.index,
+                                        "PositionBlocks");
+        }
+        if (_flags.test(efTestPositions))
+        {
+            compound.checkSequenceArray(_sel[i]->posCount(),
+                                        _sel[i]->positions()->x,
+                                        "Positions");
+        }
+    }
+}
+
+
+void
+SelectionCollectionDataTest::runEvaluateFinal()
+{
+    ASSERT_NO_THROW(_sc.evaluateFinal(_framenr));
+    if (!_checker.isWriteMode())
+    {
+        checkCompiled();
+    }
+}
+
+
+void
+SelectionCollectionDataTest::runTest(int natoms, const char * const *selections)
+{
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(setAtomCount(natoms));
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+}
+
+
+void
+SelectionCollectionDataTest::runTest(const char *filename, const char * const *selections)
+{
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology(filename));
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+    if (_flags.test(efTestEvaluation))
+    {
+        ASSERT_NO_FATAL_FAILURE(runEvaluate());
+        ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
+    }
+}
+
+
+/********************************************************************
+ * Tests for SelectionCollection functionality without reference data
+ */
+
+TEST_F(SelectionCollectionTest, HandlesNoSelections)
+{
+    EXPECT_FALSE(_sc.requiresTopology());
+    EXPECT_NO_THROW(_sc.compile());
+}
+
+// TODO: Tests for parser errors
+
+TEST_F(SelectionCollectionTest, RecoversFromUnknownGroupReference)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("group \"foo\"", &_sel));
+    ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
+    EXPECT_THROW(_sc.setIndexGroups(NULL), gmx::InvalidInputError);
+    EXPECT_THROW(_sc.compile(), gmx::APIError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("molindex 1 to 5", &_sel));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    EXPECT_THROW(_sc.compile(), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromMissingAtomTypes)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("type CA", &_sel));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    EXPECT_THROW(_sc.compile(), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromMissingPDBInfo)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("altloc A", &_sel));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    EXPECT_THROW(_sc.compile(), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("all permute 1 1", &_sel));
+    ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
+    EXPECT_THROW(_sc.compile(), gmx::InvalidInputError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation2)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("all permute 3 2 1", &_sel));
+    ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
+    EXPECT_THROW(_sc.compile(), gmx::InconsistentInputError);
+}
+
+TEST_F(SelectionCollectionTest, RecoversFromInvalidPermutation3)
+{
+    ASSERT_NO_THROW(_sc.parseFromString("x < 1.5 permute 3 2 1", &_sel));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW(_sc.compile());
+    EXPECT_THROW(_sc.evaluate(_frame, NULL), gmx::InconsistentInputError);
+}
+
+// TODO: Tests for evaluation errors
+
+
+/********************************************************************
+ * Tests for selection keywords
+ */
+
+TEST_F(SelectionCollectionDataTest, HandlesAllNone)
+{
+    static const char * const selections[] = {
+        "all",
+        "none",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+TEST_F(SelectionCollectionDataTest, HandlesAtomnr)
+{
+    static const char * const selections[] = {
+        "atomnr 1 to 3 6 to 8",
+        "atomnr 4 2 5 to 7",
+        "atomnr <= 5",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+TEST_F(SelectionCollectionDataTest, HandlesResnr)
+{
+    static const char * const selections[] = {
+        "resnr 1 2 5",
+        "resnr 4 to 3",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+// TODO: Add test for "resindex"
+// TODO: Add test for "molindex"
+
+TEST_F(SelectionCollectionDataTest, HandlesAtomname)
+{
+    static const char * const selections[] = {
+        "name CB",
+        "name S1 S2",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+// TODO: Add test for atomtype
+// TODO: Add test for insertcode
+// TODO: Add test for chain
+// TODO: Add test for mass
+// TODO: Add test for charge
+// TODO: Add test for altloc
+// TODO: Add test for occupancy
+// TODO: Add test for beta
+
+TEST_F(SelectionCollectionDataTest, HandlesResname)
+{
+    static const char * const selections[] = {
+        "resname RA",
+        "resname RB RC",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+TEST_F(SelectionCollectionDataTest, HandlesCoordinateKeywords)
+{
+    static const char * const selections[] = {
+        "x < 3",
+        "y >= 3",
+        "x {-1 to 2}",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesSameResidue)
+{
+    static const char * const selections[] = {
+        "same residue as atomnr 1 4 12",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesSameResidueName)
+{
+    static const char * const selections[] = {
+        "same resname as atomnr 1 14",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesPositionKeywords)
+{
+    static const char * const selections[] = {
+        "cog of resnr 1 3",
+        "res_cog of name CB and resnr 1 3",
+        "whole_res_cog of name CB and resnr 1 3",
+        "part_res_cog of x < 3",
+        "dyn_res_cog of x < 3",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions
+             | efTestPositionBlocks);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesDistanceKeyword)
+{
+    static const char * const selections[] = {
+        "distance from cog of resnr 1 < 2",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesMinDistanceKeyword)
+{
+    static const char * const selections[] = {
+        "mindistance from resnr 1 < 2",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesWithinKeyword)
+{
+    static const char * const selections[] = {
+        "within 1 of resnr 2",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+// TODO: Add test for "insolidangle"
+
+
+// TODO: Check the handling of mapped and reference IDs in the modifier tests
+// below.
+
+TEST_F(SelectionCollectionDataTest, HandlesPermuteModifier)
+{
+    static const char * const selections[] = {
+        "all permute 3 1 2",
+        "res_cog of resnr 1 to 4 permute 2 1",
+        "name CB S1 and res_cog x < 3 permute 2 1",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions
+             | efTestPositionBlocks);
+    runTest("simple.gro", selections);
+}
+
+
+// TODO: Add tests for plus/merge on dynamic selections
+// (can't remember whether it's actually implemented or not).
+
+TEST_F(SelectionCollectionDataTest, HandlesPlusModifier)
+{
+    static const char * const selections[] = {
+        "name S2 plus name S1",
+        "res_cog of resnr 2 plus res_cog of resnr 1 plus res_cog of resnr 3",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions
+             | efTestPositionBlocks);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesMergeModifier)
+{
+    static const char * const selections[] = {
+        "name S2 merge name S1",
+        "name S2 merge name S1 merge name CB",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+/********************************************************************
+ * Tests for selection syntactic constructs
+ */
+
+TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
+{
+    static const char * const selections[] = {
+        "[1, -2, 3.5]",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesWithinConstantPositions)
+{
+    static const char * const selections[] = {
+        "within 1 of [2, 1, 0]",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesRegexMatching)
+{
+    static const char * const selections[] = {
+        "resname \"R[BD]\"",
+        NULL
+    };
+    runTest("simple.gro", selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesBasicBoolean)
+{
+    static const char * const selections[] = {
+        "atomnr 1 to 5 and atomnr 2 to 7",
+        "atomnr 1 to 5 or not atomnr 3 to 8",
+        "atomnr 1 to 5 and atomnr 2 to 6 and not not atomnr 3 to 7",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesArithmeticExpressions)
+{
+    static const char * const selections[] = {
+        "x+1 > 3",
+        "(y-1)^2 <= 1",
+        "x+--1 > 3",
+        "-x+-1 < -3",
+        NULL
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositions);
+    runTest("simple.gro", selections);
+}
+
+
+/********************************************************************
+ * Tests for complex boolean syntax
+ */
+
+TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysis)
+{
+    static const char * const selections[] = {
+        "atomnr 1 to 5 and atomnr 2 to 7 and x < 2",
+        "atomnr 1 to 5 and (atomnr 4 to 7 or x < 2)",
+        "atomnr 1 to 5 and y < 3 and (atomnr 4 to 7 or x < 2)",
+        "atomnr 1 to 5 and not (atomnr 4 to 7 or x < 2)",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithVariables)
+{
+    static const char * const selections[] = {
+        "foo = atomnr 4 to 7 or x < 2",
+        "atomnr 1 to 4 and foo",
+        "atomnr 2 to 6 and y < 3 and foo",
+        "atomnr 6 to 10 and not foo",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+
+TEST_F(SelectionCollectionDataTest, HandlesBooleanStaticAnalysisWithMoreVariables)
+{
+    static const char * const selections[] = {
+        "foo = atomnr 4 to 7",
+        "bar = foo and x < 2",
+        "bar2 = foo and y < 2",
+        "atomnr 1 to 4 and bar",
+        "atomnr 2 to 6 and y < 3 and bar2",
+        "atomnr 6 to 10 and not foo",
+        NULL
+    };
+    runTest(10, selections);
+}
+
+} // namespace
diff --git a/src/gromacs/selection/tests/selectionoption.cpp b/src/gromacs/selection/tests/selectionoption.cpp
new file mode 100644 (file)
index 0000000..d531ccf
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests handling of selection options.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_selection
+ */
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/options/optionsassigner.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/selection/selectionoption.h"
+
+namespace
+{
+
+class SelectionOptionTest : public ::testing::Test
+{
+    public:
+        SelectionOptionTest();
+
+        gmx::SelectionCollection _sc;
+        gmx::Options             _options;
+};
+
+SelectionOptionTest::SelectionOptionTest()
+    : _sc(NULL), _options(NULL, NULL)
+{
+    _sc.setReferencePosType("atom");
+    _sc.setOutputPosType("atom");
+    _options.globalProperties().setSelectionCollection(&_sc);
+}
+
+
+TEST_F(SelectionOptionTest, ParsesSimpleSelection)
+{
+    gmx::Selection *sel = NULL;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+
+    ASSERT_TRUE(sel != NULL);
+    ASSERT_FALSE(sel->isDynamic());
+}
+
+
+TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
+{
+    gmx::Selection *sel = NULL;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").store(&sel).onlyStatic()));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_THROW(assigner.appendValue("resname RA RB and x < 5"), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+}
+
+
+TEST_F(SelectionOptionTest, HandlesTooManySelections)
+{
+    gmx::Selection *sel = NULL;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_THROW(assigner.appendValue("resname RB RC"), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    ASSERT_TRUE(sel != NULL);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesTooFewSelections)
+{
+    gmx::Selection *sel[2] = {NULL, NULL};
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").store(sel).valueCount(2)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_THROW(assigner.finishOption(), gmx::InvalidInputError);
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+}
+
+
+TEST_F(SelectionOptionTest, HandlesAdjuster)
+{
+    std::vector<gmx::Selection *> sel;
+    gmx::SelectionOptionAdjuster *adjuster;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").storeVector(&sel).multiValue()
+                            .getAdjuster(&adjuster)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_NO_THROW(adjuster->setValueCount(2));
+}
+
+
+TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
+{
+    gmx::Selection *sel;
+    gmx::SelectionOptionAdjuster *adjuster;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").store(&sel)
+                            .getAdjuster(&adjuster)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("x < 5"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_THROW(adjuster->setOnlyStatic(true), gmx::InvalidInputError);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
+{
+    std::vector<gmx::Selection *> sel;
+    gmx::SelectionOptionAdjuster *adjuster;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").storeVector(&sel).multiValue()
+                            .getAdjuster(&adjuster)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RB RC"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_THROW(adjuster->setValueCount(1), gmx::InvalidInputError);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
+{
+    std::vector<gmx::Selection *> sel;
+    gmx::SelectionOptionAdjuster *adjuster;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").storeVector(&sel).multiValue()
+                            .getAdjuster(&adjuster)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.appendValue("resname RA RB"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_THROW(adjuster->setValueCount(2), gmx::InvalidInputError);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
+{
+    gmx::Selection *sel = NULL;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").store(&sel).required()));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
+    ASSERT_TRUE(sel != NULL);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
+{
+    gmx::Selection *sel[2] = {NULL, NULL};
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").store(sel).required()
+                            .valueCount(2)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_THROW(_sc.parseRequestedFromString("resname RA RB"), gmx::InvalidInputError);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
+{
+    gmx::Selection *sel = NULL;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
+    ASSERT_TRUE(sel != NULL);
+}
+
+
+TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
+{
+    std::vector<gmx::Selection *> sel;
+    gmx::SelectionOptionAdjuster *adjuster;
+    using gmx::SelectionOption;
+    ASSERT_NO_THROW(_options.addOption(
+                        SelectionOption("sel").storeVector(&sel).valueCount(3)
+                            .getAdjuster(&adjuster)));
+
+    gmx::OptionsAssigner assigner(&_options);
+    EXPECT_NO_THROW(assigner.start());
+    ASSERT_NO_THROW(assigner.startOption("sel"));
+    EXPECT_NO_THROW(assigner.finishOption());
+    EXPECT_NO_THROW(assigner.finish());
+    EXPECT_NO_THROW(_options.finish());
+    EXPECT_NO_THROW(adjuster->setValueCount(2));
+    EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB; resname RB RC"));
+}
+
+} // namespace
diff --git a/src/gromacs/selection/tests/simple.gro b/src/gromacs/selection/tests/simple.gro
new file mode 100644 (file)
index 0000000..02690f9
--- /dev/null
@@ -0,0 +1,18 @@
+Test system
+ 15
+    1RA      CB    1   1.000   1.000   0.000
+    1RA      S1    2   1.000   2.000   0.000
+    1RA      S2    3   1.000   3.000   0.000
+    2RB      CB    4   1.000   4.000   0.000
+    2RB      S1    5   2.000   1.000   0.000
+    2RB      S2    6   2.000   2.000   0.000
+    3RA      CB    7   2.000   3.000   0.000
+    3RA      S1    8   2.000   4.000   0.000
+    3RA      S2    9   3.000   1.000   0.000
+    4RC      CB   10   3.000   2.000   0.000
+    4RC      S1   11   3.000   3.000   0.000
+    4RC      S2   12   3.000   4.000   0.000
+    5RD      CB   13   4.000   1.000   0.000
+    5RD      S1   14   4.000   2.000   0.000
+    5RD      S2   15   4.000   3.000   0.000
+  10.00000  10.00000  10.00000
diff --git a/src/gromacs/trajectoryanalysis.h b/src/gromacs/trajectoryanalysis.h
new file mode 100644 (file)
index 0000000..386c830
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \defgroup module_trajectoryanalysis Framework for Trajectory Analysis
+ * \ingroup group_analysismodules
+ * \brief
+ * Provides functionality for implementing trajectory analysis modules.
+ *
+ * This module implements a framework for implementing flexible trajectory
+ * analysis routines.  It provides a base class for implementing analysis as
+ * reusable modules that can be used from different contexts and can also
+ * support per-frame parallelization.  It integrally uses functionality from the
+ * following modules:
+ *  - \ref module_options
+ *  - \ref module_analysisdata
+ *  - \ref module_selection
+ *
+ * The main interface of this module is the gmx::TrajectoryAnalysisModule class.
+ * Analysis modules should derive from this class, and override the necessary
+ * virtual methods to provide the actual initialization and analysis routines.
+ * Classes gmx::TrajectoryAnalysisSettings and gmx::TopologyInformation (in
+ * addition to classes declared in the above-mentioned modules) are used to pass
+ * information to and from these methods.  gmx::TrajectoryAnalysisModuleData can
+ * be used in advanced scenarios where the tool requires custom thread-local
+ * data for parallel analysis.
+ *
+ * In addition to the framework for defining analysis modules, this module also
+ * provides gmx::TrajectoryAnalysisCommandLineRunner, which implements a
+ * command-line program that runs a certain analysis module.
+ *
+ * Internally, the module also defines a set of trajectory analysis modules that
+ * can be instantiated using createTrajectoryAnalysisModule().
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+/*! \file
+ * \brief
+ * Public API convenience header for trajectory analysis framework
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_H
+#define GMX_TRAJECTORYANALYSIS_H
+
+#include "analysisdata.h"
+#include "options.h"
+#include "selection.h"
+
+#include "fatalerror/exceptions.h"
+#include "trajectoryanalysis/analysismodule.h"
+#include "trajectoryanalysis/analysissettings.h"
+#include "trajectoryanalysis/cmdlinerunner.h"
+#include "trajectoryanalysis/nbsearch.h"
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/CMakeLists.txt b/src/gromacs/trajectoryanalysis/CMakeLists.txt
new file mode 100644 (file)
index 0000000..726ceb8
--- /dev/null
@@ -0,0 +1,14 @@
+file(GLOB TRAJECTORYANALYSIS_SOURCES *.cpp modules/*.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${TRAJECTORYANALYSIS_SOURCES} PARENT_SCOPE)
+
+set(TRAJECTORYANALYSIS_PUBLIC_HEADERS
+    analysismodule.h
+    analysissettings.h
+    cmdlinerunner.h)
+install(FILES ${TRAJECTORYANALYSIS_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/trajectoryanalysis
+        COMPONENT development)
+
+if (BUILD_TESTING)
+    add_subdirectory(tests)
+endif (BUILD_TESTING)
diff --git a/src/gromacs/trajectoryanalysis/analysismodule-impl.h b/src/gromacs/trajectoryanalysis/analysismodule-impl.h
new file mode 100644 (file)
index 0000000..0b568a8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation classes for gmx::TrajectoryAnalysisModule
+ * and gmx::TrajectoryAnalysisModuleData.
+ *
+ * \ingroup module_trajectoryanalysis
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_ANALYSISMODULE_IMPL_H
+#define GMX_TRAJECTORYANALYSIS_ANALYSISMODULE_IMPL_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "analysismodule.h"
+
+namespace gmx
+{
+
+class AbstractAnalysisData;
+class AnalysisData;
+class AnalysisDataHandle;
+
+class TrajectoryAnalysisModuleData::Impl
+{
+    public:
+        typedef std::map<std::string, AnalysisDataHandle *> HandleContainer;
+
+        Impl(TrajectoryAnalysisModule *module,
+             /*AnalysisDataParallelOptions*/ void* opt,
+             const SelectionCollection &selections);
+        ~Impl();
+
+        void finishHandles();
+
+        HandleContainer         _handles;
+        const SelectionCollection &_selections;
+};
+
+class TrajectoryAnalysisModule::Impl
+{
+    public:
+        typedef std::map<std::string, AbstractAnalysisData *> DatasetContainer;
+        typedef std::map<std::string, AnalysisData *> AnalysisDatasetContainer;
+
+        std::vector<std::string>        _datasetNames;
+        DatasetContainer                _datasets;
+        AnalysisDatasetContainer        _analysisDatasets;
+};
+
+/*! \internal \brief
+ * Basic thread-local trajectory analysis data storage class.
+ *
+ * Most simple tools should only require data handles and selections to be
+ * thread-local, so this class implements just that.
+ */
+class TrajectoryAnalysisModuleDataBasic : public TrajectoryAnalysisModuleData
+{
+    public:
+        TrajectoryAnalysisModuleDataBasic(TrajectoryAnalysisModule *module,
+                                          /*AnalysisDataParallelOptions*/ void* opt,
+                                          const SelectionCollection &selections);
+
+        virtual void finish();
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/analysismodule.cpp b/src/gromacs/trajectoryanalysis/analysismodule.cpp
new file mode 100644 (file)
index 0000000..f3cae4e
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in analysismodule.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#include "gromacs/trajectoryanalysis/analysismodule.h"
+
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/fatalerror/gmxassert.h"
+
+#include "analysismodule-impl.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * TrajectoryAnalysisModuleData::Impl
+ */
+
+TrajectoryAnalysisModuleData::Impl::Impl(
+        TrajectoryAnalysisModule *module,
+        AnalysisDataParallelOptions opt,
+        const SelectionCollection &selections)
+    : _selections(selections)
+{
+    TrajectoryAnalysisModule::Impl::AnalysisDatasetContainer::const_iterator i;
+    for (i = module->_impl->_analysisDatasets.begin();
+         i != module->_impl->_analysisDatasets.end(); ++i)
+    {
+        _handles[i->first] = i->second->startData(opt);
+    }
+}
+
+TrajectoryAnalysisModuleData::Impl::~Impl()
+{
+    try
+    {
+        finishHandles();
+    }
+    catch (...)
+    {
+    }
+}
+
+
+void TrajectoryAnalysisModuleData::Impl::finishHandles()
+{
+    // FIXME: Call finishData() for all handles even if one throws
+    HandleContainer::const_iterator i;
+    for (i = _handles.begin(); i != _handles.end(); ++i)
+    {
+        i->second->finishData();
+    }
+    _handles.clear();
+}
+
+
+/********************************************************************
+ * TrajectoryAnalysisModuleData
+ */
+
+TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData(
+        TrajectoryAnalysisModule *module,
+        AnalysisDataParallelOptions opt,
+        const SelectionCollection &selections)
+    : _impl(new Impl(module, opt, selections))
+{
+}
+
+
+TrajectoryAnalysisModuleData::~TrajectoryAnalysisModuleData()
+{
+    delete _impl;
+}
+
+
+void TrajectoryAnalysisModuleData::finishDataHandles()
+{
+    _impl->finishHandles();
+}
+
+
+AnalysisDataHandle *TrajectoryAnalysisModuleData::dataHandle(const char *name)
+{
+    Impl::HandleContainer::const_iterator i = _impl->_handles.find(name);
+    GMX_RELEASE_ASSERT(i != _impl->_handles.end(),
+                       "Data handle requested on unknown dataset");
+    return (i != _impl->_handles.end()) ? (*i).second : NULL;
+}
+
+
+Selection *TrajectoryAnalysisModuleData::parallelSelection(Selection *selection)
+{
+    // TODO: Implement properly.
+    return selection;
+}
+
+
+std::vector<Selection *>
+TrajectoryAnalysisModuleData::parallelSelections(const std::vector<Selection *> &selections)
+{
+    std::vector<Selection *> newSelections;
+    newSelections.reserve(selections.size());
+    std::vector<Selection *>::const_iterator i = selections.begin();
+    for ( ; i != selections.end(); ++i)
+    {
+        newSelections.push_back(parallelSelection(*i));
+    }
+    return newSelections;
+}
+
+
+/********************************************************************
+ * TrajectoryAnalysisModuleDataBasic
+ */
+TrajectoryAnalysisModuleDataBasic::TrajectoryAnalysisModuleDataBasic(
+        TrajectoryAnalysisModule *module,
+        /*AnalysisDataParallelOptions*/ void* opt,
+        const SelectionCollection &selections)
+    : TrajectoryAnalysisModuleData(module, opt, selections)
+{
+}
+
+
+void
+TrajectoryAnalysisModuleDataBasic::finish()
+{
+    finishDataHandles();
+}
+
+
+/********************************************************************
+ * TrajectoryAnalysisModule
+ */
+
+TrajectoryAnalysisModule::TrajectoryAnalysisModule()
+    : _impl(new Impl)
+{
+}
+
+
+TrajectoryAnalysisModule::~TrajectoryAnalysisModule()
+{
+    delete _impl;
+}
+
+
+void TrajectoryAnalysisModule::initOptionsDone(TrajectoryAnalysisSettings * /*settings*/)
+{
+}
+
+
+void TrajectoryAnalysisModule::initAfterFirstFrame(const t_trxframe &/*fr*/)
+{
+}
+
+
+TrajectoryAnalysisModuleData *
+TrajectoryAnalysisModule::startFrames(AnalysisDataParallelOptions opt,
+                                      const SelectionCollection &selections)
+{
+    return new TrajectoryAnalysisModuleDataBasic(this, opt, selections);
+}
+
+
+void TrajectoryAnalysisModule::finishFrames(TrajectoryAnalysisModuleData * /*pdata*/)
+{
+}
+
+
+int TrajectoryAnalysisModule::datasetCount() const
+{
+    return _impl->_datasetNames.size();
+}
+
+
+const std::vector<std::string> &TrajectoryAnalysisModule::datasetNames() const
+{
+    return _impl->_datasetNames;
+}
+
+
+AbstractAnalysisData *TrajectoryAnalysisModule::datasetFromIndex(int index) const
+{
+    if (index < 0 || index >= datasetCount())
+    {
+        return NULL;
+    }
+    return _impl->_datasets[_impl->_datasetNames[index]];
+}
+
+
+AbstractAnalysisData *TrajectoryAnalysisModule::datasetFromName(const char *name) const
+{
+    Impl::DatasetContainer::const_iterator item = _impl->_datasets.find(name);
+    if (item == _impl->_datasets.end())
+    {
+        return NULL;
+    }
+    return item->second;
+}
+
+
+void TrajectoryAnalysisModule::registerBasicDataset(AbstractAnalysisData *data,
+                                                    const char *name)
+{
+    // TODO: Check for duplicates
+    _impl->_datasets[name] = data;
+    _impl->_datasetNames.push_back(name);
+}
+
+
+void TrajectoryAnalysisModule::registerAnalysisDataset(AnalysisData *data,
+                                                       const char *name)
+{
+    registerBasicDataset(data, name);
+    _impl->_analysisDatasets[name] = data;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/analysismodule.h b/src/gromacs/trajectoryanalysis/analysismodule.h
new file mode 100644 (file)
index 0000000..28ee01e
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::TrajectoryAnalysisModule and
+ * gmx::TrajectoryAnalysisModuleData.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_ANALYSISMODULE_H
+#define GMX_TRAJECTORYANALYSIS_ANALYSISMODULE_H
+
+#include <string>
+#include <vector>
+
+#include "../legacyheaders/typedefs.h"
+
+namespace gmx
+{
+
+class AbstractAnalysisData;
+class AnalysisData;
+class AnalysisDataHandle;
+class Options;
+class Selection;
+class SelectionCollection;
+class TopologyInformation;
+class TrajectoryAnalysisModule;
+class TrajectoryAnalysisSettings;
+
+/*! \brief
+ * Base class for thread-local data storage during trajectory analysis.
+ *
+ * Thread-local storage of data handles and selections is implemented in this
+ * class; TrajectoryAnalysisModule instances can access the thread-local values
+ * using dataHandle() and parallelSelection().
+ *
+ * \see TrajectoryAnalysisModule::startFrames()
+ * \see TrajectoryAnalysisModule::analyzeFrame()
+ * \see TrajectoryAnalysisModule::finishFrames()
+ *
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisModuleData
+{
+    public:
+        virtual ~TrajectoryAnalysisModuleData();
+
+        /*! \brief
+         * Performs any finishing actions after all frames have been processed.
+         *
+         * This function is called immediately before the destructor.
+         * All implementations should call finishDataHandles().
+         */
+        virtual void finish() = 0;
+
+        /*! \brief
+         * Returns a data handle for a dataset with a given name.
+         *
+         * Allowed names are those that have been registered with
+         * TrajectoryAnalysisModule::registerAnalysisDataset().
+         */
+        AnalysisDataHandle *dataHandle(const char *name);
+        /*! \brief
+         * Returns a selection that corresponds to the given selection.
+         */
+        Selection *parallelSelection(Selection *selection);
+        /*! \brief
+         * Returns a set of selection that corresponds to the given selections.
+         */
+        std::vector<Selection *> parallelSelections(const std::vector<Selection *> &selections);
+
+    protected:
+        /*! \brief
+         * Initializes thread-local storage for data handles and selections.
+         *
+         * \param[in] module     Analysis module to use for data objects.
+         * \param[in] opt        Data parallelization options.
+         * \param[in] selections Thread-local selection collection.
+         *
+         * Calls AnalysisData::startData() on all data objects registered with
+         * TrajectoryAnalysisModule::registerAnalysisDataset() in \p module.
+         * The handles are accessible through dataHandle().
+         */
+        TrajectoryAnalysisModuleData(TrajectoryAnalysisModule *module,
+                                     /*AnalysisDataParallelOptions*/ void* opt,
+                                     const SelectionCollection &selections);
+
+        /*! \brief
+         * Calls finishData() on all data handles.
+         *
+         * This function should be called from the implementation of finish()
+         * in all subclasses.
+         */
+        void finishDataHandles();
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        TrajectoryAnalysisModuleData(const TrajectoryAnalysisModuleData &);
+        void operator =(const TrajectoryAnalysisModuleData &);
+};
+
+
+/*! \brief
+ * Base class for trajectory analysis methods.
+ *
+ * Trajectory analysis methods should derive from this class and override the
+ * necessary virtual functions to implement initialization (initOptions(),
+ * initOptionsDone(), initAnalysis(), initAfterFirstFrame()), per-frame analysis
+ * (analyzeFrame()), and final processing (finishFrames(), finishAnalysis(),
+ * writeOutput()).
+ *
+ * For parallel analysis using threads, only a single object is constructed,
+ * but the methods startFrames(), analyzeFrame() and finishFrames() are called
+ * in each thread.  Frame-local data should be initialized in startFrames() and
+ * stored in a class derived from TrajectoryAnalysisModuleData that is passed
+ * to the other methods.  The default implementation of startFrames() can be
+ * used if only data handles and selections need to be thread-local.
+ *
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisModule
+{
+    public:
+        virtual ~TrajectoryAnalysisModule();
+
+        /*! \brief
+         * Initializes options understood by the module.
+         *
+         * In addition to initializing the options, this function can also
+         * provide information about its requirements using the \p settings
+         * object; see TrajectoryAnalysisSettings for more details.
+         *
+         * If settings depend on the option values provided by the user, see
+         * initOptionsDone().
+         */
+        virtual Options *initOptions(TrajectoryAnalysisSettings *settings) = 0;
+        /*! \brief
+         * Called after all option values have been set.
+         *
+         * If the module needs to change settings that affect topology loading
+         * or selection initialization based on option values, this function
+         * has to be overridden.
+         *
+         * The default implementation does nothing.
+         */
+        virtual void initOptionsDone(TrajectoryAnalysisSettings *settings);
+        /*! \brief
+         * Initializes the analysis.
+         *
+         * When this function is called, selections have been initialized based
+         * on user input, and a topology has been loaded if provided by the
+         * user.  For dynamic selections, the selections have been evaluated to
+         * the largest possible selection, i.e., the selections passed to
+         * analyzeFrame() are always a subset of the selections provided here.
+         */
+        virtual void initAnalysis(const TopologyInformation &top) = 0;
+        /*! \brief
+         * Performs additional initialization after reading the first frame.
+         *
+         * When this function is called, selections are the same as in
+         * initAnalysis(), i.e., they have not been evaluated for the first
+         * frame.
+         *
+         * It is necessary to override this method only if the module needs to
+         * do initialization for which it requires data from the first frame.
+         *
+         * The default implementation does nothing.
+         */
+        virtual void initAfterFirstFrame(const t_trxframe &fr);
+
+        /*! \brief
+         * Starts the analysis of frames.
+         *
+         * \param[in]  opt
+         * \param[in]  selections  Frame-local selection collection object.
+         * \returns    Data structure for thread-local data.
+         *
+         * This function is necessary only for threaded parallelization.
+         * It is called once for each thread and should initialize a class that
+         * contains any required frame-local data in the returned value.
+         * The default implementation creates a basic data structure that holds
+         * thread-local data handles for all data objects registered with
+         * registerAnalysisDataset(), as well as the thread-local selection
+         * collection.  These can be accessed in analyzeFrame() using the
+         * methods in TrajectoryAnalysisModuleData.
+         * If other thread-local data is needed, this function should be
+         * overridden and it should create an instance of a class derived from
+         * TrajectoryAnalysisModuleData.
+         *
+         * \see TrajectoryAnalysisModuleData
+         */
+        virtual TrajectoryAnalysisModuleData *startFrames(
+                /*AnalysisDataParallelOptions*/ void* opt,
+                const SelectionCollection &selections);
+        /*! \brief
+         * Analyzes a single frame.
+         *
+         * \param[in]     frnr   Frame number, a zero-based index that
+         *      uniquely identifies the frame.
+         * \param[in]     fr     Current frame.
+         * \param[in]     pbc    Periodic boundary conditions for \p fr.
+         * \param[in,out] pdata  Data structure for frame-local data.
+         *
+         * This function is called once for each frame to be analyzed,
+         * and should analyze the positions provided in \p sel.
+         *
+         * For threaded analysis, this function is called asynchronously in
+         * different threads to analyze different frames. The \p pdata
+         * structure is one of the structures created with startFrames(),
+         * but no assumptions should be made about which of these data
+         * structures is used. It is guaranteed that two instances of
+         * analyzeFrame() are not running concurrently with the same \p pdata
+         * data structure.
+         * Any access to data structures not stored in \p pdata should be
+         * designed to be thread-safe.
+         */
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata) = 0;
+        /*! \brief
+         * Finishes the analysis of frames.
+         *
+         * \param[in]  pdata    Data structure for thread-local data.
+         *
+         * This function is called once for each call of startFrames(),
+         * with the data structure returned by the corresponding startFrames().
+         * The \p pdata object should be destroyed by the caller after this
+         * function has been called.
+         *
+         * You only need to override this method if you need custom
+         * operations to combine data from the frame-local data structures
+         * to get the final result. In such cases, the data should be
+         * aggregated in this function and stored in a member attribute.
+         *
+         * The default implementation does nothing.
+         *
+         * \see startFrames()
+         */
+        virtual void finishFrames(TrajectoryAnalysisModuleData *pdata);
+
+        /*! \brief
+         * Postprocesses data after frames have been read.
+         *
+         * This function is called after all finishFrames() calls have been
+         * called.
+         */
+        virtual void finishAnalysis(int nframes) = 0;
+        /*! \brief
+         * Writes output into files and/or standard output/error.
+         *
+         * All output from the module, excluding data written out for each
+         * frame during analyzeFrame(), should be confined into this function.
+         * This function is guaranteed to be called only after
+         * finishAnalysis().
+         */
+        virtual void writeOutput() = 0;
+
+        /*! \brief
+         * Returns the number of datasets provided by the module.
+         */
+        int datasetCount() const;
+        /*! \brief
+         * Returns a vector with the names of the datasets.
+         */
+        const std::vector<std::string> &datasetNames() const;
+        /*! \brief
+         * Returns a pointer to the data set \p index.
+         *
+         * \param[in] index  Data set to query for.
+         * \returns   A pointer to the data set, or NULL if \p index is not
+         *      valid.
+         *
+         * The return value is not const to allow callers to add modules to the
+         * data sets. However, the AbstractAnalysisData interface does not
+         * provide any means to alter the data, so the module does not need to
+         * care about external modifications.
+         */
+        AbstractAnalysisData *datasetFromIndex(int index) const;
+        /*! \brief
+         * Returns a pointer to the data set with name \p name
+         *
+         * \param[in] name  Data set to query for.
+         * \returns   A pointer to the data set, or NULL if \p name is not
+         *      recognized.
+         *
+         * The return value is not const to allow callers to add modules to the
+         * data sets. However, the AbstractAnalysisData interface does not
+         * provide any means to alter the data, so the module does not need to
+         * care about external modifications.
+         */
+        AbstractAnalysisData *datasetFromName(const char *name) const;
+
+    protected:
+        //! Initializes the dataset registration mechanism.
+        TrajectoryAnalysisModule();
+
+        /*! \brief
+         * Registers a dataset that exports data.
+         */
+        void registerBasicDataset(AbstractAnalysisData *data, const char *name);
+        /*! \brief
+         * Registers a parallelized dataset that exports data.
+         */
+        void registerAnalysisDataset(AnalysisData *data, const char *name);
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        /*! \brief
+         * Needed to access the registered analysis data sets.
+         */
+        friend class TrajectoryAnalysisModuleData;
+
+        // Disallow copy and assign.
+        TrajectoryAnalysisModule(const TrajectoryAnalysisModule &);
+        void operator =(const TrajectoryAnalysisModule &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/analysissettings-impl.h b/src/gromacs/trajectoryanalysis/analysissettings-impl.h
new file mode 100644 (file)
index 0000000..3c59c30
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::TrajectoryAnalysisSettings.
+ *
+ * \ingroup module_trajectoryanalysis
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_ANALYSISSETTINGS_IMPL_H
+#define GMX_TRAJECTORYANALYSIS_ANALYSISSETTINGS_IMPL_H
+
+#include "analysissettings.h"
+
+namespace gmx
+{
+
+/*! \internal \brief
+ * Private implementation class for TrajectoryAnalysisSettings.
+ *
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisSettings::Impl
+{
+    public:
+        //! Initializes the default values for the settings object.
+        Impl() : flags(0), frflags(0), bRmPBC(true), bPBC(true) {}
+
+        unsigned long        flags;
+        int                  frflags;
+
+        bool                 bRmPBC;
+        bool                 bPBC;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/analysissettings.cpp b/src/gromacs/trajectoryanalysis/analysissettings.cpp
new file mode 100644 (file)
index 0000000..3b0866c
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements classes in analysissettings.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <smalloc.h>
+#include <statutil.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/trajectoryanalysis/analysissettings.h"
+
+#include "analysissettings-impl.h"
+
+namespace gmx
+{
+
+
+/********************************************************************
+ * TrajectoryAnalysisSettings
+ */
+
+TrajectoryAnalysisSettings::TrajectoryAnalysisSettings()
+    : _impl(new Impl)
+{
+    _impl->frflags |= TRX_NEED_X;
+}
+
+
+TrajectoryAnalysisSettings::~TrajectoryAnalysisSettings()
+{
+    delete _impl;
+}
+
+
+unsigned long
+TrajectoryAnalysisSettings::flags() const
+{
+    return _impl->flags;
+}
+
+
+bool
+TrajectoryAnalysisSettings::hasFlag(unsigned long flag) const
+{
+    return _impl->flags & flag;
+}
+
+
+bool
+TrajectoryAnalysisSettings::hasPBC() const
+{
+    return _impl->bPBC;
+}
+
+
+bool
+TrajectoryAnalysisSettings::hasRmPBC() const
+{
+    return _impl->bRmPBC;
+}
+
+
+int
+TrajectoryAnalysisSettings::frflags() const
+{
+    return _impl->frflags;
+}
+
+
+void
+TrajectoryAnalysisSettings::setFlags(unsigned long flags)
+{
+    _impl->flags = flags;
+}
+
+
+void
+TrajectoryAnalysisSettings::setFlag(unsigned long flag, bool bSet)
+{
+    if (bSet)
+    {
+        _impl->flags |= flag;
+    }
+    else
+    {
+        _impl->flags &= ~flag;
+    }
+}
+
+
+void
+TrajectoryAnalysisSettings::setPBC(bool bPBC)
+{
+    _impl->bPBC = bPBC;
+}
+
+
+void
+TrajectoryAnalysisSettings::setRmPBC(bool bRmPBC)
+{
+    _impl->bRmPBC = bRmPBC;
+}
+
+
+void
+TrajectoryAnalysisSettings::setFrameFlags(int frflags)
+{
+    _impl->frflags = frflags;
+}
+
+
+/********************************************************************
+ * TopologyInformation
+ */
+
+TopologyInformation::TopologyInformation()
+    : _top(NULL), _bTop(false), _xtop(NULL), _ePBC(-1)
+{
+    clear_mat(_boxtop);
+}
+
+
+TopologyInformation::~TopologyInformation()
+{
+    if (_top)
+    {
+        done_top(_top);
+        sfree(_top);
+    }
+    sfree(_xtop);
+}
+
+
+void
+TopologyInformation::getTopologyConf(rvec **x, matrix box) const
+{
+    if (box)
+    {
+        copy_mat(const_cast<rvec *>(_boxtop), box);
+    }
+    if (x)
+    {
+        if (!_xtop)
+        {
+            *x = NULL;
+            GMX_THROW(APIError("Topology coordinates requested without setting efUseTopX"));
+        }
+        *x = _xtop;
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/analysissettings.h b/src/gromacs/trajectoryanalysis/analysissettings.h
new file mode 100644 (file)
index 0000000..7715b1c
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::TrajectoryAnalysisSettings and gmx::TopologyInformation.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_ANALYSISSETTINGS_H
+#define GMX_TRAJECTORYANALYSIS_ANALYSISSETTINGS_H
+
+#include "../legacyheaders/typedefs.h"
+
+namespace gmx
+{
+
+class Options;
+class TrajectoryAnalysisRunnerCommon;
+
+/*! \brief
+ * Trajectory analysis module configuration object.
+ *
+ * This class is used by trajectory analysis modules to inform the caller
+ * about the requirements they have on the input (e.g., whether a topology is
+ * required, or whether PBC removal makes sense). It is also used to pass
+ * similar information back to the analysis module after parsing user input.
+ *
+ * Having this functionality as a separate class makes the
+ * TrajectoryAnalysisModule interface much cleaner, and also reduces the need to
+ * change existing code when new options are added.
+ *
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisSettings
+{
+    public:
+        //! Recognized flags.
+        enum
+        {
+            /*! \brief
+             * Forces loading of a topology file.
+             *
+             * If this flag is not specified, the topology file is loaded only
+             * if it is provided on the command line explicitly.
+             */
+            efRequireTop     = 1<<0,
+            /*! \brief
+             * Requests topology coordinates.
+             *
+             * If this flag is specified, the coordinates loaded from the
+             * topology can be accessed, otherwise they are not loaded.
+             *
+             * \see TopologyInformation
+             */
+            efUseTopX        = 1<<1,
+            /*! \brief
+             * Disallows the user from changing PBC handling.
+             *
+             * If this option is not specified, the analysis module (see
+             * TrajectoryAnalysisModule::analyzeFrame()) may be passed a NULL
+             * PBC structure, and it should be able to handle such a situation.
+             *
+             * \see setPBC()
+             */
+            efNoUserPBC      = 1<<4,
+            /*! \brief
+             * Disallows the user from changing PBC removal.
+             *
+             * \see setRmPBC()
+             */
+            efNoUserRmPBC    = 1<<5,
+            /*! \brief
+             * Requests dumps of parsed and compiled selection trees.
+             *
+             * This flag is used by internal debugging tools to request
+             * the selection trees dumping to stderr.
+             */
+            efDebugSelection = 1<<16,
+        };
+
+        //! Initializes default settings.
+        TrajectoryAnalysisSettings();
+        ~TrajectoryAnalysisSettings();
+
+        //! Returns the currently set flags.
+        unsigned long flags() const;
+        //! Tests whether a flag has been set.
+        bool hasFlag(unsigned long flag) const;
+        /*! \brief
+         * Returns whether PBC should be used.
+         *
+         * Returns the value set with setPBC() and/or overridden by the user.
+         * The user-provided value can be accessed in
+         * TrajectoryAnalysisModule::initOptionsDone(), and can be overridden
+         * with a call to setPBC().
+         */
+        bool hasPBC() const;
+        /*! \brief
+         * Returns whether molecules should be made whole.
+         *
+         * See hasPBC() for information on accessing or overriding the
+         * user-provided value.
+         */
+        bool hasRmPBC() const;
+        //! Returns the currently set frame flags.
+        int frflags() const;
+
+        /*! \brief
+         * Sets flags.
+         *
+         * Overrides any earlier set flags.
+         * By default, no flags are set.
+         */
+        void setFlags(unsigned long flags);
+        //! Sets or clears an individual flag.
+        void setFlag(unsigned long flag, bool bSet = true);
+        /*! \brief
+         * Sets whether PBC are used.
+         *
+         * \param[in]  bPBC   TRUE if PBC should be used.
+         *
+         * If called in TrajectoryAnalysisModule::initOptions(), this function
+         * sets the default for whether PBC are used in the analysis.
+         * If ::efNoUserPBC is not set, a command-line option is provided
+         * for the user to override the default value.
+         * If called later, it overrides the setting provided by the user or an
+         * earlier call.
+         *
+         * If this function is not called, the default is to use PBC.
+         *
+         * If PBC are not used, the \p pbc pointer passed to
+         * TrajectoryAnalysisModule::analyzeFrame() is NULL.
+         * The value of the flag can also be accessed with hasPBC().
+         *
+         * \see ::efNoUserPBC
+         */
+        void setPBC(bool bPBC);
+        /*! \brief
+         * Sets whether molecules are made whole.
+         *
+         * \param[in]     bRmPBC TRUE if molecules should be made whole.
+         *
+         * If called in TrajectoryAnalysisModule::initOptions(), this function
+         * sets the default for whether molecules are made whole.
+         * If ::efNoUserRmPBC is not set, a command-line option is provided
+         * for the user to override the default value.
+         * If called later, it overrides the setting provided by the user or an
+         * earlier call.
+         *
+         * If this function is not called, the default is to make molecules
+         * whole.
+         *
+         * The main use of this function is to call it with \c false if your
+         * analysis program does not require whole molecules as this can
+         * increase the performance.
+         * In such a case, you can also specify ::efNoUserRmPBC to not to
+         * confuse the user with an option that would only slow the program
+         * down.
+         *
+         * \see ::efNoUserRmPBC
+         */
+        void setRmPBC(bool bRmPBC);
+        /*! \brief
+         * Sets flags that determine what to read from the trajectory.
+         *
+         * \param[in]     frflags Flags for what to read from the trajectory file.
+         *
+         * If this function is not called, the flags default to TRX_NEED_X.
+         * If the analysis module needs some other information (velocities,
+         * forces), it can call this function to load additional information
+         * from the trajectory.
+         */
+        void setFrameFlags(int frflags);
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        TrajectoryAnalysisSettings(const TrajectoryAnalysisSettings &);
+        void operator =(const TrajectoryAnalysisSettings &);
+
+        friend class TrajectoryAnalysisRunnerCommon;
+};
+
+/*! \brief
+ * Topology information passed to a trajectory analysis module.
+ *
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+class TopologyInformation
+{
+    public:
+        //! Returns true if a topology file was loaded.
+        bool hasTopology() const { return _top != NULL; }
+        //! Returns true if a full topology file was loaded.
+        bool hasFullTopology() const { return _bTop; }
+        //! Returns the loaded topology, or NULL if not loaded.
+        t_topology *topology() const { return _top; }
+        //! Returns the ePBC field from the topology.
+        int ePBC() const { return _ePBC; }
+        /*! \brief
+         * Gets the configuration from the topology.
+         *
+         * \param[out] x     Topology coordinate pointer to initialize.
+         *      (can be NULL, in which case it is not used).
+         * \param[out] box   Box size from the topology file
+         *      (can be NULL, in which case it is not used).
+         *
+         * If TrajectoryAnalysisSettings::efUseTopX has not been specified,
+         * \p x should be NULL.
+         *
+         * The pointer returned in \p *x should not be freed.
+         */
+        void getTopologyConf(rvec **x, matrix box) const;
+
+    private:
+        TopologyInformation();
+        ~TopologyInformation();
+
+        //! The topology structure, or NULL if no topology loaded.
+        t_topology          *_top;
+        //! true if full tpx file was loaded, false otherwise.
+        bool                 _bTop;
+        //! Coordinates from the topology (can be NULL).
+        rvec                *_xtop;
+        //! The box loaded from the topology file.
+        matrix               _boxtop;
+        //! The ePBC field loaded from the topology file.
+        int                  _ePBC;
+
+        // Disallow copy and assign.
+        TopologyInformation(const TopologyInformation &);
+        void operator =(const TopologyInformation &);
+
+        friend class TrajectoryAnalysisRunnerCommon;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp b/src/gromacs/trajectoryanalysis/cmdlinerunner.cpp
new file mode 100644 (file)
index 0000000..bd0aa47
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::TrajectoryAnalysisCommandLineRunner.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <memory>
+
+#include <copyrite.h>
+#include <pbc.h>
+#include <rmpbc.h>
+#include <statutil.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/options/asciihelpwriter.h"
+#include "gromacs/options/cmdlineparser.h"
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/trajectoryanalysis/analysismodule.h"
+#include "gromacs/trajectoryanalysis/analysissettings.h"
+#include "gromacs/trajectoryanalysis/cmdlinerunner.h"
+#include "gromacs/trajectoryanalysis/runnercommon.h"
+
+namespace gmx
+{
+
+/********************************************************************
+ * TrajectoryAnalysisCommandLineRunner::Impl
+ */
+
+class TrajectoryAnalysisCommandLineRunner::Impl
+{
+    public:
+        Impl(TrajectoryAnalysisModule *module);
+        ~Impl();
+
+        void printHelp(const Options &options,
+                       const TrajectoryAnalysisRunnerCommon &common);
+        bool parseOptions(TrajectoryAnalysisSettings *settings,
+                          TrajectoryAnalysisRunnerCommon *common,
+                          SelectionCollection *selections,
+                          Options *options,
+                          int *argc, char *argv[]);
+
+        TrajectoryAnalysisModule *_module;
+        int                     _debugLevel;
+};
+
+
+TrajectoryAnalysisCommandLineRunner::Impl::Impl(
+        TrajectoryAnalysisModule *module)
+    : _module(module), _debugLevel(0)
+{
+}
+
+
+TrajectoryAnalysisCommandLineRunner::Impl::~Impl()
+{
+}
+
+
+void
+TrajectoryAnalysisCommandLineRunner::Impl::printHelp(
+        const Options &options,
+        const TrajectoryAnalysisRunnerCommon &common)
+{
+    TrajectoryAnalysisRunnerCommon::HelpFlags flags = common.helpFlags();
+    if (flags != 0)
+    {
+        AsciiHelpWriter(options)
+            .setShowDescriptions(flags & TrajectoryAnalysisRunnerCommon::efHelpShowDescriptions)
+            .setShowHidden(flags & TrajectoryAnalysisRunnerCommon::efHelpShowHidden)
+            .writeHelp(stderr);
+    }
+}
+
+
+bool
+TrajectoryAnalysisCommandLineRunner::Impl::parseOptions(
+        TrajectoryAnalysisSettings *settings,
+        TrajectoryAnalysisRunnerCommon *common,
+        SelectionCollection *selections,
+        Options *options,
+        int *argc, char *argv[])
+{
+    int rc;
+
+    Options *moduleOptions = _module->initOptions(settings);
+    GMX_RELEASE_ASSERT(moduleOptions != NULL, "Module returned NULL options");
+    Options *commonOptions = common->initOptions();
+    Options *selectionOptions = selections->initOptions();
+
+    options->addSubSection(commonOptions);
+    options->addSubSection(selectionOptions);
+    options->addSubSection(moduleOptions);
+
+    options->globalProperties().setSelectionCollection(selections);
+    commonOptions->addDefaultOptions();
+
+    {
+        CommandLineParser  parser(options);
+        try
+        {
+            parser.parse(argc, argv);
+        }
+        catch (UserInputError &ex)
+        {
+            printHelp(*options, *common);
+            throw;
+        }
+        printHelp(*options, *common);
+        options->finish();
+    }
+
+    if (!common->initOptionsDone())
+    {
+        return false;
+    }
+    _module->initOptionsDone(settings);
+    /*
+    if (rc != 0)
+    {
+        if (rc == eeInconsistentInput)
+        {
+            GMX_ERROR(rc, "Invalid options provided, "
+                          "see above for detailed error messages");
+        }
+        return rc;
+    }
+    */
+
+    common->initIndexGroups(selections);
+
+    // TODO: Check whether the input is a pipe.
+    bool bInteractive = true;
+    selections->parseRequestedFromStdin(bInteractive);
+    common->doneIndexGroups(selections);
+
+    return true;
+}
+
+
+/********************************************************************
+ * TrajectoryAnalysisCommandLineRunner
+ */
+
+TrajectoryAnalysisCommandLineRunner::TrajectoryAnalysisCommandLineRunner(
+        TrajectoryAnalysisModule *module)
+    : _impl(new Impl(module))
+{
+}
+
+
+TrajectoryAnalysisCommandLineRunner::~TrajectoryAnalysisCommandLineRunner()
+{
+    delete _impl;
+}
+
+
+void
+TrajectoryAnalysisCommandLineRunner::setSelectionDebugLevel(int debuglevel)
+{
+    _impl->_debugLevel = 1;
+}
+
+
+int
+TrajectoryAnalysisCommandLineRunner::run(int argc, char *argv[])
+{
+    TrajectoryAnalysisModule *module = _impl->_module;
+    int                       rc;
+
+    CopyRight(stderr, argv[0]);
+
+    SelectionCollection  selections(NULL);
+    selections.setDebugLevel(_impl->_debugLevel);
+
+    TrajectoryAnalysisSettings  settings;
+    TrajectoryAnalysisRunnerCommon  common(&settings);
+
+    Options  options(NULL, NULL);
+    if (!_impl->parseOptions(&settings, &common, &selections, &options,
+                             &argc, argv))
+    {
+        return 0;
+    }
+
+    common.initTopology(&selections);
+    selections.compile();
+
+    const TopologyInformation &topology = common.topologyInformation();
+    module->initAnalysis(topology);
+
+    // Load first frame.
+    common.initFirstFrame();
+    module->initAfterFirstFrame(common.frame());
+
+    t_pbc  pbc;
+    t_pbc *ppbc = settings.hasPBC() ? &pbc : NULL;
+
+    int nframes = 0;
+    std::auto_ptr<TrajectoryAnalysisModuleData>
+        pdata(module->startFrames(NULL, selections));
+    do
+    {
+        common.initFrame();
+        t_trxframe &frame = common.frame();
+        if (ppbc != NULL)
+        {
+            set_pbc(ppbc, topology.ePBC(), frame.box);
+        }
+
+        selections.evaluate(&frame, ppbc);
+        module->analyzeFrame(nframes, frame, ppbc, pdata.get());
+
+        nframes++;
+    }
+    while (common.readNextFrame());
+    module->finishFrames(pdata.get());
+    if (pdata.get() != NULL)
+    {
+        pdata->finish();
+    }
+    pdata.reset();
+
+    if (common.hasTrajectory())
+    {
+        fprintf(stderr, "Analyzed %d frames, last time %.3f\n",
+                nframes, common.frame().time);
+    }
+    else
+    {
+        fprintf(stderr, "Analyzed topology coordinates\n");
+    }
+
+    // Restore the maximal groups for dynamic selections.
+    selections.evaluateFinal(nframes);
+
+    module->finishAnalysis(nframes);
+    module->writeOutput();
+
+    return 0;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/cmdlinerunner.h b/src/gromacs/trajectoryanalysis/cmdlinerunner.h
new file mode 100644 (file)
index 0000000..a43554b
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::TrajectoryAnalysisCommandLineRunner.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_CMDLINERUNNER_H
+#define GMX_TRAJECTORYANALYSIS_CMDLINERUNNER_H
+
+namespace gmx
+{
+
+class TrajectoryAnalysisModule;
+
+/*! \brief
+ * Runner class for command-line analysis tools.
+ *
+ * This class implements a command-line analysis program, given a
+ * TrajectoryAnalysisModule object.  It takes care of converting command-line
+ * parameters to a form understood by the module, as well as parsing common
+ * options, initializing and evaluating selections, and looping over trajectory
+ * frames.
+ *
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisCommandLineRunner
+{
+    public:
+        /*! \brief
+         * Create a new runner with the provided module.
+         *
+         * The caller should ensure that the provided module is not destroyed
+         * while the runner exists.
+         */
+        TrajectoryAnalysisCommandLineRunner(TrajectoryAnalysisModule *module);
+        ~TrajectoryAnalysisCommandLineRunner();
+
+        /*! \brief
+         * Sets the default debugging level for selections.
+         *
+         * This is intended only for use by internal debugging tools.
+         *
+         * \see SelectionCollection::setDebugLevel()
+         */
+        void setSelectionDebugLevel(int debuglevel);
+        /*! \brief
+         * Parses options from the given command line and runs the analysis.
+         */
+        int run(int argc, char *argv[]);
+
+    private:
+        class Impl;
+
+        Impl                *_impl;
+
+        // Disallow copy and assign.
+        TrajectoryAnalysisCommandLineRunner(const TrajectoryAnalysisCommandLineRunner &);
+        void operator =(const TrajectoryAnalysisCommandLineRunner &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/modules.cpp b/src/gromacs/trajectoryanalysis/modules.cpp
new file mode 100644 (file)
index 0000000..326f049
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements createTrajectoryAnalysisModule().
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#include "gromacs/trajectoryanalysis/modules.h"
+
+#include <string2.h>
+
+#include "modules/angle.h"
+#include "modules/distance.h"
+#include "modules/select.h"
+
+namespace
+{
+
+using namespace gmx::analysismodules;
+
+struct module_map_t
+{
+    const char                         *name;
+    gmx::TrajectoryAnalysisModule      *(*creator)(void);
+};
+
+const module_map_t modules[] =
+{
+    {gmx::analysismodules::angle,    Angle::create},
+    {gmx::analysismodules::distance, Distance::create},
+    {gmx::analysismodules::select,   Select::create},
+    {NULL,                           NULL},
+};
+
+} // namespace
+
+namespace gmx
+{
+
+TrajectoryAnalysisModule *createTrajectoryAnalysisModule(const char *name)
+{
+    size_t len = strlen(name);
+    int match_i = -1;
+
+    for (int i = 0; modules[i].name != NULL; ++i)
+    {
+        if (strncasecmp(name, modules[i].name, len) == 0)
+        {
+            if (strlen(modules[i].name) == len)
+            {
+                match_i = i;
+                break;
+            }
+            else if (match_i == -1)
+            {
+                match_i = i;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+    }
+    if (match_i != -1)
+    {
+        return modules[match_i].creator();
+    }
+    return NULL;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/modules.h b/src/gromacs/trajectoryanalysis/modules.h
new file mode 100644 (file)
index 0000000..0ee6c8f
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Generic interface for creation of trajectory analysis modules.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_MODULES_H
+#define GMX_TRAJECTORYANALYSIS_MODULES_H
+
+namespace gmx
+{
+
+class TrajectoryAnalysisModule;
+
+/*! \brief
+ * Creates a TrajectoryAnalysisModule object corresponding to a name.
+ *
+ * \param[in]  name  Name of the module to create (recognized names are
+ *      defined in modules.h).
+ * \returns  An allocated TrajectoryAnalysisModule object, or NULL if \p name
+ *      is not valid.
+ *
+ * This function should be used to instantiate selection methods defined in the
+ * library.
+ *
+ * In addition to recognizing exact matches on \p name, the function also
+ * identifies cases where \p name is a prefix of exactly one recognized name
+ * (exact matches always take precedence).
+ *
+ * \inpublicapi
+ */
+TrajectoryAnalysisModule *createTrajectoryAnalysisModule(const char *name);
+
+namespace analysismodules
+{
+
+static const char * const angle    = "angle";
+static const char * const distance = "distance";
+static const char * const select   = "select";
+
+} // namespace modules
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/modules/angle.cpp b/src/gromacs/trajectoryanalysis/modules/angle.cpp
new file mode 100644 (file)
index 0000000..e8ea63c
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::analysismodules::Angle.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#include "angle.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pbc.h>
+#include <vec.h>
+
+// FIXME: This kind of hackery should not be necessary
+#undef min
+#undef max
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/analysisdata/modules/plot.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectionoption.h"
+#include "gromacs/utility/format.h"
+
+namespace gmx
+{
+
+namespace analysismodules
+{
+
+Angle::Angle()
+    : _options("angle", "Angle calculation"),
+      _sel1Adj(NULL), _sel2Adj(NULL),
+      _bSplit1(false), _bSplit2(false), _bMulti(false), _bAll(false),
+      _bDumpDist(false), _vt0(NULL)
+{
+}
+
+
+Angle::~Angle()
+{
+    delete[] _vt0;
+}
+
+
+Options *
+Angle::initOptions(TrajectoryAnalysisSettings *settings)
+{
+    static const char *const desc[] = {
+        "g_angle computes different types of angles between vectors.",
+        "It supports both vectors defined by two positions and normals of",
+        "planes defined by three positions.",
+        "The z axis or the local normal of a sphere can also be used as",
+        "one of the vectors.",
+        "There are also convenience options 'angle' and 'dihedral' for",
+        "calculating bond angles and dihedrals defined by three/four",
+        "positions.[PAR]",
+        "The type of the angle is specified with [TT]-g1[tt] and [TT]-g2[tt].",
+        "If [TT]-g1[tt] is [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]",
+        "should not be specified.",
+        "In this case, one selection is required, and it should contain",
+        "triplets or quartets of positions that define the angles to be",
+        "calculated.",
+        "If [TT]-g1[tt] is not [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]",
+        "should not be [TT]none[tt], and the two options define two vectors",
+        "for the calculation. For vectors ([TT]vector[tt]), a selection with",
+        "pairs of positions is required, and for planes ([TT]plane[tt]),",
+        "triplets of positions are required.",
+        "If both vectors are specified by positions, the number of vectors",
+        "should be the same in both selections.",
+        "[TT]-g2 sphnorm[tt] requires a reference selection that defines",
+        "the center of the sphere.",
+        "[TT]-g2 z[tt] does not require any selection.[PAR]",
+        "With [TT]-split1[tt], the positions for [TT]-g1[tt] are specified",
+        "using N separate selections with M positions each, instead of the",
+        "default M*N positions in one selection.",
+        "[TT]-split2[tt] does the same for [TT]-g2[tt].[PAR]",
+        "There are two options for output:",
+        "[TT]-o[tt] writes an xvgr file with the time and the average angle",
+        "for each frame.",
+        "With [TT]-all[tt], also the individual angles are written (only",
+        "supported for static selections).",
+        "[TT]-od[tt] can be used to dump all the individual angles,",
+        "each on a separate line. This format is better suited for",
+        "further processing, e.g., if angles from multiple runs are needed.",
+        NULL
+    };
+    static const char *const cGroup1TypeEnum[] =
+        { "angle", "dihedral", "vector", "plane", NULL };
+    static const char *const cGroup2TypeEnum[] =
+        { "none", "vector", "plane", "t0", "z", "sphnorm", NULL };
+
+    _options.setDescription(desc);
+
+    _options.addOption(FileNameOption("o").filetype(eftPlot).writeOnly()
+                           .store(&_fnAngle).defaultValueIfSet("angle"));
+    _options.addOption(FileNameOption("od").filetype(eftPlot).writeOnly()
+                           .store(&_fnDump).defaultValueIfSet("angdump"));
+
+    _options.addOption(StringOption("g1").enumValue(cGroup1TypeEnum)
+        .defaultEnumIndex(0).store(&_g1type)
+        .description("Type of analysis/first vector group"));
+    _options.addOption(StringOption("g2").enumValue(cGroup2TypeEnum)
+        .defaultEnumIndex(0).store(&_g2type)
+        .description("Type of second vector group"));
+    _options.addOption(BooleanOption("split1").store(&_bSplit1)
+        .description("Each position of first group in separate selection"));
+    _options.addOption(BooleanOption("split2").store(&_bSplit2)
+        .description("Each position of second group in separate selection"));
+    _options.addOption(BooleanOption("multi").store(&_bMulti)
+        .description("Analyze multiple sets of angles/dihedrals"));
+    _options.addOption(BooleanOption("all").store(&_bAll)
+        .description("Print individual angles together with the average"));
+    _options.addOption(BooleanOption("dumpd").store(&_bDumpDist)
+        .description("Write also distances with -od"));
+
+    _options.addOption(SelectionOption("group1").multiValue().required()
+        .dynamicOnlyWhole().storeVector(&_sel1).getAdjuster(&_sel1Adj)
+        .description("First analysis/vector selection"));
+    _options.addOption(SelectionOption("group2").multiValue()
+        .dynamicOnlyWhole().storeVector(&_sel2).getAdjuster(&_sel2Adj)
+        .description("Second analysis/vector selection"));
+
+    return &_options;
+}
+
+
+void
+Angle::initOptionsDone(TrajectoryAnalysisSettings *settings)
+{
+    // Validity checks.
+    bool bSingle = (_g1type[0] == 'a' || _g1type[0] == 'd');
+
+    if (bSingle && _g2type[0] != 'n')
+    {
+        GMX_THROW(InconsistentInputError("Cannot use a second group (-g2) with "
+                                         "-g1 angle or dihedral"));
+    }
+    if (bSingle && _options.isSet("group2"))
+    {
+        GMX_THROW(InconsistentInputError("Cannot provide a second selection "
+                                         "(-group2) with -g1 angle or dihedral"));
+    }
+    if (!bSingle && _g2type[0] == 'n')
+    {
+        GMX_THROW(InconsistentInputError("Should specify a second group (-g2) "
+                                         "if the first group is not an angle or a dihedral"));
+    }
+    if (bSingle && _bDumpDist)
+    {
+        GMX_THROW(InconsistentInputError("Cannot calculate distances with -g1 angle or dihedral"));
+        // _bDumpDist = false;
+    }
+    if (_bMulti && !bSingle)
+    {
+        GMX_THROW(InconsistentInputError("-mult can only be combined with -g1 angle or dihedral"));
+    }
+    if (_bMulti && _bSplit1)
+    {
+        GMX_THROW(InconsistentInputError("-mult can not be combined with -split1"));
+    }
+    if (_bMulti && _bAll)
+    {
+        GMX_THROW(InconsistentInputError("-mult and -all are mutually exclusive options"));
+    }
+
+    if (_bAll)
+    {
+        _sel1Adj->setOnlyStatic(true);
+    }
+
+    // Set up the number of positions per angle.
+    switch (_g1type[0])
+    {
+        case 'a': _natoms1 = 3; break;
+        case 'd': _natoms1 = 4; break;
+        case 'v': _natoms1 = 2; break;
+        case 'p': _natoms1 = 3; break;
+        default:
+            GMX_THROW(InternalError("invalid -g1 value"));
+    }
+    switch (_g2type[0])
+    {
+        case 'n': _natoms2 = 0; break;
+        case 'v': _natoms2 = 2; break;
+        case 'p': _natoms2 = 3; break;
+        case 't': _natoms2 = 0; break;
+        case 'z': _natoms2 = 0; break;
+        case 's': _natoms2 = 1; break;
+        default:
+            GMX_THROW(InternalError("invalid -g2 value"));
+    }
+    if (_natoms2 == 0 && _options.isSet("group2"))
+    {
+        GMX_THROW(InconsistentInputError("Cannot provide a second selection (-group2) with -g2 t0 or z"));
+    }
+
+    if (!_bMulti)
+    {
+        _sel1Adj->setValueCount(_bSplit1 ? _natoms1 : 1);
+    }
+    if (_natoms2 > 0)
+    {
+        _sel2Adj->setValueCount(_bSplit2 ? _natoms2 : 1);
+    }
+}
+
+
+void
+Angle::checkSelections(const std::vector<Selection *> &sel1,
+                       const std::vector<Selection *> &sel2) const
+{
+    if (_bMulti)
+    {
+        for (size_t g = 0; g < sel1.size(); ++g)
+        {
+            if (sel1[g]->posCount() % _natoms1 != 0)
+            {
+                GMX_THROW(InconsistentInputError(formatString(
+                    "Number of positions in selection %d not divisible by %d",
+                    static_cast<int>(g + 1), _natoms1)));
+            }
+        }
+        return;
+    }
+
+    int na1 = sel1[0]->posCount();
+    int na2 = (_natoms2 > 0) ? sel2[0]->posCount() : 0;
+
+    if (!_bSplit1 && _natoms1 > 1 && na1 % _natoms1 != 0)
+    {
+        GMX_THROW(InconsistentInputError(formatString(
+            "Number of positions in the first group not divisible by %d",
+            _natoms1)));
+    }
+    if (!_bSplit2 && _natoms2 > 1 && na2 % _natoms2 != 0)
+    {
+        GMX_THROW(InconsistentInputError(formatString(
+            "Number of positions in the second group not divisible by %d",
+            _natoms2)));
+    }
+
+    if (_bSplit1)
+    {
+        for (int g = 1; g < _natoms1; ++g)
+        {
+            if (sel1[g]->posCount() != na1)
+            {
+                GMX_THROW(InconsistentInputError(
+                          "All selections in the first group should contain "
+                          "the same number of positions"));
+            }
+        }
+    }
+    else
+    {
+        na1 /= _natoms1;
+    }
+    if (_natoms2 > 1)
+    {
+        if (_bSplit2)
+        {
+            for (int g = 1; g < _natoms2; ++g)
+            {
+                if (sel2[g]->posCount() != na2)
+                {
+                    GMX_THROW(InconsistentInputError(
+                              "All selections in the second group should contain "
+                              "the same number of positions"));
+                }
+            }
+        }
+        else
+        {
+            na2 /= _natoms2;
+        }
+    }
+    if (_natoms1 > 0 && _natoms2 > 1 && na1 != na2)
+    {
+        GMX_THROW(InconsistentInputError(
+                  "Number of vectors defined by the two groups are not the same"));
+    }
+    if (_g2type[0] == 's' && sel2[0]->posCount() != 1)
+    {
+        GMX_THROW(InconsistentInputError(
+                  "The second group should contain a single position with -g2 sphnorm"));
+    }
+}
+
+
+void
+Angle::initAnalysis(const TopologyInformation &top)
+{
+    checkSelections(_sel1, _sel2);
+
+    if (_bMulti)
+    {
+        _data.setColumns(_sel1.size());
+    }
+    else if (_bAll)
+    {
+        int na = _sel1[0]->posCount();
+        if (!_bSplit1)
+        {
+            na /= _natoms1;
+        }
+        _data.setColumns(na + 1);
+    }
+    else
+    {
+        _data.setColumns(1);
+    }
+
+    if (_g2type == "t0")
+    {
+        int na = _sel1[0]->posCount();
+        if (!_bSplit1)
+        {
+            na /= _natoms1;
+        }
+        _vt0 = new rvec[na];
+    }
+
+    registerAnalysisDataset(&_data, "angle");
+
+    AnalysisDataPlotModule *plotm = new AnalysisDataPlotModule(_options);
+    plotm->setFileName(_fnAngle);
+    plotm->setTitle("Angle");
+    plotm->setXTimeLabel();
+    plotm->setYLabel("Angle [degrees]");
+    _data.addModule(plotm);
+}
+
+
+static void
+copy_pos(const std::vector<Selection *> &sel, bool bSplit, int natoms,
+         int firstg, int first, rvec x[])
+{
+    if (bSplit)
+    {
+        for (int k = 0; k < natoms; ++k)
+        {
+            copy_rvec(sel[firstg + k]->x(first), x[k]);
+        }
+    }
+    else
+    {
+        for (int k = 0; k < natoms; ++k)
+        {
+            copy_rvec(sel[firstg]->x(first + k), x[k]);
+        }
+    }
+}
+
+
+static void
+calc_vec(int natoms, rvec x[], t_pbc *pbc, rvec xout, rvec cout)
+{
+    switch (natoms)
+    {
+        case 2:
+            if (pbc)
+            {
+                pbc_dx(pbc, x[1], x[0], xout);
+            }
+            else
+            {
+                rvec_sub(x[1], x[0], xout);
+            }
+            svmul(0.5, xout, cout);
+            rvec_add(x[0], cout, cout);
+            break;
+        case 3: {
+            rvec v1, v2;
+            if (pbc)
+            {
+                pbc_dx(pbc, x[1], x[0], v1);
+                pbc_dx(pbc, x[2], x[0], v2);
+            }
+            else
+            {
+                rvec_sub(x[1], x[0], v1);
+                rvec_sub(x[2], x[0], v2);
+            }
+            cprod(v1, v2, xout);
+            rvec_add(x[0], x[1], cout);
+            rvec_add(cout, x[2], cout);
+            svmul(1.0/3.0, cout, cout);
+            break;
+        }
+    }
+}
+
+
+void
+Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                    TrajectoryAnalysisModuleData *pdata)
+{
+    AnalysisDataHandle *dh = pdata->dataHandle("angle");
+    std::vector<Selection *> sel1 = pdata->parallelSelections(_sel1);
+    std::vector<Selection *> sel2 = pdata->parallelSelections(_sel2);
+
+    checkSelections(sel1, sel2);
+
+    rvec  v1, v2;
+    rvec  c1, c2;
+    switch (_g2type[0])
+    {
+        case 'z':
+            clear_rvec(v2);
+            v2[ZZ] = 1.0;
+            clear_rvec(c2);
+            break;
+        case 's':
+            copy_rvec(_sel2[0]->x(0), c2);
+            break;
+    }
+
+    dh->startFrame(frnr, fr.time);
+
+    int incr1 = _bSplit1 ? 1 : _natoms1;
+    int incr2 = _bSplit2 ? 1 : _natoms2;
+    int ngrps = _bMulti ? _sel1.size() : 1;
+
+    for (int g = 0; g < ngrps; ++g)
+    {
+        real ave = 0.0;
+        int n = 0;
+        int i, j;
+        for (i = j = 0; i < sel1[g]->posCount(); i += incr1)
+        {
+            rvec x[4];
+            real angle;
+            copy_pos(sel1, _bSplit1, _natoms1, g, i, x);
+            switch (_g1type[0])
+            {
+                case 'a':
+                    if (pbc)
+                    {
+                        pbc_dx(pbc, x[0], x[1], v1);
+                        pbc_dx(pbc, x[2], x[1], v2);
+                    }
+                    else
+                    {
+                        rvec_sub(x[0], x[1], v1);
+                        rvec_sub(x[2], x[1], v2);
+                    }
+                    angle = gmx_angle(v1, v2);
+                    break;
+                case 'd': {
+                    rvec dx[3];
+                    if (pbc)
+                    {
+                        pbc_dx(pbc, x[0], x[1], dx[0]);
+                        pbc_dx(pbc, x[2], x[1], dx[1]);
+                        pbc_dx(pbc, x[2], x[3], dx[2]);
+                    }
+                    else
+                    {
+                        rvec_sub(x[0], x[1], dx[0]);
+                        rvec_sub(x[2], x[1], dx[1]);
+                        rvec_sub(x[2], x[3], dx[2]);
+                    }
+                    cprod(dx[0], dx[1], v1);
+                    cprod(dx[1], dx[2], v2);
+                    angle = gmx_angle(v1, v2);
+                    real ipr = iprod(dx[0], v2);
+                    if (ipr < 0)
+                    {
+                        angle = -angle;
+                    }
+                    break;
+                }
+                case 'v':
+                case 'p':
+                    calc_vec(_natoms1, x, pbc, v1, c1);
+                    switch (_g2type[0])
+                    {
+                        case 'v':
+                        case 'p':
+                            copy_pos(sel2, _bSplit2, _natoms2, 0, j, x);
+                            calc_vec(_natoms2, x, pbc, v2, c2);
+                            j += incr2;
+                            break;
+                        case 't':
+                            // FIXME: This is not parallelizable.
+                            if (frnr == 0)
+                            {
+                                copy_rvec(v1, _vt0[n]);
+                            }
+                            copy_rvec(_vt0[n], v2);
+                            break;
+                        case 'z':
+                            c1[XX] = c1[YY] = 0.0;
+                            break;
+                        case 's':
+                            if (pbc)
+                            {
+                                pbc_dx(pbc, c1, c2, v2);
+                            }
+                            else
+                            {
+                                rvec_sub(c1, c2, v2);
+                            }
+                            break;
+                        default:
+                            GMX_THROW(InternalError("invalid -g2 value"));
+                    }
+                    angle = gmx_angle(v1, v2);
+                    break;
+                default:
+                    GMX_THROW(InternalError("invalid -g1 value"));
+            }
+            angle *= RAD2DEG;
+            real dist = 0.0;
+            if (_bDumpDist)
+            {
+                if (pbc)
+                {
+                    rvec dx;
+                    pbc_dx(pbc, c2, c1, dx);
+                    dist = norm(dx);
+                }
+                else
+                {
+                    dist = sqrt(distance2(c1, c2));
+                }
+            }
+            if (_bAll)
+            {
+                dh->addPoint(n + 1, angle);
+            }
+            ave += angle;
+            ++n;
+        }
+        if (n > 0)
+        {
+            ave /= n;
+        }
+        dh->addPoint(g, ave);
+    }
+    dh->finishFrame();
+}
+
+
+void
+Angle::finishAnalysis(int /*nframes*/)
+{
+}
+
+
+void
+Angle::writeOutput()
+{
+}
+
+
+TrajectoryAnalysisModule *
+Angle::create()
+{
+    return new Angle();
+}
+
+} // namespace modules
+
+} // namespace gmxana
diff --git a/src/gromacs/trajectoryanalysis/modules/angle.h b/src/gromacs/trajectoryanalysis/modules/angle.h
new file mode 100644 (file)
index 0000000..583fdd9
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares trajectory analysis module for angle calculations.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_MODULES_ANGLE_H
+#define GMX_TRAJECTORYANALYSIS_MODULES_ANGLE_H
+
+#include <string>
+#include <vector>
+
+#include "../analysismodule.h"
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/options/options.h"
+
+namespace gmx
+{
+
+class Selection;
+class SelectionOptionAdjuster;
+
+namespace analysismodules
+{
+
+class Angle : public TrajectoryAnalysisModule
+{
+    public:
+        Angle();
+        virtual ~Angle();
+
+        static TrajectoryAnalysisModule *create();
+
+        virtual Options *initOptions(TrajectoryAnalysisSettings *settings);
+        virtual void initOptionsDone(TrajectoryAnalysisSettings *settings);
+        virtual void initAnalysis(const TopologyInformation &top);
+
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata);
+
+        virtual void finishAnalysis(int nframes);
+        virtual void writeOutput();
+
+    private:
+        void checkSelections(const std::vector<Selection *> &sel1,
+                             const std::vector<Selection *> &sel2) const;
+
+        Options                 _options;
+
+        std::vector<Selection *> _sel1;
+        std::vector<Selection *> _sel2;
+        SelectionOptionAdjuster *_sel1Adj;
+        SelectionOptionAdjuster *_sel2Adj;
+        std::string             _fnAngle;
+        std::string             _fnDump;
+
+        std::string             _g1type;
+        std::string             _g2type;
+        bool                    _bSplit1;
+        bool                    _bSplit2;
+        bool                    _bMulti;
+        bool                    _bAll;
+        bool                    _bDumpDist;
+
+        AnalysisData            _data;
+        int                     _natoms1;
+        int                     _natoms2;
+        rvec                   *_vt0;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace analysismodules
+
+} // namespace gmxana
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/modules/distance.cpp b/src/gromacs/trajectoryanalysis/modules/distance.cpp
new file mode 100644 (file)
index 0000000..78cabf5
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::analysismodules::Distance.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#include "distance.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pbc.h>
+#include <vec.h>
+
+// FIXME: This kind of hackery should not be necessary
+#undef min
+#undef max
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/analysisdata/modules/average.h"
+#include "gromacs/analysisdata/modules/plot.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectionoption.h"
+
+namespace gmx
+{
+
+namespace analysismodules
+{
+
+Distance::Distance()
+    : _options("distance", "Distance calculation")
+{
+    _sel[0] = _sel[1] = NULL;
+}
+
+
+Distance::~Distance()
+{
+}
+
+
+Options *
+Distance::initOptions(TrajectoryAnalysisSettings *settings)
+{
+    static const char *const desc[] = {
+        "g_dist can calculate the distance between two positions as",
+        "a function of time. The total distance and its",
+        "x, y and z components are plotted.",
+        NULL
+    };
+
+    _options.setDescription(desc);
+
+    _options.addOption(FileNameOption("o").filetype(eftPlot).writeOnly()
+                           .store(&_fnDist).defaultValue("dist"));
+    _options.addOption(SelectionOption("select").required().valueCount(2)
+                           .store(_sel));
+    return &_options;
+}
+
+
+void
+Distance::initAnalysis(const TopologyInformation & /*top*/)
+{
+    if (_sel[0]->posCount() != 1)
+    {
+        GMX_THROW(InvalidInputError("The first selection does not define a single position"));
+    }
+    if (_sel[1]->posCount() != 1)
+    {
+        GMX_THROW(InvalidInputError("The second selection does not define a single position"));
+    }
+    _data.setColumns(4);
+    registerAnalysisDataset(&_data, "distance");
+
+    _avem = new AnalysisDataAverageModule();
+    _data.addModule(_avem);
+
+    _plotm = new AnalysisDataPlotModule(_options);
+    _plotm->setFileName(_fnDist);
+    _plotm->setTitle("Distance");
+    _plotm->setXLabel("Time [ps]");
+    _plotm->setYLabel("Distance [nm]");
+    _data.addModule(_plotm);
+}
+
+
+void
+Distance::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                       TrajectoryAnalysisModuleData *pdata)
+{
+    AnalysisDataHandle *dh = pdata->dataHandle("distance");
+    Selection          *sel1 = pdata->parallelSelection(_sel[0]);
+    Selection          *sel2 = pdata->parallelSelection(_sel[1]);
+    rvec                dx;
+    real                r;
+
+    if (pbc != NULL)
+    {
+        pbc_dx(pbc, sel1->x(0), sel2->x(0), dx);
+    }
+    else
+    {
+        rvec_sub(sel1->x(0), sel2->x(0), dx);
+    }
+    r = norm(dx);
+    dh->startFrame(frnr, fr.time);
+    dh->addPoint(0, r);
+    dh->addPoints(1, 3, dx);
+    dh->finishFrame();
+}
+
+
+void
+Distance::finishAnalysis(int /*nframes*/)
+{
+}
+
+
+void
+Distance::writeOutput()
+{
+    const real *ave;
+
+    _avem->getData(0, NULL, &ave, NULL);
+    fprintf(stderr, "Average distance: %f\n", ave[0]);
+    fprintf(stderr, "Std. deviation:   %f\n", ave[1]);
+}
+
+
+TrajectoryAnalysisModule *
+Distance::create()
+{
+    return new Distance();
+}
+
+} // namespace analysismodules
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/modules/distance.h b/src/gromacs/trajectoryanalysis/modules/distance.h
new file mode 100644 (file)
index 0000000..c8e42c2
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares trajectory analysis module for distance calculations.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_MODULES_DISTANCE_H
+#define GMX_TRAJECTORYANALYSIS_MODULES_DISTANCE_H
+
+#include <string>
+#include <vector>
+
+#include "../analysismodule.h"
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/options/options.h"
+
+namespace gmx
+{
+
+class AnalysisDataAverageModule;
+class AnalysisDataPlotModule;
+class Selection;
+
+namespace analysismodules
+{
+
+class Distance : public TrajectoryAnalysisModule
+{
+    public:
+        Distance();
+        virtual ~Distance();
+
+        static TrajectoryAnalysisModule *create();
+
+        virtual Options *initOptions(TrajectoryAnalysisSettings *settings);
+        virtual void initAnalysis(const TopologyInformation &top);
+
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata);
+
+        virtual void finishAnalysis(int nframes);
+        virtual void writeOutput();
+
+    private:
+        Options                         _options;
+        std::string                     _fnDist;
+        Selection                      *_sel[2];
+        AnalysisData                    _data;
+        AnalysisDataAverageModule      *_avem;
+        AnalysisDataPlotModule         *_plotm;
+
+        // Copy and assign disallowed by base.
+};
+
+} // namespace analysismodules
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/modules/select.cpp b/src/gromacs/trajectoryanalysis/modules/select.cpp
new file mode 100644 (file)
index 0000000..af73874
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::analysismodules::Select.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#include "select.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <algorithm>
+#include <cstdio>
+#include <string>
+#include <vector>
+
+#include <gmxfio.h>
+#include <smalloc.h>
+
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/analysisdata/datamodule.h"
+#include "gromacs/analysisdata/modules/plot.h"
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selectionoption.h"
+#include "gromacs/trajectoryanalysis/analysissettings.h"
+#include "gromacs/utility/format.h"
+
+namespace gmx
+{
+
+namespace analysismodules
+{
+
+/*! \internal \brief
+ * Data module for writing index files.
+ *
+ * \ingroup module_analysisdata
+ */
+class IndexFileWriterModule : public AnalysisDataModuleInterface
+{
+    public:
+        IndexFileWriterModule();
+        virtual ~IndexFileWriterModule();
+
+        void setFileName(const std::string &fnm);
+        void addGroup(const std::string &name, bool bDynamic);
+
+        virtual int flags() const;
+
+        virtual void dataStarted(AbstractAnalysisData *data);
+        virtual void frameStarted(real x, real dx);
+        virtual void pointsAdded(real x, real dx, int firstcol, int n,
+                                 const real *y, const real *dy,
+                                 const bool *present);
+        virtual void frameFinished();
+        virtual void dataFinished();
+
+    private:
+        void closeFile();
+
+        struct GroupInfo
+        {
+            GroupInfo(const std::string &name, bool bDynamic)
+                : name(name), bDynamic(bDynamic)
+            { }
+
+            std::string         name;
+            bool                bDynamic;
+        };
+
+        std::string             _fnm;
+        std::vector<GroupInfo>  _groups;
+        FILE                   *_fp;
+        int                     _framenr;
+        int                     _currentGroup;
+        int                     _currentSize;
+        bool                    _bAnyWritten;
+};
+
+/********************************************************************
+ * IndexFileWriterModule
+ */
+
+IndexFileWriterModule::IndexFileWriterModule() : _fp(NULL), _framenr(0)
+{
+}
+
+
+IndexFileWriterModule::~IndexFileWriterModule()
+{
+    closeFile();
+}
+
+
+void IndexFileWriterModule::closeFile()
+{
+    if (_fp != NULL)
+    {
+        gmx_fio_fclose(_fp);
+        _fp = NULL;
+    }
+}
+
+
+void IndexFileWriterModule::setFileName(const std::string &fnm)
+{
+    _fnm = fnm;
+}
+
+
+void IndexFileWriterModule::addGroup(const std::string &name, bool bDynamic)
+{
+    std::string newName(name);
+    std::replace(newName.begin(), newName.end(), ' ', '_');
+    _groups.push_back(GroupInfo(newName, bDynamic));
+}
+
+
+int IndexFileWriterModule::flags() const
+{
+    return efAllowMulticolumn | efAllowMultipoint;
+}
+
+
+void IndexFileWriterModule::dataStarted(AbstractAnalysisData * /*data*/)
+{
+    if (!_fnm.empty())
+    {
+        _fp = gmx_fio_fopen(_fnm.c_str(), "w");
+    }
+}
+
+
+void IndexFileWriterModule::frameStarted(real /*x*/, real /*dx*/)
+{
+    _bAnyWritten = false;
+    _currentGroup = -1;
+}
+
+
+void
+IndexFileWriterModule::pointsAdded(real x, real /*dx*/, int firstcol, int n,
+                                   const real *y, const real * /*dy*/,
+                                   const bool * /*present*/)
+{
+    if (_fp == NULL)
+    {
+        return;
+    }
+    if (firstcol == 0)
+    {
+        ++_currentGroup;
+        if (_framenr == 0 || _groups[_currentGroup].bDynamic)
+        {
+            if (_framenr > 0 || _currentGroup > 0)
+            {
+                std::fprintf(_fp, "\n\n");
+            }
+            std::string name = _groups[_currentGroup].name;
+            if (_groups[_currentGroup].bDynamic)
+            {
+                name += formatString("_f%d_t%.3f", _framenr, x);
+            }
+            std::fprintf(_fp, "[ %s ]", name.c_str());
+            _bAnyWritten = true;
+            _currentSize = 0;
+        }
+    }
+    else
+    {
+        if (_framenr == 0 || _groups[_currentGroup].bDynamic)
+        {
+            if (_currentSize % 15 == 0)
+            {
+                std::fprintf(_fp, "\n");
+            }
+            std::fprintf(_fp, "%4d ", static_cast<int>(y[0]));
+            ++_currentSize;
+        }
+    }
+}
+
+
+void IndexFileWriterModule::frameFinished()
+{
+    ++_framenr;
+}
+
+
+void IndexFileWriterModule::dataFinished()
+{
+    if (_fp != NULL)
+    {
+        std::fprintf(_fp, "\n");
+    }
+    closeFile();
+}
+
+
+/********************************************************************
+ * Select::ModuleData
+ */
+
+class Select::ModuleData : public TrajectoryAnalysisModuleData
+{
+    public:
+        ModuleData(TrajectoryAnalysisModule *module,
+                   AnalysisDataParallelOptions opt,
+                   const SelectionCollection &selections)
+            : TrajectoryAnalysisModuleData(module, opt, selections),
+              _mmap(NULL)
+        {
+        }
+
+        virtual ~ModuleData()
+        {
+            if (_mmap)
+            {
+                gmx_ana_indexmap_deinit(_mmap);
+                sfree(_mmap);
+            }
+        }
+
+        virtual void finish()
+        {
+            finishDataHandles();
+        }
+
+        gmx_ana_indexmap_t  *_mmap;
+};
+
+
+/********************************************************************
+ * Select
+ */
+
+Select::Select()
+    : _options("select", "Selection information"),
+      _bDump(false), _bTotNorm(false), _bFracNorm(false), _bResInd(false)
+{
+}
+
+
+Select::~Select()
+{
+}
+
+
+Options *
+Select::initOptions(TrajectoryAnalysisSettings *settings)
+{
+    static const char *const desc[] = {
+        "[TT]g_select[tt] writes out basic data about dynamic selections.",
+        "It can be used for some simple analyses, or the output can",
+        "be combined with output from other programs and/or external",
+        "analysis programs to calculate more complex things.",
+        "Any combination of the output options is possible, but note",
+        "that [TT]-om[tt] only operates on the first selection.[PAR]",
+        "With [TT]-os[tt], calculates the number of positions in each",
+        "selection for each frame. With [TT]-norm[tt], the output is",
+        "between 0 and 1 and describes the fraction from the maximum",
+        "number of positions (e.g., for selection 'resname RA and x < 5'",
+        "the maximum number of positions is the number of atoms in",
+        "RA residues). With [TT]-cfnorm[tt], the output is divided",
+        "by the fraction covered by the selection.",
+        "[TT]-norm[tt] and [TT]-cfnorm[tt] can be specified independently",
+        "of one another.[PAR]",
+        "With [TT]-oc[tt], the fraction covered by each selection is",
+        "written out as a function of time.[PAR]",
+        "With [TT]-oi[tt], the selected atoms/residues/molecules are",
+        "written out as a function of time. In the output, the first",
+        "column contains the frame time, the second contains the number",
+        "of positions, followed by the atom/residue/molecule numbers.",
+        "If more than one selection is specified, the size of the second",
+        "group immediately follows the last number of the first group",
+        "and so on. With [TT]-dump[tt], the frame time and the number",
+        "of positions is omitted from the output. In this case, only one",
+        "selection can be given.[PAR]",
+        "With [TT]-on[tt], the selected atoms are written as a index file",
+        "compatible with [TT]make_ndx[tt] and the analyzing tools. Each selection",
+        "is written as a selection group and for dynamic selections a",
+        "group is written for each frame.[PAR]",
+        "For residue numbers, the output of [TT]-oi[tt] can be controlled",
+        "with [TT]-resnr[tt]: [TT]number[tt] (default) prints the residue",
+        "numbers as they appear in the input file, while [TT]index[tt] prints",
+        "unique numbers assigned to the residues in the order they appear",
+        "in the input file, starting with 1. The former is more intuitive,",
+        "but if the input contains multiple residues with the same number,",
+        "the output can be less useful.[PAR]",
+        "With [TT]-om[tt], a mask is printed for the first selection",
+        "as a function of time. Each line in the output corresponds to",
+        "one frame, and contains either 0/1 for each atom/residue/molecule",
+        "possibly selected. 1 stands for the atom/residue/molecule being",
+        "selected for the current frame, 0 for not selected.",
+        "With [TT]-dump[tt], the frame time is omitted from the output.",
+        NULL
+    };
+
+    _options.setDescription(desc);
+
+    _options.addOption(FileNameOption("os").filetype(eftPlot).writeOnly()
+                           .store(&_fnSize).defaultValueIfSet("size"));
+    _options.addOption(FileNameOption("oc").filetype(eftPlot).writeOnly()
+                           .store(&_fnFrac).defaultValueIfSet("frac"));
+    _options.addOption(FileNameOption("oi").filetype(eftGenericData).writeOnly()
+                           .store(&_fnIndex).defaultValueIfSet("index"));
+    _options.addOption(FileNameOption("on").filetype(eftIndex).writeOnly()
+                           .store(&_fnNdx).defaultValueIfSet("index"));
+    _options.addOption(FileNameOption("om").filetype(eftPlot).writeOnly()
+                           .store(&_fnMask).defaultValueIfSet("mask"));
+
+    _options.addOption(SelectionOption("select").required().multiValue()
+                           .storeVector(&_sel));
+
+    _options.addOption(BooleanOption("dump").store(&_bDump)
+        .description("Do not print the frame time (-om, -oi) or the index size (-oi)"));
+    _options.addOption(BooleanOption("norm").store(&_bTotNorm)
+        .description("Normalize by total number of positions with -os"));
+    _options.addOption(BooleanOption("cfnorm").store(&_bFracNorm)
+        .description("Normalize by covered fraction with -os"));
+    const char *const cResNumberEnum[] = { "number", "index", NULL };
+    _options.addOption(StringOption("resnr").store(&_resNumberType)
+        .enumValue(cResNumberEnum).defaultEnumIndex(0)
+        .description("Residue number output type"));
+
+    return &_options;
+}
+
+
+void
+Select::initAnalysis(const TopologyInformation &top)
+{
+    if (!_fnIndex.empty() && _bDump && _sel.size() > 1U)
+    {
+        GMX_THROW(InconsistentInputError("With -oi and -dump, there can be only one selection"));
+    }
+    _bResInd = (_resNumberType == "index");
+
+    for (std::vector<Selection *>::const_iterator i = _sel.begin(); i != _sel.end(); ++i)
+    {
+        (*i)->initCoveredFraction(CFRAC_SOLIDANGLE);
+    }
+
+    // TODO: For large systems, a float may not have enough precision
+    _sdata.setColumns(_sel.size());
+    registerAnalysisDataset(&_sdata, "size");
+    snew(_totsize, _sel.size());
+    for (size_t g = 0; g < _sel.size(); ++g)
+    {
+        _totsize[g] = _bTotNorm ? _sel[g]->posCount() : 1;
+    }
+    if (!_fnSize.empty())
+    {
+        AnalysisDataPlotModule *plot = new AnalysisDataPlotModule(_options);
+        plot->setFileName(_fnSize);
+        plot->setTitle("Selection size");
+        plot->setXLabel("Time [ps]");
+        plot->setYLabel("Number");
+        _sdata.addModule(plot);
+    }
+
+    _cdata.setColumns(_sel.size());
+    registerAnalysisDataset(&_cdata, "cfrac");
+    if (!_fnFrac.empty())
+    {
+        AnalysisDataPlotModule *plot = new AnalysisDataPlotModule(_options);
+        plot->setFileName(_fnFrac);
+        plot->setTitle("Covered fraction");
+        plot->setXLabel("Time [ps]");
+        plot->setYLabel("Fraction");
+        plot->setYFormat(6, 4);
+        _cdata.addModule(plot);
+    }
+
+    // TODO: For large systems, a float may not have enough precision
+    _idata.setColumns(2, true);
+    registerAnalysisDataset(&_idata, "index");
+    if (!_fnIndex.empty())
+    {
+        AnalysisDataPlotModule *plot = new AnalysisDataPlotModule(_options);
+        plot->setFileName(_fnIndex);
+        plot->setPlainOutput(true);
+        plot->setYFormat(4, 0);
+        if (_bDump)
+        {
+            plot->setOmitX(_bDump);
+            _idata.addColumnModule(1, 1, plot);
+        }
+        else
+        {
+            _idata.addModule(plot);
+        }
+    }
+    if (!_fnNdx.empty())
+    {
+        IndexFileWriterModule *writer = new IndexFileWriterModule();
+        writer->setFileName(_fnNdx);
+        for (size_t g = 0; g < _sel.size(); ++g)
+        {
+            writer->addGroup(_sel[g]->name(), _sel[g]->isDynamic());
+        }
+        _idata.addModule(writer);
+    }
+
+    _mdata.setColumns(_sel[0]->posCount());
+    registerAnalysisDataset(&_mdata, "mask");
+    if (!_fnMask.empty())
+    {
+        if (_sel.size() > 1U)
+        {
+            fprintf(stderr, "WARNING: the mask (-om) will only be written for the first group\n");
+        }
+        if (!_sel[0]->isDynamic())
+        {
+            fprintf(stderr, "WARNING: will not write the mask (-om) for a static selection\n");
+        }
+        else
+        {
+            AnalysisDataPlotModule *plot = new AnalysisDataPlotModule(_options);
+            plot->setFileName(_fnMask);
+            plot->setPlainOutput(_bDump);
+            plot->setOmitX(_bDump);
+            plot->setTitle("Selection mask");
+            plot->setXLabel("Time [ps]");
+            plot->setYLabel("Occupancy");
+            plot->setYFormat(1, 0);
+            _mdata.addModule(plot);
+        }
+    }
+
+    _top = top.topology();
+}
+
+
+TrajectoryAnalysisModuleData *
+Select::startFrames(AnalysisDataParallelOptions opt,
+                    const SelectionCollection &selections)
+{
+    ModuleData *pdata = new ModuleData(this, opt, selections);
+    snew(pdata->_mmap, 1);
+    gmx_ana_indexmap_init(pdata->_mmap, pdata->parallelSelection(_sel[0])->indexGroup(),
+                          _top, _sel[0]->type());
+    return pdata;
+}
+
+
+void
+Select::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                     TrajectoryAnalysisModuleData *pdata)
+{
+    ModuleData *d = static_cast<ModuleData *>(pdata);
+    AnalysisDataHandle *sdh = pdata->dataHandle("size");
+    AnalysisDataHandle *cdh = pdata->dataHandle("cfrac");
+    AnalysisDataHandle *idh = pdata->dataHandle("index");
+    AnalysisDataHandle *mdh = pdata->dataHandle("mask");
+    std::vector<Selection *> sel(pdata->parallelSelections(_sel));
+
+    if (sdh != NULL)
+    {
+        sdh->startFrame(frnr, fr.time);
+        for (size_t g = 0; g < sel.size(); ++g)
+        {
+            real normfac = _bFracNorm ? 1.0 / sel[g]->cfrac() : 1.0;
+            normfac /= _totsize[g];
+            sdh->addPoint(g, sel[g]->posCount() * normfac);
+        }
+        sdh->finishFrame();
+    }
+
+    if (cdh != NULL)
+    {
+        cdh->startFrame(frnr, fr.time);
+        for (size_t g = 0; g < sel.size(); ++g)
+        {
+            cdh->addPoint(g, sel[g]->cfrac());
+        }
+        cdh->finishFrame();
+    }
+
+    if (idh != NULL)
+    {
+        idh->startFrame(frnr, fr.time);
+        for (size_t g = 0; g < sel.size(); ++g)
+        {
+            idh->addPoint(0, sel[g]->posCount());
+            for (int i = 0; i < sel[g]->posCount(); ++i)
+            {
+                if (sel[g]->type() == INDEX_RES && !_bResInd)
+                {
+                    idh->addPoint(1, _top->atoms.resinfo[sel[g]->mapId(i)].nr);
+                }
+                else
+                {
+                    idh->addPoint(1, sel[g]->mapId(i) + 1);
+                }
+            }
+        }
+        idh->finishFrame();
+    }
+
+    if (mdh != NULL)
+    {
+        gmx_ana_indexmap_update(d->_mmap, sel[0]->indexGroup(), TRUE);
+        mdh->startFrame(frnr, fr.time);
+        for (int b = 0; b < d->_mmap->nr; ++b)
+        {
+            mdh->addPoint(b, d->_mmap->refid[b] == -1 ? 0 : 1);
+        }
+        mdh->finishFrame();
+    }
+}
+
+
+void
+Select::finishAnalysis(int /*nframes*/)
+{
+}
+
+
+void
+Select::writeOutput()
+{
+}
+
+
+TrajectoryAnalysisModule *
+Select::create()
+{
+    return new Select();
+}
+
+} // namespace analysismodules
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/modules/select.h b/src/gromacs/trajectoryanalysis/modules/select.h
new file mode 100644 (file)
index 0000000..cf2777f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares trajectory analysis module for basic selection information.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_MODULES_SELECT_H
+#define GMX_TRAJECTORYANALYSIS_MODULES_SELECT_H
+
+#include <string>
+#include <vector>
+
+#include "../analysismodule.h"
+#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/options/options.h"
+
+namespace gmx
+{
+
+class AnalysisDataPlotModule;
+class Selection;
+
+namespace analysismodules
+{
+
+class Select : public TrajectoryAnalysisModule
+{
+    public:
+        Select();
+        virtual ~Select();
+
+        static TrajectoryAnalysisModule *create();
+
+        virtual Options *initOptions(TrajectoryAnalysisSettings *settings);
+        virtual void initAnalysis(const TopologyInformation &top);
+
+        virtual TrajectoryAnalysisModuleData *startFrames(
+                    AnalysisDataParallelOptions opt,
+                    const SelectionCollection &selections);
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata);
+
+        virtual void finishAnalysis(int nframes);
+        virtual void writeOutput();
+
+    private:
+        class ModuleData;
+
+        Options                  _options;
+        std::vector<Selection *> _sel;
+
+        std::string              _fnSize;
+        std::string              _fnFrac;
+        std::string              _fnIndex;
+        std::string              _fnNdx;
+        std::string              _fnMask;
+        bool                     _bDump;
+        bool                     _bTotNorm;
+        bool                     _bFracNorm;
+        bool                     _bResInd;
+        std::string              _resNumberType;
+
+        t_topology              *_top;
+        int                     *_totsize;
+        AnalysisData             _sdata;
+        AnalysisData             _cdata;
+        AnalysisData             _idata;
+        AnalysisData             _mdata;
+        std::vector<std::string> _modnames;
+};
+
+} // namespace analysismodules
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/nbsearch.h b/src/gromacs/trajectoryanalysis/nbsearch.h
new file mode 100644 (file)
index 0000000..5d0a908
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * C++ wrapper for analysis tool neighborhood searching.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_NBSEARCH_H
+#define GMX_TRAJECTORYANALYSIS_NBSEARCH_H
+
+#include "../selection/nbsearch.h"
+
+namespace gmx
+{
+
+/*! \brief
+ * C++ wrapper for neighborhood searching in selection/nbsearch.h.
+ *
+ * \ingroup module_trajectoryanalysis
+ */
+class NeighborhoodSearch
+{
+    public:
+        NeighborhoodSearch(real cutoff, int maxn)
+            : _d(gmx_ana_nbsearch_create(cutoff, maxn))
+        {
+        }
+        ~NeighborhoodSearch() { gmx_ana_nbsearch_free(_d); }
+
+        void init(t_pbc *pbc, int n, const rvec x[])
+        { gmx_ana_nbsearch_init(_d, pbc, n, x); }
+
+        void init(t_pbc *pbc, const gmx_ana_pos_t *p)
+        { gmx_ana_nbsearch_pos_init(_d, pbc, p); }
+
+        void setExclusions(int nexcl, atom_id *excl)
+        { gmx_ana_nbsearch_set_excl(_d, nexcl, excl); }
+
+
+        bool isWithin(const rvec x)
+        { return gmx_ana_nbsearch_is_within(_d, x); }
+
+        bool isWithin(const gmx_ana_pos_t *p, int i)
+        { return gmx_ana_nbsearch_pos_is_within(_d, p, i); }
+
+        real minimumDistance(const rvec x)
+        { return gmx_ana_nbsearch_mindist(_d, x); }
+
+        real minimumDistance(const gmx_ana_pos_t *p, int i)
+        { return gmx_ana_nbsearch_pos_mindist(_d, p, i); }
+
+        bool firstWithin(const rvec x, int *jp)
+        { return gmx_ana_nbsearch_first_within(_d, x, jp); }
+
+        bool firstWithin(const gmx_ana_pos_t *p, int i, int *jp)
+        { return gmx_ana_nbsearch_pos_first_within(_d, p, i, jp); }
+
+        bool nextWithin(int *jp)
+        { return gmx_ana_nbsearch_next_within(_d, jp); }
+
+    private:
+        gmx_ana_nbsearch_t  *_d;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/runnercommon.cpp b/src/gromacs/trajectoryanalysis/runnercommon.cpp
new file mode 100644 (file)
index 0000000..161a0a7
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::TrajectoryAnalysisRunnerCommon.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <rmpbc.h>
+#include <smalloc.h>
+#include <statutil.h>
+#include <tpxio.h>
+#include <vec.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/globalproperties.h"
+#include "gromacs/options/options.h"
+#include "gromacs/selection/indexutil.h"
+#include "gromacs/selection/selectioncollection.h"
+#include "gromacs/trajectoryanalysis/analysissettings.h"
+#include "gromacs/trajectoryanalysis/runnercommon.h"
+#include "gromacs/utility/format.h"
+
+#include "analysissettings-impl.h"
+
+namespace gmx
+{
+
+class TrajectoryAnalysisRunnerCommon::Impl
+{
+    public:
+        Impl(TrajectoryAnalysisSettings *settings);
+        ~Impl();
+
+        void finishTrajectory();
+
+        TrajectoryAnalysisSettings &_settings;
+        Options                 _options;
+        TopologyInformation     _topInfo;
+
+        bool                    _bHelp;
+        bool                    _bShowHidden;
+        bool                    _bQuiet;
+        //! Name of the trajectory file (empty if not provided).
+        std::string             _trjfile;
+        //! Name of the topology file (empty if no topology provided).
+        std::string             _topfile;
+        //! Name of the index file (empty if no index file provided).
+        std::string             _ndxfile;
+        double                  _startTime;
+        double                  _endTime;
+        double                  _deltaTime;
+
+        gmx_ana_indexgrps_t    *_grps;
+        bool                    _bTrajOpen;
+        //! The current frame, or \p NULL if no frame loaded yet.
+        t_trxframe          *fr;
+        gmx_rmpbc_t             _gpbc;
+        //! Used to store the status variable from read_first_frame().
+        t_trxstatus            *_status;
+        output_env_t            _oenv;
+};
+
+
+TrajectoryAnalysisRunnerCommon::Impl::Impl(TrajectoryAnalysisSettings *settings)
+    : _settings(*settings), _options("common", "Common analysis control"),
+      _bHelp(false), _bShowHidden(false), _bQuiet(false),
+      _startTime(0.0), _endTime(0.0), _deltaTime(0.0),
+      _grps(NULL),
+      _bTrajOpen(false), fr(NULL), _gpbc(NULL), _status(NULL), _oenv(NULL)
+{
+}
+
+
+TrajectoryAnalysisRunnerCommon::Impl::~Impl()
+{
+    if (_grps != NULL)
+    {
+        gmx_ana_indexgrps_free(_grps);
+    }
+    finishTrajectory();
+    if (fr)
+    {
+        // There doesn't seem to be a function for freeing frame data
+        sfree(fr->x);
+        sfree(fr->v);
+        sfree(fr->f);
+        sfree(fr);
+    }
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::Impl::finishTrajectory()
+{
+    if (_bTrajOpen)
+    {
+        close_trx(_status);
+        _bTrajOpen = false;
+    }
+    if (_gpbc != NULL)
+    {
+        gmx_rmpbc_done(_gpbc);
+        _gpbc = NULL;
+    }
+}
+
+/*********************************************************************
+ * TrajectoryAnalysisRunnerCommon
+ */
+
+TrajectoryAnalysisRunnerCommon::TrajectoryAnalysisRunnerCommon(
+        TrajectoryAnalysisSettings *settings)
+    : _impl(new Impl(settings))
+{
+}
+
+
+TrajectoryAnalysisRunnerCommon::~TrajectoryAnalysisRunnerCommon()
+{
+    delete _impl;
+}
+
+
+Options *
+TrajectoryAnalysisRunnerCommon::initOptions()
+{
+    TrajectoryAnalysisSettings &settings = _impl->_settings;
+    Options &options = _impl->_options;
+
+    // Add options for help.
+    options.addOption(BooleanOption("h").store(&_impl->_bHelp)
+                          .description("Print help and quit"));
+    options.addOption(BooleanOption("hidden").store(&_impl->_bShowHidden)
+                          .hidden()
+                          .description("Show hidden options"));
+    options.addOption(BooleanOption("quiet").store(&_impl->_bQuiet)
+                          .hidden()
+                          .description("Hide options in normal run"));
+
+    // Add common file name arguments.
+    options.addOption(FileNameOption("f")
+                          .filetype(eftTrajectory).readOnly()
+                          .store(&_impl->_trjfile)
+                          .description("Input trajectory"));
+    options.addOption(FileNameOption("s")
+                          .filetype(eftTopology).readOnly()
+                          .store(&_impl->_topfile)
+                          .description("Input topology"));
+    options.addOption(FileNameOption("n")
+                          .filetype(eftIndex).readOnly()
+                          .store(&_impl->_ndxfile)
+                          .description("Extra index groups"));
+
+    // Add options for trajectory time control.
+    options.addOption(DoubleOption("b").store(&_impl->_startTime).timeValue()
+                          .description("First frame (%t) to read from trajectory"));
+    options.addOption(DoubleOption("e").store(&_impl->_endTime).timeValue()
+                          .description("Last frame (%t) to read from trajectory"));
+    options.addOption(DoubleOption("dt").store(&_impl->_deltaTime).timeValue()
+                          .description("Only use frame if t MOD dt == first time (%t)"));
+
+    // Add common options for trajectory processing.
+    if (!settings.hasFlag(TrajectoryAnalysisSettings::efNoUserRmPBC))
+    {
+        options.addOption(BooleanOption("rmpbc").store(&settings._impl->bRmPBC)
+                              .description("Make molecules whole for each frame"));
+    }
+    if (!settings.hasFlag(TrajectoryAnalysisSettings::efNoUserPBC))
+    {
+        options.addOption(BooleanOption("pbc").store(&settings._impl->bPBC)
+                              .description("Use periodic boundary conditions for distance calculation"));
+    }
+
+    return &_impl->_options;
+}
+
+
+bool
+TrajectoryAnalysisRunnerCommon::initOptionsDone()
+{
+    if (_impl->_bHelp)
+    {
+        return false;
+    }
+
+    if (_impl->_trjfile.empty() && _impl->_topfile.empty())
+    {
+        GMX_THROW(InconsistentInputError("No trajectory or topology provided, nothing to do!"));
+    }
+
+    if (_impl->_options.isSet("b"))
+        setTimeValue(TBEGIN, _impl->_startTime);
+    if (_impl->_options.isSet("e"))
+        setTimeValue(TEND, _impl->_endTime);
+    if (_impl->_options.isSet("dt"))
+        setTimeValue(TDELTA, _impl->_deltaTime);
+
+    return true;
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::initIndexGroups(SelectionCollection *selections)
+{
+    if (_impl->_ndxfile.empty())
+    {
+        // TODO: Initialize default selections
+        selections->setIndexGroups(NULL);
+    }
+    else
+    {
+        gmx_ana_indexgrps_init(&_impl->_grps, NULL, _impl->_ndxfile.c_str());
+        selections->setIndexGroups(_impl->_grps);
+    }
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::doneIndexGroups(SelectionCollection *selections)
+{
+    if (_impl->_grps != NULL)
+    {
+        selections->setIndexGroups(NULL);
+        gmx_ana_indexgrps_free(_impl->_grps);
+        _impl->_grps = NULL;
+    }
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::initTopology(SelectionCollection *selections)
+{
+    const TrajectoryAnalysisSettings &settings = _impl->_settings;
+    bool bRequireTop
+        = settings.hasFlag(TrajectoryAnalysisSettings::efRequireTop)
+          || selections->requiresTopology();
+    if (bRequireTop && _impl->_topfile.empty())
+    {
+        GMX_THROW(InconsistentInputError("No topology provided, but one is required for analysis"));
+    }
+
+    // Load the topology if requested.
+    if (!_impl->_topfile.empty())
+    {
+        char  title[STRLEN];
+
+        snew(_impl->_topInfo._top, 1);
+        _impl->_topInfo._bTop = read_tps_conf(_impl->_topfile.c_str(), title,
+                _impl->_topInfo._top, &_impl->_topInfo._ePBC,
+                &_impl->_topInfo._xtop, NULL, _impl->_topInfo._boxtop, TRUE);
+        if (hasTrajectory()
+            && !settings.hasFlag(TrajectoryAnalysisSettings::efUseTopX))
+        {
+            sfree(_impl->_topInfo._xtop);
+            _impl->_topInfo._xtop = NULL;
+        }
+    }
+
+    // Read the first frame if we don't know the maximum number of atoms
+    // otherwise.
+    int  natoms = -1;
+    if (!_impl->_topInfo.hasTopology())
+    {
+        initFirstFrame();
+        natoms = _impl->fr->natoms;
+    }
+    selections->setTopology(_impl->_topInfo.topology(), natoms);
+
+    /*
+    if (_impl->bSelDump)
+    {
+        gmx_ana_poscalc_coll_print_tree(stderr, _impl->pcc);
+        fprintf(stderr, "\n");
+    }
+    */
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::initFirstFrame()
+{
+    // Return if we have already initialized the trajectory.
+    if (_impl->fr)
+    {
+        return;
+    }
+    _impl->_oenv = _impl->_options.globalProperties().output_env();
+
+    int frflags = _impl->_settings.frflags();
+    frflags |= TRX_NEED_X;
+
+    snew(_impl->fr, 1);
+
+    const TopologyInformation &top = _impl->_topInfo;
+    if (hasTrajectory())
+    {
+        if (!read_first_frame(_impl->_oenv, &_impl->_status,
+                              _impl->_trjfile.c_str(), _impl->fr, frflags))
+        {
+            GMX_THROW(FileIOError("Could not read coordinates from trajectory"));
+        }
+        _impl->_bTrajOpen = true;
+
+        if (top.hasTopology() && _impl->fr->natoms > top.topology()->atoms.nr)
+        {
+            GMX_THROW(InconsistentInputError(formatString(
+                      "Trajectory (%d atoms) does not match topology (%d atoms)",
+                      _impl->fr->natoms, top.topology()->atoms.nr)));
+        }
+        // Check index groups if they have been initialized based on the topology.
+        /*
+        if (top)
+        {
+            for (int i = 0; i < _impl->sel->nr(); ++i)
+            {
+                gmx_ana_index_check(_impl->sel->sel(i)->indexGroup(),
+                                    _impl->fr->natoms);
+            }
+        }
+        */
+    }
+    else
+    {
+        // Prepare a frame from topology information.
+        // TODO: Initialize more of the fields.
+        if (frflags & (TRX_NEED_V))
+        {
+            GMX_THROW(NotImplementedError("Velocity reading from a topology not implemented"));
+        }
+        if (frflags & (TRX_NEED_F))
+        {
+            GMX_THROW(InvalidInputError("Forces cannot be read from a topology"));
+        }
+        _impl->fr->flags  = frflags;
+        _impl->fr->natoms = top.topology()->atoms.nr;
+        _impl->fr->bX     = TRUE;
+        snew(_impl->fr->x, _impl->fr->natoms);
+        memcpy(_impl->fr->x, top._xtop,
+               sizeof(*_impl->fr->x) * _impl->fr->natoms);
+        _impl->fr->bBox   = TRUE;
+        copy_mat(const_cast<rvec *>(top._boxtop), _impl->fr->box);
+    }
+
+    set_trxframe_ePBC(_impl->fr, top.ePBC());
+    if (top.hasTopology() && _impl->_settings.hasRmPBC())
+    {
+        _impl->_gpbc = gmx_rmpbc_init(&top.topology()->idef, top.ePBC(),
+                                      _impl->fr->natoms, _impl->fr->box);
+    }
+}
+
+
+bool
+TrajectoryAnalysisRunnerCommon::readNextFrame()
+{
+    bool bContinue = FALSE;
+    if (hasTrajectory())
+    {
+        bContinue = read_next_frame(_impl->_oenv, _impl->_status, _impl->fr);
+    }
+    if (!bContinue)
+    {
+        _impl->finishTrajectory();
+    }
+    return bContinue;
+}
+
+
+void
+TrajectoryAnalysisRunnerCommon::initFrame()
+{
+    if (_impl->_gpbc != NULL)
+    {
+        gmx_rmpbc_trxfr(_impl->_gpbc, _impl->fr);
+    }
+}
+
+
+TrajectoryAnalysisRunnerCommon::HelpFlags
+TrajectoryAnalysisRunnerCommon::helpFlags() const
+{
+    HelpFlags flags = 0;
+
+    if (!_impl->_bQuiet)
+    {
+        flags |= efHelpShowOptions;
+        if (_impl->_bHelp)
+        {
+            flags |= efHelpShowDescriptions;
+        }
+        if (_impl->_bShowHidden)
+        {
+            flags |= efHelpShowHidden;
+        }
+    }
+    return flags;
+}
+
+bool
+TrajectoryAnalysisRunnerCommon::hasTrajectory() const
+{
+    return !_impl->_trjfile.empty();
+}
+
+
+const TopologyInformation &
+TrajectoryAnalysisRunnerCommon::topologyInformation() const
+{
+    return _impl->_topInfo;
+}
+
+
+t_trxframe &
+TrajectoryAnalysisRunnerCommon::frame() const
+{
+    assert(_impl->fr != NULL);
+    return *_impl->fr;
+}
+
+} // namespace gmx
diff --git a/src/gromacs/trajectoryanalysis/runnercommon.h b/src/gromacs/trajectoryanalysis/runnercommon.h
new file mode 100644 (file)
index 0000000..bf53178
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares gmx::TrajectoryAnalysisRunnerCommon.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_trajectoryanalysis
+ */
+#ifndef GMX_TRAJECTORYANALYSIS_RUNNERCOMMON_H
+#define GMX_TRAJECTORYANALYSIS_RUNNERCOMMON_H
+
+#include <typedefs.h>
+
+namespace gmx
+{
+
+class Options;
+class SelectionCollection;
+class TopologyInformation;
+class TrajectoryAnalysisSettings;
+
+/*! \internal \brief
+ * Implements common trajectory analysis runner functionality.
+ *
+ * As there is currently only one runner (TrajectoryAnalysisCommandLineRunner),
+ * the division of responsibilities is not yet very clear.
+ *
+ * \ingroup module_trajectoryanalysis
+ */
+class TrajectoryAnalysisRunnerCommon
+{
+    public:
+        /*! \brief
+         * Flags that define what kind of help should be printed.
+         */
+        enum HelpFlag
+        {
+            efHelpShowOptions           = 1<<0,
+            efHelpShowHidden            = 1<<1,
+            efHelpShowDescriptions      = 1<<2,
+        };
+        //! Combination of ::HelpFlag values.
+        typedef unsigned long HelpFlags;
+
+        explicit TrajectoryAnalysisRunnerCommon(TrajectoryAnalysisSettings *settings);
+        ~TrajectoryAnalysisRunnerCommon();
+
+        Options *initOptions();
+        bool initOptionsDone();
+        void initIndexGroups(SelectionCollection *selections);
+        void doneIndexGroups(SelectionCollection *selections);
+        void initTopology(SelectionCollection *selections);
+        void initFirstFrame();
+        bool readNextFrame();
+        void initFrame();
+
+        //! Returns flags for help printing.
+        HelpFlags helpFlags() const;
+        //! Returns true if input data comes from a trajectory.
+        bool hasTrajectory() const;
+        //! Returns the topology information object.
+        const TopologyInformation &topologyInformation() const;
+        //! Returns the currently loaded frame.
+        t_trxframe &frame() const;
+
+    private:
+        class Impl;
+
+        Impl                *_impl;
+
+        // Disallow copy and assign.
+        TrajectoryAnalysisRunnerCommon(const TrajectoryAnalysisRunnerCommon &);
+        void operator =(const TrajectoryAnalysisRunnerCommon &);
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/trajectoryanalysis/tests/CMakeLists.txt b/src/gromacs/trajectoryanalysis/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6e6a858
--- /dev/null
@@ -0,0 +1,2 @@
+add_executable(test_selection test_selection.cpp)
+target_link_libraries(test_selection libgromacs)
diff --git a/src/gromacs/trajectoryanalysis/tests/test_selection.cpp b/src/gromacs/trajectoryanalysis/tests/test_selection.cpp
new file mode 100644 (file)
index 0000000..df07271
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Testing/debugging tool for the selection engine.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <vector>
+
+#include <gromacs/fatalerror/exceptions.h>
+#include <gromacs/options/basicoptions.h>
+#include <gromacs/options/options.h>
+#include <gromacs/selection/selection.h>
+#include <gromacs/selection/selectionoption.h>
+#include <gromacs/trajectoryanalysis/analysismodule.h>
+#include <gromacs/trajectoryanalysis/analysissettings.h>
+#include <gromacs/trajectoryanalysis/cmdlinerunner.h>
+
+namespace gmx
+{
+
+class SelectionTester : public TrajectoryAnalysisModule
+{
+    public:
+        SelectionTester();
+        ~SelectionTester();
+
+        Options *initOptions(TrajectoryAnalysisSettings *settings);
+        void initAnalysis(const TopologyInformation &top);
+
+        void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                          TrajectoryAnalysisModuleData *pdata);
+
+        void finishAnalysis(int nframes);
+        void writeOutput();
+
+    private:
+        void printSelections();
+
+        Options                  _options;
+        std::vector<Selection *> _selections;
+        int                      _nmaxind;
+};
+
+SelectionTester::SelectionTester()
+    : _options("testing", "Selection testing and debugging"),
+      _nmaxind(20)
+{
+}
+
+SelectionTester::~SelectionTester()
+{
+}
+
+void
+SelectionTester::printSelections()
+{
+    fprintf(stderr, "\nSelections:\n");
+    for (size_t g = 0; g < _selections.size(); ++g)
+    {
+        _selections[g]->printDebugInfo(stderr, _nmaxind);
+    }
+    fprintf(stderr, "\n");
+}
+
+Options *
+SelectionTester::initOptions(TrajectoryAnalysisSettings * /*settings*/)
+{
+    static const char *const desc[] = {
+        "This is a test program for selections.",
+        NULL
+    };
+
+    _options.setDescription(desc);
+
+    _options.addOption(SelectionOption("select").storeVector(&_selections)
+                           .required().multiValue().allowMultiple()
+                           .description("Selections to test"));
+    _options.addOption(IntegerOption("pmax").store(&_nmaxind)
+                           .description("Maximum number of indices to print in lists (-1 = print all)"));
+
+    return &_options;
+}
+
+void
+SelectionTester::initAnalysis(const TopologyInformation &/*top*/)
+{
+    printSelections();
+}
+
+void
+SelectionTester::analyzeFrame(int /*frnr*/, const t_trxframe &/*fr*/, t_pbc * /*pbc*/,
+                              TrajectoryAnalysisModuleData * /*pdata*/)
+{
+    int                 g, i, n;
+
+    fprintf(stderr, "\n");
+    for (size_t g = 0; g < _selections.size(); ++g)
+    {
+        const Selection *sel = _selections[g];
+
+        gmx_ana_index_dump(stderr, sel->indexGroup(), g, _nmaxind);
+        fprintf(stderr, "  Positions (%d pcs):\n", sel->posCount());
+        n = sel->posCount();
+        if (_nmaxind >= 0 && n > _nmaxind)
+        {
+            n = _nmaxind;
+        }
+        for (i = 0; i < n; ++i)
+        {
+            fprintf(stderr, "    (%.2f,%.2f,%.2f) r=%d, m=%d, n=%d\n",
+                    sel->x(i)[XX], sel->x(i)[YY], sel->x(i)[ZZ],
+                    sel->refId(i), sel->mapId(i),
+                    sel->atomCount(i));
+        }
+        if (n < sel->posCount())
+        {
+            fprintf(stderr, "    ...\n");
+        }
+    }
+    fprintf(stderr, "\n");
+}
+
+void
+SelectionTester::finishAnalysis(int /*nframes*/)
+{
+    printSelections();
+}
+
+void
+SelectionTester::writeOutput()
+{
+}
+
+}
+
+int
+main(int argc, char *argv[])
+{
+    try
+    {
+        gmx::SelectionTester module;
+        gmx::TrajectoryAnalysisCommandLineRunner runner(&module);
+        runner.setSelectionDebugLevel(1);
+        return runner.run(argc, argv);
+    }
+    catch (std::exception &ex)
+    {
+        fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
+        return 1;
+    }
+}
diff --git a/src/gromacs/utility/CMakeLists.txt b/src/gromacs/utility/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2a96037
--- /dev/null
@@ -0,0 +1,8 @@
+file(GLOB UTILITY_SOURCES *.cpp)
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${UTILITY_SOURCES} PARENT_SCOPE)
+
+set(UTILITY_PUBLIC_HEADERS
+    flags.h format.h)
+install(FILES ${UTILITY_PUBLIC_HEADERS}
+        DESTINATION ${INCL_INSTALL_DIR}/gromacs/utility
+        COMPONENT development)
diff --git a/src/gromacs/utility/flags.h b/src/gromacs/utility/flags.h
new file mode 100644 (file)
index 0000000..e73528f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares gmx::FlagsTemplate.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_utility
+ */
+#ifndef GMX_UTILITY_FLAGS_H
+#define GMX_UTILITY_FLAGS_H
+
+namespace gmx
+{
+
+/*! \brief
+ * Template class for typesafe handling of combination of flags.
+ *
+ * \tparam T An enumerated type that holds the possible single flags.
+ *
+ * This class is not used publicly, but is present in an installed header
+ * because it is used internally in public template classes.
+ *
+ * \inlibraryapi
+ * \ingroup module_utility
+ */
+template <typename T>
+class FlagsTemplate
+{
+    public:
+        //! Creates a flags object with no flags set.
+        FlagsTemplate() : _flags(0) {}
+        //! Creates a flags object from a single flag.
+        FlagsTemplate(T flag) : _flags(flag) {}
+
+        //! Returns true if the given flag is set.
+        bool test(T flag) const { return _flags & flag; }
+        //! Clears all flags.
+        void clearAll() { _flags = 0; }
+        //! Sets the given flag.
+        void set(T flag) { _flags |= flag; }
+        //! Clears the given flag.
+        void clear(T flag) { _flags &= ~flag; }
+        //! Sets or clears the given flag.
+        void set(T flag, bool bSet)
+        {
+            if (bSet)
+            {
+                set(flag);
+            }
+            else
+            {
+                clear(flag);
+            }
+        }
+
+        //! Combines flags from two flags objects.
+        FlagsTemplate<T> operator |(const FlagsTemplate<T> &other) const
+        {
+            return FlagsTemplate<T>(_flags | other._flags);
+        }
+        //! Combines flags from another flag object.
+        FlagsTemplate<T> &operator |=(const FlagsTemplate<T> &other)
+        {
+            _flags |= other._flags;
+            return *this;
+        }
+
+    private:
+        //! Creates a flags object with the given flags.
+        explicit FlagsTemplate(unsigned long flags) : _flags(flags) {}
+
+        unsigned long           _flags;
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/utility/format.cpp b/src/gromacs/utility/format.cpp
new file mode 100644 (file)
index 0000000..bcc9e71
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in format.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_utility
+ */
+#include "gromacs/utility/format.h"
+
+#include <cstdio>
+#include <cstdarg>
+
+namespace gmx
+{
+
+std::string formatString(const char *fmt, ...)
+{
+    va_list ap;
+    char staticBuf[1024];
+    int length = 1024;
+    char *buf = staticBuf;
+
+    // TODO: This might not work on Windows, Microsoft provides their own
+    // way of doing things...
+    while (1)
+    {
+        va_start(ap, fmt);
+        int n = vsnprintf(buf, length, fmt, ap);
+        va_end(ap);
+        if (n > -1 && n < length)
+        {
+            std::string result(buf);
+            if (buf != staticBuf)
+            {
+                delete[] buf;
+            }
+            return result;
+        }
+        if (n > -1)
+        {
+            length = n + 1;
+        }
+        else
+        {
+            length *= 2;
+        }
+        if (buf != staticBuf)
+        {
+            delete[] buf;
+        }
+        buf = new char[length];
+    }
+}
+
+} // namespace gmx
diff --git a/src/gromacs/utility/format.h b/src/gromacs/utility/format.h
new file mode 100644 (file)
index 0000000..923a303
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \file
+ * \brief
+ * Declares common string formatting routines.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inpublicapi
+ * \ingroup module_utility
+ */
+#ifndef GMX_UTILITY_FORMAT_H
+#define GMX_UTILITY_FORMAT_H
+
+#include <string>
+
+namespace gmx
+{
+
+/*! \brief
+ * Format a string (snprintf() wrapper).
+ *
+ * This function works like sprintf(), except that it returns an std::string
+ * instead of requiring a preallocated buffer.  Arbitrary length output is
+ * supported.  Throws if there is not enough memory.
+ *
+ * \inpublicapi
+ */
+std::string formatString(const char *fmt, ...);
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/utility/path.cpp b/src/gromacs/utility/path.cpp
new file mode 100644 (file)
index 0000000..a3f2c91
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in path.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_utility
+ */
+#include "path.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+
+static const char cDirSeparator = '/';
+
+namespace gmx
+{
+
+std::string Path::join(const std::string &path1,
+                       const std::string &path2)
+{
+    // TODO: Remove extra separators if they are present in the input paths.
+    return path1 + cDirSeparator + path2;
+}
+
+
+std::string Path::join(const std::string &path1,
+                       const std::string &path2,
+                       const std::string &path3)
+{
+    // TODO: Remove extra separators if they are present in the input paths.
+    return path1 + cDirSeparator + path2 + cDirSeparator + path3;
+}
+
+
+int Directory::create(const char *path)
+{
+    if (Directory::exists(path))
+    {
+        return 0;
+    }
+    if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IWOTH) != 0)
+    {
+        // TODO: Proper error handling.
+        return -1;
+    }
+    return 0;
+}
+
+
+int Directory::create(const std::string &path)
+{
+    return create(path.c_str());
+}
+
+
+bool Directory::exists(const char *path)
+{
+    struct stat info;
+    if (stat(path, &info) != 0)
+    {
+        if (errno != ENOENT && errno != ENOTDIR)
+        {
+            // TODO: Proper error handling.
+        }
+        return false;
+    }
+    return S_ISDIR(info.st_mode);
+}
+
+
+bool Directory::exists(const std::string &path)
+{
+    return exists(path.c_str());
+}
+
+} // namespace gmx
diff --git a/src/gromacs/utility/path.h b/src/gromacs/utility/path.h
new file mode 100644 (file)
index 0000000..27f22bb
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ *
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares functions for OS-independent path handling.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ */
+#ifndef GMX_UTILITY_PATH_H
+#define GMX_UTILITY_PATH_H
+
+#include <string>
+
+namespace gmx
+{
+
+class Path
+{
+    public:
+        static std::string join(const std::string &path1,
+                                const std::string &path2);
+        static std::string join(const std::string &path1,
+                                const std::string &path2,
+                                const std::string &path3);
+
+    private:
+        // Disallow instantiation.
+        Path();
+};
+
+
+class Directory
+{
+    public:
+        static int create(const char *path);
+        static int create(const std::string &path);
+        static bool exists(const char *path);
+        static bool exists(const std::string &path);
+
+    private:
+        // Disallow instantiation.
+        Directory();
+};
+
+} // namespace gmx
+
+#endif
diff --git a/src/gromacs/version.c.cmakein b/src/gromacs/version.c.cmakein
new file mode 100644 (file)
index 0000000..c59f8b0
--- /dev/null
@@ -0,0 +1,4 @@
+#include "gromacs/gmxlib/version.h"
+const char _gmx_ver_string[] = "VERSION @GMX_PROJECT_VERSION_STR@";
+const char _gmx_full_git_hash[] = "@GMX_GIT_HEAD_HASH@";
+const char _gmx_central_base_hash[] = "@GMX_GIT_REMOTE_HASH@";
diff --git a/src/kernel/.cvsignore b/src/kernel/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/kernel/.gitignore b/src/kernel/.gitignore
new file mode 100644 (file)
index 0000000..80fb129
--- /dev/null
@@ -0,0 +1 @@
+g_luck
index 1e6cf9656bd92aeb85994c8feb53e0c1981721ec..a05b9e6659a019aa659cdb72dc0af5aca66df2fa 100644 (file)
+if(NOT GMX_FAHCORE)
 
-set(GMXPREPROCESS_SOURCES 
-    add_par.c       
-    compute_io.c    
-    convparm.c      
-    gen_ad.c        
-    gen_vsite.c     
-    genhydro.c   
-    gpp_atomtype.c  
-    gpp_bond_atomtype.c     
-    h_db.c          
-    hackblock.c             
-    hizzie.c        
-    nm2type.c
-    pdb2top.c       
-    pgutil.c        
-    readir.c        
-    readpull.c      
-    resall.c        
-    sorting.c       
-    specbond.c      
-    ter_db.c        
-    tomorse.c       
-    topdirs.c       
-    topexcl.c       
-    topio.c         
-    toppush.c       
-    topshake.c      
-    toputil.c       
-    tpbcmp.c        
-    vsite_parm.c    
-    fflibutil.c
-    xlate.c)
-
-set(MDRUN_SOURCES 
-    gctio.c    ionize.c runner.c
-    do_gct.c     repl_ex.c  xutils.c
-    md.c         mdrun.c    genalg.c md_openmm.c)
-
-add_library(gmxpreprocess ${GMXPREPROCESS_SOURCES})
-target_link_libraries(gmxpreprocess md)
-set_target_properties(gmxpreprocess PROPERTIES OUTPUT_NAME "gmxpreprocess${GMX_LIBS_SUFFIX}" SOVERSION ${SOVERSION} INSTALL_NAME_DIR "${LIB_INSTALL_DIR}")
-
-
-if(GMX_OPENMM) 
-    add_subdirectory(gmx_gpu_utils)
-    include_directories(./gmx_gpu_utils ${OpenMM_INCLUDE_DIR})
-    link_directories(${OpenMM_LIBRARY_DIR}) 
-    # with this define no evn.var. is needed with OPENMM_PLUGIN_DIR
-    # if the same OpenMM installation is used for running and building 
-    add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" ) 
-    file(TO_CMAKE_PATH ${OpenMM_PLUGIN_DIR} _path)
-    add_library(openmm_api_wrapper STATIC openmm_wrapper.cpp)
-    target_link_libraries(openmm_api_wrapper gmx_gpu_utils ${OpenMM_LIBRARIES})
-    set(GMX_OPENMM_LIBRARIES openmm_api_wrapper gmx_gpu_utils ${OpenMM_LIBRARIES})   
-endif(GMX_OPENMM)
-
-if(GMX_FAHCORE)
-  add_library(fahcore ${MDRUN_SOURCES})
-else(GMX_FAHCORE)
-
-list(APPEND GMX_EXTRA_LIBRARIES gmxpreprocess md)
-
-add_executable(grompp grompp.c)
-target_link_libraries(grompp ${GMX_EXTRA_LIBRARIES})
-set_target_properties(grompp PROPERTIES OUTPUT_NAME "grompp${GMX_BINARY_SUFFIX}")
-
-add_executable(tpbconv tpbconv.c)
-target_link_libraries(tpbconv ${GMX_EXTRA_LIBRARIES})
-set_target_properties(tpbconv PROPERTIES OUTPUT_NAME "tpbconv${GMX_BINARY_SUFFIX}")
-
-add_executable(pdb2gmx pdb2gmx.c)
-target_link_libraries(pdb2gmx ${GMX_EXTRA_LIBRARIES})
-set_target_properties(pdb2gmx PROPERTIES OUTPUT_NAME "pdb2gmx${GMX_BINARY_SUFFIX}")
-
-add_executable(g_protonate g_protonate.c)
-target_link_libraries(g_protonate ${GMX_EXTRA_LIBRARIES})
-set_target_properties(g_protonate PROPERTIES OUTPUT_NAME "g_protonate${GMX_BINARY_SUFFIX}")
+list(APPEND GMX_EXTRA_LIBRARIES libgromacs)
 
 add_executable(g_luck g_luck.c)
 target_link_libraries(g_luck ${GMX_EXTRA_LIBRARIES})
 set_target_properties(g_luck PROPERTIES OUTPUT_NAME "g_luck${GMX_BINARY_SUFFIX}")
 
-add_executable(gmxdump gmxdump.c)
-target_link_libraries(gmxdump ${GMX_EXTRA_LIBRARIES})
-set_target_properties(gmxdump PROPERTIES OUTPUT_NAME "gmxdump${GMX_BINARY_SUFFIX}")
-
-add_executable(g_x2top g_x2top.c)
-target_link_libraries(g_x2top ${GMX_EXTRA_LIBRARIES})
-set_target_properties(g_x2top PROPERTIES OUTPUT_NAME "g_x2top${GMX_BINARY_SUFFIX}")
-
-add_executable(gmxcheck gmxcheck.c)
-target_link_libraries(gmxcheck ${GMX_EXTRA_LIBRARIES})
-set_target_properties(gmxcheck PROPERTIES OUTPUT_NAME "gmxcheck${GMX_BINARY_SUFFIX}")
-
-add_executable(mdrun ${MDRUN_SOURCES})
-target_link_libraries(mdrun ${GMX_EXTRA_LIBRARIES} ${GMX_OPENMM_LIBRARIES})
-set_target_properties(mdrun PROPERTIES OUTPUT_NAME "mdrun${GMX_BINARY_SUFFIX}")
-
-# this is to circumvent the following MSVC error: 
-# warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
-# fatal error LNK1169: one or more multiply defined symbols found
-if(GMX_OPENMM AND MSVC)
-    set_target_properties(mdrun PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT")
-endif()
-
-
-install(TARGETS gmxpreprocess DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
-install(TARGETS mdrun DESTINATION ${BIN_INSTALL_DIR} COMPONENT mdrun)
 install(TARGETS 
-        grompp
-        tpbconv
-        pdb2gmx
-        g_protonate
         g_luck
-        gmxdump
-        g_x2top
-        gmxcheck
         COMPONENT runtime
         RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 
-# Create the custom install-mdrun target
-if (BUILD_SHARED_LIBS)
-    # If shared libraries are used, we need to install the libraries in
-    # addition to the mdrun binary.
-    add_custom_target(install-mdrun
-        COMMAND ${CMAKE_COMMAND} -DCOMPONENT=libraries
-                -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
-        COMMAND ${CMAKE_COMMAND} -DCOMPONENT=mdrun
-                -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
-        COMMENT "Installing mdrun")
-else (BUILD_SHARED_LIBS)
-    add_custom_target(install-mdrun
-        COMMAND ${CMAKE_COMMAND} -DCOMPONENT=mdrun
-                -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
-        COMMENT "Installing mdrun")
-endif (BUILD_SHARED_LIBS)
-add_dependencies(install-mdrun mdrun)
-
-endif(GMX_FAHCORE)
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libgmxpreprocess.pc.cmakein ${CMAKE_CURRENT_BINARY_DIR}/libgmxpreprocess.pc @ONLY)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgmxpreprocess.pc
-        DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
-        RENAME "libgmxpreprocess${GMX_LIBS_SUFFIX}.pc"
-        COMPONENT development)
+endif(NOT GMX_FAHCORE)
diff --git a/src/kernel/gctio.c b/src/kernel/gctio.c
deleted file mode 100644 (file)
index 27d46ad..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "typedefs.h"
-#include "xmdrun.h"
-#include "futil.h"
-#include "xvgr.h"
-#include "macros.h"
-#include "physics.h"
-#include "network.h"
-#include "smalloc.h"
-#include "string2.h"
-#include "readinp.h"
-#include "readir.h"
-#include "filenm.h"
-#include "names.h"
-#include "gmxfio.h"
-
-const char *eoNames[eoNR] = { 
-  "Pres", "Epot", "Vir", "Dist", "Mu", "Force", "Fx", "Fy", "Fz",
-  "Px", "Py", "Pz",
-  "Polarizability", "Dipole", "Memory", "UseEinter", "UseVirial",
-  "CombinationRule"
-};
-
-static int Name2eo(char *s)
-{
-  int i,res;
-  
-  res=-1;
-  
-  for(i=0; (i<eoNR); i++)
-    if (gmx_strcasecmp(s,eoNames[i]) == 0) {
-      res=i;
-      fprintf(stderr,"Coupling to observable %d (%s)\n",res,eoNames[res]);
-      break;
-    }
-  
-  return res;
-}
-
-#define  block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
-#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
-#define   snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
-
-static void low_comm_tcr(t_commrec *cr,t_coupl_rec *tcr)
-{
-  nblock_bc(cr,eoObsNR,tcr->ref_value);
-  
-  block_bc(cr,tcr->nLJ);
-  snew_bc(cr,tcr->tcLJ,tcr->nLJ);
-  nblock_bc(cr,tcr->nLJ,tcr->tcLJ);
-  
-  block_bc(cr,tcr->nBU);
-  snew_bc(cr,tcr->tcBU,tcr->nBU);
-  nblock_bc(cr,tcr->nBU,tcr->tcBU);
-  
-  block_bc(cr,tcr->nQ);
-  snew_bc(cr,tcr->tcQ,tcr->nQ);
-  nblock_bc(cr,tcr->nQ,tcr->tcQ);
-  
-  block_bc(cr,tcr->nmemory);
-  block_bc(cr,tcr->bInter);
-  block_bc(cr,tcr->bVirial);
-  block_bc(cr,tcr->combrule);
-}
-
-void comm_tcr(FILE *log,t_commrec *cr,t_coupl_rec **tcr)
-{
-  if (!MASTER(cr))
-    snew(*tcr,1);
-  
-  low_comm_tcr(cr,*tcr);
-} 
-
-static void clear_lj(t_coupl_LJ *tc)
-{
-  tc->at_i   = 0;
-  tc->at_j   = 0;
-  tc->eObs   = -1;
-  tc->bPrint = TRUE;
-  tc->c6     = 0.0;
-  tc->c12    = 0.0;
-  tc->xi_6   = 0.0;
-  tc->xi_12  = 0.0;
-}
-
-static void clear_bu(t_coupl_BU *tc)
-{
-  tc->at_i   = 0;
-  tc->at_j   = 0;
-  tc->eObs   = -1;
-  tc->bPrint = TRUE;
-  tc->a      = 0.0;
-  tc->b      = 0.0;
-  tc->c      = 0.0;
-  tc->xi_a   = 0.0;
-  tc->xi_b   = 0.0;
-  tc->xi_c   = 0.0;
-}
-
-static void clear_q(t_coupl_Q *tc)
-{
-  tc->at_i   = 0;
-  tc->eObs   = -1;
-  tc->bPrint = TRUE;
-  tc->Q      = 0.0;
-  tc->xi_Q   = 0.0;
-}
-
-void copy_ff(t_coupl_rec *tcr,t_forcerec *fr,t_mdatoms *md,t_idef *idef)
-{
-  int        i,j,ati,atj,type;
-  t_coupl_LJ *tclj;
-  t_coupl_BU *tcbu;
-  t_coupl_Q  *tcq;
-  
-  /* Save values for printing */
-  for(i=0; (i<tcr->nLJ); i++) {
-    tclj = &(tcr->tcLJ[i]);
-    
-    ati  = tclj->at_i;
-    atj  = tclj->at_j;
-    if (atj == -1)
-      atj = ati;
-    tclj->c6  = C6(fr->nbfp,fr->ntype,ati,atj);
-    tclj->c12 = C12(fr->nbfp,fr->ntype,ati,atj);
-  }
-  
-  for(i=0; (i<tcr->nBU); i++) {
-    tcbu = &(tcr->tcBU[i]);
-    
-    ati  = tcbu->at_i;
-    atj  = tcbu->at_j;
-    if (atj == -1)
-      atj = ati;
-    tcbu->a = BHAMA(fr->nbfp,fr->ntype,ati,atj);
-    tcbu->b = BHAMB(fr->nbfp,fr->ntype,ati,atj);
-    tcbu->c = BHAMC(fr->nbfp,fr->ntype,ati,atj);
-  }
-  
-  for(i=0; (i<tcr->nQ); i++) {
-    tcq = &(tcr->tcQ[i]);
-    for(j=0; (j<md->nr); j++) {
-      if (md->typeA[j] == tcq->at_i) {
-       tcr->tcQ[i].Q = md->chargeA[j];
-       break;
-      }
-    }
-  }
-  for(i=0; (i<tcr->nIP); i++) {
-    /* Let's just copy the whole struct !*/
-    type = tcr->tIP[i].type;
-    tcr->tIP[i].iprint=idef->iparams[type];
-  }
-}
-
-void write_gct(const char *fn,t_coupl_rec *tcr,t_idef *idef)
-{
-  FILE *fp;
-  int  i,ftype;
-  
-  fp=gmx_fio_fopen(fn,"w");
-  nice_header(fp,fn);
-  fprintf(fp,"%-15s = %12g  ; Reference pressure for coupling\n",
-         eoNames[eoPres],tcr->ref_value[eoPres]);
-  fprintf(fp,"%-15s = %12g  ; Reference potential energy\n",
-         eoNames[eoEpot],tcr->ref_value[eoEpot]);
-  fprintf(fp,"%-15s = %12g  ; Reference distance\n",
-         eoNames[eoDist],tcr->ref_value[eoDist]);
-  fprintf(fp,"%-15s = %12g  ; Reference dipole\n",
-         eoNames[eoMu],tcr->ref_value[eoMu]);
-  fprintf(fp,"%-15s = %12g  ; Reference force\n",
-         eoNames[eoForce],tcr->ref_value[eoForce]);
-  fprintf(fp,"%-15s = %12g  ; Reference force in X dir\n",
-         eoNames[eoFx],tcr->ref_value[eoFx]);
-  fprintf(fp,"%-15s = %12g  ; Reference force in Y dir\n",
-         eoNames[eoFy],tcr->ref_value[eoFy]);
-  fprintf(fp,"%-15s = %12g  ; Reference force in Z dir\n",
-         eoNames[eoFz],tcr->ref_value[eoFz]);
-  fprintf(fp,"%-15s = %12g  ; Reference pres in X dir\n",
-         eoNames[eoPx],tcr->ref_value[eoPx]);
-  fprintf(fp,"%-15s = %12g  ; Reference pres in Y dir\n",
-         eoNames[eoPy],tcr->ref_value[eoPy]);
-  fprintf(fp,"%-15s = %12g  ; Reference pres in Z dir\n",
-         eoNames[eoPz],tcr->ref_value[eoPz]);
-  fprintf(fp,"%-15s = %12g  ; Polarizability used for the Epot correction\n",
-         eoNames[eoPolarizability],tcr->ref_value[eoPolarizability]);
-  fprintf(fp,"%-15s = %12g  ; Gas phase dipole moment used for Epot correction\n", 
-         eoNames[eoDipole],tcr->ref_value[eoDipole]);
-  fprintf(fp,"%-15s = %12d  ; Memory for coupling. Makes it converge faster.\n",
-         eoNames[eoMemory],tcr->nmemory);
-  fprintf(fp,"%-15s = %12s  ; Use intermolecular Epot only (LJ+Coul)\n",
-         eoNames[eoInter],yesno_names[tcr->bInter]);
-  fprintf(fp,"%-15s = %12s  ; Use virial iso pressure\n",
-         eoNames[eoUseVirial],yesno_names[tcr->bVirial]);
-  fprintf(fp,"%-15s = %12d  ; Combination rule, same coding as in grompp.\n",
-         eoNames[eoCombRule],tcr->combrule);
-  
-  fprintf(fp,"\n; Q-Coupling   %6s  %12s\n","type","xi");
-  for(i=0; (i<tcr->nQ); i++) {
-    fprintf(fp,"%-8s = %8s  %6d  %12g\n",
-           "Q",eoNames[tcr->tcQ[i].eObs],tcr->tcQ[i].at_i,tcr->tcQ[i].xi_Q);
-  }
-  
-  fprintf(fp,"\n; %8s %8s  %6s  %6s  %12s  %12s\n","Couple","To",
-         "i-type","j-type","xi-c6","xi-c12");
-  fprintf(fp,"; j-type == -1 means mixing rules will be applied!\n");
-  for(i=0; (i<tcr->nLJ); i++) {
-    fprintf(fp,"%-8s = %8s  %6d  %6d  %12g  %12g\n",
-           "LJ",eoNames[tcr->tcLJ[i].eObs],
-           tcr->tcLJ[i].at_i,tcr->tcLJ[i].at_j,
-           tcr->tcLJ[i].xi_6,tcr->tcLJ[i].xi_12);
-  }
-  
-  fprintf(fp,"\n; %8s %8s  %6s  %6s  %12s  %12s  %12s\n","Couple","To",
-         "i-type","j-type","xi-A","xi-B","xi-C");
-  fprintf(fp,"; j-type == -1 means mixing rules will be applied!\n");
-  for(i=0; (i<tcr->nBU); i++) {
-    fprintf(fp,"%-8s = %8s  %6d  %6d  %12g  %12g  %12g\n",
-           "BU",eoNames[tcr->tcBU[i].eObs],
-           tcr->tcBU[i].at_i,tcr->tcBU[i].at_j,
-           tcr->tcBU[i].xi_a,tcr->tcBU[i].xi_b,tcr->tcBU[i].xi_c);
-  }
-  
-  fprintf(fp,"\n; More Coupling\n");
-  for(i=0; (i<tcr->nIP); i++) {
-    ftype=idef->functype[tcr->tIP[i].type];
-    switch (ftype) {
-    case F_BONDS:
-      fprintf(fp,"%-15s = %-8s  %4d  %12g  %12g\n",
-             "Bonds",eoNames[tcr->tIP[i].eObs],tcr->tIP[i].type,
-             tcr->tIP[i].xi.harmonic.krA,
-             tcr->tIP[i].xi.harmonic.rA);
-      break;
-    default:
-      fprintf(stderr,"ftype %s not supported (yet)\n",
-             interaction_function[ftype].longname);
-    }
-  }
-  gmx_fio_fclose(fp);
-}
-
-static gmx_bool add_lj(int *nLJ,t_coupl_LJ **tcLJ,char *s,gmx_bool bObsUsed[])
-{
-  int       j,ati,atj,eo;
-  char      buf[256];
-  double    xi6,xi12;
-  
-  if (sscanf(s,"%s%d%d%lf%lf",buf,&ati,&atj,&xi6,&xi12) != 5) 
-    return TRUE;
-  if ((eo=Name2eo(buf)) == -1)
-    gmx_fatal(FARGS,"Invalid observable for LJ coupling: %s",buf);
-  
-  for(j=0; (j<*nLJ); j++) {
-    if ((((*tcLJ)[j].at_i == ati) && ((*tcLJ)[j].at_j == atj)) &&
-       ((*tcLJ)[j].xi_6 || (*tcLJ)[j].xi_12) &&
-       ((*tcLJ)[j].eObs == eo))
-      break;
-  }
-  if (j == *nLJ) {
-    ++(*nLJ);
-    srenew((*tcLJ),*nLJ);
-  }
-  else
-    fprintf(stderr,"\n*** WARNING: overwriting entry for LJ coupling '%s'\n",s);
-  
-  clear_lj(&((*tcLJ)[j]));
-  if (((*tcLJ)[j].eObs = eo) == -1) {
-    gmx_fatal(FARGS,"Invalid observable for LJ coupling: %s",buf);
-  }
-  (*tcLJ)[j].at_i   = ati;
-  (*tcLJ)[j].at_j   = atj;
-  (*tcLJ)[j].xi_6   = xi6;
-  (*tcLJ)[j].xi_12  = xi12;
-  bObsUsed[eo] = TRUE;
-  
-  return FALSE;
-}
-
-static gmx_bool add_bu(int *nBU,t_coupl_BU **tcBU,char *s,gmx_bool bObsUsed[])
-{
-  int       j,ati,atj,eo;
-  char      buf[256];
-  double    xia,xib,xic;
-  
-  if (sscanf(s,"%s%d%d%lf%lf%lf",buf,&ati,&atj,&xia,&xib,&xic) != 6) 
-    return TRUE;
-  if ((eo=Name2eo(buf)) == -1)
-    gmx_fatal(FARGS,"Invalid observable for BU coupling: %s",buf);
-  
-  for(j=0; (j<*nBU); j++) {
-    if ((((*tcBU)[j].at_i == ati) && ((*tcBU)[j].at_j == atj)) &&
-       ((*tcBU)[j].xi_a || (*tcBU)[j].xi_b || (*tcBU)[j].xi_c ) &&
-       ((*tcBU)[j].eObs == eo))
-      break;
-  }
-  if (j == *nBU) {
-    ++(*nBU);
-    srenew((*tcBU),*nBU);
-  }
-  else
-    fprintf(stderr,"\n*** WARNING: overwriting entry for BU coupling '%s'\n",s);
-  
-  clear_bu(&((*tcBU)[j]));
-  if (((*tcBU)[j].eObs = eo) == -1) {
-    gmx_fatal(FARGS,"Invalid observable for BU coupling: %s",buf);
-  }
-  (*tcBU)[j].at_i   = ati;
-  (*tcBU)[j].at_j   = atj;
-  (*tcBU)[j].xi_a   = xia;
-  (*tcBU)[j].xi_b   = xib;
-  (*tcBU)[j].xi_c   = xic;
-  bObsUsed[eo] = TRUE;
-
-  return FALSE;
-}
-
-static gmx_bool add_ip(int *nIP,t_coupl_iparams **tIP,char *s,int ftype,gmx_bool bObsUsed[])
-{
-  int    i,eo,type;
-  char   buf[256];
-  double kb,b0;
-  
-  switch (ftype) {
-  case F_BONDS:
-    /* Pick out the type */
-    if (sscanf(s,"%s%d",buf,&type) != 2)
-      return TRUE;
-    if ((eo=Name2eo(buf)) == -1)
-      gmx_fatal(FARGS,"Invalid observable for IP coupling: %s",buf);
-      
-    /* Check whether this entry is there already */
-    for(i=0; (i<*nIP); i++) {
-      if ((*tIP)[i].type == type)
-       break;
-    }
-    if (i < *nIP) {
-      fprintf(stderr,"*** WARNING: overwriting entry for type %d\n",type);
-    }
-    else {
-      i=*nIP;
-      srenew((*tIP),i+1);
-      (*nIP)++;
-    }
-    if (sscanf(s,"%s%d%lf%lf",buf,&type,&kb,&b0) != 4)
-      return TRUE;
-    (*tIP)[i].type=type;
-    (*tIP)[i].eObs=eo;
-    (*tIP)[i].xi.harmonic.krA = kb;
-    (*tIP)[i].xi.harmonic.rA  = b0;
-    bObsUsed[eo] = TRUE;
-    break;
-  default:
-    fprintf(stderr,"ftype %s not supported (yet)\n",
-           interaction_function[ftype].longname);
-    return TRUE;
-  }
-  return FALSE;
-}
-
-static gmx_bool add_q(int *nQ,t_coupl_Q **tcQ,char *s,gmx_bool bObsUsed[])
-{
-  int       j,ati,eo;
-  char      buf[256];
-  double    xiQ;
-  
-  if (sscanf(s,"%s%d%lf",buf,&ati,&xiQ) != 3) 
-    return TRUE;
-  
-  for(j=0; (j<*nQ); j++) {
-    if ((*tcQ)[j].at_i == ati)
-      break;
-  }
-  if (j == *nQ) {
-    ++(*nQ);
-    srenew((*tcQ),*nQ);
-  }
-  else
-    fprintf(stderr,"\n*** WARNING: overwriting entry for Q coupling '%s'\n",s);
-  
-  clear_q(&((*tcQ)[j]));
-  eo = (*tcQ)[j].eObs = Name2eo(buf);
-  if ((*tcQ)[j].eObs == -1) {
-    gmx_fatal(FARGS,"Invalid observable for Q coupling: %s",buf);
-  }
-  (*tcQ)[j].at_i   = ati;
-  (*tcQ)[j].xi_Q  = xiQ;
-  bObsUsed[eo] = TRUE;
-  
-  return FALSE;
-}
-
-void read_gct(const char *fn,t_coupl_rec *tcr)
-{
-  warninp_t wi;
-  t_inpfile *inp;
-  int       i,j,ninp,nQ,nLJ,nBU,nIP;
-  gmx_bool      bWrong;
-  
-  wi = init_warning(FALSE,0);
-
-  inp=read_inpfile(fn,&ninp,NULL,wi);
-
-  for(i=0; (i<eoObsNR); i++) {
-    tcr->bObsUsed[i] = FALSE;
-    RTYPE (eoNames[i], tcr->ref_value[i],      0.0);
-  }
-  ITYPE (eoNames[eoMemory],     tcr->nmemory,   1);
-  ETYPE (eoNames[eoInter],      tcr->bInter,    yesno_names);
-  ETYPE (eoNames[eoUseVirial],  tcr->bVirial,   yesno_names);
-  ITYPE (eoNames[eoCombRule],   tcr->combrule,  1);
-  tcr->tcLJ=NULL;
-  tcr->tcBU=NULL;
-  tcr->tcQ=NULL;
-  tcr->tIP=NULL;
-  nQ=nLJ=nBU=nIP=0;
-  
-  for(i=0; (i<ninp); i++) {
-    bWrong=FALSE;
-    if (gmx_strcasecmp(inp[i].name,"LJ") == 0) 
-      bWrong=add_lj(&nLJ,&(tcr->tcLJ),inp[i].value,tcr->bObsUsed);
-    else if (gmx_strcasecmp(inp[i].name,"BU") == 0) 
-      bWrong=add_bu(&nBU,&(tcr->tcBU),inp[i].value,tcr->bObsUsed);
-    else if (gmx_strcasecmp(inp[i].name,"Q") == 0) 
-      bWrong=add_q(&nQ,&(tcr->tcQ),inp[i].value,tcr->bObsUsed);
-    else if (gmx_strcasecmp(inp[i].name,"Bonds") == 0)
-      bWrong=add_ip(&nIP,&(tcr->tIP),inp[i].value,F_BONDS,tcr->bObsUsed);
-      
-    if (bWrong)
-      fprintf(stderr,"Wrong line in %s: '%s = %s'\n",
-             fn,inp[i].name,inp[i].value);
-    /*sfree(inp[i].name);
-      sfree(inp[i].value);*/
-  }
-  /* Check which ones have to be printed */
-  for(i=1; (i<nQ); i++)
-    for(j=0; (j<i); j++) {
-      if (tcr->tcQ[i].at_i == tcr->tcQ[j].at_i)
-       tcr->tcQ[j].bPrint=FALSE;
-    }
-  for(i=1; (i<nLJ); i++)
-    for(j=0; (j<i); j++) {
-      if (((tcr->tcLJ[i].at_i == tcr->tcLJ[j].at_i) &&
-          (tcr->tcLJ[i].at_j == tcr->tcLJ[j].at_j)) ||
-         ((tcr->tcLJ[i].at_i == tcr->tcLJ[j].at_j) &&
-          (tcr->tcLJ[i].at_j == tcr->tcLJ[j].at_i))) 
-       tcr->tcLJ[j].bPrint=FALSE;
-    }
-  
-  for(i=1; (i<nBU); i++)
-    for(j=0; (j<i); j++) {
-      if (((tcr->tcBU[i].at_i == tcr->tcBU[j].at_i) &&
-          (tcr->tcBU[i].at_j == tcr->tcBU[j].at_j)) ||
-         ((tcr->tcBU[i].at_i == tcr->tcBU[j].at_j) &&
-          (tcr->tcBU[i].at_j == tcr->tcBU[j].at_i))) 
-       tcr->tcBU[j].bPrint=FALSE;
-    }
-  
-  tcr->nQ  = nQ;
-  tcr->nLJ = nLJ;
-  tcr->nBU = nBU;
-  tcr->nIP = nIP;
-  
-  sfree(inp);
-
-  done_warning(wi,FARGS);
-}
-
diff --git a/src/kernel/grompp.c b/src/kernel/grompp.c
deleted file mode 100644 (file)
index 2d3b716..0000000
+++ /dev/null
@@ -1,1592 +0,0 @@
-/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.03
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <math.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "string2.h"
-#include "readir.h"
-#include "toputil.h"
-#include "topio.h"
-#include "confio.h"
-#include "copyrite.h"
-#include "readir.h"
-#include "symtab.h"
-#include "names.h"
-#include "grompp.h"
-#include "random.h"
-#include "vec.h"
-#include "futil.h"
-#include "statutil.h"
-#include "splitter.h"
-#include "sortwater.h"
-#include "convparm.h"
-#include "gmx_fatal.h"
-#include "warninp.h"
-#include "index.h"
-#include "gmxfio.h"
-#include "trnio.h"
-#include "tpxio.h"
-#include "vsite_parm.h"
-#include "txtdump.h"
-#include "calcgrid.h"
-#include "add_par.h"
-#include "enxio.h"
-#include "perf_est.h"
-#include "compute_io.h"
-#include "gpp_atomtype.h"
-#include "gpp_tomorse.h"
-#include "mtop_util.h"
-#include "genborn.h"
-
-static int rm_interactions(int ifunc,int nrmols,t_molinfo mols[])
-{
-  int  i,n;
-  
-  n=0;
-  /* For all the molecule types */
-  for(i=0; i<nrmols; i++) {
-    n += mols[i].plist[ifunc].nr;
-    mols[i].plist[ifunc].nr=0;
-  }
-  return n;
-}
-
-static int check_atom_names(const char *fn1, const char *fn2, 
-                           gmx_mtop_t *mtop, t_atoms *at)
-{
-  int mb,m,i,j,nmismatch;
-  t_atoms *tat;
-#define MAXMISMATCH 20
-
-  if (mtop->natoms != at->nr)
-    gmx_incons("comparing atom names");
-  
-  nmismatch=0;
-  i = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    tat = &mtop->moltype[mtop->molblock[mb].type].atoms;
-    for(m=0; m<mtop->molblock[mb].nmol; m++) {
-      for(j=0; j < tat->nr; j++) {
-       if (strcmp( *(tat->atomname[j]) , *(at->atomname[i]) ) != 0) {
-         if (nmismatch < MAXMISMATCH) {
-           fprintf(stderr,
-                   "Warning: atom name %d in %s and %s does not match (%s - %s)\n",
-                   i+1, fn1, fn2, *(tat->atomname[j]), *(at->atomname[i]));
-         } else if (nmismatch == MAXMISMATCH) {
-           fprintf(stderr,"(more than %d non-matching atom names)\n",MAXMISMATCH);
-         }
-         nmismatch++;
-       }
-       i++;
-      }
-    }
-  }
-
-  return nmismatch;
-}
-
-static void check_eg_vs_cg(gmx_mtop_t *mtop)
-{
-  int astart,mb,m,cg,j,firstj;
-  unsigned char firsteg,eg;
-  gmx_moltype_t *molt;
-  
-  /* Go through all the charge groups and make sure all their
-   * atoms are in the same energy group.
-   */
-  
-  astart = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    molt = &mtop->moltype[mtop->molblock[mb].type];
-    for(m=0; m<mtop->molblock[mb].nmol; m++) {
-      for(cg=0; cg<molt->cgs.nr;cg++) {
-       /* Get the energy group of the first atom in this charge group */
-       firstj = astart + molt->cgs.index[cg];
-       firsteg = ggrpnr(&mtop->groups,egcENER,firstj);
-       for(j=molt->cgs.index[cg]+1;j<molt->cgs.index[cg+1];j++) {
-         eg = ggrpnr(&mtop->groups,egcENER,astart+j);
-         if(eg != firsteg) {
-           gmx_fatal(FARGS,"atoms %d and %d in charge group %d of molecule type '%s' are in different energy groups",
-                     firstj+1,astart+j+1,cg+1,*molt->name);
-         }
-       }
-      }
-      astart += molt->atoms.nr;
-    }
-  }  
-}
-
-static void check_cg_sizes(const char *topfn,t_block *cgs,warninp_t wi)
-{
-    int  maxsize,cg;
-    char warn_buf[STRLEN];
-
-    maxsize = 0;
-    for(cg=0; cg<cgs->nr; cg++)
-    {
-        maxsize = max(maxsize,cgs->index[cg+1]-cgs->index[cg]);
-    }
-    
-    if (maxsize > MAX_CHARGEGROUP_SIZE)
-    {
-        gmx_fatal(FARGS,"The largest charge group contains %d atoms. The maximum is %d.",maxsize,MAX_CHARGEGROUP_SIZE);
-    }
-    else if (maxsize > 10)
-    {
-        set_warning_line(wi,topfn,-1);
-        sprintf(warn_buf,
-                "The largest charge group contains %d atoms.\n"
-                "Since atoms only see each other when the centers of geometry of the charge groups they belong to are within the cut-off distance, too large charge groups can lead to serious cut-off artifacts.\n"
-                "For efficiency and accuracy, charge group should consist of a few atoms.\n"
-                "For all-atom force fields use: CH3, CH2, CH, NH2, NH, OH, CO2, CO, etc.",
-                maxsize);
-        warning_note(wi,warn_buf);
-    }
-}
-
-static void check_bonds_timestep(gmx_mtop_t *mtop,double dt,warninp_t wi)
-{
-    /* This check is not intended to ensure accurate integration,
-     * rather it is to signal mistakes in the mdp settings.
-     * A common mistake is to forget to turn on constraints
-     * for MD after energy minimization with flexible bonds.
-     * This check can also detect too large time steps for flexible water
-     * models, but such errors will often be masked by the constraints
-     * mdp options, which turns flexible water into water with bond constraints,
-     * but without an angle constraint. Unfortunately such incorrect use
-     * of water models can not easily be detected without checking
-     * for specific model names.
-     *
-     * The stability limit of leap-frog or velocity verlet is 4.44 steps
-     * per oscillational period.
-     * But accurate bonds distributions are lost far before that limit.
-     * To allow relatively common schemes (although not common with Gromacs)
-     * of dt=1 fs without constraints and dt=2 fs with only H-bond constraints
-     * we set the note limit to 10.
-     */
-    int       min_steps_warn=5;
-    int       min_steps_note=10;
-    t_iparams *ip;
-    int       molt;
-    gmx_moltype_t *moltype,*w_moltype;
-    t_atom    *atom;
-    t_ilist   *ilist,*ilb,*ilc,*ils;
-    int       ftype;
-    int       i,a1,a2,w_a1,w_a2,j;
-    real      twopi2,limit2,fc,re,m1,m2,period2,w_period2;
-    gmx_bool  bFound,bWater,bWarn;
-    char      warn_buf[STRLEN];
-
-    ip = mtop->ffparams.iparams;
-
-    twopi2 = sqr(2*M_PI);
-
-    limit2 = sqr(min_steps_note*dt);
-
-    w_a1 = w_a2 = -1;
-    w_period2 = -1.0;
-    
-    w_moltype = NULL;
-    for(molt=0; molt<mtop->nmoltype; molt++)
-    {
-        moltype = &mtop->moltype[molt];
-        atom  = moltype->atoms.atom;
-        ilist = moltype->ilist;
-        ilc = &ilist[F_CONSTR];
-        ils = &ilist[F_SETTLE];
-        for(ftype=0; ftype<F_NRE; ftype++)
-        {
-            if (!(ftype == F_BONDS || ftype == F_G96BONDS || ftype == F_HARMONIC))
-            {
-                continue;
-            }
-            
-            ilb = &ilist[ftype];
-            for(i=0; i<ilb->nr; i+=3)
-            {
-                fc = ip[ilb->iatoms[i]].harmonic.krA;
-                re = ip[ilb->iatoms[i]].harmonic.rA;
-                if (ftype == F_G96BONDS)
-                {
-                    /* Convert squared sqaure fc to harmonic fc */
-                    fc = 2*fc*re;
-                }
-                a1 = ilb->iatoms[i+1];
-                a2 = ilb->iatoms[i+2];
-                m1 = atom[a1].m;
-                m2 = atom[a2].m;
-                if (fc > 0 && m1 > 0 && m2 > 0)
-                {
-                    period2 = twopi2*m1*m2/((m1 + m2)*fc);
-                }
-                else
-                {
-                    period2 = GMX_FLOAT_MAX;
-                }
-                if (debug)
-                {
-                    fprintf(debug,"fc %g m1 %g m2 %g period %g\n",
-                            fc,m1,m2,sqrt(period2));
-                }
-                if (period2 < limit2)
-                {
-                    bFound = FALSE;
-                    for(j=0; j<ilc->nr; j+=3)
-                    {
-                        if ((ilc->iatoms[j+1] == a1 && ilc->iatoms[j+2] == a2) ||
-                            (ilc->iatoms[j+1] == a2 && ilc->iatoms[j+2] == a1))
-                            {
-                                bFound = TRUE;
-                            }
-                        }
-                    for(j=0; j<ils->nr; j+=2)
-                    {
-                        if ((a1 >= ils->iatoms[j+1] && a1 < ils->iatoms[j+1]+3) &&
-                            (a2 >= ils->iatoms[j+1] && a2 < ils->iatoms[j+1]+3))
-                        {
-                            bFound = TRUE;
-                        }
-                    }
-                    if (!bFound &&
-                        (w_moltype == NULL || period2 < w_period2))
-                    {
-                        w_moltype = moltype;
-                        w_a1      = a1;
-                        w_a2      = a2;
-                        w_period2 = period2;
-                    }
-                }
-            }
-        }
-    }
-    
-    if (w_moltype != NULL)
-    {
-        bWarn = (w_period2 < sqr(min_steps_warn*dt));
-        /* A check that would recognize most water models */
-        bWater = ((*w_moltype->atoms.atomname[0])[0] == 'O' &&
-                  w_moltype->atoms.nr <= 5);
-        sprintf(warn_buf,"The bond in molecule-type %s between atoms %d %s and %d %s has an estimated oscillational period of %.1e ps, which is less than %d times the time step of %.1e ps.\n"
-                "%s",
-                *w_moltype->name,
-                w_a1+1,*w_moltype->atoms.atomname[w_a1],
-                w_a2+1,*w_moltype->atoms.atomname[w_a2],
-                sqrt(w_period2),bWarn ? min_steps_warn : min_steps_note,dt,
-                bWater ?
-                "Maybe you asked for fexible water." :
-                "Maybe you forgot to change the constraints mdp option.");
-        if (bWarn)
-        {
-            warning(wi,warn_buf);
-        }
-        else
-        {
-            warning_note(wi,warn_buf);
-        }
-    }
-}
-
-static void check_vel(gmx_mtop_t *mtop,rvec v[])
-{
-  gmx_mtop_atomloop_all_t aloop;
-  t_atom *atom;
-  int a;
-
-  aloop = gmx_mtop_atomloop_all_init(mtop);
-  while (gmx_mtop_atomloop_all_next(aloop,&a,&atom)) {
-    if (atom->ptype == eptShell ||
-       atom->ptype == eptBond  ||
-       atom->ptype == eptVSite) {
-      clear_rvec(v[a]);
-    }
-  }
-}
-
-static gmx_bool nint_ftype(gmx_mtop_t *mtop,t_molinfo *mi,int ftype)
-{
-  int nint,mb;
-
-  nint = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    nint += mtop->molblock[mb].nmol*mi[mtop->molblock[mb].type].plist[ftype].nr;
-  }
-
-  return nint;
-}
-
-/* This routine reorders the molecule type array
- * in the order of use in the molblocks,
- * unused molecule types are deleted.
- */
-static void renumber_moltypes(gmx_mtop_t *sys,
-                             int *nmolinfo,t_molinfo **molinfo)
-{
-  int *order,norder,i;
-  int mb,mi;
-  t_molinfo *minew;
-
-  snew(order,*nmolinfo);
-  norder = 0;
-  for(mb=0; mb<sys->nmolblock; mb++) {
-    for(i=0; i<norder; i++) {
-      if (order[i] == sys->molblock[mb].type) {
-       break;
-      }
-    }
-    if (i == norder) {
-      /* This type did not occur yet, add it */
-      order[norder] = sys->molblock[mb].type;
-      /* Renumber the moltype in the topology */
-      norder++;
-    }
-    sys->molblock[mb].type = i;
-  }
-  
-  /* We still need to reorder the molinfo structs */
-  snew(minew,norder);
-  for(mi=0; mi<*nmolinfo; mi++) {
-    for(i=0; i<norder; i++) {
-      if (order[i] == mi) {
-       break;
-      }
-    }
-    if (i == norder) {
-      done_mi(&(*molinfo)[mi]);
-    } else {
-      minew[i] = (*molinfo)[mi];
-    }
-  }
-  sfree(*molinfo);
-
-  *nmolinfo = norder;
-  *molinfo  = minew;
-}
-
-static void molinfo2mtop(int nmi,t_molinfo *mi,gmx_mtop_t *mtop)
-{
-  int m;
-  gmx_moltype_t *molt;
-
-  mtop->nmoltype = nmi;
-  snew(mtop->moltype,nmi);
-  for(m=0; m<nmi; m++) {
-    molt = &mtop->moltype[m];
-    molt->name  = mi[m].name;
-    molt->atoms = mi[m].atoms;
-    /* ilists are copied later */
-    molt->cgs   = mi[m].cgs;
-    molt->excls = mi[m].excls;
-  }
-}
-
-static void
-new_status(const char *topfile,const char *topppfile,const char *confin,
-           t_gromppopts *opts,t_inputrec *ir,gmx_bool bZero,
-           gmx_bool bGenVel,gmx_bool bVerbose,t_state *state,
-           gpp_atomtype_t atype,gmx_mtop_t *sys,
-           int *nmi,t_molinfo **mi,t_params plist[],
-           int *comb,double *reppow,real *fudgeQQ,
-           gmx_bool bMorse,
-           warninp_t wi)
-{
-  t_molinfo   *molinfo=NULL;
-  int         nmolblock;
-  gmx_molblock_t *molblock,*molbs;
-  t_atoms     *confat;
-  int         mb,i,nrmols,nmismatch;
-  char        buf[STRLEN];
-  gmx_bool        bGB=FALSE;
-  char        warn_buf[STRLEN];
-
-  init_mtop(sys);
-
-  /* Set gmx_boolean for GB */
-  if(ir->implicit_solvent)
-    bGB=TRUE;
-  
-  /* TOPOLOGY processing */
-  sys->name = do_top(bVerbose,topfile,topppfile,opts,bZero,&(sys->symtab),
-                     plist,comb,reppow,fudgeQQ,
-                     atype,&nrmols,&molinfo,ir,
-                     &nmolblock,&molblock,bGB,
-                     wi);
-  
-  sys->nmolblock = 0;
-  snew(sys->molblock,nmolblock);
-  
-  sys->natoms = 0;
-  for(mb=0; mb<nmolblock; mb++) {
-    if (sys->nmolblock > 0 &&
-       molblock[mb].type == sys->molblock[sys->nmolblock-1].type) {
-      /* Merge consecutive blocks with the same molecule type */
-      sys->molblock[sys->nmolblock-1].nmol += molblock[mb].nmol;
-      sys->natoms += molblock[mb].nmol*sys->molblock[sys->nmolblock-1].natoms_mol;
-    } else if (molblock[mb].nmol > 0) {
-      /* Add a new molblock to the topology */
-      molbs = &sys->molblock[sys->nmolblock];
-      *molbs = molblock[mb];
-      molbs->natoms_mol = molinfo[molbs->type].atoms.nr;
-      molbs->nposres_xA = 0;
-      molbs->nposres_xB = 0;
-      sys->natoms += molbs->nmol*molbs->natoms_mol;
-      sys->nmolblock++;
-    }
-  }
-  if (sys->nmolblock == 0) {
-    gmx_fatal(FARGS,"No molecules were defined in the system");
-  }
-
-  renumber_moltypes(sys,&nrmols,&molinfo);
-
-  if (bMorse)
-    convert_harmonics(nrmols,molinfo,atype);
-
-  if (ir->eDisre == edrNone) {
-    i = rm_interactions(F_DISRES,nrmols,molinfo);
-    if (i > 0) {
-      set_warning_line(wi,"unknown",-1);
-      sprintf(warn_buf,"disre = no, removed %d distance restraints",i);
-      warning_note(wi,warn_buf);
-    }
-  }
-  if (opts->bOrire == FALSE) {
-    i = rm_interactions(F_ORIRES,nrmols,molinfo);
-    if (i > 0) {
-      set_warning_line(wi,"unknown",-1);
-      sprintf(warn_buf,"orire = no, removed %d orientation restraints",i);
-      warning_note(wi,warn_buf);
-    }
-  }
-  if (opts->bDihre == FALSE) {
-    i = rm_interactions(F_DIHRES,nrmols,molinfo);
-    if (i > 0) {
-      set_warning_line(wi,"unknown",-1);
-      sprintf(warn_buf,"dihre = no, removed %d dihedral restraints",i);
-      warning_note(wi,warn_buf);
-    }
-  }
-  
-  /* Copy structures from msys to sys */
-  molinfo2mtop(nrmols,molinfo,sys);
-
-  gmx_mtop_finalize(sys);
-  /* COORDINATE file processing */
-  if (bVerbose) 
-    fprintf(stderr,"processing coordinates...\n");
-
-  get_stx_coordnum(confin,&state->natoms);
-  if (state->natoms != sys->natoms)
-    gmx_fatal(FARGS,"number of coordinates in coordinate file (%s, %d)\n"
-               "             does not match topology (%s, %d)",
-             confin,state->natoms,topfile,sys->natoms);
-  else {
-    /* make space for coordinates and velocities */
-    char title[STRLEN];
-    snew(confat,1);
-    init_t_atoms(confat,state->natoms,FALSE);
-    init_state(state,state->natoms,0,0,0);
-    read_stx_conf(confin,title,confat,state->x,state->v,NULL,state->box);
-    /* This call fixes the box shape for runs with pressure scaling */
-    set_box_rel(ir,state);
-
-    nmismatch = check_atom_names(topfile, confin, sys, confat);
-    free_t_atoms(confat,TRUE);
-    sfree(confat);
-    
-    if (nmismatch) {
-      sprintf(buf,"%d non-matching atom name%s\n"
-             "atom names from %s will be used\n"
-             "atom names from %s will be ignored\n",
-             nmismatch,(nmismatch == 1) ? "" : "s",topfile,confin);
-      warning(wi,buf);
-    }    
-    if (bVerbose) 
-      fprintf(stderr,"double-checking input for internal consistency...\n");
-    double_check(ir,state->box,nint_ftype(sys,molinfo,F_CONSTR),wi);
-  }
-
-  if (bGenVel) {
-    real *mass;
-    gmx_mtop_atomloop_all_t aloop;
-    t_atom *atom;
-
-    snew(mass,state->natoms);
-    aloop = gmx_mtop_atomloop_all_init(sys);
-    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
-      mass[i] = atom->m;
-    }
-
-    if (opts->seed == -1) {
-      opts->seed = make_seed();
-      fprintf(stderr,"Setting gen_seed to %d\n",opts->seed);
-    }
-    maxwell_speed(opts->tempi,opts->seed,sys,state->v);
-
-    stop_cm(stdout,state->natoms,mass,state->x,state->v);
-    sfree(mass);
-  }
-
-  *nmi = nrmols;
-  *mi  = molinfo;
-}
-
-static void copy_state(const char *slog,t_trxframe *fr,
-                       gmx_bool bReadVel,t_state *state,
-                       double *use_time)
-{
-    int i;
-
-    if (fr->not_ok & FRAME_NOT_OK)
-    {
-        gmx_fatal(FARGS,"Can not start from an incomplete frame");
-    }
-    if (!fr->bX)
-    {
-        gmx_fatal(FARGS,"Did not find a frame with coordinates in file %s",
-                  slog);
-    }
-
-    for(i=0; i<state->natoms; i++)
-    {
-        copy_rvec(fr->x[i],state->x[i]);
-    }
-    if (bReadVel)
-    {
-        if (!fr->bV)
-        {
-            gmx_incons("Trajecory frame unexpectedly does not contain velocities");
-        }
-        for(i=0; i<state->natoms; i++)
-        {
-            copy_rvec(fr->v[i],state->v[i]);
-        }
-    }
-    if (fr->bBox)
-    {
-        copy_mat(fr->box,state->box);
-    }
-
-    *use_time = fr->time;
-}
-
-static void cont_status(const char *slog,const char *ener,
-                       gmx_bool bNeedVel,gmx_bool bGenVel, real fr_time,
-                       t_inputrec *ir,t_state *state,
-                       gmx_mtop_t *sys,
-                        const output_env_t oenv)
-     /* If fr_time == -1 read the last frame available which is complete */
-{
-    gmx_bool bReadVel;
-    t_trxframe  fr;
-    t_trxstatus *fp;
-    int i;
-    double use_time;
-
-    bReadVel = (bNeedVel && !bGenVel);
-
-    fprintf(stderr,
-            "Reading Coordinates%s and Box size from old trajectory\n",
-            bReadVel ? ", Velocities" : "");
-    if (fr_time == -1)
-    {
-        fprintf(stderr,"Will read whole trajectory\n");
-    }
-    else
-    {
-        fprintf(stderr,"Will read till time %g\n",fr_time);
-    }
-    if (!bReadVel)
-    {
-        if (bGenVel)
-        {
-            fprintf(stderr,"Velocities generated: "
-                    "ignoring velocities in input trajectory\n");
-        }
-        read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X);
-    }
-    else
-    {
-        read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X | TRX_NEED_V);
-        
-        if (!fr.bV)
-        {
-            fprintf(stderr,
-                    "\n"
-                    "WARNING: Did not find a frame with velocities in file %s,\n"
-                    "         all velocities will be set to zero!\n\n",slog);
-            for(i=0; i<sys->natoms; i++)
-            {
-                clear_rvec(state->v[i]);
-            }
-            close_trj(fp);
-            /* Search for a frame without velocities */
-            bReadVel = FALSE;
-            read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X);
-        }
-    }
-
-    state->natoms = fr.natoms;
-
-    if (sys->natoms != state->natoms)
-    {
-        gmx_fatal(FARGS,"Number of atoms in Topology "
-                  "is not the same as in Trajectory");
-    }
-    copy_state(slog,&fr,bReadVel,state,&use_time);
-
-    /* Find the appropriate frame */
-    while ((fr_time == -1 || fr.time < fr_time) &&
-           read_next_frame(oenv,fp,&fr))
-    {
-        copy_state(slog,&fr,bReadVel,state,&use_time);
-    }
-  
-    close_trj(fp);
-
-    /* Set the relative box lengths for preserving the box shape.
-     * Note that this call can lead to differences in the last bit
-     * with respect to using tpbconv to create a [TT].tpx[tt] file.
-     */
-    set_box_rel(ir,state);
-
-    fprintf(stderr,"Using frame at t = %g ps\n",use_time);
-    fprintf(stderr,"Starting time for run is %g ps\n",ir->init_t); 
-  
-    if ((ir->epc != epcNO  || ir->etc ==etcNOSEHOOVER) && ener)
-    {
-        get_enx_state(ener,use_time,&sys->groups,ir,state);
-        preserve_box_shape(ir,state->box_rel,state->boxv);
-    }
-}
-
-static void read_posres(gmx_mtop_t *mtop,t_molinfo *molinfo,gmx_bool bTopB,
-                        char *fn,
-                        int rc_scaling, int ePBC, 
-                        rvec com,
-                        warninp_t wi)
-{
-  gmx_bool   bFirst = TRUE;
-  rvec   *x,*v,*xp;
-  dvec   sum;
-  double totmass;
-  t_atoms dumat;
-  matrix box,invbox;
-  int    natoms,npbcdim=0;
-  char   warn_buf[STRLEN],title[STRLEN];
-  int    a,i,ai,j,k,mb,nat_molb;
-  gmx_molblock_t *molb;
-  t_params *pr;
-  t_atom *atom;
-
-  get_stx_coordnum(fn,&natoms);
-  if (natoms != mtop->natoms) {
-    sprintf(warn_buf,"The number of atoms in %s (%d) does not match the number of atoms in the topology (%d). Will assume that the first %d atoms in the topology and %s match.",fn,natoms,mtop->natoms,min(mtop->natoms,natoms),fn);
-    warning(wi,warn_buf);
-  }
-  snew(x,natoms);
-  snew(v,natoms);
-  init_t_atoms(&dumat,natoms,FALSE);
-  read_stx_conf(fn,title,&dumat,x,v,NULL,box);
-  
-  npbcdim = ePBC2npbcdim(ePBC);
-  clear_rvec(com);
-  if (rc_scaling != erscNO) {
-    copy_mat(box,invbox);
-    for(j=npbcdim; j<DIM; j++) {
-      clear_rvec(invbox[j]);
-      invbox[j][j] = 1;
-    }
-    m_inv_ur0(invbox,invbox);
-  }
-
-  /* Copy the reference coordinates to mtop */
-  clear_dvec(sum);
-  totmass = 0;
-  a = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    molb = &mtop->molblock[mb];
-    nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
-    pr = &(molinfo[molb->type].plist[F_POSRES]);
-    if (pr->nr > 0) {
-      atom = mtop->moltype[molb->type].atoms.atom;
-      for(i=0; (i<pr->nr); i++) {
-       ai=pr->param[i].AI;
-       if (ai >= natoms) {
-         gmx_fatal(FARGS,"Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n",
-                   ai+1,*molinfo[molb->type].name,fn,natoms);
-       }
-       if (rc_scaling == erscCOM) {
-         /* Determine the center of mass of the posres reference coordinates */
-         for(j=0; j<npbcdim; j++) {
-           sum[j] += atom[ai].m*x[a+ai][j];
-         }
-         totmass  += atom[ai].m;
-       }
-      }
-      if (!bTopB) {
-       molb->nposres_xA = nat_molb;
-       snew(molb->posres_xA,molb->nposres_xA);
-       for(i=0; i<nat_molb; i++) {
-         copy_rvec(x[a+i],molb->posres_xA[i]);
-       }
-      } else {
-       molb->nposres_xB = nat_molb;
-       snew(molb->posres_xB,molb->nposres_xB);
-       for(i=0; i<nat_molb; i++) {
-         copy_rvec(x[a+i],molb->posres_xB[i]);
-       }
-      }
-    }
-    a += nat_molb;
-  }
-  if (rc_scaling == erscCOM) {
-    if (totmass == 0)
-      gmx_fatal(FARGS,"The total mass of the position restraint atoms is 0");
-    for(j=0; j<npbcdim; j++)
-      com[j] = sum[j]/totmass;
-    fprintf(stderr,"The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n",com[XX],com[YY],com[ZZ]);
-  }
-
-  if (rc_scaling != erscNO) {
-    for(mb=0; mb<mtop->nmolblock; mb++) {
-      molb = &mtop->molblock[mb];
-      nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
-      if (molb->nposres_xA > 0 || molb->nposres_xB > 0) {
-       xp = (!bTopB ? molb->posres_xA : molb->posres_xB);
-       for(i=0; i<nat_molb; i++) {
-         for(j=0; j<npbcdim; j++) {
-           if (rc_scaling == erscALL) {
-             /* Convert from Cartesian to crystal coordinates */
-             xp[i][j] *= invbox[j][j];
-             for(k=j+1; k<npbcdim; k++) {
-               xp[i][j] += invbox[k][j]*xp[i][k];
-             }
-           } else if (rc_scaling == erscCOM) {
-             /* Subtract the center of mass */
-             xp[i][j] -= com[j];
-           }
-         }
-       }
-      }
-    }
-
-    if (rc_scaling == erscCOM) {
-      /* Convert the COM from Cartesian to crystal coordinates */
-      for(j=0; j<npbcdim; j++) {
-       com[j] *= invbox[j][j];
-       for(k=j+1; k<npbcdim; k++) {
-         com[j] += invbox[k][j]*com[k];
-       }
-      }
-    }
-  }
-  
-  free_t_atoms(&dumat,TRUE);
-  sfree(x);
-  sfree(v);
-}
-
-static void gen_posres(gmx_mtop_t *mtop,t_molinfo *mi,
-                       char *fnA, char *fnB,
-                       int rc_scaling, int ePBC,
-                       rvec com, rvec comB,
-                       warninp_t wi)
-{
-  int i,j;
-
-  read_posres  (mtop,mi,FALSE,fnA,rc_scaling,ePBC,com,wi);
-  if (strcmp(fnA,fnB) != 0) {
-      read_posres(mtop,mi,TRUE ,fnB,rc_scaling,ePBC,comB,wi);
-  }
-}
-
-static void set_wall_atomtype(gpp_atomtype_t at,t_gromppopts *opts,
-                             t_inputrec *ir)
-{
-  int i;
-
-  if (ir->nwall > 0)
-    fprintf(stderr,"Searching the wall atom type(s)\n");
-  for(i=0; i<ir->nwall; i++)
-    ir->wall_atomtype[i] = get_atomtype_type(opts->wall_atomtype[i],at);
-}
-
-static int nrdf_internal(t_atoms *atoms)
-{
-  int i,nmass,nrdf;
-
-  nmass = 0;
-  for(i=0; i<atoms->nr; i++) {
-    /* Vsite ptype might not be set here yet, so also check the mass */
-    if ((atoms->atom[i].ptype == eptAtom ||
-        atoms->atom[i].ptype == eptNucleus)
-       && atoms->atom[i].m > 0) {
-      nmass++;
-    }
-  }
-  switch (nmass) {
-  case 0:  nrdf = 0; break;
-  case 1:  nrdf = 0; break;
-  case 2:  nrdf = 1; break;
-  default: nrdf = nmass*3 - 6; break;
-  }
-  
-  return nrdf;
-}
-
-void
-spline1d( double        dx,
-                double *      y,
-                int           n,
-                double *      u,
-                double *      y2 )
-{
-    int i;
-    double p,q;
-       
-    y2[0] = 0.0;
-    u[0]  = 0.0;
-       
-    for(i=1;i<n-1;i++)
-    {
-               p = 0.5*y2[i-1]+2.0;
-        y2[i] = -0.5/p;
-        q = (y[i+1]-2.0*y[i]+y[i-1])/dx;
-               u[i] = (3.0*q/dx-0.5*u[i-1])/p;
-    }
-       
-    y2[n-1] = 0.0;
-       
-    for(i=n-2;i>=0;i--)
-    {
-        y2[i] = y2[i]*y2[i+1]+u[i];
-    }
-}
-
-
-void
-interpolate1d( double     xmin,
-                         double     dx,
-                         double *   ya,
-                         double *   y2a,
-                         double     x,
-                         double *   y,
-                         double *   y1)
-{
-    int ix;
-    double a,b;
-       
-    ix = (x-xmin)/dx;
-       
-    a = (xmin+(ix+1)*dx-x)/dx;
-    b = (x-xmin-ix*dx)/dx;
-       
-    *y  = a*ya[ix]+b*ya[ix+1]+((a*a*a-a)*y2a[ix]+(b*b*b-b)*y2a[ix+1])*(dx*dx)/6.0;
-    *y1 = (ya[ix+1]-ya[ix])/dx-(3.0*a*a-1.0)/6.0*dx*y2a[ix]+(3.0*b*b-1.0)/6.0*dx*y2a[ix+1];
-}
-
-
-void
-setup_cmap (int              grid_spacing,
-                       int              nc,
-                       real *           grid ,
-                       gmx_cmap_t *     cmap_grid)
-{
-       double *tmp_u,*tmp_u2,*tmp_yy,*tmp_y1,*tmp_t2,*tmp_grid;
-       
-    int    i,j,k,ii,jj,kk,idx;
-       int    offset;
-    double dx,xmin,v,v1,v2,v12;
-    double phi,psi;
-       
-       snew(tmp_u,2*grid_spacing);
-       snew(tmp_u2,2*grid_spacing);
-       snew(tmp_yy,2*grid_spacing);
-       snew(tmp_y1,2*grid_spacing);
-       snew(tmp_t2,2*grid_spacing*2*grid_spacing);
-       snew(tmp_grid,2*grid_spacing*2*grid_spacing);
-       
-    dx = 360.0/grid_spacing;
-    xmin = -180.0-dx*grid_spacing/2;
-       
-       for(kk=0;kk<nc;kk++)
-       {
-               /* Compute an offset depending on which cmap we are using                                 
-                * Offset will be the map number multiplied with the grid_spacing * grid_spacing * 2      
-                */
-               offset = kk * grid_spacing * grid_spacing * 2;
-               
-               for(i=0;i<2*grid_spacing;i++)
-               {
-                       ii=(i+grid_spacing-grid_spacing/2)%grid_spacing;
-                       
-                       for(j=0;j<2*grid_spacing;j++)
-                       {
-                               jj=(j+grid_spacing-grid_spacing/2)%grid_spacing;
-                               tmp_grid[i*grid_spacing*2+j] = grid[offset+ii*grid_spacing+jj];
-                       }
-               }
-               
-               for(i=0;i<2*grid_spacing;i++)
-               {
-                       spline1d(dx,&(tmp_grid[2*grid_spacing*i]),2*grid_spacing,tmp_u,&(tmp_t2[2*grid_spacing*i]));
-               }
-               
-               for(i=grid_spacing/2;i<grid_spacing+grid_spacing/2;i++)
-               {
-                       ii = i-grid_spacing/2;
-                       phi = ii*dx-180.0;
-                       
-                       for(j=grid_spacing/2;j<grid_spacing+grid_spacing/2;j++)
-                       {
-                               jj = j-grid_spacing/2;
-                               psi = jj*dx-180.0;
-                               
-                               for(k=0;k<2*grid_spacing;k++)
-                               {
-                                       interpolate1d(xmin,dx,&(tmp_grid[2*grid_spacing*k]),
-                                                                 &(tmp_t2[2*grid_spacing*k]),psi,&tmp_yy[k],&tmp_y1[k]);
-                               }
-                               
-                               spline1d(dx,tmp_yy,2*grid_spacing,tmp_u,tmp_u2);
-                               interpolate1d(xmin,dx,tmp_yy,tmp_u2,phi,&v,&v1);
-                               spline1d(dx,tmp_y1,2*grid_spacing,tmp_u,tmp_u2);
-                               interpolate1d(xmin,dx,tmp_y1,tmp_u2,phi,&v2,&v12);
-                               
-                               idx = ii*grid_spacing+jj;
-                               cmap_grid->cmapdata[kk].cmap[idx*4] = grid[offset+ii*grid_spacing+jj];
-                               cmap_grid->cmapdata[kk].cmap[idx*4+1] = v1;
-                               cmap_grid->cmapdata[kk].cmap[idx*4+2] = v2;
-                               cmap_grid->cmapdata[kk].cmap[idx*4+3] = v12;
-                       }
-               }
-       }
-}                              
-                               
-void init_cmap_grid(gmx_cmap_t *cmap_grid, int ngrid, int grid_spacing)
-{
-       int i,k,nelem;
-       
-       cmap_grid->ngrid        = ngrid;
-       cmap_grid->grid_spacing = grid_spacing;
-       nelem                   = cmap_grid->grid_spacing*cmap_grid->grid_spacing;
-       
-       snew(cmap_grid->cmapdata,ngrid);
-       
-       for(i=0;i<cmap_grid->ngrid;i++)
-       {
-               snew(cmap_grid->cmapdata[i].cmap,4*nelem);
-       }
-}
-
-
-static int count_constraints(gmx_mtop_t *mtop,t_molinfo *mi,warninp_t wi)
-{
-  int count,count_mol,i,mb;
-  gmx_molblock_t *molb;
-  t_params *plist;
-  char buf[STRLEN];
-
-  count = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    count_mol = 0;
-    molb  = &mtop->molblock[mb];
-    plist = mi[molb->type].plist;
-      
-    for(i=0; i<F_NRE; i++) {
-      if (i == F_SETTLE)
-       count_mol += 3*plist[i].nr;
-      else if (interaction_function[i].flags & IF_CONSTRAINT)
-       count_mol += plist[i].nr;
-    }
-      
-    if (count_mol > nrdf_internal(&mi[molb->type].atoms)) {
-      sprintf(buf,
-             "Molecule type '%s' has %d constraints.\n"
-             "For stability and efficiency there should not be more constraints than internal number of degrees of freedom: %d.\n",
-             *mi[molb->type].name,count_mol,
-             nrdf_internal(&mi[molb->type].atoms));
-      warning(wi,buf);
-    }
-    count += molb->nmol*count_mol;
-  }
-
-  return count;
-}
-
-static void check_gbsa_params_charged(gmx_mtop_t *sys, gpp_atomtype_t atype)
-{
-    int i,nmiss,natoms,mt;
-    real q;
-    const t_atoms *atoms;
-  
-    nmiss = 0;
-    for(mt=0;mt<sys->nmoltype;mt++)
-    {
-        atoms  = &sys->moltype[mt].atoms;
-        natoms = atoms->nr;
-
-        for(i=0;i<natoms;i++)
-        {
-            q = atoms->atom[i].q;
-            if ((get_atomtype_radius(atoms->atom[i].type,atype)    == 0  ||
-                 get_atomtype_vol(atoms->atom[i].type,atype)       == 0  ||
-                 get_atomtype_surftens(atoms->atom[i].type,atype)  == 0  ||
-                 get_atomtype_gb_radius(atoms->atom[i].type,atype) == 0  ||
-                 get_atomtype_S_hct(atoms->atom[i].type,atype)     == 0) &&
-                q != 0)
-            {
-                fprintf(stderr,"\nGB parameter(s) zero for atom type '%s' while charge is %g\n",
-                        get_atomtype_name(atoms->atom[i].type,atype),q);
-                nmiss++;
-            }
-        }
-    }
-
-    if (nmiss > 0)
-    {
-        gmx_fatal(FARGS,"Can't do GB electrostatics; the implicit_genborn_params section of the forcefield has parameters with value zero for %d atomtypes that occur as charged atoms.",nmiss);
-    }
-}
-
-
-static void check_gbsa_params(t_inputrec *ir,gpp_atomtype_t atype)
-{
-    int  nmiss,i;
-
-    /* If we are doing GBSA, check that we got the parameters we need
-     * This checking is to see if there are GBSA paratmeters for all
-     * atoms in the force field. To go around this for testing purposes
-     * comment out the nerror++ counter temporarily
-     */
-    nmiss = 0;
-    for(i=0;i<get_atomtype_ntypes(atype);i++)
-    {
-        if (get_atomtype_radius(i,atype)    < 0 ||
-            get_atomtype_vol(i,atype)       < 0 ||
-            get_atomtype_surftens(i,atype)  < 0 ||
-            get_atomtype_gb_radius(i,atype) < 0 ||
-            get_atomtype_S_hct(i,atype)     < 0)
-        {
-            fprintf(stderr,"\nGB parameter(s) missing or negative for atom type '%s'\n",
-                    get_atomtype_name(i,atype));
-            nmiss++;
-        }
-    }
-    
-    if (nmiss > 0)
-    {
-        gmx_fatal(FARGS,"Can't do GB electrostatics; the implicit_genborn_params section of the forcefield is missing parameters for %d atomtypes or they might be negative.",nmiss);
-    }
-  
-}
-
-int main (int argc, char *argv[])
-{
-  static const char *desc[] = {
-    "The gromacs preprocessor",
-    "reads a molecular topology file, checks the validity of the",
-    "file, expands the topology from a molecular description to an atomic",
-    "description. The topology file contains information about",
-    "molecule types and the number of molecules, the preprocessor",
-    "copies each molecule as needed. ",
-    "There is no limitation on the number of molecule types. ",
-    "Bonds and bond-angles can be converted into constraints, separately",
-    "for hydrogens and heavy atoms.",
-    "Then a coordinate file is read and velocities can be generated",
-    "from a Maxwellian distribution if requested.",
-    "[TT]grompp[tt] also reads parameters for the [TT]mdrun[tt] ",
-    "(eg. number of MD steps, time step, cut-off), and others such as",
-    "NEMD parameters, which are corrected so that the net acceleration",
-    "is zero.",
-    "Eventually a binary file is produced that can serve as the sole input",
-    "file for the MD program.[PAR]",
-    
-    "[TT]grompp[tt] uses the atom names from the topology file. The atom names",
-    "in the coordinate file (option [TT]-c[tt]) are only read to generate",
-    "warnings when they do not match the atom names in the topology.",
-    "Note that the atom names are irrelevant for the simulation as",
-    "only the atom types are used for generating interaction parameters.[PAR]",
-
-    "[TT]grompp[tt] uses a built-in preprocessor to resolve includes, macros, ",
-    "etc. The preprocessor supports the following keywords:[PAR]",
-    "#ifdef VARIABLE[BR]",
-    "#ifndef VARIABLE[BR]",
-    "#else[BR]",
-    "#endif[BR]",
-    "#define VARIABLE[BR]",
-    "#undef VARIABLE[BR]"
-    "#include \"filename\"[BR]",
-    "#include <filename>[PAR]",
-    "The functioning of these statements in your topology may be modulated by",
-    "using the following two flags in your [TT].mdp[tt] file:[PAR]",
-    "[TT]define = -DVARIABLE1 -DVARIABLE2[BR]",
-    "include = -I/home/john/doe[tt][BR]",
-    "For further information a C-programming textbook may help you out.",
-    "Specifying the [TT]-pp[tt] flag will get the pre-processed",
-    "topology file written out so that you can verify its contents.[PAR]",
-   
-    /* cpp has been unnecessary for some time, hasn't it?
-        "If your system does not have a C-preprocessor, you can still",
-        "use [TT]grompp[tt], but you do not have access to the features ",
-        "from the cpp. Command line options to the C-preprocessor can be given",
-        "in the [TT].mdp[tt] file. See your local manual (man cpp).[PAR]",
-    */
-    
-    "When using position restraints a file with restraint coordinates",
-    "can be supplied with [TT]-r[tt], otherwise restraining will be done",
-    "with respect to the conformation from the [TT]-c[tt] option.",
-    "For free energy calculation the the coordinates for the B topology",
-    "can be supplied with [TT]-rb[tt], otherwise they will be equal to",
-    "those of the A topology.[PAR]",
-    
-    "Starting coordinates can be read from trajectory with [TT]-t[tt].",
-    "The last frame with coordinates and velocities will be read,",
-    "unless the [TT]-time[tt] option is used. Only if this information",
-    "is absent will the coordinates in the [TT]-c[tt] file be used.",
-    "Note that these velocities will not be used when [TT]gen_vel = yes[tt]",
-    "in your [TT].mdp[tt] file. An energy file can be supplied with",
-    "[TT]-e[tt] to read Nose-Hoover and/or Parrinello-Rahman coupling",
-    "variables.[PAR]",
-
-    "[TT]grompp[tt] can be used to restart simulations (preserving",
-    "continuity) by supplying just a checkpoint file with [TT]-t[tt].",
-    "However, for simply changing the number of run steps to extend",
-    "a run, using [TT]tpbconv[tt] is more convenient than [TT]grompp[tt].",
-    "You then supply the old checkpoint file directly to [TT]mdrun[tt]",
-    "with [TT]-cpi[tt]. If you wish to change the ensemble or things",
-    "like output frequency, then supplying the checkpoint file to",
-    "[TT]grompp[tt] with [TT]-t[tt] along with a new [TT].mdp[tt] file",
-    "with [TT]-f[tt] is the recommended procedure.[PAR]",
-
-    "By default, all bonded interactions which have constant energy due to",
-    "virtual site constructions will be removed. If this constant energy is",
-    "not zero, this will result in a shift in the total energy. All bonded",
-    "interactions can be kept by turning off [TT]-rmvsbds[tt]. Additionally,",
-    "all constraints for distances which will be constant anyway because",
-    "of virtual site constructions will be removed. If any constraints remain",
-    "which involve virtual sites, a fatal error will result.[PAR]"
-    
-    "To verify your run input file, please take note of all warnings",
-    "on the screen, and correct where necessary. Do also look at the contents",
-    "of the [TT]mdout.mdp[tt] file; this contains comment lines, as well as",
-    "the input that [TT]grompp[tt] has read. If in doubt, you can start [TT]grompp[tt]",
-    "with the [TT]-debug[tt] option which will give you more information",
-    "in a file called [TT]grompp.log[tt] (along with real debug info). You",
-    "can see the contents of the run input file with the [TT]gmxdump[tt]",
-    "program. [TT]gmxcheck[tt] can be used to compare the contents of two",
-    "run input files.[PAR]"
-
-    "The [TT]-maxwarn[tt] option can be used to override warnings printed",
-    "by [TT]grompp[tt] that otherwise halt output. In some cases, warnings are",
-    "harmless, but usually they are not. The user is advised to carefully",
-    "interpret the output messages before attempting to bypass them with",
-    "this option."
-  };
-  t_gromppopts *opts;
-  gmx_mtop_t   *sys;
-  int          nmi;
-  t_molinfo    *mi;
-  gpp_atomtype_t atype;
-  t_inputrec   *ir;
-  int          natoms,nvsite,comb,mt;
-  t_params     *plist;
-  t_state      state;
-  matrix       box;
-  real         max_spacing,fudgeQQ;
-  double       reppow;
-  char         fn[STRLEN],fnB[STRLEN];
-  const char   *mdparin;
-  int          ntype;
-  gmx_bool         bNeedVel,bGenVel;
-  gmx_bool         have_atomnumber;
-  int             n12,n13,n14;
-  t_params     *gb_plist = NULL;
-  gmx_genborn_t *born = NULL;
-  output_env_t oenv;
-  gmx_bool         bVerbose = FALSE;
-  warninp_t    wi;
-  char         warn_buf[STRLEN];
-
-  t_filenm fnm[] = {
-    { efMDP, NULL,  NULL,        ffREAD  },
-    { efMDP, "-po", "mdout",     ffWRITE },
-    { efSTX, "-c",  NULL,        ffREAD  },
-    { efSTX, "-r",  NULL,        ffOPTRD },
-    { efSTX, "-rb", NULL,        ffOPTRD },
-    { efNDX, NULL,  NULL,        ffOPTRD },
-    { efTOP, NULL,  NULL,        ffREAD  },
-    { efTOP, "-pp", "processed", ffOPTWR },
-    { efTPX, "-o",  NULL,        ffWRITE },
-    { efTRN, "-t",  NULL,        ffOPTRD },
-    { efEDR, "-e",  NULL,        ffOPTRD }
-  };
-#define NFILE asize(fnm)
-
-  /* Command line options */
-  static gmx_bool bRenum=TRUE;
-  static gmx_bool bRmVSBds=TRUE,bZero=FALSE;
-  static int  i,maxwarn=0;
-  static real fr_time=-1;
-  t_pargs pa[] = {
-    { "-v",       FALSE, etBOOL,{&bVerbose},  
-      "Be loud and noisy" },
-    { "-time",    FALSE, etREAL, {&fr_time},
-      "Take frame at or first after this time." },
-    { "-rmvsbds",FALSE, etBOOL, {&bRmVSBds},
-      "Remove constant bonded interactions with virtual sites" },
-    { "-maxwarn", FALSE, etINT,  {&maxwarn},
-      "Number of allowed warnings during input processing. Not for normal use and may generate unstable systems" },
-    { "-zero",    FALSE, etBOOL, {&bZero},
-      "Set parameters for bonded interactions without defaults to zero instead of generating an error" },
-    { "-renum",   FALSE, etBOOL, {&bRenum},
-      "Renumber atomtypes and minimize number of atomtypes" }
-  };
-  
-  CopyRight(stdout,argv[0]);
-  
-  /* Initiate some variables */
-  snew(ir,1);
-  snew(opts,1);
-  init_ir(ir,opts);
-  
-  /* Parse the command line */
-  parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
-                    asize(desc),desc,0,NULL,&oenv);
-  
-  wi = init_warning(TRUE,maxwarn);
-  
-  /* PARAMETER file processing */
-  mdparin = opt2fn("-f",NFILE,fnm);
-  set_warning_line(wi,mdparin,-1);    
-  get_ir(mdparin,opt2fn("-po",NFILE,fnm),ir,opts,wi);
-  
-  if (bVerbose) 
-    fprintf(stderr,"checking input for internal consistency...\n");
-  check_ir(mdparin,ir,opts,wi);
-
-  if (ir->ld_seed == -1) {
-    ir->ld_seed = make_seed();
-    fprintf(stderr,"Setting the LD random seed to %d\n",ir->ld_seed);
-  }
-
-  bNeedVel = EI_STATE_VELOCITY(ir->eI);
-  bGenVel  = (bNeedVel && opts->bGenVel);
-
-  snew(plist,F_NRE);
-  init_plist(plist);
-  snew(sys,1);
-  atype = init_atomtype();
-  if (debug)
-    pr_symtab(debug,0,"Just opened",&sys->symtab);
-    
-  strcpy(fn,ftp2fn(efTOP,NFILE,fnm));
-  if (!gmx_fexist(fn)) 
-    gmx_fatal(FARGS,"%s does not exist",fn);
-  new_status(fn,opt2fn_null("-pp",NFILE,fnm),opt2fn("-c",NFILE,fnm),
-            opts,ir,bZero,bGenVel,bVerbose,&state,
-            atype,sys,&nmi,&mi,plist,&comb,&reppow,&fudgeQQ,
-            opts->bMorse,
-            wi);
-  
-  if (debug)
-    pr_symtab(debug,0,"After new_status",&sys->symtab);
-  
-  if (count_constraints(sys,mi,wi) && (ir->eConstrAlg == econtSHAKE)) {
-    if (ir->eI == eiCG || ir->eI == eiLBFGS) {
-        sprintf(warn_buf,"Can not do %s with %s, use %s",
-                EI(ir->eI),econstr_names[econtSHAKE],econstr_names[econtLINCS]);
-        warning_error(wi,warn_buf);
-    }
-    if (ir->bPeriodicMols) {
-        sprintf(warn_buf,"Can not do periodic molecules with %s, use %s",
-                econstr_names[econtSHAKE],econstr_names[econtLINCS]);
-        warning_error(wi,warn_buf);
-    }
-  }
-
-  /* If we are doing QM/MM, check that we got the atom numbers */
-  have_atomnumber = TRUE;
-  for (i=0; i<get_atomtype_ntypes(atype); i++) {
-    have_atomnumber = have_atomnumber && (get_atomtype_atomnumber(i,atype) >= 0);
-  }
-  if (!have_atomnumber && ir->bQMMM)
-  {
-      warning_error(wi,
-                    "\n"
-                    "It appears as if you are trying to run a QM/MM calculation, but the force\n"
-                    "field you are using does not contain atom numbers fields. This is an\n"
-                    "optional field (introduced in Gromacs 3.3) for general runs, but mandatory\n"
-                    "for QM/MM. The good news is that it is easy to add - put the atom number as\n"
-                    "an integer just before the mass column in ffXXXnb.itp.\n"
-                    "NB: United atoms have the same atom numbers as normal ones.\n\n"); 
-  }
-
-  /* Check for errors in the input now, since they might cause problems
-   * during processing further down.
-   */
-  check_warning_error(wi,FARGS);
-
-  if (opt2bSet("-r",NFILE,fnm))
-    sprintf(fn,"%s",opt2fn("-r",NFILE,fnm));
-  else
-    sprintf(fn,"%s",opt2fn("-c",NFILE,fnm));
-  if (opt2bSet("-rb",NFILE,fnm))
-    sprintf(fnB,"%s",opt2fn("-rb",NFILE,fnm));
-  else
-    strcpy(fnB,fn);
-
-    if (nint_ftype(sys,mi,F_POSRES) > 0)
-    {
-        if (bVerbose)
-        {
-            fprintf(stderr,"Reading position restraint coords from %s",fn);
-            if (strcmp(fn,fnB) == 0)
-            {
-                fprintf(stderr,"\n");
-            }
-            else
-            {
-                fprintf(stderr," and %s\n",fnB);
-                if (ir->efep != efepNO && ir->n_flambda > 0)
-                {
-                    warning_error(wi,"Can not change the position restraint reference coordinates with lambda togther with foreign lambda calculation.");
-                }
-            }
-        }
-        gen_posres(sys,mi,fn,fnB,
-                   ir->refcoord_scaling,ir->ePBC,
-                   ir->posres_com,ir->posres_comB,
-                   wi);
-    }
-               
-  nvsite = 0;
-  /* set parameters for virtual site construction (not for vsiten) */
-  for(mt=0; mt<sys->nmoltype; mt++) {
-    nvsite +=
-      set_vsites(bVerbose, &sys->moltype[mt].atoms, atype, mi[mt].plist);
-  }
-  /* now throw away all obsolete bonds, angles and dihedrals: */
-  /* note: constraints are ALWAYS removed */
-  if (nvsite) {
-    for(mt=0; mt<sys->nmoltype; mt++) {
-      clean_vsite_bondeds(mi[mt].plist,sys->moltype[mt].atoms.nr,bRmVSBds);
-    }
-  }
-  
-       /* If we are using CMAP, setup the pre-interpolation grid */
-       if(plist->ncmap>0)
-       {
-               init_cmap_grid(&sys->ffparams.cmap_grid, plist->nc, plist->grid_spacing);
-               setup_cmap(plist->grid_spacing, plist->nc, plist->cmap,&sys->ffparams.cmap_grid);
-       }
-       
-  set_wall_atomtype(atype,opts,ir);
-  if (bRenum) {
-    renum_atype(plist, sys, ir->wall_atomtype, atype, bVerbose);
-    ntype = get_atomtype_ntypes(atype);
-  }
-
-    if (ir->implicit_solvent != eisNO)
-    {
-        /* Now we have renumbered the atom types, we can check the GBSA params */
-        check_gbsa_params(ir,atype);
-      
-      /* Check that all atoms that have charge and/or LJ-parameters also have 
-       * sensible GB-parameters
-       */
-      check_gbsa_params_charged(sys,atype);
-    }
-
-       /* PELA: Copy the atomtype data to the topology atomtype list */
-       copy_atomtype_atomtypes(atype,&(sys->atomtypes));
-
-       if (debug)
-    pr_symtab(debug,0,"After renum_atype",&sys->symtab);
-
-  if (bVerbose) 
-    fprintf(stderr,"converting bonded parameters...\n");
-       
-  ntype = get_atomtype_ntypes(atype);
-  convert_params(ntype, plist, mi, comb, reppow, fudgeQQ, sys);
-       
-  if (debug)
-    pr_symtab(debug,0,"After convert_params",&sys->symtab);
-
-  /* set ptype to VSite for virtual sites */
-  for(mt=0; mt<sys->nmoltype; mt++) {
-    set_vsites_ptype(FALSE,&sys->moltype[mt]);
-  }
-  if (debug) {
-    pr_symtab(debug,0,"After virtual sites",&sys->symtab);
-  }
-  /* Check velocity for virtual sites and shells */
-  if (bGenVel) {
-    check_vel(sys,state.v);
-  }
-    
-  /* check masses */
-  check_mol(sys,wi);
-  
-  for(i=0; i<sys->nmoltype; i++) {
-      check_cg_sizes(ftp2fn(efTOP,NFILE,fnm),&sys->moltype[i].cgs,wi);
-  }
-
-  if (EI_DYNAMICS(ir->eI) && ir->eI != eiBD)
-  {
-      check_bonds_timestep(sys,ir->delta_t,wi);
-  }
-
-  if (EI_ENERGY_MINIMIZATION(ir->eI) && 0 == ir->nsteps)
-  {
-      warning_note(wi,"Zero-step energy minimization will alter the coordinates before calculating the energy. If you just want the energy of a single point, try zero-step MD (with unconstrained_start = yes). To do multiple single-point energy evaluations of different configurations of the same topology, use mdrun -rerun.");
-  }
-
-  check_warning_error(wi,FARGS);
-       
-  if (bVerbose) 
-    fprintf(stderr,"initialising group options...\n");
-  do_index(mdparin,ftp2fn_null(efNDX,NFILE,fnm),
-           sys,bVerbose,ir,
-           bGenVel ? state.v : NULL,
-           wi);
-  
-  /* Init the temperature coupling state */
-  init_gtc_state(&state,ir->opts.ngtc,0,ir->opts.nhchainlength);
-
-  if (bVerbose)
-    fprintf(stderr,"Checking consistency between energy and charge groups...\n");
-  check_eg_vs_cg(sys);
-  
-  if (debug)
-    pr_symtab(debug,0,"After index",&sys->symtab);
-  triple_check(mdparin,ir,sys,wi);
-  close_symtab(&sys->symtab);
-  if (debug)
-    pr_symtab(debug,0,"After close",&sys->symtab);
-
-  /* make exclusions between QM atoms */
-  if (ir->bQMMM) {
-    generate_qmexcl(sys,ir);
-  }
-
-  if (ftp2bSet(efTRN,NFILE,fnm)) {
-    if (bVerbose)
-      fprintf(stderr,"getting data from old trajectory ...\n");
-    cont_status(ftp2fn(efTRN,NFILE,fnm),ftp2fn_null(efEDR,NFILE,fnm),
-               bNeedVel,bGenVel,fr_time,ir,&state,sys,oenv);
-  }
-
-    if (ir->ePBC==epbcXY && ir->nwall!=2)
-    {
-        clear_rvec(state.box[ZZ]);
-    }
-  
-    if (ir->rlist > 0)
-    {
-        set_warning_line(wi,mdparin,-1);
-        check_chargegroup_radii(sys,ir,state.x,wi);
-    }
-
-  if (EEL_FULL(ir->coulombtype)) {
-    /* Calculate the optimal grid dimensions */
-    copy_mat(state.box,box);
-    if (ir->ePBC==epbcXY && ir->nwall==2)
-      svmul(ir->wall_ewald_zfac,box[ZZ],box[ZZ]);
-    max_spacing = calc_grid(stdout,box,opts->fourierspacing,
-                            &(ir->nkx),&(ir->nky),&(ir->nkz));
-    if ((ir->coulombtype == eelPPPM) && (max_spacing > 0.1)) {
-        set_warning_line(wi,mdparin,-1);
-        warning_note(wi,"Grid spacing larger then 0.1 while using PPPM.");
-    }
-  }
-
-  if (ir->ePull != epullNO)
-    set_pull_init(ir,sys,state.x,state.box,oenv,opts->pull_start);
-
-  /*  reset_multinr(sys); */
-  
-  if (EEL_PME(ir->coulombtype)) {
-    float ratio = pme_load_estimate(sys,ir,state.box);
-    fprintf(stderr,"Estimate for the relative computational load of the PME mesh part: %.2f\n",ratio);
-    /* With free energy we might need to do PME both for the A and B state
-     * charges. This will double the cost, but the optimal performance will
-     * then probably be at a slightly larger cut-off and grid spacing.
-     */
-    if ((ir->efep == efepNO && ratio > 1.0/2.0) ||
-        (ir->efep != efepNO && ratio > 2.0/3.0)) {
-        warning_note(wi,
-                     "The optimal PME mesh load for parallel simulations is below 0.5\n"
-                  "and for highly parallel simulations between 0.25 and 0.33,\n"
-                  "for higher performance, increase the cut-off and the PME grid spacing");
-    }
-  }
-
-    {
-        char warn_buf[STRLEN];
-        double cio = compute_io(ir,sys->natoms,&sys->groups,F_NRE,1);
-        sprintf(warn_buf,"This run will generate roughly %.0f Mb of data",cio);
-        if (cio > 2000) {
-            set_warning_line(wi,mdparin,-1);
-            warning_note(wi,warn_buf);
-        } else {
-            printf("%s\n",warn_buf);
-        }
-    }
-       
-  if (bVerbose) 
-    fprintf(stderr,"writing run input file...\n");
-
-  done_warning(wi,FARGS);
-
-  state.lambda = ir->init_lambda;
-  write_tpx_state(ftp2fn(efTPX,NFILE,fnm),ir,&state,sys);
-  
-  thanx(stderr);
-  
-  return 0;
-}
diff --git a/src/kernel/libgmxpreprocess.pc.cmakein b/src/kernel/libgmxpreprocess.pc.cmakein
deleted file mode 100644 (file)
index 3cba1ef..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCL_INSTALL_DIR@
-
-Name: libgmxpreprocess
-Description: Gromacs preprocess lib
-URL: http://www.gromacs.org
-Version: @PROJECT_VERSION@
-Requires: libgmx@GMX_LIBS_SUFFIX@ libmd@GMX_LIBS_SUFFIX@ 
-Libs.private: -lm @CMAKE_THREAD_LIBS_INIT@
-Libs: -L${libdir} -lgmxpreprocess@GMX_LIBS_SUFFIX@
-Cflags: -I${includedir} @PKG_CFLAGS@
-
diff --git a/src/kernel/md.c b/src/kernel/md.c
deleted file mode 100644 (file)
index 8ae0b4c..0000000
+++ /dev/null
@@ -1,1878 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-/* _isnan() */
-#include <float.h>
-#endif
-
-#include "typedefs.h"
-#include "smalloc.h"
-#include "sysstuff.h"
-#include "vec.h"
-#include "statutil.h"
-#include "vcm.h"
-#include "mdebin.h"
-#include "nrnb.h"
-#include "calcmu.h"
-#include "index.h"
-#include "vsite.h"
-#include "update.h"
-#include "ns.h"
-#include "trnio.h"
-#include "xtcio.h"
-#include "mdrun.h"
-#include "confio.h"
-#include "network.h"
-#include "pull.h"
-#include "xvgr.h"
-#include "physics.h"
-#include "names.h"
-#include "xmdrun.h"
-#include "ionize.h"
-#include "disre.h"
-#include "orires.h"
-#include "dihre.h"
-#include "pppm.h"
-#include "pme.h"
-#include "mdatoms.h"
-#include "repl_ex.h"
-#include "qmmm.h"
-#include "mpelogging.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "topsort.h"
-#include "coulomb.h"
-#include "constr.h"
-#include "shellfc.h"
-#include "compute_io.h"
-#include "mvdata.h"
-#include "checkpoint.h"
-#include "mtop_util.h"
-#include "sighandler.h"
-#include "string2.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#ifdef GMX_FAHCORE
-#include "corewrap.h"
-#endif
-
-
-double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-             int nstglobalcomm,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int stepout,t_inputrec *ir,
-             gmx_mtop_t *top_global,
-             t_fcdata *fcd,
-             t_state *state_global,
-             t_mdatoms *mdatoms,
-             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-             gmx_edsam_t ed,t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
-             real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags,
-             gmx_runtime_t *runtime)
-{
-    gmx_mdoutf_t *outf;
-    gmx_large_int_t step,step_rel;
-    double     run_time;
-    double     t,t0,lam0;
-    gmx_bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
-    gmx_bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
-               bFirstStep,bStateFromTPX,bInitStep,bLastStep,
-               bBornRadii,bStartingFromCpt;
-    gmx_bool       bDoDHDL=FALSE;
-    gmx_bool       do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
-               bForceUpdate=FALSE,bCPT;
-    int        mdof_flags;
-    gmx_bool       bMasterState;
-    int        force_flags,cglo_flags;
-    tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
-    int        i,m;
-    t_trxstatus *status;
-    rvec       mu_tot;
-    t_vcm      *vcm;
-    t_state    *bufstate=NULL;   
-    matrix     *scale_tot,pcoupl_mu,M,ebox;
-    gmx_nlheur_t nlh;
-    t_trxframe rerun_fr;
-    gmx_repl_ex_t repl_ex=NULL;
-    int        nchkpt=1;
-
-    gmx_localtop_t *top;       
-    t_mdebin *mdebin=NULL;
-    t_state    *state=NULL;
-    rvec       *f_global=NULL;
-    int        n_xtc=-1;
-    rvec       *x_xtc=NULL;
-    gmx_enerdata_t *enerd;
-    rvec       *f=NULL;
-    gmx_global_stat_t gstat;
-    gmx_update_t upd=NULL;
-    t_graph    *graph=NULL;
-    globsig_t   gs;
-
-    gmx_bool        bFFscan;
-    gmx_groups_t *groups;
-    gmx_ekindata_t *ekind, *ekind_save;
-    gmx_shellfc_t shellfc;
-    int         count,nconverged=0;
-    real        timestep=0;
-    double      tcount=0;
-    gmx_bool        bIonize=FALSE;
-    gmx_bool        bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
-    gmx_bool        bAppend;
-    gmx_bool        bResetCountersHalfMaxH=FALSE;
-    gmx_bool        bVV,bIterations,bFirstIterate,bTemp,bPres,bTrotter;
-    real        temp0,mu_aver=0,dvdl;
-    int         a0,a1,gnx=0,ii;
-    atom_id     *grpindex=NULL;
-    char        *grpname;
-    t_coupl_rec *tcr=NULL;
-    rvec        *xcopy=NULL,*vcopy=NULL,*cbuf=NULL;
-    matrix      boxcopy={{0}},lastbox;
-       tensor      tmpvir;
-       real        fom,oldfom,veta_save,pcurr,scalevir,tracevir;
-       real        vetanew = 0;
-    double      cycles;
-       real        saved_conserved_quantity = 0;
-    real        last_ekin = 0;
-       int         iter_i;
-       t_extmass   MassQ;
-    int         **trotter_seq; 
-    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
-    int         handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
-    gmx_iterate_t iterate;
-    gmx_large_int_t multisim_nsteps=-1; /* number of steps to do  before first multisim 
-                                          simulation stops. If equal to zero, don't
-                                          communicate any more between multisims.*/
-#ifdef GMX_FAHCORE
-    /* Temporary addition for FAHCORE checkpointing */
-    int chkpt_ret;
-#endif
-
-    /* Check for special mdrun options */
-    bRerunMD = (Flags & MD_RERUN);
-    bIonize  = (Flags & MD_IONIZE);
-    bFFscan  = (Flags & MD_FFSCAN);
-    bAppend  = (Flags & MD_APPENDFILES);
-    if (Flags & MD_RESETCOUNTERSHALFWAY)
-    {
-        if (ir->nsteps > 0)
-        {
-            /* Signal to reset the counters half the simulation steps. */
-            wcycle_set_reset_counters(wcycle,ir->nsteps/2);
-        }
-        /* Signal to reset the counters halfway the simulation time. */
-        bResetCountersHalfMaxH = (max_hours > 0);
-    }
-
-    /* md-vv uses averaged full step velocities for T-control 
-       md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
-       md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
-    bVV = EI_VV(ir->eI);
-    if (bVV) /* to store the initial velocities while computing virial */
-    {
-        snew(cbuf,top_global->natoms);
-    }
-    /* all the iteratative cases - only if there are constraints */ 
-    bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
-    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));        
-    
-    if (bRerunMD)
-    {
-        /* Since we don't know if the frames read are related in any way,
-         * rebuild the neighborlist at every step.
-         */
-        ir->nstlist       = 1;
-        ir->nstcalcenergy = 1;
-        nstglobalcomm     = 1;
-    }
-
-    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
-
-    nstglobalcomm = check_nstglobalcomm(fplog,cr,nstglobalcomm,ir);
-    bGStatEveryStep = (nstglobalcomm == 1);
-
-    if (!bGStatEveryStep && ir->nstlist == -1 && fplog != NULL)
-    {
-        fprintf(fplog,
-                "To reduce the energy communication with nstlist = -1\n"
-                "the neighbor list validity should not be checked at every step,\n"
-                "this means that exact integration is not guaranteed.\n"
-                "The neighbor list validity is checked after:\n"
-                "  <n.list life time> - 2*std.dev.(n.list life time)  steps.\n"
-                "In most cases this will result in exact integration.\n"
-                "This reduces the energy communication by a factor of 2 to 3.\n"
-                "If you want less energy communication, set nstlist > 3.\n\n");
-    }
-
-    if (bRerunMD || bFFscan)
-    {
-        ir->nstxtcout = 0;
-    }
-    groups = &top_global->groups;
-
-    /* Initial values */
-    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
-            nrnb,top_global,&upd,
-            nfile,fnm,&outf,&mdebin,
-            force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
-
-    clear_mat(total_vir);
-    clear_mat(pres);
-    /* Energy terms and groups */
-    snew(enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
-    if (DOMAINDECOMP(cr))
-    {
-        f = NULL;
-    }
-    else
-    {
-        snew(f,top_global->natoms);
-    }
-
-    /* Kinetic energy data */
-    snew(ekind,1);
-    init_ekindata(fplog,top_global,&(ir->opts),ekind);
-    /* needed for iteration of constraints */
-    snew(ekind_save,1);
-    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
-    /* Copy the cos acceleration to the groups struct */    
-    ekind->cosacc.cos_accel = ir->cos_accel;
-
-    gstat = global_stat_init(ir);
-    debug_gmx();
-
-    /* Check for polarizable models and flexible constraints */
-    shellfc = init_shell_flexcon(fplog,
-                                 top_global,n_flexible_constraints(constr),
-                                 (ir->bContinuation || 
-                                  (DOMAINDECOMP(cr) && !MASTER(cr))) ?
-                                 NULL : state_global->x);
-
-    if (DEFORM(*ir))
-    {
-#ifdef GMX_THREADS
-        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
-#endif
-        set_deform_reference_box(upd,
-                                 deform_init_init_step_tpx,
-                                 deform_init_box_tpx);
-#ifdef GMX_THREADS
-        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
-#endif
-    }
-
-    {
-        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
-        if ((io > 2000) && MASTER(cr))
-            fprintf(stderr,
-                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
-                    io);
-    }
-
-    if (DOMAINDECOMP(cr)) {
-        top = dd_init_local_top(top_global);
-
-        snew(state,1);
-        dd_init_local_state(cr->dd,state_global,state);
-
-        if (DDMASTER(cr->dd) && ir->nstfout) {
-            snew(f_global,state_global->natoms);
-        }
-    } else {
-        if (PAR(cr)) {
-            /* Initialize the particle decomposition and split the topology */
-            top = split_system(fplog,top_global,ir,cr);
-
-            pd_cg_range(cr,&fr->cg0,&fr->hcg);
-            pd_at_range(cr,&a0,&a1);
-        } else {
-            top = gmx_mtop_generate_local_top(top_global,ir);
-
-            a0 = 0;
-            a1 = top_global->natoms;
-        }
-
-        state = partdec_init_local_state(cr,state_global);
-        f_global = f;
-
-        atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
-
-        if (vsite) {
-            set_vsite_top(vsite,top,mdatoms,cr);
-        }
-
-        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
-            graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
-        }
-
-        if (shellfc) {
-            make_local_shells(cr,mdatoms,shellfc);
-        }
-
-        if (ir->pull && PAR(cr)) {
-            dd_make_local_pull_groups(NULL,ir->pull,mdatoms);
-        }
-    }
-
-    if (DOMAINDECOMP(cr))
-    {
-        /* Distribute the charge groups over the nodes from the master node */
-        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
-                            state_global,top_global,ir,
-                            state,&f,mdatoms,top,fr,
-                            vsite,shellfc,constr,
-                            nrnb,wcycle,FALSE);
-    }
-
-    update_mdatoms(mdatoms,state->lambda);
-
-    if (MASTER(cr))
-    {
-        if (opt2bSet("-cpi",nfile,fnm))
-        {
-            /* Update mdebin with energy history if appending to output files */
-            if ( Flags & MD_APPENDFILES )
-            {
-                restore_energyhistory_from_state(mdebin,&state_global->enerhist);
-            }
-            else
-            {
-                /* We might have read an energy history from checkpoint,
-                 * free the allocated memory and reset the counts.
-                 */
-                done_energyhistory(&state_global->enerhist);
-                init_energyhistory(&state_global->enerhist);
-            }
-        }
-        /* Set the initial energy history in state by updating once */
-        update_energyhistory(&state_global->enerhist,mdebin);
-    }  
-
-    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
-        /* Set the random state if we read a checkpoint file */
-        set_stochd_state(upd,state);
-    }
-
-    /* Initialize constraints */
-    if (constr) {
-        if (!DOMAINDECOMP(cr))
-            set_constraints(constr,top,ir,mdatoms,cr);
-    }
-
-    /* Check whether we have to GCT stuff */
-    bTCR = ftp2bSet(efGCT,nfile,fnm);
-    if (bTCR) {
-        if (MASTER(cr)) {
-            fprintf(stderr,"Will do General Coupling Theory!\n");
-        }
-        gnx = top_global->mols.nr;
-        snew(grpindex,gnx);
-        for(i=0; (i<gnx); i++) {
-            grpindex[i] = i;
-        }
-    }
-
-    if (repl_ex_nst > 0)
-    {
-        /* We need to be sure replica exchange can only occur
-         * when the energies are current */
-        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                        "repl_ex_nst",&repl_ex_nst);
-        /* This check needs to happen before inter-simulation
-         * signals are initialized, too */
-    }
-    if (repl_ex_nst > 0 && MASTER(cr))
-        repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
-                                        repl_ex_nst,repl_ex_seed);
-
-    if (!ir->bContinuation && !bRerunMD)
-    {
-        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
-        {
-            /* Set the velocities of frozen particles to zero */
-            for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
-            {
-                for(m=0; m<DIM; m++)
-                {
-                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
-                    {
-                        state->v[i][m] = 0;
-                    }
-                }
-            }
-        }
-
-        if (constr)
-        {
-            /* Constrain the initial coordinates and velocities */
-            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
-                               graph,cr,nrnb,fr,top,shake_vir);
-        }
-        if (vsite)
-        {
-            /* Construct the virtual sites for the initial configuration */
-            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
-                             top->idef.iparams,top->idef.il,
-                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-        }
-    }
-
-    debug_gmx();
-  
-    /* I'm assuming we need global communication the first time! MRS */
-    cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
-                  | (bVV ? CGLO_PRESSURE:0)
-                  | (bVV ? CGLO_CONSTRAINT:0)
-                  | (bRerunMD ? CGLO_RERUNMD:0)
-                  | ((Flags & MD_READ_EKIN) ? CGLO_READEKIN:0));
-    
-    bSumEkinhOld = FALSE;
-    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
-                    constr,NULL,FALSE,state->box,
-                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
-    if (ir->eI == eiVVAK) {
-        /* a second call to get the half step temperature initialized as well */ 
-        /* we do the same call as above, but turn the pressure off -- internally to 
-           compute_globals, this is recognized as a velocity verlet half-step 
-           kinetic energy calculation.  This minimized excess variables, but 
-           perhaps loses some logic?*/
-        
-        compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                        wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
-                        constr,NULL,FALSE,state->box,
-                        top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                        cglo_flags &~ CGLO_PRESSURE);
-    }
-    
-    /* Calculate the initial half step temperature, and save the ekinh_old */
-    if (!(Flags & MD_STARTFROMCPT)) 
-    {
-        for(i=0; (i<ir->opts.ngtc); i++) 
-        {
-            copy_mat(ekind->tcstat[i].ekinh,ekind->tcstat[i].ekinh_old);
-        } 
-    }
-    if (ir->eI != eiVV) 
-    {
-        enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
-                                     and there is no previous step */
-    }
-    temp0 = enerd->term[F_TEMP];
-    
-    /* if using an iterative algorithm, we need to create a working directory for the state. */
-    if (bIterations) 
-    {
-            bufstate = init_bufstate(state);
-    }
-    if (bFFscan) 
-    {
-        snew(xcopy,state->natoms);
-        snew(vcopy,state->natoms);
-        copy_rvecn(state->x,xcopy,0,state->natoms);
-        copy_rvecn(state->v,vcopy,0,state->natoms);
-        copy_mat(state->box,boxcopy);
-    } 
-    
-    /* need to make an initiation call to get the Trotter variables set, as well as other constants for non-trotter
-       temperature control */
-    trotter_seq = init_npt_vars(ir,state,&MassQ,bTrotter);
-    
-    if (MASTER(cr))
-    {
-        if (constr && !ir->bContinuation && ir->eConstrAlg == econtLINCS)
-        {
-            fprintf(fplog,
-                    "RMS relative constraint deviation after constraining: %.2e\n",
-                    constr_rmsd(constr,FALSE));
-        }
-        fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
-        if (bRerunMD)
-        {
-            fprintf(stderr,"starting md rerun '%s', reading coordinates from"
-                    " input trajectory '%s'\n\n",
-                    *(top_global->name),opt2fn("-rerun",nfile,fnm));
-            if (bVerbose)
-            {
-                fprintf(stderr,"Calculated time to finish depends on nsteps from "
-                        "run input file,\nwhich may not correspond to the time "
-                        "needed to process input trajectory.\n\n");
-            }
-        }
-        else
-        {
-            char tbuf[20];
-            fprintf(stderr,"starting mdrun '%s'\n",
-                    *(top_global->name));
-            if (ir->nsteps >= 0)
-            {
-                sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
-            }
-            else
-            {
-                sprintf(tbuf,"%s","infinite");
-            }
-            if (ir->init_step > 0)
-            {
-                fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
-                        gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
-                        gmx_step_str(ir->init_step,sbuf2),
-                        ir->init_step*ir->delta_t);
-            }
-            else
-            {
-                fprintf(stderr,"%s steps, %s ps.\n",
-                        gmx_step_str(ir->nsteps,sbuf),tbuf);
-            }
-        }
-        fprintf(fplog,"\n");
-    }
-
-    /* Set and write start time */
-    runtime_start(runtime);
-    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
-    wallcycle_start(wcycle,ewcRUN);
-    if (fplog)
-        fprintf(fplog,"\n");
-
-    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
-#ifdef GMX_FAHCORE
-    chkpt_ret=fcCheckPointParallel( cr->nodeid,
-                                    NULL,0);
-    if ( chkpt_ret == 0 ) 
-        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", 0 );
-#endif
-
-    debug_gmx();
-    /***********************************************************
-     *
-     *             Loop over MD steps 
-     *
-     ************************************************************/
-
-    /* if rerunMD then read coordinates and velocities from input trajectory */
-    if (bRerunMD)
-    {
-        if (getenv("GMX_FORCE_UPDATE"))
-        {
-            bForceUpdate = TRUE;
-        }
-
-        rerun_fr.natoms = 0;
-        if (MASTER(cr))
-        {
-            bNotLastFrame = read_first_frame(oenv,&status,
-                                             opt2fn("-rerun",nfile,fnm),
-                                             &rerun_fr,TRX_NEED_X | TRX_READ_V);
-            if (rerun_fr.natoms != top_global->natoms)
-            {
-                gmx_fatal(FARGS,
-                          "Number of atoms in trajectory (%d) does not match the "
-                          "run input file (%d)\n",
-                          rerun_fr.natoms,top_global->natoms);
-            }
-            if (ir->ePBC != epbcNONE)
-            {
-                if (!rerun_fr.bBox)
-                {
-                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
-                }
-                if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
-                {
-                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
-                }
-            }
-        }
-
-        if (PAR(cr))
-        {
-            rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
-        }
-
-        if (ir->ePBC != epbcNONE)
-        {
-            /* Set the shift vectors.
-             * Necessary here when have a static box different from the tpr box.
-             */
-            calc_shifts(rerun_fr.box,fr->shift_vec);
-        }
-    }
-
-    /* loop over MD steps or if rerunMD to end of input trajectory */
-    bFirstStep = TRUE;
-    /* Skip the first Nose-Hoover integration when we get the state from tpx */
-    bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
-    bInitStep = bFirstStep && (bStateFromTPX || bVV);
-    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
-    bLastStep    = FALSE;
-    bSumEkinhOld = FALSE;
-    bExchanged   = FALSE;
-
-    init_global_signals(&gs,cr,ir,repl_ex_nst);
-
-    step = ir->init_step;
-    step_rel = 0;
-
-    if (ir->nstlist == -1)
-    {
-        init_nlistheuristics(&nlh,bGStatEveryStep,step);
-    }
-
-    if (MULTISIM(cr) && (repl_ex_nst <=0 ))
-    {
-        /* check how many steps are left in other sims */
-        multisim_nsteps=get_multisim_nsteps(cr, ir->nsteps);
-    }
-
-
-    /* and stop now if we should */
-    bLastStep = (bRerunMD || (ir->nsteps >= 0 && step_rel > ir->nsteps) ||
-                 ((multisim_nsteps >= 0) && (step_rel >= multisim_nsteps )));
-    while (!bLastStep || (bRerunMD && bNotLastFrame)) {
-
-        wallcycle_start(wcycle,ewcSTEP);
-
-        GMX_MPE_LOG(ev_timestep1);
-
-        if (bRerunMD) {
-            if (rerun_fr.bStep) {
-                step = rerun_fr.step;
-                step_rel = step - ir->init_step;
-            }
-            if (rerun_fr.bTime) {
-                t = rerun_fr.time;
-            }
-            else
-            {
-                t = step;
-            }
-        } 
-        else 
-        {
-            bLastStep = (step_rel == ir->nsteps);
-            t = t0 + step*ir->delta_t;
-        }
-
-        if (ir->efep != efepNO)
-        {
-            if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
-            {
-                state_global->lambda = rerun_fr.lambda;
-            }
-            else
-            {
-                state_global->lambda = lam0 + step*ir->delta_lambda;
-            }
-            state->lambda = state_global->lambda;
-            bDoDHDL = do_per_step(step,ir->nstdhdl);
-        }
-
-        if (bSimAnn) 
-        {
-            update_annealing_target_temp(&(ir->opts),t);
-        }
-
-        if (bRerunMD)
-        {
-            if (!(DOMAINDECOMP(cr) && !MASTER(cr)))
-            {
-                for(i=0; i<state_global->natoms; i++)
-                {
-                    copy_rvec(rerun_fr.x[i],state_global->x[i]);
-                }
-                if (rerun_fr.bV)
-                {
-                    for(i=0; i<state_global->natoms; i++)
-                    {
-                        copy_rvec(rerun_fr.v[i],state_global->v[i]);
-                    }
-                }
-                else
-                {
-                    for(i=0; i<state_global->natoms; i++)
-                    {
-                        clear_rvec(state_global->v[i]);
-                    }
-                    if (bRerunWarnNoV)
-                    {
-                        fprintf(stderr,"\nWARNING: Some frames do not contain velocities.\n"
-                                "         Ekin, temperature and pressure are incorrect,\n"
-                                "         the virial will be incorrect when constraints are present.\n"
-                                "\n");
-                        bRerunWarnNoV = FALSE;
-                    }
-                }
-            }
-            copy_mat(rerun_fr.box,state_global->box);
-            copy_mat(state_global->box,state->box);
-
-            if (vsite && (Flags & MD_RERUN_VSITE))
-            {
-                if (DOMAINDECOMP(cr))
-                {
-                    gmx_fatal(FARGS,"Vsite recalculation with -rerun is not implemented for domain decomposition, use particle decomposition");
-                }
-                if (graph)
-                {
-                    /* Following is necessary because the graph may get out of sync
-                     * with the coordinates if we only have every N'th coordinate set
-                     */
-                    mk_mshift(fplog,graph,fr->ePBC,state->box,state->x);
-                    shift_self(graph,state->box,state->x);
-                }
-                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
-                                 top->idef.iparams,top->idef.il,
-                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-                if (graph)
-                {
-                    unshift_self(graph,state->box,state->x);
-                }
-            }
-        }
-
-        /* Stop Center of Mass motion */
-        bStopCM = (ir->comm_mode != ecmNO && do_per_step(step,ir->nstcomm));
-
-        /* Copy back starting coordinates in case we're doing a forcefield scan */
-        if (bFFscan)
-        {
-            for(ii=0; (ii<state->natoms); ii++)
-            {
-                copy_rvec(xcopy[ii],state->x[ii]);
-                copy_rvec(vcopy[ii],state->v[ii]);
-            }
-            copy_mat(boxcopy,state->box);
-        }
-
-        if (bRerunMD)
-        {
-            /* for rerun MD always do Neighbour Searching */
-            bNS = (bFirstStep || ir->nstlist != 0);
-            bNStList = bNS;
-        }
-        else
-        {
-            /* Determine whether or not to do Neighbour Searching and LR */
-            bNStList = (ir->nstlist > 0  && step % ir->nstlist == 0);
-            
-            bNS = (bFirstStep || bExchanged || bNStList ||
-                   (ir->nstlist == -1 && nlh.nabnsb > 0));
-
-            if (bNS && ir->nstlist == -1)
-            {
-                set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
-            }
-        } 
-
-        /* check whether we should stop because another simulation has 
-           stopped. */
-        if (MULTISIM(cr))
-        {
-            if ( (multisim_nsteps >= 0) &&  (step_rel >= multisim_nsteps)  &&  
-                 (multisim_nsteps != ir->nsteps) )  
-            {
-                if (bNS)
-                {
-                    if (MASTER(cr))
-                    {
-                        fprintf(stderr, 
-                                "Stopping simulation %d because another one has finished\n",
-                                cr->ms->sim);
-                    }
-                    bLastStep=TRUE;
-                    gs.sig[eglsCHKPT] = 1;
-                }
-            }
-        }
-
-        /* < 0 means stop at next step, > 0 means stop at next NS step */
-        if ( (gs.set[eglsSTOPCOND] < 0 ) ||
-             ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
-        {
-            bLastStep = TRUE;
-        }
-
-        /* Determine whether or not to update the Born radii if doing GB */
-        bBornRadii=bFirstStep;
-        if (ir->implicit_solvent && (step % ir->nstgbradii==0))
-        {
-            bBornRadii=TRUE;
-        }
-        
-        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
-        do_verbose = bVerbose &&
-                  (step % stepout == 0 || bFirstStep || bLastStep);
-
-        if (bNS && !(bFirstStep && ir->bContinuation && !bRerunMD))
-        {
-            if (bRerunMD)
-            {
-                bMasterState = TRUE;
-            }
-            else
-            {
-                bMasterState = FALSE;
-                /* Correct the new box if it is too skewed */
-                if (DYNAMIC_BOX(*ir))
-                {
-                    if (correct_box(fplog,step,state->box,graph))
-                    {
-                        bMasterState = TRUE;
-                    }
-                }
-                if (DOMAINDECOMP(cr) && bMasterState)
-                {
-                    dd_collect_state(cr->dd,state,state_global);
-                }
-            }
-
-            if (DOMAINDECOMP(cr))
-            {
-                /* Repartition the domain decomposition */
-                wallcycle_start(wcycle,ewcDOMDEC);
-                dd_partition_system(fplog,step,cr,
-                                    bMasterState,nstglobalcomm,
-                                    state_global,top_global,ir,
-                                    state,&f,mdatoms,top,fr,
-                                    vsite,shellfc,constr,
-                                    nrnb,wcycle,do_verbose);
-                wallcycle_stop(wcycle,ewcDOMDEC);
-                /* If using an iterative integrator, reallocate space to match the decomposition */
-            }
-        }
-
-        if (MASTER(cr) && do_log && !bFFscan)
-        {
-            print_ebin_header(fplog,step,t,state->lambda);
-        }
-
-        if (ir->efep != efepNO)
-        {
-            update_mdatoms(mdatoms,state->lambda); 
-        }
-
-        if (bRerunMD && rerun_fr.bV)
-        {
-            
-            /* We need the kinetic energy at minus the half step for determining
-             * the full step kinetic energy and possibly for T-coupling.*/
-            /* This may not be quite working correctly yet . . . . */
-            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                            wcycle,enerd,NULL,NULL,NULL,NULL,mu_tot,
-                            constr,NULL,FALSE,state->box,
-                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                            CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
-        }
-        clear_mat(force_vir);
-        
-        /* Ionize the atoms if necessary */
-        if (bIonize)
-        {
-            ionize(fplog,oenv,mdatoms,top_global,t,ir,state->x,state->v,
-                   mdatoms->start,mdatoms->start+mdatoms->homenr,state->box,cr);
-        }
-        
-        /* Update force field in ffscan program */
-        if (bFFscan)
-        {
-            if (update_forcefield(fplog,
-                                  nfile,fnm,fr,
-                                  mdatoms->nr,state->x,state->box)) {
-                if (gmx_parallel_env_initialized())
-                {
-                    gmx_finalize();
-                }
-                exit(0);
-            }
-        }
-
-        GMX_MPE_LOG(ev_timestep2);
-
-        /* We write a checkpoint at this MD step when:
-         * either at an NS step when we signalled through gs,
-         * or at the last step (but not when we do not want confout),
-         * but never at the first step or with rerun.
-         */
-        bCPT = (((gs.set[eglsCHKPT] && (bNS || ir->nstlist == 0)) ||
-                 (bLastStep && (Flags & MD_CONFOUT))) &&
-                step > ir->init_step && !bRerunMD);
-        if (bCPT)
-        {
-            gs.set[eglsCHKPT] = 0;
-        }
-
-        /* Determine the energy and pressure:
-         * at nstcalcenergy steps and at energy output steps (set below).
-         */
-        bNstEner = do_per_step(step,ir->nstcalcenergy);
-        bCalcEnerPres =
-            (bNstEner ||
-             (ir->epc != epcNO && do_per_step(step,ir->nstpcouple)));
-
-        /* Do we need global communication ? */
-        bGStat = (bCalcEnerPres || bStopCM ||
-                  do_per_step(step,nstglobalcomm) ||
-                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
-
-        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
-
-        if (do_ene || do_log)
-        {
-            bCalcEnerPres = TRUE;
-            bGStat        = TRUE;
-        }
-        
-        /* these CGLO_ options remain the same throughout the iteration */
-        cglo_flags = ((bRerunMD ? CGLO_RERUNMD : 0) |
-                      (bStopCM ? CGLO_STOPCM : 0) |
-                      (bGStat ? CGLO_GSTAT : 0)
-            );
-        
-        force_flags = (GMX_FORCE_STATECHANGED |
-                       ((DYNAMIC_BOX(*ir) || bRerunMD) ? GMX_FORCE_DYNAMICBOX : 0) |
-                       GMX_FORCE_ALLFORCES |
-                       (bNStList ? GMX_FORCE_DOLR : 0) |
-                       GMX_FORCE_SEPLRF |
-                       (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
-                       (bDoDHDL ? GMX_FORCE_DHDL : 0)
-            );
-        
-        if (shellfc)
-        {
-            /* Now is the time to relax the shells */
-            count=relax_shell_flexcon(fplog,cr,bVerbose,bFFscan ? step+1 : step,
-                                      ir,bNS,force_flags,
-                                      bStopCM,top,top_global,
-                                      constr,enerd,fcd,
-                                      state,f,force_vir,mdatoms,
-                                      nrnb,wcycle,graph,groups,
-                                      shellfc,fr,bBornRadii,t,mu_tot,
-                                      state->natoms,&bConverged,vsite,
-                                      outf->fp_field);
-            tcount+=count;
-
-            if (bConverged)
-            {
-                nconverged++;
-            }
-        }
-        else
-        {
-            /* The coordinates (x) are shifted (to get whole molecules)
-             * in do_force.
-             * This is parallellized as well, and does communication too. 
-             * Check comments in sim_util.c
-             */
-        
-            do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
-                     state->box,state->x,&state->hist,
-                     f,force_vir,mdatoms,enerd,fcd,
-                     state->lambda,graph,
-                     fr,vsite,mu_tot,t,outf->fp_field,ed,bBornRadii,
-                     (bNS ? GMX_FORCE_NS : 0) | force_flags);
-        }
-    
-        GMX_BARRIER(cr->mpi_comm_mygroup);
-        
-        if (bTCR)
-        {
-            mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
-                                   mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
-        }
-        
-        if (bTCR && bFirstStep)
-        {
-            tcr=init_coupling(fplog,nfile,fnm,cr,fr,mdatoms,&(top->idef));
-            fprintf(fplog,"Done init_coupling\n"); 
-            fflush(fplog);
-        }
-        
-        if (bVV && !bStartingFromCpt && !bRerunMD)
-        /*  ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
-        {
-            if (ir->eI==eiVV && bInitStep) 
-            {
-                /* if using velocity verlet with full time step Ekin,
-                 * take the first half step only to compute the 
-                 * virial for the first step. From there,
-                 * revert back to the initial coordinates
-                 * so that the input is actually the initial step.
-                 */
-                copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
-            } else {
-                /* this is for NHC in the Ekin(t+dt/2) version of vv */
-                trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ1);            
-            }
-
-            update_coords(fplog,step,ir,mdatoms,state,
-                          f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
-                          ekind,M,wcycle,upd,bInitStep,etrtVELOCITY1,
-                          cr,nrnb,constr,&top->idef);
-            
-            if (bIterations)
-            {
-                gmx_iterate_init(&iterate,bIterations && !bInitStep);
-            }
-            /* for iterations, we save these vectors, as we will be self-consistently iterating
-               the calculations */
-
-            /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
-            
-            /* save the state */
-            if (bIterations && iterate.bIterate) { 
-                copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
-            }
-            
-            bFirstIterate = TRUE;
-            while (bFirstIterate || (bIterations && iterate.bIterate))
-            {
-                if (bIterations && iterate.bIterate) 
-                {
-                    copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
-                    if (bFirstIterate && bTrotter) 
-                    {
-                        /* The first time through, we need a decent first estimate
-                           of veta(t+dt) to compute the constraints.  Do
-                           this by computing the box volume part of the
-                           trotter integration at this time. Nothing else
-                           should be changed by this routine here.  If
-                           !(first time), we start with the previous value
-                           of veta.  */
-                        
-                        veta_save = state->veta;
-                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ0);
-                        vetanew = state->veta;
-                        state->veta = veta_save;
-                    } 
-                } 
-                
-                bOK = TRUE;
-                if ( !bRerunMD || rerun_fr.bV || bForceUpdate) {  /* Why is rerun_fr.bV here?  Unclear. */
-                    dvdl = 0;
-                    
-                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
-                                       &top->idef,shake_vir,NULL,
-                                       cr,nrnb,wcycle,upd,constr,
-                                       bInitStep,TRUE,bCalcEnerPres,vetanew);
-                    
-                    if (!bOK && !bFFscan)
-                    {
-                        gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
-                    }
-                    
-                } 
-                else if (graph)
-                { /* Need to unshift here if a do_force has been
-                     called in the previous step */
-                    unshift_self(graph,state->box,state->x);
-                }
-                
-                
-                /* if VV, compute the pressure and constraints */
-                /* For VV2, we strictly only need this if using pressure
-                 * control, but we really would like to have accurate pressures
-                 * printed out.
-                 * Think about ways around this in the future?
-                 * For now, keep this choice in comments.
-                 */
-                /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
-                    /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
-                bPres = TRUE;
-                bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
-                compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                                wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
-                                constr,NULL,FALSE,state->box,
-                                top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                                cglo_flags 
-                                | CGLO_ENERGY 
-                                | (bTemp ? CGLO_TEMPERATURE:0) 
-                                | (bPres ? CGLO_PRESSURE : 0) 
-                                | (bPres ? CGLO_CONSTRAINT : 0)
-                                | ((bIterations && iterate.bIterate) ? CGLO_ITERATE : 0)  
-                                | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
-                                | CGLO_SCALEEKIN 
-                    );
-                /* explanation of above: 
-                   a) We compute Ekin at the full time step
-                   if 1) we are using the AveVel Ekin, and it's not the
-                   initial step, or 2) if we are using AveEkin, but need the full
-                   time step kinetic energy for the pressure (always true now, since we want accurate statistics).
-                   b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in 
-                   EkinAveVel because it's needed for the pressure */
-                
-                /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
-                if (!bInitStep) 
-                {
-                    if (bTrotter)
-                    {
-                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ2);
-                    } 
-                    else 
-                    {
-                        update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
-                    }
-                }
-                
-                if (bIterations &&
-                    done_iterating(cr,fplog,step,&iterate,bFirstIterate,
-                                   state->veta,&vetanew)) 
-                {
-                    break;
-                }
-                bFirstIterate = FALSE;
-            }
-
-            if (bTrotter && !bInitStep) {
-                copy_mat(shake_vir,state->svir_prev);
-                copy_mat(force_vir,state->fvir_prev);
-                if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
-                    /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
-                    enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,NULL,(ir->eI==eiVV),FALSE,FALSE);
-                    enerd->term[F_EKIN] = trace(ekind->ekin);
-                }
-            }
-            /* if it's the initial step, we performed this first step just to get the constraint virial */
-            if (bInitStep && ir->eI==eiVV) {
-                copy_rvecn(cbuf,state->v,0,state->natoms);
-            }
-            
-            if (fr->bSepDVDL && fplog && do_log) 
-            {
-                fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
-            }
-            enerd->term[F_DHDL_CON] += dvdl;
-            
-            GMX_MPE_LOG(ev_timestep1);
-        }
-    
-        /* MRS -- now done iterating -- compute the conserved quantity */
-        if (bVV) {
-            saved_conserved_quantity = compute_conserved_from_auxiliary(ir,state,&MassQ);
-            if (ir->eI==eiVV) 
-            {
-                last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
-            }
-            if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres)) 
-            {
-                saved_conserved_quantity -= enerd->term[F_DISPCORR];
-            }
-        }
-        
-        /* ########  END FIRST UPDATE STEP  ############## */
-        /* ########  If doing VV, we now have v(dt) ###### */
-        
-        /* ################## START TRAJECTORY OUTPUT ################# */
-        
-        /* Now we have the energies and forces corresponding to the 
-         * coordinates at time t. We must output all of this before
-         * the update.
-         * for RerunMD t is read from input trajectory
-         */
-        GMX_MPE_LOG(ev_output_start);
-
-        mdof_flags = 0;
-        if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
-        if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
-        if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
-        if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
-        if (bCPT) { mdof_flags |= MDOF_CPT; };
-
-#if defined(GMX_FAHCORE) || defined(GMX_WRITELASTSTEP)
-        if (bLastStep)
-        {
-            /* Enforce writing positions and velocities at end of run */
-            mdof_flags |= (MDOF_X | MDOF_V);
-        }
-#endif
-#ifdef GMX_FAHCORE
-        if (MASTER(cr))
-            fcReportProgress( ir->nsteps, step );
-
-        /* sync bCPT and fc record-keeping */
-        if (bCPT && MASTER(cr))
-            fcRequestCheckPoint();
-#endif
-        
-        if (mdof_flags != 0)
-        {
-            wallcycle_start(wcycle,ewcTRAJ);
-            if (bCPT)
-            {
-                if (state->flags & (1<<estLD_RNG))
-                {
-                    get_stochd_state(upd,state);
-                }
-                if (MASTER(cr))
-                {
-                    if (bSumEkinhOld)
-                    {
-                        state_global->ekinstate.bUpToDate = FALSE;
-                    }
-                    else
-                    {
-                        update_ekinstate(&state_global->ekinstate,ekind);
-                        state_global->ekinstate.bUpToDate = TRUE;
-                    }
-                    update_energyhistory(&state_global->enerhist,mdebin);
-                }
-            }
-            write_traj(fplog,cr,outf,mdof_flags,top_global,
-                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
-            if (bCPT)
-            {
-                nchkpt++;
-                bCPT = FALSE;
-            }
-            debug_gmx();
-            if (bLastStep && step_rel == ir->nsteps &&
-                (Flags & MD_CONFOUT) && MASTER(cr) &&
-                !bRerunMD && !bFFscan)
-            {
-                /* x and v have been collected in write_traj,
-                 * because a checkpoint file will always be written
-                 * at the last step.
-                 */
-                fprintf(stderr,"\nWriting final coordinates.\n");
-                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols &&
-                    DOMAINDECOMP(cr))
-                {
-                    /* Make molecules whole only for confout writing */
-                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
-                }
-                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
-                                    *top_global->name,top_global,
-                                    state_global->x,state_global->v,
-                                    ir->ePBC,state->box);
-                debug_gmx();
-            }
-            wallcycle_stop(wcycle,ewcTRAJ);
-        }
-        GMX_MPE_LOG(ev_output_finish);
-        
-        /* kludge -- virial is lost with restart for NPT control. Must restart */
-        if (bStartingFromCpt && bVV) 
-        {
-            copy_mat(state->svir_prev,shake_vir);
-            copy_mat(state->fvir_prev,force_vir);
-        }
-        /*  ################## END TRAJECTORY OUTPUT ################ */
-        
-        /* Determine the wallclock run time up till now */
-        run_time = gmx_gettime() - (double)runtime->real;
-
-        /* Check whether everything is still allright */    
-        if (((int)gmx_get_stop_condition() > handled_stop_condition)
-#ifdef GMX_THREADS
-            && MASTER(cr)
-#endif
-            )
-        {
-            /* this is just make gs.sig compatible with the hack 
-               of sending signals around by MPI_Reduce with together with
-               other floats */
-            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
-                gs.sig[eglsSTOPCOND]=1;
-            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
-                gs.sig[eglsSTOPCOND]=-1;
-            /* < 0 means stop at next step, > 0 means stop at next NS step */
-            if (fplog)
-            {
-                fprintf(fplog,
-                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                        gmx_get_signal_name(),
-                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
-                fflush(fplog);
-            }
-            fprintf(stderr,
-                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                    gmx_get_signal_name(),
-                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
-            fflush(stderr);
-            handled_stop_condition=(int)gmx_get_stop_condition();
-        }
-        else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
-                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
-                 gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
-        {
-            /* Signal to terminate the run */
-            gs.sig[eglsSTOPCOND] = 1;
-            if (fplog)
-            {
-                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
-            }
-            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
-        }
-
-        if (bResetCountersHalfMaxH && MASTER(cr) &&
-            run_time > max_hours*60.0*60.0*0.495)
-        {
-            gs.sig[eglsRESETCOUNTERS] = 1;
-        }
-
-        if (ir->nstlist == -1 && !bRerunMD)
-        {
-            /* When bGStatEveryStep=FALSE, global_stat is only called
-             * when we check the atom displacements, not at NS steps.
-             * This means that also the bonded interaction count check is not
-             * performed immediately after NS. Therefore a few MD steps could
-             * be performed with missing interactions.
-             * But wrong energies are never written to file,
-             * since energies are only written after global_stat
-             * has been called.
-             */
-            if (step >= nlh.step_nscheck)
-            {
-                nlh.nabnsb = natoms_beyond_ns_buffer(ir,fr,&top->cgs,
-                                                     nlh.scale_tot,state->x);
-            }
-            else
-            {
-                /* This is not necessarily true,
-                 * but step_nscheck is determined quite conservatively.
-                 */
-                nlh.nabnsb = 0;
-            }
-        }
-
-        /* In parallel we only have to check for checkpointing in steps
-         * where we do global communication,
-         *  otherwise the other nodes don't know.
-         */
-        if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
-                           cpt_period >= 0 &&
-                           (cpt_period == 0 || 
-                            run_time >= nchkpt*cpt_period*60.0)) &&
-            gs.set[eglsCHKPT] == 0)
-        {
-            gs.sig[eglsCHKPT] = 1;
-        }
-  
-        if (bIterations)
-        {
-            gmx_iterate_init(&iterate,bIterations);
-        }
-    
-        /* for iterations, we save these vectors, as we will be redoing the calculations */
-        if (bIterations && iterate.bIterate) 
-        {
-            copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
-        }
-        bFirstIterate = TRUE;
-        while (bFirstIterate || (bIterations && iterate.bIterate))
-        {
-            /* We now restore these vectors to redo the calculation with improved extended variables */    
-            if (bIterations) 
-            { 
-                copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
-            }
-
-            /* We make the decision to break or not -after- the calculation of Ekin and Pressure,
-               so scroll down for that logic */
-            
-            /* #########   START SECOND UPDATE STEP ################# */
-            GMX_MPE_LOG(ev_update_start);
-            /* Box is changed in update() when we do pressure coupling,
-             * but we should still use the old box for energy corrections and when
-             * writing it to the energy file, so it matches the trajectory files for
-             * the same timestep above. Make a copy in a separate array.
-             */
-            copy_mat(state->box,lastbox);
-
-            bOK = TRUE;
-            if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
-            {
-                wallcycle_start(wcycle,ewcUPDATE);
-                dvdl = 0;
-                /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
-                if (bTrotter) 
-                {
-                    if (bIterations && iterate.bIterate) 
-                    {
-                        if (bFirstIterate) 
-                        {
-                            scalevir = 1;
-                        }
-                        else 
-                        {
-                            /* we use a new value of scalevir to converge the iterations faster */
-                            scalevir = tracevir/trace(shake_vir);
-                        }
-                        msmul(shake_vir,scalevir,shake_vir); 
-                        m_add(force_vir,shake_vir,total_vir);
-                        clear_mat(shake_vir);
-                    }
-                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ3);
-                /* We can only do Berendsen coupling after we have summed
-                 * the kinetic energy or virial. Since the happens
-                 * in global_state after update, we should only do it at
-                 * step % nstlist = 1 with bGStatEveryStep=FALSE.
-                 */
-                }
-                else 
-                {
-                    update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
-                    update_pcouple(fplog,step,ir,state,pcoupl_mu,M,wcycle,
-                                   upd,bInitStep);
-                }
-
-                if (bVV)
-                {
-                    /* velocity half-step update */
-                    update_coords(fplog,step,ir,mdatoms,state,f,
-                                  fr->bTwinRange && bNStList,fr->f_twin,fcd,
-                                  ekind,M,wcycle,upd,FALSE,etrtVELOCITY2,
-                                  cr,nrnb,constr,&top->idef);
-                }
-
-                /* Above, initialize just copies ekinh into ekin,
-                 * it doesn't copy position (for VV),
-                 * and entire integrator for MD.
-                 */
-                
-                if (ir->eI==eiVVAK) 
-                {
-                    copy_rvecn(state->x,cbuf,0,state->natoms);
-                }
-                
-                update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
-                              ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
-                wallcycle_stop(wcycle,ewcUPDATE);
-
-                update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
-                                   &top->idef,shake_vir,force_vir,
-                                   cr,nrnb,wcycle,upd,constr,
-                                   bInitStep,FALSE,bCalcEnerPres,state->veta);  
-                
-                if (ir->eI==eiVVAK) 
-                {
-                    /* erase F_EKIN and F_TEMP here? */
-                    /* just compute the kinetic energy at the half step to perform a trotter step */
-                    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
-                                    constr,NULL,FALSE,lastbox,
-                                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                                    cglo_flags | CGLO_TEMPERATURE    
-                        );
-                    wallcycle_start(wcycle,ewcUPDATE);
-                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ4);            
-                    /* now we know the scaling, we can compute the positions again again */
-                    copy_rvecn(cbuf,state->x,0,state->natoms);
-
-                    update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
-                                  ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
-                    wallcycle_stop(wcycle,ewcUPDATE);
-
-                    /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
-                    /* are the small terms in the shake_vir here due
-                     * to numerical errors, or are they important
-                     * physically? I'm thinking they are just errors, but not completely sure. 
-                     * For now, will call without actually constraining, constr=NULL*/
-                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
-                                       &top->idef,tmp_vir,force_vir,
-                                       cr,nrnb,wcycle,upd,NULL,
-                                       bInitStep,FALSE,bCalcEnerPres,
-                                       state->veta);  
-                }
-                if (!bOK && !bFFscan) 
-                {
-                    gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
-                }
-                
-                if (fr->bSepDVDL && fplog && do_log) 
-                {
-                    fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
-                }
-                enerd->term[F_DHDL_CON] += dvdl;
-            } 
-            else if (graph) 
-            {
-                /* Need to unshift here */
-                unshift_self(graph,state->box,state->x);
-            }
-            
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_update_finish);
-
-            if (vsite != NULL) 
-            {
-                wallcycle_start(wcycle,ewcVSITECONSTR);
-                if (graph != NULL) 
-                {
-                    shift_self(graph,state->box,state->x);
-                }
-                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
-                                 top->idef.iparams,top->idef.il,
-                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-                
-                if (graph != NULL) 
-                {
-                    unshift_self(graph,state->box,state->x);
-                }
-                wallcycle_stop(wcycle,ewcVSITECONSTR);
-            }
-            
-            /* ############## IF NOT VV, Calculate globals HERE, also iterate constraints ############ */
-            if (ir->nstlist == -1 && bFirstIterate)
-            {
-                gs.sig[eglsNABNSB] = nlh.nabnsb;
-            }
-            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
-                            wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
-                            constr,
-                            bFirstIterate ? &gs : NULL, 
-                            (step_rel % gs.nstms == 0) && 
-                                (multisim_nsteps<0 || (step_rel<multisim_nsteps)),
-                            lastbox,
-                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                            cglo_flags 
-                            | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0) 
-                            | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0) 
-                            | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0) 
-                            | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0) 
-                            | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
-                            | CGLO_CONSTRAINT 
-                );
-            if (ir->nstlist == -1 && bFirstIterate)
-            {
-                nlh.nabnsb = gs.set[eglsNABNSB];
-                gs.set[eglsNABNSB] = 0;
-            }
-            /* bIterate is set to keep it from eliminating the old ekin kinetic energy terms */
-            /* #############  END CALC EKIN AND PRESSURE ################# */
-        
-            /* Note: this is OK, but there are some numerical precision issues with using the convergence of
-               the virial that should probably be addressed eventually. state->veta has better properies,
-               but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
-               generate the new shake_vir, but test the veta value for convergence.  This will take some thought. */
-
-            if (bIterations && 
-                done_iterating(cr,fplog,step,&iterate,bFirstIterate,
-                               trace(shake_vir),&tracevir)) 
-            {
-                break;
-            }
-            bFirstIterate = FALSE;
-        }
-
-        update_box(fplog,step,ir,mdatoms,state,graph,f,
-                   ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
-        
-        /* ################# END UPDATE STEP 2 ################# */
-        /* #### We now have r(t+dt) and v(t+dt/2)  ############# */
-    
-        /* The coordinates (x) were unshifted in update */
-        if (bFFscan && (shellfc==NULL || bConverged))
-        {
-            if (print_forcefield(fplog,enerd->term,mdatoms->homenr,
-                                 f,NULL,xcopy,
-                                 &(top_global->mols),mdatoms->massT,pres))
-            {
-                if (gmx_parallel_env_initialized())
-                {
-                    gmx_finalize();
-                }
-                fprintf(stderr,"\n");
-                exit(0);
-            }
-        }
-        if (!bGStat)
-        {
-            /* We will not sum ekinh_old,                                                            
-             * so signal that we still have to do it.                                                
-             */
-            bSumEkinhOld = TRUE;
-        }
-        
-        if (bTCR)
-        {
-            /* Only do GCT when the relaxation of shells (minimization) has converged,
-             * otherwise we might be coupling to bogus energies. 
-             * In parallel we must always do this, because the other sims might
-             * update the FF.
-             */
-
-            /* Since this is called with the new coordinates state->x, I assume
-             * we want the new box state->box too. / EL 20040121
-             */
-            do_coupling(fplog,oenv,nfile,fnm,tcr,t,step,enerd->term,fr,
-                        ir,MASTER(cr),
-                        mdatoms,&(top->idef),mu_aver,
-                        top_global->mols.nr,cr,
-                        state->box,total_vir,pres,
-                        mu_tot,state->x,f,bConverged);
-            debug_gmx();
-        }
-
-        /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
-        
-        /* sum up the foreign energy and dhdl terms */
-        sum_dhdl(enerd,state->lambda,ir);
-
-        /* use the directly determined last velocity, not actually the averaged half steps */
-        if (bTrotter && ir->eI==eiVV) 
-        {
-            enerd->term[F_EKIN] = last_ekin;
-        }
-        enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
-        
-        if (bVV)
-        {
-            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + saved_conserved_quantity;
-        }
-        else 
-        {
-            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + compute_conserved_from_auxiliary(ir,state,&MassQ);
-        }
-        /* Check for excessively large energies */
-        if (bIonize) 
-        {
-#ifdef GMX_DOUBLE
-            real etot_max = 1e200;
-#else
-            real etot_max = 1e30;
-#endif
-            if (fabs(enerd->term[F_ETOT]) > etot_max) 
-            {
-                fprintf(stderr,"Energy too large (%g), giving up\n",
-                        enerd->term[F_ETOT]);
-            }
-        }
-        /* #########  END PREPARING EDR OUTPUT  ###########  */
-        
-        /* Time for performance */
-        if (((step % stepout) == 0) || bLastStep) 
-        {
-            runtime_upd_proc(runtime);
-        }
-        
-        /* Output stuff */
-        if (MASTER(cr))
-        {
-            gmx_bool do_dr,do_or;
-            
-            if (!(bStartingFromCpt && (EI_VV(ir->eI)))) 
-            {
-                if (bNstEner)
-                {
-                    upd_mdebin(mdebin,bDoDHDL, TRUE,
-                               t,mdatoms->tmass,enerd,state,lastbox,
-                               shake_vir,force_vir,total_vir,pres,
-                               ekind,mu_tot,constr);
-                }
-                else
-                {
-                    upd_mdebin_step(mdebin);
-                }
-                
-                do_dr  = do_per_step(step,ir->nstdisreout);
-                do_or  = do_per_step(step,ir->nstorireout);
-                
-                print_ebin(outf->fp_ene,do_ene,do_dr,do_or,do_log?fplog:NULL,
-                           step,t,
-                           eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
-            }
-            if (ir->ePull != epullNO)
-            {
-                pull_print_output(ir->pull,step,t);
-            }
-            
-            if (do_per_step(step,ir->nstlog))
-            {
-                if(fflush(fplog) != 0)
-                {
-                    gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
-                }
-            }
-        }
-
-
-        /* Remaining runtime */
-        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
-        {
-            if (shellfc) 
-            {
-                fprintf(stderr,"\n");
-            }
-            print_time(stderr,runtime,step,ir,cr);
-        }
-
-        /* Replica exchange */
-        bExchanged = FALSE;
-        if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
-            do_per_step(step,repl_ex_nst)) 
-        {
-            bExchanged = replica_exchange(fplog,cr,repl_ex,
-                                          state_global,enerd->term,
-                                          state,step,t);
-
-            if (bExchanged && DOMAINDECOMP(cr)) 
-            {
-                dd_partition_system(fplog,step,cr,TRUE,1,
-                                    state_global,top_global,ir,
-                                    state,&f,mdatoms,top,fr,
-                                    vsite,shellfc,constr,
-                                    nrnb,wcycle,FALSE);
-            }
-        }
-        
-        bFirstStep = FALSE;
-        bInitStep = FALSE;
-        bStartingFromCpt = FALSE;
-
-        /* #######  SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
-        /* With all integrators, except VV, we need to retain the pressure
-         * at the current step for coupling at the next step.
-         */
-        if ((state->flags & (1<<estPRES_PREV)) &&
-            (bGStatEveryStep ||
-             (ir->nstpcouple > 0 && step % ir->nstpcouple == 0)))
-        {
-            /* Store the pressure in t_state for pressure coupling
-             * at the next MD step.
-             */
-            copy_mat(pres,state->pres_prev);
-        }
-        
-        /* #######  END SET VARIABLES FOR NEXT ITERATION ###### */
-        
-        if (bRerunMD) 
-        {
-            if (MASTER(cr))
-            {
-                /* read next frame from input trajectory */
-                bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
-            }
-
-            if (PAR(cr))
-            {
-                rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
-            }
-        }
-        
-        if (!bRerunMD || !rerun_fr.bStep)
-        {
-            /* increase the MD step number */
-            step++;
-            step_rel++;
-        }
-        
-        cycles = wallcycle_stop(wcycle,ewcSTEP);
-        if (DOMAINDECOMP(cr) && wcycle)
-        {
-            dd_cycles_add(cr->dd,cycles,ddCyclStep);
-        }
-        
-        if (step_rel == wcycle_get_reset_counters(wcycle) ||
-            gs.set[eglsRESETCOUNTERS] != 0)
-        {
-            /* Reset all the counters related to performance over the run */
-            reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
-            wcycle_set_reset_counters(wcycle,-1);
-            /* Correct max_hours for the elapsed time */
-            max_hours -= run_time/(60.0*60.0);
-            bResetCountersHalfMaxH = FALSE;
-            gs.set[eglsRESETCOUNTERS] = 0;
-        }
-
-    }
-    /* End of main MD loop */
-    debug_gmx();
-    
-    /* Stop the time */
-    runtime_end(runtime);
-    
-    if (bRerunMD && MASTER(cr))
-    {
-        close_trj(status);
-    }
-    
-    if (!(cr->duty & DUTY_PME))
-    {
-        /* Tell the PME only node to finish */
-        gmx_pme_finish(cr);
-    }
-    
-    if (MASTER(cr))
-    {
-        if (ir->nstcalcenergy > 0 && !bRerunMD) 
-        {
-            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
-                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
-        }
-    }
-
-    done_mdoutf(outf);
-
-    debug_gmx();
-
-    if (ir->nstlist == -1 && nlh.nns > 0 && fplog)
-    {
-        fprintf(fplog,"Average neighborlist lifetime: %.1f steps, std.dev.: %.1f steps\n",nlh.s1/nlh.nns,sqrt(nlh.s2/nlh.nns - sqr(nlh.s1/nlh.nns)));
-        fprintf(fplog,"Average number of atoms that crossed the half buffer length: %.1f\n\n",nlh.ab/nlh.nns);
-    }
-    
-    if (shellfc && fplog)
-    {
-        fprintf(fplog,"Fraction of iterations that converged:           %.2f %%\n",
-                (nconverged*100.0)/step_rel);
-        fprintf(fplog,"Average number of force evaluations per MD step: %.2f\n\n",
-                tcount/step_rel);
-    }
-    
-    if (repl_ex_nst > 0 && MASTER(cr))
-    {
-        print_replica_exchange_statistics(fplog,repl_ex);
-    }
-    
-    runtime->nsteps_done = step_rel;
-    
-    return 0;
-}
diff --git a/src/kernel/md_openmm.c b/src/kernel/md_openmm.c
deleted file mode 100644 (file)
index bbc9d1d..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2010, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <signal.h>
-#include <stdlib.h>
-
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-/* _isnan() */
-#include <float.h>
-#endif
-
-#include "typedefs.h"
-#include "smalloc.h"
-#include "sysstuff.h"
-#include "vec.h"
-#include "statutil.h"
-#include "vcm.h"
-#include "mdebin.h"
-#include "nrnb.h"
-#include "calcmu.h"
-#include "index.h"
-#include "vsite.h"
-#include "update.h"
-#include "ns.h"
-#include "trnio.h"
-#include "xtcio.h"
-#include "mdrun.h"
-#include "confio.h"
-#include "network.h"
-#include "pull.h"
-#include "xvgr.h"
-#include "physics.h"
-#include "names.h"
-#include "xmdrun.h"
-#include "ionize.h"
-#include "disre.h"
-#include "orires.h"
-#include "dihre.h"
-#include "pppm.h"
-#include "pme.h"
-#include "mdatoms.h"
-#include "qmmm.h"
-#include "mpelogging.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "topsort.h"
-#include "coulomb.h"
-#include "constr.h"
-#include "compute_io.h"
-#include "mvdata.h"
-#include "checkpoint.h"
-#include "mtop_util.h"
-#include "sighandler.h"
-#include "genborn.h"
-#include "string2.h"
-#include "copyrite.h"
-
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-/* include even when OpenMM not used to force compilation of do_md_openmm */
-#include "openmm_wrapper.h"
-
-double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-                    const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-                    int nstglobalcomm,
-                    gmx_vsite_t *vsite,gmx_constr_t constr,
-                    int stepout,t_inputrec *ir,
-                    gmx_mtop_t *top_global,
-                    t_fcdata *fcd,
-                    t_state *state_global,
-                    t_mdatoms *mdatoms,
-                    t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                    gmx_edsam_t ed,t_forcerec *fr,
-                    int repl_ex_nst,int repl_ex_seed,
-                    real cpt_period,real max_hours,
-                    const char *deviceOptions,
-                    unsigned long Flags,
-                    gmx_runtime_t *runtime)
-{
-    gmx_mdoutf_t *outf;
-    gmx_large_int_t step,step_rel;
-    double     run_time;
-    double     t,t0,lam0;
-    gmx_bool       bSimAnn,
-    bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
-    gmx_bool       bInitStep=TRUE;
-    gmx_bool       do_ene,do_log, do_verbose,
-    bX,bV,bF,bCPT;
-    tensor     force_vir,shake_vir,total_vir,pres;
-    int        i,m;
-    int        mdof_flags;
-    rvec       mu_tot;
-    t_vcm      *vcm;
-    int        nchkpt=1;
-    gmx_localtop_t *top;
-    t_mdebin *mdebin=NULL;
-    t_state    *state=NULL;
-    rvec       *f_global=NULL;
-    int        n_xtc=-1;
-    rvec       *x_xtc=NULL;
-    gmx_enerdata_t *enerd;
-    rvec       *f=NULL;
-    gmx_global_stat_t gstat;
-    gmx_update_t upd=NULL;
-    t_graph    *graph=NULL;
-    globsig_t   gs;
-
-    gmx_groups_t *groups;
-    gmx_ekindata_t *ekind, *ekind_save;
-    gmx_bool        bAppend;
-    int         a0,a1;
-    matrix      lastbox;
-    real        reset_counters=0,reset_counters_now=0;
-    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
-    int         handled_stop_condition=gmx_stop_cond_none; 
-
-    const char *ommOptions = NULL;
-    void   *openmmData;
-
-#ifdef GMX_DOUBLE
-    /* Checks in cmake should prevent the compilation in double precision
-     * with OpenMM, but just to be sure we check here.
-     */
-    gmx_fatal(FARGS,"Compilation was performed in double precision, but OpenMM only supports single precision. If you want to use to OpenMM, compile in single precision.");
-#endif
-
-    bAppend  = (Flags & MD_APPENDFILES);
-    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
-
-    groups = &top_global->groups;
-
-    /* Initial values */
-    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
-            nrnb,top_global,&upd,
-            nfile,fnm,&outf,&mdebin,
-            force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
-
-    clear_mat(total_vir);
-    clear_mat(pres);
-    /* Energy terms and groups */
-    snew(enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
-    snew(f,top_global->natoms);
-
-    /* Kinetic energy data */
-    snew(ekind,1);
-    init_ekindata(fplog,top_global,&(ir->opts),ekind);
-    /* needed for iteration of constraints */
-    snew(ekind_save,1);
-    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
-    /* Copy the cos acceleration to the groups struct */
-    ekind->cosacc.cos_accel = ir->cos_accel;
-
-    gstat = global_stat_init(ir);
-    debug_gmx();
-
-    {
-        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
-        if ((io > 2000) && MASTER(cr))
-            fprintf(stderr,
-                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
-                    io);
-    }
-
-    top = gmx_mtop_generate_local_top(top_global,ir);
-
-    a0 = 0;
-    a1 = top_global->natoms;
-
-    state = partdec_init_local_state(cr,state_global);
-    f_global = f;
-
-    atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
-
-    if (vsite)
-    {
-        set_vsite_top(vsite,top,mdatoms,cr);
-    }
-
-    if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
-    {
-        graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
-    }
-
-    update_mdatoms(mdatoms,state->lambda);
-
-    if (deviceOptions[0]=='\0')
-    {
-        /* empty options, which should default to OpenMM in this build */
-        ommOptions=deviceOptions;
-    }
-    else
-    {
-        if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
-        {
-            gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
-        }
-        else
-        {
-            ommOptions=strchr(deviceOptions,':');
-            if (NULL!=ommOptions)
-            {
-                /* Increase the pointer to skip the colon */
-                ommOptions++;
-            }
-        }
-    }
-
-    openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state);
-    please_cite(fplog,"Friedrichs2009");
-
-    if (MASTER(cr))
-    {
-        /* Update mdebin with energy history if appending to output files */
-        if ( Flags & MD_APPENDFILES )
-        {
-            restore_energyhistory_from_state(mdebin,&state_global->enerhist);
-        }
-        /* Set the initial energy history in state to zero by updating once */
-        update_energyhistory(&state_global->enerhist,mdebin);
-    }
-
-    if (constr)
-    {
-        set_constraints(constr,top,ir,mdatoms,cr);
-    }
-
-    if (!ir->bContinuation)
-    {
-        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
-        {
-            /* Set the velocities of frozen particles to zero */
-            for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
-            {
-                for (m=0; m<DIM; m++)
-                {
-                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
-                    {
-                        state->v[i][m] = 0;
-                    }
-                }
-            }
-        }
-
-        if (constr)
-        {
-            /* Constrain the initial coordinates and velocities */
-            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
-                               graph,cr,nrnb,fr,top,shake_vir);
-        }
-        if (vsite)
-        {
-            /* Construct the virtual sites for the initial configuration */
-            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
-                             top->idef.iparams,top->idef.il,
-                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-        }
-    }
-
-    debug_gmx();
-
-    if (MASTER(cr))
-    {
-        char tbuf[20];
-        fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
-        fprintf(stderr,"starting mdrun '%s'\n",
-                *(top_global->name));
-        if (ir->nsteps >= 0)
-        {
-            sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
-        }
-        else
-        {
-            sprintf(tbuf,"%s","infinite");
-        }
-        if (ir->init_step > 0)
-        {
-            fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
-                    gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
-                    gmx_step_str(ir->init_step,sbuf2),
-                    ir->init_step*ir->delta_t);
-        }
-        else
-        {
-            fprintf(stderr,"%s steps, %s ps.\n",
-                    gmx_step_str(ir->nsteps,sbuf),tbuf);
-        }
-    }
-
-    fprintf(fplog,"\n");
-
-    /* Set and write start time */
-    runtime_start(runtime);
-    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
-    wallcycle_start(wcycle,ewcRUN);
-    if (fplog)
-        fprintf(fplog,"\n");
-
-    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
-
-    debug_gmx();
-    /***********************************************************
-     *
-     *             Loop over MD steps
-     *
-     ************************************************************/
-
-    /* loop over MD steps or if rerunMD to end of input trajectory */
-    bFirstStep = TRUE;
-    /* Skip the first Nose-Hoover integration when we get the state from tpx */
-    bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
-    bInitStep = bFirstStep && bStateFromTPX;
-    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
-    bLastStep = FALSE;
-
-    init_global_signals(&gs,cr,ir,repl_ex_nst);
-
-    step = ir->init_step;
-    step_rel = 0;
-
-    while (!bLastStep)
-    {
-        wallcycle_start(wcycle,ewcSTEP);
-
-        GMX_MPE_LOG(ev_timestep1);
-
-        bLastStep = (step_rel == ir->nsteps);
-        t = t0 + step*ir->delta_t;
-
-        if (gs.set[eglsSTOPCOND] != 0)
-        {
-            bLastStep = TRUE;
-        }
-
-        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
-        do_verbose = bVerbose &&
-                     (step % stepout == 0 || bFirstStep || bLastStep);
-
-        if (MASTER(cr) && do_log)
-        {
-            print_ebin_header(fplog,step,t,state->lambda);
-        }
-
-        clear_mat(force_vir);
-        GMX_MPE_LOG(ev_timestep2);
-
-        /* We write a checkpoint at this MD step when:
-         * either when we signalled through gs (in OpenMM NS works different),
-         * or at the last step (but not when we do not want confout),
-         * but never at the first step.
-         */
-        bCPT = ((gs.set[eglsCHKPT] ||
-                 (bLastStep && (Flags & MD_CONFOUT))) &&
-                step > ir->init_step );
-        if (bCPT)
-        {
-            gs.set[eglsCHKPT] = 0;
-        }
-
-        /* Now we have the energies and forces corresponding to the
-         * coordinates at time t. We must output all of this before
-         * the update.
-         * for RerunMD t is read from input trajectory
-         */
-        GMX_MPE_LOG(ev_output_start);
-
-        mdof_flags = 0;
-        if (do_per_step(step,ir->nstxout))
-        {
-            mdof_flags |= MDOF_X;
-        }
-        if (do_per_step(step,ir->nstvout))
-        {
-            mdof_flags |= MDOF_V;
-        }
-        if (do_per_step(step,ir->nstfout))
-        {
-            mdof_flags |= MDOF_F;
-        }
-        if (do_per_step(step,ir->nstxtcout))
-        {
-            mdof_flags |= MDOF_XTC;
-        }
-        if (bCPT)
-        {
-            mdof_flags |= MDOF_CPT;
-        };
-        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
-
-        if (mdof_flags != 0 || do_ene || do_log)
-        {
-            wallcycle_start(wcycle,ewcTRAJ);
-            bF = (mdof_flags & MDOF_F);
-            bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT));
-            bV = (mdof_flags & (MDOF_V | MDOF_CPT));
-
-            openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, bF, do_ene);
-
-            upd_mdebin(mdebin,FALSE,TRUE,
-                       t,mdatoms->tmass,enerd,state,lastbox,
-                       shake_vir,force_vir,total_vir,pres,
-                       ekind,mu_tot,constr);
-            print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
-                       step,t,
-                       eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
-            write_traj(fplog,cr,outf,mdof_flags,top_global,
-                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
-            if (bCPT)
-            {
-                nchkpt++;
-                bCPT = FALSE;
-            }
-            debug_gmx();
-            if (bLastStep && step_rel == ir->nsteps &&
-                    (Flags & MD_CONFOUT) && MASTER(cr))
-            {
-                /* x and v have been collected in write_traj,
-                 * because a checkpoint file will always be written
-                 * at the last step.
-                 */
-                fprintf(stderr,"\nWriting final coordinates.\n");
-                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
-                {
-                    /* Make molecules whole only for confout writing */
-                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
-                }
-                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
-                                    *top_global->name,top_global,
-                                    state_global->x,state_global->v,
-                                    ir->ePBC,state->box);
-                debug_gmx();
-            }
-            wallcycle_stop(wcycle,ewcTRAJ);
-        }
-        GMX_MPE_LOG(ev_output_finish);
-
-
-        /* Determine the wallclock run time up till now */
-        run_time = gmx_gettime() - (double)runtime->real;
-
-        /* Check whether everything is still allright */
-        if (((int)gmx_get_stop_condition() > handled_stop_condition)
-#ifdef GMX_THREADS
-            && MASTER(cr)
-#endif
-            )
-        {
-           /* this is just make gs.sig compatible with the hack 
-               of sending signals around by MPI_Reduce with together with
-               other floats */
-            /* NOTE: this only works for serial code. For code that allows
-               MPI nodes to propagate their condition, see kernel/md.c*/
-            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
-                gs.set[eglsSTOPCOND]=1;
-            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
-                gs.set[eglsSTOPCOND]=1;
-            /* < 0 means stop at next step, > 0 means stop at next NS step */
-            if (fplog)
-            {
-                fprintf(fplog,
-                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                        gmx_get_signal_name(),
-                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
-                fflush(fplog);
-            }
-            fprintf(stderr,
-                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                    gmx_get_signal_name(),
-                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
-            fflush(stderr);
-            handled_stop_condition=(int)gmx_get_stop_condition();
-        }
-        else if (MASTER(cr) &&
-                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
-                 gs.set[eglsSTOPCOND] == 0)
-        {
-            /* Signal to terminate the run */
-            gs.set[eglsSTOPCOND] = 1;
-            if (fplog)
-            {
-                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
-            }
-            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
-        }
-
-        /* checkpoints */
-        if (MASTER(cr) && (cpt_period >= 0 &&
-                           (cpt_period == 0 ||
-                            run_time >= nchkpt*cpt_period*60.0)) &&
-                gs.set[eglsCHKPT] == 0)
-        {
-            gs.set[eglsCHKPT] = 1;
-        }
-
-        /* Time for performance */
-        if (((step % stepout) == 0) || bLastStep)
-        {
-            runtime_upd_proc(runtime);
-        }
-
-        if (do_per_step(step,ir->nstlog))
-        {
-            if (fflush(fplog) != 0)
-            {
-                gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
-            }
-        }
-
-        /* Remaining runtime */
-        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
-        {
-            print_time(stderr,runtime,step,ir,cr);
-        }
-
-        bFirstStep = FALSE;
-        bInitStep = FALSE;
-        bStartingFromCpt = FALSE;
-        step++;
-        step_rel++;
-
-        openmm_take_one_step(openmmData);
-    }
-    /* End of main MD loop */
-    debug_gmx();
-
-    /* Stop the time */
-    runtime_end(runtime);
-
-    if (MASTER(cr))
-    {
-        if (ir->nstcalcenergy > 0) 
-        {
-            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
-                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
-        }
-    }
-
-    openmm_cleanup(fplog, openmmData);
-
-    done_mdoutf(outf);
-
-    debug_gmx();
-
-    runtime->nsteps_done = step_rel;
-
-    return 0;
-}
diff --git a/src/kernel/md_openmm.h b/src/kernel/md_openmm.h
deleted file mode 100644 (file)
index b697c0f..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2010, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifndef _MD_OPENMM_H
-#define _MD_OPENMM_H
-
-double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-             int nstglobalcomm,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int stepout,t_inputrec *ir,
-             gmx_mtop_t *top_global,
-             t_fcdata *fcd,
-             t_state *state_global,
-             t_mdatoms *mdatoms,
-             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-             gmx_edsam_t ed,t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
-             real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags,
-             gmx_runtime_t *runtime);
-
-#endif /* _MD_OPENMM_H */
diff --git a/src/kernel/mdrun.c b/src/kernel/mdrun.c
deleted file mode 100644 (file)
index 1a6021a..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "typedefs.h"
-#include "macros.h"
-#include "copyrite.h"
-#include "main.h"
-#include "statutil.h"
-#include "smalloc.h"
-#include "futil.h"
-#include "smalloc.h"
-#include "edsam.h"
-#include "mdrun.h"
-#include "xmdrun.h"
-#include "checkpoint.h"
-#ifdef GMX_THREADS
-#include "thread_mpi.h"
-#endif
-
-/* afm stuf */
-#include "pull.h"
-
-int main(int argc,char *argv[])
-{
-  const char *desc[] = {
- #ifdef GMX_OPENMM
-    "This is an experimental release of GROMACS for accelerated",
-       "Molecular Dynamics simulations on GPU processors. Support is provided",
-       "by the OpenMM library (https://simtk.org/home/openmm).[PAR]",
-       "*Warning*[BR]",
-       "This release is targeted at developers and advanced users and",
-       "care should be taken before production use. The following should be",
-       "noted before using the program:[PAR]",
-       " * The current release runs only on modern nVidia GPU hardware with CUDA support.",
-       "Make sure that the necessary CUDA drivers and libraries for your operating system",
-       "are already installed. The CUDA SDK also should be installed in order to compile",
-       "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]",
-       " * Multiple GPU cards are not supported.[PAR]",
-       " * Only a small subset of the GROMACS features and options are supported on the GPUs.",
-       "See below for a detailed list.[PAR]",
-       " * Consumer level GPU cards are known to often have problems with faulty memory.",
-       "It is recommended that a full memory check of the cards is done at least once",
-       "(for example, using the memtest=full option).",
-       "A partial memory check (for example, memtest=15) before and",
-       "after the simulation run would help spot",
-       "problems resulting from processor overheating.[PAR]",
-       " * The maximum size of the simulated systems depends on the available",
-       "GPU memory,for example, a GTX280 with 1GB memory has been tested with systems",
-       "of up to about 100,000 atoms.[PAR]",
-       " * In order to take a full advantage of the GPU platform features, many algorithms",
-       "have been implemented in a very different way than they are on the CPUs.",
-       "Therefore numercal correspondence between properties of the state of",
-       "simulated systems should not be expected. Moreover, the values will likely vary",
-       "when simulations are done on different GPU hardware.[PAR]",
-       " * Frequent retrieval of system state information such as",
-       "trajectory coordinates and energies can greatly influence the performance",
-       "of the program due to slow CPU<->GPU memory transfer speed.[PAR]",
-       " * MD algorithms are complex, and although the Gromacs code is highly tuned for them,",
-       "they often do not translate very well onto the streaming architetures.",
-       "Realistic expectations about the achievable speed-up from test with GTX280:",
-       "For small protein systems in implicit solvent using all-vs-all kernels the acceleration",
-       "can be as high as 20 times, but in most other setups involving cutoffs and PME the",
-       "acceleration is usually only ~4 times relative to a 3GHz CPU.[PAR]",
-       "Supported features:[PAR]",
-       " * Integrators: md/md-vv/md-vv-avek, sd/sd1 and bd.\n",
-       " * Long-range interactions (option coulombtype): Reaction-Field, Ewald, PME, and cut-off (for Implicit Solvent only)\n",
-       " * Temperature control: Supported only with the md/md-vv/md-vv-avek, sd/sd1 and bd integrators.\n",
-       " * Pressure control: Supported.\n",
-       " * Implicit solvent: Supported.\n",
-       "A detailed description can be found on the GROMACS website:\n",
-       "http://www.gromacs.org/gpu[PAR]",
-/* From the original mdrun documentaion */
-    "The [TT]mdrun[tt] program reads the run input file ([TT]-s[tt])",
-    "and distributes the topology over nodes if needed.",
-    "[TT]mdrun[tt] produces at least four output files.",
-    "A single log file ([TT]-g[tt]) is written, unless the option",
-    "[TT]-seppot[tt] is used, in which case each node writes a log file.",
-    "The trajectory file ([TT]-o[tt]), contains coordinates, velocities and",
-    "optionally forces.",
-    "The structure file ([TT]-c[tt]) contains the coordinates and",
-    "velocities of the last step.",
-    "The energy file ([TT]-e[tt]) contains energies, the temperature,",
-    "pressure, etc, a lot of these things are also printed in the log file.",
-    "Optionally coordinates can be written to a compressed trajectory file",
-    "([TT]-x[tt]).[PAR]",
-/* openmm specific information */
-       "Usage with OpenMM:[BR]",
-       "[TT]mdrun -device \"OpenMM:platform=Cuda,memtest=15,deviceid=0,force-device=no\"[tt][PAR]",
-       "Options:[PAR]",
-       "      [TT]platform[tt] = Cuda\t\t:\tThe only available value. OpenCL support will be available in future.\n",
-       "      [TT]memtest[tt] = 15\t\t:\tRun a partial, random GPU memory test for the given amount of seconds. A full test",
-       "(recommended!) can be run with \"memtest=full\". Memory testing can be disabled with \"memtest=off\".\n",
-       "      [TT]deviceid[tt] = 0\t\t:\tSpecify the target device when multiple cards are present.",
-       "Only one card can be used at any given time though.\n",
-       "      [TT]force-device[tt] = no\t\t:\tIf set to \"yes\" [TT]mdrun[tt]  will be forced to execute on",
-       "hardware that is not officially supported. GPU acceleration can also be achieved on older",
-       "but Cuda capable cards, although the simulation might be too slow, and the memory limits too strict.",
-#else
-    "The [TT]mdrun[tt] program is the main computational chemistry engine",
-    "within GROMACS. Obviously, it performs Molecular Dynamics simulations,",
-    "but it can also perform Stochastic Dynamics, Energy Minimization,",
-    "test particle insertion or (re)calculation of energies.",
-    "Normal mode analysis is another option. In this case [TT]mdrun[tt]",
-    "builds a Hessian matrix from single conformation.",
-    "For usual Normal Modes-like calculations, make sure that",
-    "the structure provided is properly energy-minimized.",
-    "The generated matrix can be diagonalized by [TT]g_nmeig[tt].[PAR]",
-    "The [TT]mdrun[tt] program reads the run input file ([TT]-s[tt])",
-    "and distributes the topology over nodes if needed.",
-    "[TT]mdrun[tt] produces at least four output files.",
-    "A single log file ([TT]-g[tt]) is written, unless the option",
-    "[TT]-seppot[tt] is used, in which case each node writes a log file.",
-    "The trajectory file ([TT]-o[tt]), contains coordinates, velocities and",
-    "optionally forces.",
-    "The structure file ([TT]-c[tt]) contains the coordinates and",
-    "velocities of the last step.",
-    "The energy file ([TT]-e[tt]) contains energies, the temperature,",
-    "pressure, etc, a lot of these things are also printed in the log file.",
-    "Optionally coordinates can be written to a compressed trajectory file",
-    "([TT]-x[tt]).[PAR]",
-    "The option [TT]-dhdl[tt] is only used when free energy calculation is",
-    "turned on.[PAR]",
-    "When [TT]mdrun[tt] is started using MPI with more than 1 node, parallelization",
-    "is used. By default domain decomposition is used, unless the [TT]-pd[tt]",
-    "option is set, which selects particle decomposition.[PAR]",
-    "With domain decomposition, the spatial decomposition can be set",
-    "with option [TT]-dd[tt]. By default [TT]mdrun[tt] selects a good decomposition.",
-    "The user only needs to change this when the system is very inhomogeneous.",
-    "Dynamic load balancing is set with the option [TT]-dlb[tt],",
-    "which can give a significant performance improvement,",
-    "especially for inhomogeneous systems. The only disadvantage of",
-    "dynamic load balancing is that runs are no longer binary reproducible,",
-    "but in most cases this is not important.",
-    "By default the dynamic load balancing is automatically turned on",
-    "when the measured performance loss due to load imbalance is 5% or more.",
-    "At low parallelization these are the only important options",
-    "for domain decomposition.",
-    "At high parallelization the options in the next two sections",
-    "could be important for increasing the performace.",
-    "[PAR]",
-    "When PME is used with domain decomposition, separate nodes can",
-    "be assigned to do only the PME mesh calculation;",
-    "this is computationally more efficient starting at about 12 nodes.",
-    "The number of PME nodes is set with option [TT]-npme[tt],",
-    "this can not be more than half of the nodes.",
-    "By default [TT]mdrun[tt] makes a guess for the number of PME",
-    "nodes when the number of nodes is larger than 11 or performance wise",
-    "not compatible with the PME grid x dimension.",
-    "But the user should optimize npme. Performance statistics on this issue",
-    "are written at the end of the log file.",
-    "For good load balancing at high parallelization, the PME grid x and y",
-    "dimensions should be divisible by the number of PME nodes",
-    "(the simulation will run correctly also when this is not the case).",
-    "[PAR]",
-    "This section lists all options that affect the domain decomposition.",
-    "[PAR]",
-    "Option [TT]-rdd[tt] can be used to set the required maximum distance",
-    "for inter charge-group bonded interactions.",
-    "Communication for two-body bonded interactions below the non-bonded",
-    "cut-off distance always comes for free with the non-bonded communication.",
-    "Atoms beyond the non-bonded cut-off are only communicated when they have",
-    "missing bonded interactions; this means that the extra cost is minor",
-    "and nearly indepedent of the value of [TT]-rdd[tt].",
-    "With dynamic load balancing option [TT]-rdd[tt] also sets",
-    "the lower limit for the domain decomposition cell sizes.",
-    "By default [TT]-rdd[tt] is determined by [TT]mdrun[tt] based on",
-    "the initial coordinates. The chosen value will be a balance",
-    "between interaction range and communication cost.",
-    "[PAR]",
-    "When inter charge-group bonded interactions are beyond",
-    "the bonded cut-off distance, [TT]mdrun[tt] terminates with an error message.",
-    "For pair interactions and tabulated bonds",
-    "that do not generate exclusions, this check can be turned off",
-    "with the option [TT]-noddcheck[tt].",
-    "[PAR]",
-    "When constraints are present, option [TT]-rcon[tt] influences",
-    "the cell size limit as well.",
-    "Atoms connected by NC constraints, where NC is the LINCS order plus 1,",
-    "should not be beyond the smallest cell size. A error message is",
-    "generated when this happens and the user should change the decomposition",
-    "or decrease the LINCS order and increase the number of LINCS iterations.",
-    "By default [TT]mdrun[tt] estimates the minimum cell size required for P-LINCS",
-    "in a conservative fashion. For high parallelization it can be useful",
-    "to set the distance required for P-LINCS with the option [TT]-rcon[tt].",
-    "[PAR]",
-    "The [TT]-dds[tt] option sets the minimum allowed x, y and/or z scaling",
-    "of the cells with dynamic load balancing. [TT]mdrun[tt] will ensure that",
-    "the cells can scale down by at least this factor. This option is used",
-    "for the automated spatial decomposition (when not using [TT]-dd[tt])",
-    "as well as for determining the number of grid pulses, which in turn",
-    "sets the minimum allowed cell size. Under certain circumstances",
-    "the value of [TT]-dds[tt] might need to be adjusted to account for",
-    "high or low spatial inhomogeneity of the system.",
-    "[PAR]",
-    "The option [TT]-gcom[tt] can be used to only do global communication",
-    "every n steps.",
-    "This can improve performance for highly parallel simulations",
-    "where this global communication step becomes the bottleneck.",
-    "For a global thermostat and/or barostat the temperature",
-    "and/or pressure will also only be updated every [TT]-gcom[tt] steps.",
-    "By default it is set to the minimum of nstcalcenergy and nstlist.[PAR]",
-    "With [TT]-rerun[tt] an input trajectory can be given for which ",
-    "forces and energies will be (re)calculated. Neighbor searching will be",
-    "performed for every frame, unless [TT]nstlist[tt] is zero",
-    "(see the [TT].mdp[tt] file).[PAR]",
-    "ED (essential dynamics) sampling is switched on by using the [TT]-ei[tt]",
-    "flag followed by an [TT].edi[tt] file.",
-    "The [TT].edi[tt] file can be produced using options in the essdyn",
-    "menu of the WHAT IF program. [TT]mdrun[tt] produces a [TT].edo[tt] file that",
-    "contains projections of positions, velocities and forces onto selected",
-    "eigenvectors.[PAR]",
-    "When user-defined potential functions have been selected in the",
-    "[TT].mdp[tt] file the [TT]-table[tt] option is used to pass [TT]mdrun[tt]",
-    "a formatted table with potential functions. The file is read from",
-    "either the current directory or from the [TT]GMXLIB[tt] directory.",
-    "A number of pre-formatted tables are presented in the [TT]GMXLIB[tt] dir,",
-    "for 6-8, 6-9, 6-10, 6-11, 6-12 Lennard-Jones potentials with",
-    "normal Coulomb.",
-    "When pair interactions are present, a separate table for pair interaction",
-    "functions is read using the [TT]-tablep[tt] option.[PAR]",
-    "When tabulated bonded functions are present in the topology,",
-    "interaction functions are read using the [TT]-tableb[tt] option.",
-    "For each different tabulated interaction type the table file name is",
-    "modified in a different way: before the file extension an underscore is",
-    "appended, then a 'b' for bonds, an 'a' for angles or a 'd' for dihedrals",
-    "and finally the table number of the interaction type.[PAR]",
-    "The options [TT]-px[tt] and [TT]-pf[tt] are used for writing pull COM",
-    "coordinates and forces when pulling is selected",
-    "in the [TT].mdp[tt] file.[PAR]",
-    "With [TT]-multi[tt] or [TT]-multidir[tt], multiple systems can be ",
-    "simulated in parallel.",
-    "As many input files/directories are required as the number of systems. ",
-    "The [TT]-multidir[tt] option takes a list of directories (one for each ",
-    "system) and runs in each of them, using the input/output file names, ",
-    "such as specified by e.g. the [TT]-s[tt] option, relative to these ",
-    "directories.",
-    "With [TT]-multi[tt], the system number is appended to the run input ",
-    "and each output filename, for instance [TT]topol.tpr[tt] becomes",
-    "[TT]topol0.tpr[tt], [TT]topol1.tpr[tt] etc.",
-    "The number of nodes per system is the total number of nodes",
-    "divided by the number of systems.",
-    "One use of this option is for NMR refinement: when distance",
-    "or orientation restraints are present these can be ensemble averaged",
-    "over all the systems.[PAR]",
-    "With [TT]-replex[tt] replica exchange is attempted every given number",
-    "of steps. The number of replicas is set with the [TT]-multi[tt] or ",
-    "[TT]-multidir[tt] option, described above.",
-    "All run input files should use a different coupling temperature,",
-    "the order of the files is not important. The random seed is set with",
-    "[TT]-reseed[tt]. The velocities are scaled and neighbor searching",
-    "is performed after every exchange.[PAR]",
-    "Finally some experimental algorithms can be tested when the",
-    "appropriate options have been given. Currently under",
-    "investigation are: polarizability and X-ray bombardments.",
-    "[PAR]",
-    "The option [TT]-pforce[tt] is useful when you suspect a simulation",
-    "crashes due to too large forces. With this option coordinates and",
-    "forces of atoms with a force larger than a certain value will",
-    "be printed to stderr.",
-    "[PAR]",
-    "Checkpoints containing the complete state of the system are written",
-    "at regular intervals (option [TT]-cpt[tt]) to the file [TT]-cpo[tt],",
-    "unless option [TT]-cpt[tt] is set to -1.",
-    "The previous checkpoint is backed up to [TT]state_prev.cpt[tt] to",
-    "make sure that a recent state of the system is always available,",
-    "even when the simulation is terminated while writing a checkpoint.",
-    "With [TT]-cpnum[tt] all checkpoint files are kept and appended",
-    "with the step number.",
-    "A simulation can be continued by reading the full state from file",
-    "with option [TT]-cpi[tt]. This option is intelligent in the way that",
-    "if no checkpoint file is found, Gromacs just assumes a normal run and",
-    "starts from the first step of the [TT].tpr[tt] file. By default the output",
-    "will be appending to the existing output files. The checkpoint file",
-    "contains checksums of all output files, such that you will never",
-    "loose data when some output files are modified, corrupt or removed.",
-    "There are three scenarios with [TT]-cpi[tt]:[PAR]",
-    "[TT]*[tt] no files with matching names are present: new output files are written[PAR]",
-    "[TT]*[tt] all files are present with names and checksums matching those stored",
-    "in the checkpoint file: files are appended[PAR]",
-    "[TT]*[tt] otherwise no files are modified and a fatal error is generated[PAR]",
-    "With [TT]-noappend[tt] new output files are opened and the simulation",
-    "part number is added to all output file names.",
-    "Note that in all cases the checkpoint file itself is not renamed",
-    "and will be overwritten, unless its name does not match",
-    "the [TT]-cpo[tt] option.",
-    "[PAR]",
-    "With checkpointing the output is appended to previously written",
-    "output files, unless [TT]-noappend[tt] is used or none of the previous",
-    "output files are present (except for the checkpoint file).",
-    "The integrity of the files to be appended is verified using checksums",
-    "which are stored in the checkpoint file. This ensures that output can",
-    "not be mixed up or corrupted due to file appending. When only some",
-    "of the previous output files are present, a fatal error is generated",
-    "and no old output files are modified and no new output files are opened.",
-    "The result with appending will be the same as from a single run.",
-    "The contents will be binary identical, unless you use a different number",
-    "of nodes or dynamic load balancing or the FFT library uses optimizations",
-    "through timing.",
-    "[PAR]",
-    "With option [TT]-maxh[tt] a simulation is terminated and a checkpoint",
-    "file is written at the first neighbor search step where the run time",
-    "exceeds [TT]-maxh[tt]*0.99 hours.",
-    "[PAR]",
-    "When [TT]mdrun[tt] receives a TERM signal, it will set nsteps to the current",
-    "step plus one. When [TT]mdrun[tt] receives an INT signal (e.g. when ctrl+C is",
-    "pressed), it will stop after the next neighbor search step ",
-    "(with nstlist=0 at the next step).",
-    "In both cases all the usual output will be written to file.",
-    "When running with MPI, a signal to one of the [TT]mdrun[tt] processes",
-    "is sufficient, this signal should not be sent to mpirun or",
-    "the [TT]mdrun[tt] process that is the parent of the others.",
-    "[PAR]",
-    "When [TT]mdrun[tt] is started with MPI, it does not run niced by default."
-#endif
-  };
-  t_commrec    *cr;
-  t_filenm fnm[] = {
-    { efTPX, NULL,      NULL,       ffREAD },
-    { efTRN, "-o",      NULL,       ffWRITE },
-    { efXTC, "-x",      NULL,       ffOPTWR },
-    { efCPT, "-cpi",    NULL,       ffOPTRD },
-    { efCPT, "-cpo",    NULL,       ffOPTWR },
-    { efSTO, "-c",      "confout",  ffWRITE },
-    { efEDR, "-e",      "ener",     ffWRITE },
-    { efLOG, "-g",      "md",       ffWRITE },
-    { efXVG, "-dhdl",   "dhdl",     ffOPTWR },
-    { efXVG, "-field",  "field",    ffOPTWR },
-    { efXVG, "-table",  "table",    ffOPTRD },
-    { efXVG, "-tablep", "tablep",   ffOPTRD },
-    { efXVG, "-tableb", "table",    ffOPTRD },
-    { efTRX, "-rerun",  "rerun",    ffOPTRD },
-    { efXVG, "-tpi",    "tpi",      ffOPTWR },
-    { efXVG, "-tpid",   "tpidist",  ffOPTWR },
-    { efEDI, "-ei",     "sam",      ffOPTRD },
-    { efEDO, "-eo",     "sam",      ffOPTWR },
-    { efGCT, "-j",      "wham",     ffOPTRD },
-    { efGCT, "-jo",     "bam",      ffOPTWR },
-    { efXVG, "-ffout",  "gct",      ffOPTWR },
-    { efXVG, "-devout", "deviatie", ffOPTWR },
-    { efXVG, "-runav",  "runaver",  ffOPTWR },
-    { efXVG, "-px",     "pullx",    ffOPTWR },
-    { efXVG, "-pf",     "pullf",    ffOPTWR },
-    { efMTX, "-mtx",    "nm",       ffOPTWR },
-    { efNDX, "-dn",     "dipole",   ffOPTWR },
-    { efRND, "-multidir",NULL,      ffOPTRDMULT}
-  };
-#define NFILE asize(fnm)
-
-  /* Command line options ! */
-  gmx_bool bCart        = FALSE;
-  gmx_bool bPPPME       = FALSE;
-  gmx_bool bPartDec     = FALSE;
-  gmx_bool bDDBondCheck = TRUE;
-  gmx_bool bDDBondComm  = TRUE;
-  gmx_bool bVerbose     = FALSE;
-  gmx_bool bCompact     = TRUE;
-  gmx_bool bSepPot      = FALSE;
-  gmx_bool bRerunVSite  = FALSE;
-  gmx_bool bIonize      = FALSE;
-  gmx_bool bConfout     = TRUE;
-  gmx_bool bReproducible = FALSE;
-    
-  int  npme=-1;
-  int  nmultisim=0;
-  int  nstglobalcomm=-1;
-  int  repl_ex_nst=0;
-  int  repl_ex_seed=-1;
-  int  nstepout=100;
-  int  nthreads=0; /* set to determine # of threads automatically */
-  int  resetstep=-1;
-  
-  rvec realddxyz={0,0,0};
-  const char *ddno_opt[ddnoNR+1] =
-    { NULL, "interleave", "pp_pme", "cartesian", NULL };
-    const char *dddlb_opt[] =
-    { NULL, "auto", "no", "yes", NULL };
-  real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
-  char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
-  real cpt_period=15.0,max_hours=-1;
-  gmx_bool bAppendFiles=TRUE;
-  gmx_bool bKeepAndNumCPT=FALSE;
-  gmx_bool bResetCountersHalfWay=FALSE;
-  output_env_t oenv=NULL;
-  const char *deviceOptions = "";
-
-  t_pargs pa[] = {
-
-    { "-pd",      FALSE, etBOOL,{&bPartDec},
-      "Use particle decompostion" },
-    { "-dd",      FALSE, etRVEC,{&realddxyz},
-      "Domain decomposition grid, 0 is optimize" },
-#ifdef GMX_THREADS
-    { "-nt",      FALSE, etINT, {&nthreads},
-      "Number of threads to start (0 is guess)" },
-#endif
-    { "-npme",    FALSE, etINT, {&npme},
-      "Number of separate nodes to be used for PME, -1 is guess" },
-    { "-ddorder", FALSE, etENUM, {ddno_opt},
-      "DD node order" },
-    { "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
-      "Check for all bonded interactions with DD" },
-    { "-ddbondcomm", FALSE, etBOOL, {&bDDBondComm},
-      "HIDDENUse special bonded atom communication when [TT]-rdd[tt] > cut-off" },
-    { "-rdd",     FALSE, etREAL, {&rdd},
-      "The maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
-    { "-rcon",    FALSE, etREAL, {&rconstr},
-      "Maximum distance for P-LINCS (nm), 0 is estimate" },
-    { "-dlb",     FALSE, etENUM, {dddlb_opt},
-      "Dynamic load balancing (with DD)" },
-    { "-dds",     FALSE, etREAL, {&dlb_scale},
-      "Minimum allowed dlb scaling of the DD cell size" },
-    { "-ddcsx",   FALSE, etSTR, {&ddcsx},
-      "HIDDENThe DD cell sizes in x" },
-    { "-ddcsy",   FALSE, etSTR, {&ddcsy},
-      "HIDDENThe DD cell sizes in y" },
-    { "-ddcsz",   FALSE, etSTR, {&ddcsz},
-      "HIDDENThe DD cell sizes in z" },
-    { "-gcom",    FALSE, etINT,{&nstglobalcomm},
-      "Global communication frequency" },
-    { "-v",       FALSE, etBOOL,{&bVerbose},  
-      "Be loud and noisy" },
-    { "-compact", FALSE, etBOOL,{&bCompact},  
-      "Write a compact log file" },
-    { "-seppot",  FALSE, etBOOL, {&bSepPot},
-      "Write separate V and dVdl terms for each interaction type and node to the log file(s)" },
-    { "-pforce",  FALSE, etREAL, {&pforce},
-      "Print all forces larger than this (kJ/mol nm)" },
-    { "-reprod",  FALSE, etBOOL,{&bReproducible},  
-      "Try to avoid optimizations that affect binary reproducibility" },
-    { "-cpt",     FALSE, etREAL, {&cpt_period},
-      "Checkpoint interval (minutes)" },
-    { "-cpnum",   FALSE, etBOOL, {&bKeepAndNumCPT},
-      "Keep and number checkpoint files" },
-    { "-append",  FALSE, etBOOL, {&bAppendFiles},
-      "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
-    { "-maxh",   FALSE, etREAL, {&max_hours},
-      "Terminate after 0.99 times this time (hours)" },
-    { "-multi",   FALSE, etINT,{&nmultisim}, 
-      "Do multiple simulations in parallel" },
-    { "-replex",  FALSE, etINT, {&repl_ex_nst}, 
-      "Attempt replica exchange every # steps" },
-    { "-reseed",  FALSE, etINT, {&repl_ex_seed}, 
-      "Seed for replica exchange, -1 is generate a seed" },
-    { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
-      "HIDDENRecalculate virtual site coordinates with [TT]-rerun[tt]" },
-    { "-ionize",  FALSE, etBOOL,{&bIonize},
-      "Do a simulation including the effect of an X-Ray bombardment on your system" },
-    { "-confout", FALSE, etBOOL, {&bConfout},
-      "HIDDENWrite the last configuration with [TT]-c[tt] and force checkpointing at the last step" },
-    { "-stepout", FALSE, etINT, {&nstepout},
-      "HIDDENFrequency of writing the remaining runtime" },
-    { "-resetstep", FALSE, etINT, {&resetstep},
-      "HIDDENReset cycle counters after these many time steps" },
-    { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
-      "HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt]" }
-#ifdef GMX_OPENMM
-    ,
-    { "-device",  FALSE, etSTR, {&deviceOptions},
-      "Device option string" }
-#endif
-  };
-  gmx_edsam_t  ed;
-  unsigned long Flags, PCA_Flags;
-  ivec     ddxyz;
-  int      dd_node_order;
-  gmx_bool     bAddPart;
-  FILE     *fplog,*fptest;
-  int      sim_part,sim_part_fn;
-  const char *part_suffix=".part";
-  char     suffix[STRLEN];
-  int      rc;
-  char **multidir=NULL;
-
-
-  cr = init_par(&argc,&argv);
-
-  if (MASTER(cr))
-    CopyRight(stderr, argv[0]);
-
-  PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
-              | (MASTER(cr) ? 0 : PCA_QUIET));
-  
-
-  /* Comment this in to do fexist calls only on master
-   * works not with rerun or tables at the moment
-   * also comment out the version of init_forcerec in md.c 
-   * with NULL instead of opt2fn
-   */
-  /*
-     if (!MASTER(cr))
-     {
-     PCA_Flags |= PCA_NOT_READ_NODE;
-     }
-     */
-
-  parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
-                    asize(desc),desc,0,NULL, &oenv);
-
-
-
-  /* we set these early because they might be used in init_multisystem() 
-     Note that there is the potential for npme>nnodes until the number of
-     threads is set later on, if there's thread parallelization. That shouldn't
-     lead to problems. */ 
-  dd_node_order = nenum(ddno_opt);
-  cr->npmenodes = npme;
-
-#ifndef GMX_THREADS
-  nthreads=1;
-#endif
-
-  /* now check the -multi and -multidir option */
-  if (opt2bSet("-multidir", NFILE, fnm))
-  {
-      int i;
-      if (nmultisim > 0)
-      {
-          gmx_fatal(FARGS, "mdrun -multi and -multidir options are mutually exclusive.");
-      }
-      nmultisim = opt2fns(&multidir, "-multidir", NFILE, fnm);
-  }
-
-
-  if (repl_ex_nst != 0 && nmultisim < 2)
-      gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
-
-  if (nmultisim > 1) {
-#ifndef GMX_THREADS
-    gmx_bool bParFn = (multidir == NULL);
-    init_multisystem(cr, nmultisim, multidir, NFILE, fnm, bParFn);
-#else
-    gmx_fatal(FARGS,"mdrun -multi is not supported with the thread library.Please compile GROMACS with MPI support");
-#endif
-  }
-
-  bAddPart = !bAppendFiles;
-
-  /* Check if there is ANY checkpoint file available */        
-  sim_part    = 1;
-  sim_part_fn = sim_part;
-  if (opt2bSet("-cpi",NFILE,fnm))
-  {
-      if (bSepPot && bAppendFiles)
-      {
-          gmx_fatal(FARGS,"Output file appending is not supported with -seppot");
-      }
-
-      bAppendFiles =
-                read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
-                                                              fnm,cr),
-                                                &sim_part_fn,NULL,cr,
-                                                bAppendFiles,NFILE,fnm,
-                                                part_suffix,&bAddPart);
-      if (sim_part_fn==0 && MASTER(cr))
-      {
-          fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
-      }
-      else
-      {
-          sim_part = sim_part_fn + 1;
-      }
-
-      if (MULTISIM(cr) && MASTER(cr))
-      {
-          check_multi_int(stdout,cr->ms,sim_part,"simulation part");
-      }
-  } 
-  else
-  {
-      bAppendFiles = FALSE;
-  }
-
-  if (!bAppendFiles)
-  {
-      sim_part_fn = sim_part;
-  }
-
-  if (bAddPart)
-  {
-      /* Rename all output files (except checkpoint files) */
-      /* create new part name first (zero-filled) */
-      sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
-
-      add_suffix_to_output_names(fnm,NFILE,suffix);
-      if (MASTER(cr))
-      {
-          fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
-      }
-  }
-
-  Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
-  Flags = Flags | (bSepPot       ? MD_SEPPOT       : 0);
-  Flags = Flags | (bIonize       ? MD_IONIZE       : 0);
-  Flags = Flags | (bPartDec      ? MD_PARTDEC      : 0);
-  Flags = Flags | (bDDBondCheck  ? MD_DDBONDCHECK  : 0);
-  Flags = Flags | (bDDBondComm   ? MD_DDBONDCOMM   : 0);
-  Flags = Flags | (bConfout      ? MD_CONFOUT      : 0);
-  Flags = Flags | (bRerunVSite   ? MD_RERUN_VSITE  : 0);
-  Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
-  Flags = Flags | (bAppendFiles  ? MD_APPENDFILES  : 0); 
-  Flags = Flags | (bKeepAndNumCPT ? MD_KEEPANDNUMCPT : 0); 
-  Flags = Flags | (sim_part>1    ? MD_STARTFROMCPT : 0); 
-  Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
-
-
-  /* We postpone opening the log file if we are appending, so we can 
-     first truncate the old log file and append to the correct position 
-     there instead.  */
-  if ((MASTER(cr) || bSepPot) && !bAppendFiles) 
-  {
-      gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
-      CopyRight(fplog,argv[0]);
-      please_cite(fplog,"Hess2008b");
-      please_cite(fplog,"Spoel2005a");
-      please_cite(fplog,"Lindahl2001a");
-      please_cite(fplog,"Berendsen95a");
-  }
-  else if (!MASTER(cr) && bSepPot)
-  {
-      gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
-  }
-  else
-  {
-      fplog = NULL;
-  }
-
-  ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
-  ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
-  ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
-
-  rc = mdrunner(nthreads, fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,
-                nstglobalcomm, ddxyz,dd_node_order,rdd,rconstr,
-                dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
-                nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
-                pforce, cpt_period,max_hours,deviceOptions,Flags);
-
-  if (gmx_parallel_env_initialized())
-      gmx_finalize();
-
-  if (MULTIMASTER(cr)) {
-      thanx(stderr);
-  }
-
-  /* Log file has to be closed in mdrunner if we are appending to it 
-     (fplog not set here) */
-  if (MASTER(cr) && !bAppendFiles) 
-  {
-      gmx_log_close(fplog);
-  }
-
-  return rc;
-}
-
diff --git a/src/kernel/readir.c b/src/kernel/readir.c
deleted file mode 100644 (file)
index 50f6a8a..0000000
+++ /dev/null
@@ -1,2591 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <limits.h>
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "typedefs.h"
-#include "physics.h"
-#include "names.h"
-#include "gmx_fatal.h"
-#include "macros.h"
-#include "index.h"
-#include "symtab.h"
-#include "string2.h"
-#include "readinp.h"
-#include "warninp.h"
-#include "readir.h" 
-#include "toputil.h"
-#include "index.h"
-#include "network.h"
-#include "vec.h"
-#include "pbc.h"
-#include "mtop_util.h"
-#include "chargegroup.h"
-#include "inputrec.h"
-
-#define MAXPTR 254
-#define NOGID  255
-
-/* Resource parameters 
- * Do not change any of these until you read the instruction
- * in readinp.h. Some cpp's do not take spaces after the backslash
- * (like the c-shell), which will give you a very weird compiler
- * message.
- */
-
-static char tcgrps[STRLEN],tau_t[STRLEN],ref_t[STRLEN],
-  acc[STRLEN],accgrps[STRLEN],freeze[STRLEN],frdim[STRLEN],
-  energy[STRLEN],user1[STRLEN],user2[STRLEN],vcm[STRLEN],xtc_grps[STRLEN],
-  couple_moltype[STRLEN],orirefitgrp[STRLEN],egptable[STRLEN],egpexcl[STRLEN],
-  wall_atomtype[STRLEN],wall_density[STRLEN],deform[STRLEN],QMMM[STRLEN];
-static char foreign_lambda[STRLEN];
-static char **pull_grp;
-static char anneal[STRLEN],anneal_npoints[STRLEN],
-  anneal_time[STRLEN],anneal_temp[STRLEN];
-static char QMmethod[STRLEN],QMbasis[STRLEN],QMcharge[STRLEN],QMmult[STRLEN],
-  bSH[STRLEN],CASorbitals[STRLEN], CASelectrons[STRLEN],SAon[STRLEN],
-  SAoff[STRLEN],SAsteps[STRLEN],bTS[STRLEN],bOPT[STRLEN]; 
-static char efield_x[STRLEN],efield_xt[STRLEN],efield_y[STRLEN],
-  efield_yt[STRLEN],efield_z[STRLEN],efield_zt[STRLEN];
-
-enum {
-    egrptpALL,         /* All particles have to be a member of a group.     */
-    egrptpALL_GENREST, /* A rest group with name is generated for particles *
-                        * that are not part of any group.                   */
-    egrptpPART,        /* As egrptpALL_GENREST, but no name is generated    *
-                        * for the rest group.                               */
-    egrptpONE          /* Merge all selected groups into one group,         *
-                        * make a rest group for the remaining particles.    */
-};
-
-
-void init_ir(t_inputrec *ir, t_gromppopts *opts)
-{
-  snew(opts->include,STRLEN); 
-  snew(opts->define,STRLEN);
-}
-
-static void _low_check(gmx_bool b,char *s,warninp_t wi)
-{
-    if (b)
-    {
-        warning_error(wi,s);
-    }
-}
-
-static void check_nst(const char *desc_nst,int nst,
-                      const char *desc_p,int *p,
-                      warninp_t wi)
-{
-    char buf[STRLEN];
-
-    if (*p > 0 && *p % nst != 0)
-    {
-        /* Round up to the next multiple of nst */
-        *p = ((*p)/nst + 1)*nst;
-        sprintf(buf,"%s should be a multiple of %s, changing %s to %d\n",
-               desc_p,desc_nst,desc_p,*p);
-        warning(wi,buf);
-    }
-}
-
-static gmx_bool ir_NVE(const t_inputrec *ir)
-{
-    return ((ir->eI == eiMD || EI_VV(ir->eI)) && ir->etc == etcNO);
-}
-
-static int lcd(int n1,int n2)
-{
-    int d,i;
-    
-    d = 1;
-    for(i=2; (i<=n1 && i<=n2); i++)
-    {
-        if (n1 % i == 0 && n2 % i == 0)
-        {
-            d = i;
-        }
-    }
-    
-  return d;
-}
-
-void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
-              warninp_t wi)
-/* Check internal consistency */
-{
-    /* Strange macro: first one fills the err_buf, and then one can check 
-     * the condition, which will print the message and increase the error
-     * counter.
-     */
-#define CHECK(b) _low_check(b,err_buf,wi)
-    char err_buf[256],warn_buf[STRLEN];
-    int  ns_type=0;
-    real dt_pcoupl;
-
-  set_warning_line(wi,mdparin,-1);
-
-  /* BASIC CUT-OFF STUFF */
-  if (ir->rlist == 0 ||
-      !((EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > ir->rlist) ||
-        (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype)    && ir->rvdw     > ir->rlist))) {
-    /* No switched potential and/or no twin-range:
-     * we can set the long-range cut-off to the maximum of the other cut-offs.
-     */
-    ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
-  } else if (ir->rlistlong < 0) {
-    ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
-    sprintf(warn_buf,"rlistlong was not set, setting it to %g (no buffer)",
-           ir->rlistlong);
-    warning(wi,warn_buf);
-  }
-  if (ir->rlistlong == 0 && ir->ePBC != epbcNONE) {
-      warning_error(wi,"Can not have an infinite cut-off with PBC");
-  }
-  if (ir->rlistlong > 0 && (ir->rlist == 0 || ir->rlistlong < ir->rlist)) {
-      warning_error(wi,"rlistlong can not be shorter than rlist");
-  }
-  if (IR_TWINRANGE(*ir) && ir->nstlist <= 0) {
-      warning_error(wi,"Can not have nstlist<=0 with twin-range interactions");
-  }
-
-    /* GENERAL INTEGRATOR STUFF */
-    if (!(ir->eI == eiMD || EI_VV(ir->eI)))
-    {
-        ir->etc = etcNO;
-    }
-    if (!EI_DYNAMICS(ir->eI))
-    {
-        ir->epc = epcNO;
-    }
-    if (EI_DYNAMICS(ir->eI))
-    {
-        if (ir->nstcalcenergy < 0)
-        {
-            ir->nstcalcenergy = ir_optimal_nstcalcenergy(ir);
-            if (ir->nstenergy != 0 && ir->nstenergy < ir->nstcalcenergy)
-            {
-                /* nstcalcenergy larger than nstener does not make sense.
-                 * We ideally want nstcalcenergy=nstener.
-                 */
-                if (ir->nstlist > 0)
-                {
-                    ir->nstcalcenergy = lcd(ir->nstenergy,ir->nstlist);
-                }
-                else
-                {
-                    ir->nstcalcenergy = ir->nstenergy;
-                }
-            }
-        }
-        if (ir->epc != epcNO)
-        {
-            if (ir->nstpcouple < 0)
-            {
-                ir->nstpcouple = ir_optimal_nstpcouple(ir);
-            }
-        }
-        if (IR_TWINRANGE(*ir))
-        {
-            check_nst("nstlist",ir->nstlist,
-                      "nstcalcenergy",&ir->nstcalcenergy,wi);
-            if (ir->epc != epcNO)
-            {
-                check_nst("nstlist",ir->nstlist,
-                          "nstpcouple",&ir->nstpcouple,wi); 
-            }
-        }
-
-        if (ir->nstcalcenergy > 1)
-        {
-            /* for storing exact averages nstenergy should be
-             * a multiple of nstcalcenergy
-             */
-            check_nst("nstcalcenergy",ir->nstcalcenergy,
-                      "nstenergy",&ir->nstenergy,wi);
-            if (ir->efep != efepNO)
-            {
-                /* nstdhdl should be a multiple of nstcalcenergy */
-                check_nst("nstcalcenergy",ir->nstcalcenergy,
-                          "nstdhdl",&ir->nstdhdl,wi);
-            }
-        }
-    }
-
-  /* LD STUFF */
-  if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
-      ir->bContinuation && ir->ld_seed != -1) {
-      warning_note(wi,"You are doing a continuation with SD or BD, make sure that ld_seed is different from the previous run (using ld_seed=-1 will ensure this)");
-  }
-
-  /* TPI STUFF */
-  if (EI_TPI(ir->eI)) {
-    sprintf(err_buf,"TPI only works with pbc = %s",epbc_names[epbcXYZ]);
-    CHECK(ir->ePBC != epbcXYZ);
-    sprintf(err_buf,"TPI only works with ns = %s",ens_names[ensGRID]);
-    CHECK(ir->ns_type != ensGRID);
-    sprintf(err_buf,"with TPI nstlist should be larger than zero");
-    CHECK(ir->nstlist <= 0);
-    sprintf(err_buf,"TPI does not work with full electrostatics other than PME");
-    CHECK(EEL_FULL(ir->coulombtype) && !EEL_PME(ir->coulombtype));
-  }
-
-  /* SHAKE / LINCS */
-  if ( (opts->nshake > 0) && (opts->bMorse) ) {
-    sprintf(warn_buf,
-           "Using morse bond-potentials while constraining bonds is useless");
-    warning(wi,warn_buf);
-  }
-  
-  sprintf(err_buf,"shake_tol must be > 0 instead of %g while using shake",
-         ir->shake_tol);
-  CHECK(((ir->shake_tol <= 0.0) && (opts->nshake>0) && 
-        (ir->eConstrAlg == econtSHAKE)));
-     
-  /* PBC/WALLS */
-  sprintf(err_buf,"walls only work with pbc=%s",epbc_names[epbcXY]);
-  CHECK(ir->nwall && ir->ePBC!=epbcXY);
-
-  /* VACUUM STUFF */
-  if (ir->ePBC != epbcXYZ && ir->nwall != 2) {
-    if (ir->ePBC == epbcNONE) {
-      if (ir->epc != epcNO) {
-          warning(wi,"Turning off pressure coupling for vacuum system");
-          ir->epc = epcNO;
-      }
-    } else {
-      sprintf(err_buf,"Can not have pressure coupling with pbc=%s",
-             epbc_names[ir->ePBC]);
-      CHECK(ir->epc != epcNO);
-    }
-    sprintf(err_buf,"Can not have Ewald with pbc=%s",epbc_names[ir->ePBC]);
-    CHECK(EEL_FULL(ir->coulombtype));
-    
-    sprintf(err_buf,"Can not have dispersion correction with pbc=%s",
-           epbc_names[ir->ePBC]);
-    CHECK(ir->eDispCorr != edispcNO);
-  }
-
-  if (ir->rlist == 0.0) {
-    sprintf(err_buf,"can only have neighborlist cut-off zero (=infinite)\n"
-           "with coulombtype = %s or coulombtype = %s\n"
-           "without periodic boundary conditions (pbc = %s) and\n"
-           "rcoulomb and rvdw set to zero",
-           eel_names[eelCUT],eel_names[eelUSER],epbc_names[epbcNONE]);
-    CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER)) ||
-         (ir->ePBC     != epbcNONE) || 
-         (ir->rcoulomb != 0.0)      || (ir->rvdw != 0.0));
-
-    if (ir->nstlist < 0) {
-        warning_error(wi,"Can not have heuristic neighborlist updates without cut-off");
-    }
-    if (ir->nstlist > 0) {
-        warning_note(wi,"Simulating without cut-offs is usually (slightly) faster with nstlist=0, nstype=simple and particle decomposition");
-    }
-  }
-
-  /* COMM STUFF */
-  if (ir->nstcomm == 0) {
-    ir->comm_mode = ecmNO;
-  }
-  if (ir->comm_mode != ecmNO) {
-    if (ir->nstcomm < 0) {
-        warning(wi,"If you want to remove the rotation around the center of mass, you should set comm_mode = Angular instead of setting nstcomm < 0. nstcomm is modified to its absolute value");
-      ir->nstcomm = abs(ir->nstcomm);
-    }
-    
-    if (ir->nstcalcenergy > 0 && ir->nstcomm < ir->nstcalcenergy) {
-        warning_note(wi,"nstcomm < nstcalcenergy defeats the purpose of nstcalcenergy, setting nstcomm to nstcalcenergy");
-      ir->nstcomm = ir->nstcalcenergy;
-    }
-
-    if (ir->comm_mode == ecmANGULAR) {
-      sprintf(err_buf,"Can not remove the rotation around the center of mass with periodic molecules");
-      CHECK(ir->bPeriodicMols);
-      if (ir->ePBC != epbcNONE)
-          warning(wi,"Removing the rotation around the center of mass in a periodic system (this is not a problem when you have only one molecule).");
-    }
-  }
-    
-  if (EI_STATE_VELOCITY(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR) {
-      warning_note(wi,"Tumbling and or flying ice-cubes: We are not removing rotation around center of mass in a non-periodic system. You should probably set comm_mode = ANGULAR.");
-  }
-  
-  sprintf(err_buf,"Free-energy not implemented for Ewald and PPPM");
-  CHECK((ir->coulombtype==eelEWALD || ir->coulombtype==eelPPPM)
-       && (ir->efep!=efepNO));
-  
-  sprintf(err_buf,"Twin-range neighbour searching (NS) with simple NS"
-         " algorithm not implemented");
-  CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist)) 
-       && (ir->ns_type == ensSIMPLE));
-  
-    /* TEMPERATURE COUPLING */
-    if (ir->etc == etcYES)
-    {
-        ir->etc = etcBERENDSEN;
-        warning_note(wi,"Old option for temperature coupling given: "
-                     "changing \"yes\" to \"Berendsen\"\n");
-    }
-  
-    if (ir->etc == etcNOSEHOOVER)
-    {
-        if (ir->opts.nhchainlength < 1) 
-        {
-            sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
-            ir->opts.nhchainlength =1;
-            warning(wi,warn_buf);
-        }
-        
-        if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
-        {
-            warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
-            ir->opts.nhchainlength = 1;
-        }
-    }
-    else
-    {
-        ir->opts.nhchainlength = 0;
-    }
-
-    if (ir->etc == etcBERENDSEN)
-    {
-        sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
-                ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
-        warning_note(wi,warn_buf);
-    }
-
-    if ((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL) 
-        && ir->epc==epcBERENDSEN)
-    {
-        sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
-                "true ensemble for the thermostat");
-        warning(wi,warn_buf);
-    }
-
-    /* PRESSURE COUPLING */
-    if (ir->epc == epcISOTROPIC)
-    {
-        ir->epc = epcBERENDSEN;
-        warning_note(wi,"Old option for pressure coupling given: "
-                     "changing \"Isotropic\" to \"Berendsen\"\n"); 
-    }
-
-    if (ir->epc != epcNO)
-    {
-        dt_pcoupl = ir->nstpcouple*ir->delta_t;
-
-        sprintf(err_buf,"tau-p must be > 0 instead of %g\n",ir->tau_p);
-        CHECK(ir->tau_p <= 0);
-        
-        if (ir->tau_p/dt_pcoupl < pcouple_min_integration_steps(ir->epc))
-        {
-            sprintf(warn_buf,"For proper integration of the %s barostat, tau-p (%g) should be at least %d times larger than nstpcouple*dt (%g)",
-                    EPCOUPLTYPE(ir->epc),ir->tau_p,pcouple_min_integration_steps(ir->epc),dt_pcoupl);
-            warning(wi,warn_buf);
-        }      
-        
-        sprintf(err_buf,"compressibility must be > 0 when using pressure" 
-                " coupling %s\n",EPCOUPLTYPE(ir->epc));
-        CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || 
-              ir->compress[ZZ][ZZ] < 0 || 
-              (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
-               ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
-        
-        sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
-        CHECK(ir->coulombtype == eelPPPM);
-        
-    }
-    else if (ir->coulombtype == eelPPPM)
-    {
-        sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
-        warning(wi,warn_buf);
-    }
-    
-    if (EI_VV(ir->eI))
-    {
-        if (ir->epc > epcNO)
-        {
-            if (ir->epc!=epcMTTK)
-            {
-                warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");          
-            }
-        }
-    }
-
-  /* ELECTROSTATICS */
-  /* More checks are in triple check (grompp.c) */
-    if (ir->coulombtype == eelPPPM)
-    {
-        warning_error(wi,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code");
-    }
-
-  if (ir->coulombtype == eelSWITCH) {
-    sprintf(warn_buf,"coulombtype = %s is only for testing purposes and can lead to serious artifacts, advice: use coulombtype = %s",
-           eel_names[ir->coulombtype],
-           eel_names[eelRF_ZERO]);
-    warning(wi,warn_buf);
-  }
-
-  if (ir->epsilon_r!=1 && ir->implicit_solvent==eisGBSA) {
-    sprintf(warn_buf,"epsilon-r = %g with GB implicit solvent, will use this value for inner dielectric",ir->epsilon_r);
-    warning_note(wi,warn_buf);
-  }
-
-  if (EEL_RF(ir->coulombtype) && ir->epsilon_rf==1 && ir->epsilon_r!=1) {
-    sprintf(warn_buf,"epsilon-r = %g and epsilon-rf = 1 with reaction field, assuming old format and exchanging epsilon-r and epsilon-rf",ir->epsilon_r);
-    warning(wi,warn_buf);
-    ir->epsilon_rf = ir->epsilon_r;
-    ir->epsilon_r  = 1.0;
-  }
-
-  if (getenv("GALACTIC_DYNAMICS") == NULL) {  
-    sprintf(err_buf,"epsilon-r must be >= 0 instead of %g\n",ir->epsilon_r);
-    CHECK(ir->epsilon_r < 0);
-  }
-  
-  if (EEL_RF(ir->coulombtype)) {
-    /* reaction field (at the cut-off) */
-    
-    if (ir->coulombtype == eelRF_ZERO) {
-       sprintf(err_buf,"With coulombtype = %s, epsilon-rf must be 0",
-              eel_names[ir->coulombtype]);
-      CHECK(ir->epsilon_rf != 0);
-    }
-
-    sprintf(err_buf,"epsilon-rf must be >= epsilon-r");
-    CHECK((ir->epsilon_rf < ir->epsilon_r && ir->epsilon_rf != 0) ||
-         (ir->epsilon_r == 0));
-    if (ir->epsilon_rf == ir->epsilon_r) {
-      sprintf(warn_buf,"Using epsilon-rf = epsilon-r with %s does not make sense",
-             eel_names[ir->coulombtype]);
-      warning(wi,warn_buf);
-    }
-  }
-  /* Allow rlist>rcoulomb for tabulated long range stuff. This just
-   * means the interaction is zero outside rcoulomb, but it helps to
-   * provide accurate energy conservation.
-   */
-  if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype)) {
-    if (EEL_SWITCHED(ir->coulombtype)) {
-      sprintf(err_buf,
-             "With coulombtype = %s rcoulomb_switch must be < rcoulomb",
-             eel_names[ir->coulombtype]);
-      CHECK(ir->rcoulomb_switch >= ir->rcoulomb);
-    }
-  } else if (ir->coulombtype == eelCUT || EEL_RF(ir->coulombtype)) {
-    sprintf(err_buf,"With coulombtype = %s, rcoulomb must be >= rlist",
-           eel_names[ir->coulombtype]);
-    CHECK(ir->rlist > ir->rcoulomb);
-  }
-
-  if (EEL_FULL(ir->coulombtype)) {
-    if (ir->coulombtype==eelPMESWITCH || ir->coulombtype==eelPMEUSER ||
-        ir->coulombtype==eelPMEUSERSWITCH) {
-      sprintf(err_buf,"With coulombtype = %s, rcoulomb must be <= rlist",
-             eel_names[ir->coulombtype]);
-      CHECK(ir->rcoulomb > ir->rlist);
-    } else {
-      if (ir->coulombtype == eelPME) {
-       sprintf(err_buf,
-               "With coulombtype = %s, rcoulomb must be equal to rlist\n"
-               "If you want optimal energy conservation or exact integration use %s",
-               eel_names[ir->coulombtype],eel_names[eelPMESWITCH]);
-      } else { 
-       sprintf(err_buf,
-               "With coulombtype = %s, rcoulomb must be equal to rlist",
-               eel_names[ir->coulombtype]);
-      }
-      CHECK(ir->rcoulomb != ir->rlist);
-    }
-  }
-
-  if (EEL_PME(ir->coulombtype)) {
-    if (ir->pme_order < 3) {
-        warning_error(wi,"pme-order can not be smaller than 3");
-    }
-  }
-
-  if (ir->nwall==2 && EEL_FULL(ir->coulombtype)) {
-    if (ir->ewald_geometry == eewg3D) {
-      sprintf(warn_buf,"With pbc=%s you should use ewald-geometry=%s",
-             epbc_names[ir->ePBC],eewg_names[eewg3DC]);
-      warning(wi,warn_buf);
-    }
-    /* This check avoids extra pbc coding for exclusion corrections */
-    sprintf(err_buf,"wall-ewald-zfac should be >= 2");
-    CHECK(ir->wall_ewald_zfac < 2);
-  }
-
-  if (EVDW_SWITCHED(ir->vdwtype)) {
-    sprintf(err_buf,"With vdwtype = %s rvdw-switch must be < rvdw",
-           evdw_names[ir->vdwtype]);
-    CHECK(ir->rvdw_switch >= ir->rvdw);
-  } else if (ir->vdwtype == evdwCUT) {
-    sprintf(err_buf,"With vdwtype = %s, rvdw must be >= rlist",evdw_names[ir->vdwtype]);
-    CHECK(ir->rlist > ir->rvdw);
-  }
-  if (EEL_IS_ZERO_AT_CUTOFF(ir->coulombtype)
-      && (ir->rlistlong <= ir->rcoulomb)) {
-    sprintf(warn_buf,"For energy conservation with switch/shift potentials, %s should be 0.1 to 0.3 nm larger than rcoulomb.",
-           IR_TWINRANGE(*ir) ? "rlistlong" : "rlist");
-    warning_note(wi,warn_buf);
-  }
-  if (EVDW_SWITCHED(ir->vdwtype) && (ir->rlistlong <= ir->rvdw)) {
-    sprintf(warn_buf,"For energy conservation with switch/shift potentials, %s should be 0.1 to 0.3 nm larger than rvdw.",
-           IR_TWINRANGE(*ir) ? "rlistlong" : "rlist");
-    warning_note(wi,warn_buf);
-  }
-
-  if (ir->vdwtype == evdwUSER && ir->eDispCorr != edispcNO) {
-      warning_note(wi,"You have selected user tables with dispersion correction, the dispersion will be corrected to -C6/r^6 beyond rvdw_switch (the tabulated interaction between rvdw_switch and rvdw will not be double counted). Make sure that you really want dispersion correction to -C6/r^6.");
-  }
-
-  if (ir->nstlist == -1) {
-    sprintf(err_buf,
-           "nstlist=-1 only works with switched or shifted potentials,\n"
-           "suggestion: use vdw-type=%s and coulomb-type=%s",
-           evdw_names[evdwSHIFT],eel_names[eelPMESWITCH]);
-    CHECK(!(EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) &&
-            EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype)));
-
-    sprintf(err_buf,"With nstlist=-1 rvdw and rcoulomb should be smaller than rlist to account for diffusion and possibly charge-group radii");
-    CHECK(ir->rvdw >= ir->rlist || ir->rcoulomb >= ir->rlist);
-  }
-  sprintf(err_buf,"nstlist can not be smaller than -1");
-  CHECK(ir->nstlist < -1);
-
-  if (ir->eI == eiLBFGS && (ir->coulombtype==eelCUT || ir->vdwtype==evdwCUT)
-     && ir->rvdw != 0) {
-    warning(wi,"For efficient BFGS minimization, use switch/shift/pme instead of cut-off.");
-  }
-
-  if (ir->eI == eiLBFGS && ir->nbfgscorr <= 0) {
-    warning(wi,"Using L-BFGS with nbfgscorr<=0 just gets you steepest descent.");
-  }
-
-  /* FREE ENERGY */
-  if (ir->efep != efepNO) {
-    sprintf(err_buf,"The soft-core power is %d and can only be 1 or 2",
-           ir->sc_power);
-    CHECK(ir->sc_alpha!=0 && ir->sc_power!=1 && ir->sc_power!=2);
-  }
-
-    /* ENERGY CONSERVATION */
-    if (ir_NVE(ir))
-    {
-        if (!EVDW_MIGHT_BE_ZERO_AT_CUTOFF(ir->vdwtype) && ir->rvdw > 0)
-        {
-            sprintf(warn_buf,"You are using a cut-off for VdW interactions with NVE, for good energy conservation use vdwtype = %s (possibly with DispCorr)",
-                    evdw_names[evdwSHIFT]);
-            warning_note(wi,warn_buf);
-        }
-        if (!EEL_MIGHT_BE_ZERO_AT_CUTOFF(ir->coulombtype) && ir->rcoulomb > 0)
-        {
-            sprintf(warn_buf,"You are using a cut-off for electrostatics with NVE, for good energy conservation use coulombtype = %s or %s",
-                    eel_names[eelPMESWITCH],eel_names[eelRF_ZERO]);
-            warning_note(wi,warn_buf);
-        }
-    }
-  
-  /* IMPLICIT SOLVENT */
-  if(ir->coulombtype==eelGB_NOTUSED)
-  {
-    ir->coulombtype=eelCUT;
-    ir->implicit_solvent=eisGBSA;
-    fprintf(stderr,"Note: Old option for generalized born electrostatics given:\n"
-           "Changing coulombtype from \"generalized-born\" to \"cut-off\" and instead\n"
-            "setting implicit-solvent value to \"GBSA\" in input section.\n");
-  }
-
-  if(ir->sa_algorithm==esaSTILL)
-  {
-    sprintf(err_buf,"Still SA algorithm not available yet, use %s or %s instead\n",esa_names[esaAPPROX],esa_names[esaNO]);
-    CHECK(ir->sa_algorithm == esaSTILL);
-  }
-  
-  if(ir->implicit_solvent==eisGBSA)
-  {
-    sprintf(err_buf,"With GBSA implicit solvent, rgbradii must be equal to rlist.");
-    CHECK(ir->rgbradii != ir->rlist);
-         
-    if(ir->coulombtype!=eelCUT)
-         {
-                 sprintf(err_buf,"With GBSA, coulombtype must be equal to %s\n",eel_names[eelCUT]);
-                 CHECK(ir->coulombtype!=eelCUT);
-         }
-         if(ir->vdwtype!=evdwCUT)
-         {
-                 sprintf(err_buf,"With GBSA, vdw-type must be equal to %s\n",evdw_names[evdwCUT]);
-                 CHECK(ir->vdwtype!=evdwCUT);
-         }
-    if(ir->nstgbradii<1)
-    {
-      sprintf(warn_buf,"Using GBSA with nstgbradii<1, setting nstgbradii=1");
-      warning_note(wi,warn_buf);
-      ir->nstgbradii=1;
-    }
-    if(ir->sa_algorithm==esaNO)
-    {
-      sprintf(warn_buf,"No SA (non-polar) calculation requested together with GB. Are you sure this is what you want?\n");
-      warning_note(wi,warn_buf);
-    }
-    if(ir->sa_surface_tension<0 && ir->sa_algorithm!=esaNO)
-    {
-      sprintf(warn_buf,"Value of sa_surface_tension is < 0. Changing it to 2.05016 or 2.25936 kJ/nm^2/mol for Still and HCT/OBC respectively\n");
-      warning_note(wi,warn_buf);
-      
-      if(ir->gb_algorithm==egbSTILL)
-      {
-        ir->sa_surface_tension = 0.0049 * CAL2JOULE * 100;
-      }
-      else
-      {
-        ir->sa_surface_tension = 0.0054 * CAL2JOULE * 100;
-      }
-    }
-    if(ir->sa_surface_tension==0 && ir->sa_algorithm!=esaNO)
-    {
-      sprintf(err_buf, "Surface tension set to 0 while SA-calculation requested\n");
-      CHECK(ir->sa_surface_tension==0 && ir->sa_algorithm!=esaNO);
-    }
-    
-  }
-}
-
-static int str_nelem(const char *str,int maxptr,char *ptr[])
-{
-  int  np=0;
-  char *copy0,*copy;
-  
-  copy0=strdup(str); 
-  copy=copy0;
-  ltrim(copy);
-  while (*copy != '\0') {
-    if (np >= maxptr)
-      gmx_fatal(FARGS,"Too many groups on line: '%s' (max is %d)",
-                 str,maxptr);
-    if (ptr) 
-      ptr[np]=copy;
-    np++;
-    while ((*copy != '\0') && !isspace(*copy))
-      copy++;
-    if (*copy != '\0') {
-      *copy='\0';
-      copy++;
-    }
-    ltrim(copy);
-  }
-  if (ptr == NULL)
-    sfree(copy0);
-
-  return np;
-}
-
-static void parse_n_double(char *str,int *n,double **r)
-{
-  char *ptr[MAXPTR];
-  int  i;
-
-  *n = str_nelem(str,MAXPTR,ptr);
-
-  snew(*r,*n);
-  for(i=0; i<*n; i++) {
-    (*r)[i] = strtod(ptr[i],NULL);
-  }
-}
-
-static void do_wall_params(t_inputrec *ir,
-                           char *wall_atomtype, char *wall_density,
-                           t_gromppopts *opts)
-{
-    int  nstr,i;
-    char *names[MAXPTR];
-    double dbl;
-
-    opts->wall_atomtype[0] = NULL;
-    opts->wall_atomtype[1] = NULL;
-
-    ir->wall_atomtype[0] = -1;
-    ir->wall_atomtype[1] = -1;
-    ir->wall_density[0] = 0;
-    ir->wall_density[1] = 0;
-  
-    if (ir->nwall > 0)
-    {
-        nstr = str_nelem(wall_atomtype,MAXPTR,names);
-        if (nstr != ir->nwall)
-        {
-            gmx_fatal(FARGS,"Expected %d elements for wall_atomtype, found %d",
-                      ir->nwall,nstr);
-        }
-        for(i=0; i<ir->nwall; i++)
-        {
-            opts->wall_atomtype[i] = strdup(names[i]);
-        }
-    
-        if (ir->wall_type == ewt93 || ir->wall_type == ewt104) {
-            nstr = str_nelem(wall_density,MAXPTR,names);
-            if (nstr != ir->nwall)
-            {
-                gmx_fatal(FARGS,"Expected %d elements for wall-density, found %d",ir->nwall,nstr);
-            }
-            for(i=0; i<ir->nwall; i++)
-            {
-                sscanf(names[i],"%lf",&dbl);
-                if (dbl <= 0)
-                {
-                    gmx_fatal(FARGS,"wall-density[%d] = %f\n",i,dbl);
-                }
-                ir->wall_density[i] = dbl;
-            }
-        }
-    }
-}
-
-static void add_wall_energrps(gmx_groups_t *groups,int nwall,t_symtab *symtab)
-{
-  int  i;
-  t_grps *grps;
-  char str[STRLEN];
-  
-  if (nwall > 0) {
-    srenew(groups->grpname,groups->ngrpname+nwall);
-    grps = &(groups->grps[egcENER]);
-    srenew(grps->nm_ind,grps->nr+nwall);
-    for(i=0; i<nwall; i++) {
-      sprintf(str,"wall%d",i);
-      groups->grpname[groups->ngrpname] = put_symtab(symtab,str);
-      grps->nm_ind[grps->nr++] = groups->ngrpname++;
-    }
-  }
-}
-
-void get_ir(const char *mdparin,const char *mdparout,
-            t_inputrec *ir,t_gromppopts *opts,
-            warninp_t wi)
-{
-  char      *dumstr[2];
-  double    dumdub[2][6];
-  t_inpfile *inp;
-  const char *tmp;
-  int       i,j,m,ninp;
-  char      warn_buf[STRLEN];
-  
-  inp = read_inpfile(mdparin, &ninp, NULL, wi);
-
-  snew(dumstr[0],STRLEN);
-  snew(dumstr[1],STRLEN);
-
-  REM_TYPE("title");
-  REM_TYPE("cpp");
-  REM_TYPE("domain-decomposition");
-  REPL_TYPE("unconstrained-start","continuation");
-  REM_TYPE("dihre-tau");
-  REM_TYPE("nstdihreout");
-  REM_TYPE("nstcheckpoint");
-
-  CCTYPE ("VARIOUS PREPROCESSING OPTIONS");
-  CTYPE ("Preprocessor information: use cpp syntax.");
-  CTYPE ("e.g.: -I/home/joe/doe -I/home/mary/roe");
-  STYPE ("include",    opts->include,  NULL);
-  CTYPE ("e.g.: -DPOSRES -DFLEXIBLE (note these variable names are case sensitive)");
-  STYPE ("define",     opts->define,   NULL);
-    
-  CCTYPE ("RUN CONTROL PARAMETERS");
-  EETYPE("integrator",  ir->eI,         ei_names);
-  CTYPE ("Start time and timestep in ps");
-  RTYPE ("tinit",      ir->init_t,     0.0);
-  RTYPE ("dt",         ir->delta_t,    0.001);
-  STEPTYPE ("nsteps",   ir->nsteps,     0);
-  CTYPE ("For exact run continuation or redoing part of a run");
-  STEPTYPE ("init-step",ir->init_step,  0);
-  CTYPE ("Part index is updated automatically on checkpointing (keeps files separate)");
-  ITYPE ("simulation-part", ir->simulation_part, 1);
-  CTYPE ("mode for center of mass motion removal");
-  EETYPE("comm-mode",   ir->comm_mode,  ecm_names);
-  CTYPE ("number of steps for center of mass motion removal");
-  ITYPE ("nstcomm",    ir->nstcomm,    10);
-  CTYPE ("group(s) for center of mass motion removal");
-  STYPE ("comm-grps",   vcm,            NULL);
-  
-  CCTYPE ("LANGEVIN DYNAMICS OPTIONS");
-  CTYPE ("Friction coefficient (amu/ps) and random seed");
-  RTYPE ("bd-fric",     ir->bd_fric,    0.0);
-  ITYPE ("ld-seed",     ir->ld_seed,    1993);
-  
-  /* Em stuff */
-  CCTYPE ("ENERGY MINIMIZATION OPTIONS");
-  CTYPE ("Force tolerance and initial step-size");
-  RTYPE ("emtol",       ir->em_tol,     10.0);
-  RTYPE ("emstep",      ir->em_stepsize,0.01);
-  CTYPE ("Max number of iterations in relax-shells");
-  ITYPE ("niter",       ir->niter,      20);
-  CTYPE ("Step size (ps^2) for minimization of flexible constraints");
-  RTYPE ("fcstep",      ir->fc_stepsize, 0);
-  CTYPE ("Frequency of steepest descents steps when doing CG");
-  ITYPE ("nstcgsteep", ir->nstcgsteep, 1000);
-  ITYPE ("nbfgscorr",   ir->nbfgscorr,  10); 
-
-  CCTYPE ("TEST PARTICLE INSERTION OPTIONS");
-  RTYPE ("rtpi",       ir->rtpi,       0.05);
-
-  /* Output options */
-  CCTYPE ("OUTPUT CONTROL OPTIONS");
-  CTYPE ("Output frequency for coords (x), velocities (v) and forces (f)");
-  ITYPE ("nstxout",    ir->nstxout,    100);
-  ITYPE ("nstvout",    ir->nstvout,    100);
-  ITYPE ("nstfout",    ir->nstfout,    0);
-  ir->nstcheckpoint = 1000;
-  CTYPE ("Output frequency for energies to log file and energy file");
-  ITYPE ("nstlog",     ir->nstlog,     100);
-  ITYPE ("nstcalcenergy",ir->nstcalcenergy,    -1);
-  ITYPE ("nstenergy",   ir->nstenergy,  100);
-  CTYPE ("Output frequency and precision for .xtc file");
-  ITYPE ("nstxtcout",   ir->nstxtcout,  0);
-  RTYPE ("xtc-precision",ir->xtcprec,   1000.0);
-  CTYPE ("This selects the subset of atoms for the .xtc file. You can");
-  CTYPE ("select multiple groups. By default all atoms will be written.");
-  STYPE ("xtc-grps",    xtc_grps,       NULL);
-  CTYPE ("Selection of energy groups");
-  STYPE ("energygrps",  energy,         NULL);
-
-  /* Neighbor searching */  
-  CCTYPE ("NEIGHBORSEARCHING PARAMETERS");
-  CTYPE ("nblist update frequency");
-  ITYPE ("nstlist",    ir->nstlist,    10);
-  CTYPE ("ns algorithm (simple or grid)");
-  EETYPE("ns-type",     ir->ns_type,    ens_names);
-  /* set ndelta to the optimal value of 2 */
-  ir->ndelta = 2;
-  CTYPE ("Periodic boundary conditions: xyz, no, xy");
-  EETYPE("pbc",         ir->ePBC,       epbc_names);
-  EETYPE("periodic-molecules", ir->bPeriodicMols, yesno_names);
-  CTYPE ("nblist cut-off");
-  RTYPE ("rlist",      ir->rlist,      1.0);
-  CTYPE ("long-range cut-off for switched potentials");
-  RTYPE ("rlistlong",  ir->rlistlong,  -1);
-
-  /* Electrostatics */
-  CCTYPE ("OPTIONS FOR ELECTROSTATICS AND VDW");
-  CTYPE ("Method for doing electrostatics");
-  EETYPE("coulombtype",        ir->coulombtype,    eel_names);
-  CTYPE ("cut-off lengths");
-  RTYPE ("rcoulomb-switch",    ir->rcoulomb_switch,    0.0);
-  RTYPE ("rcoulomb",   ir->rcoulomb,   1.0);
-  CTYPE ("Relative dielectric constant for the medium and the reaction field");
-  RTYPE ("epsilon-r",   ir->epsilon_r,  1.0);
-  RTYPE ("epsilon-rf",  ir->epsilon_rf, 1.0);
-  CTYPE ("Method for doing Van der Waals");
-  EETYPE("vdw-type",   ir->vdwtype,    evdw_names);
-  CTYPE ("cut-off lengths");
-  RTYPE ("rvdw-switch",        ir->rvdw_switch,        0.0);
-  RTYPE ("rvdw",       ir->rvdw,       1.0);
-  CTYPE ("Apply long range dispersion corrections for Energy and Pressure");
-  EETYPE("DispCorr",    ir->eDispCorr,  edispc_names);
-  CTYPE ("Extension of the potential lookup tables beyond the cut-off");
-  RTYPE ("table-extension", ir->tabext, 1.0);
-  CTYPE ("Seperate tables between energy group pairs");
-  STYPE ("energygrp-table", egptable,   NULL);
-  CTYPE ("Spacing for the PME/PPPM FFT grid");
-  RTYPE ("fourierspacing", opts->fourierspacing,0.12);
-  CTYPE ("FFT grid size, when a value is 0 fourierspacing will be used");
-  ITYPE ("fourier-nx",  ir->nkx,         0);
-  ITYPE ("fourier-ny",  ir->nky,         0);
-  ITYPE ("fourier-nz",  ir->nkz,         0);
-  CTYPE ("EWALD/PME/PPPM parameters");
-  ITYPE ("pme-order",   ir->pme_order,   4);
-  RTYPE ("ewald-rtol",  ir->ewald_rtol, 0.00001);
-  EETYPE("ewald-geometry", ir->ewald_geometry, eewg_names);
-  RTYPE ("epsilon-surface", ir->epsilon_surface, 0.0);
-  EETYPE("optimize-fft",ir->bOptFFT,  yesno_names);
-
-  CCTYPE("IMPLICIT SOLVENT ALGORITHM");
-  EETYPE("implicit-solvent", ir->implicit_solvent, eis_names);
-       
-  CCTYPE ("GENERALIZED BORN ELECTROSTATICS"); 
-  CTYPE ("Algorithm for calculating Born radii");
-  EETYPE("gb-algorithm", ir->gb_algorithm, egb_names);
-  CTYPE ("Frequency of calculating the Born radii inside rlist");
-  ITYPE ("nstgbradii", ir->nstgbradii, 1);
-  CTYPE ("Cutoff for Born radii calculation; the contribution from atoms");
-  CTYPE ("between rlist and rgbradii is updated every nstlist steps");
-  RTYPE ("rgbradii",  ir->rgbradii, 1.0);
-  CTYPE ("Dielectric coefficient of the implicit solvent");
-  RTYPE ("gb-epsilon-solvent",ir->gb_epsilon_solvent, 80.0);
-  CTYPE ("Salt concentration in M for Generalized Born models");
-  RTYPE ("gb-saltconc",  ir->gb_saltconc, 0.0);
-  CTYPE ("Scaling factors used in the OBC GB model. Default values are OBC(II)");
-  RTYPE ("gb-obc-alpha", ir->gb_obc_alpha, 1.0);
-  RTYPE ("gb-obc-beta", ir->gb_obc_beta, 0.8);
-  RTYPE ("gb-obc-gamma", ir->gb_obc_gamma, 4.85);
-  RTYPE ("gb-dielectric-offset", ir->gb_dielectric_offset, 0.009);
-  EETYPE("sa-algorithm", ir->sa_algorithm, esa_names);
-  CTYPE ("Surface tension (kJ/mol/nm^2) for the SA (nonpolar surface) part of GBSA");
-  CTYPE ("The value -1 will set default value for Still/HCT/OBC GB-models.");
-  RTYPE ("sa-surface-tension", ir->sa_surface_tension, -1);
-                
-  /* Coupling stuff */
-  CCTYPE ("OPTIONS FOR WEAK COUPLING ALGORITHMS");
-  CTYPE ("Temperature coupling");
-  EETYPE("tcoupl",     ir->etc,        etcoupl_names);
-  ITYPE ("nsttcouple", ir->nsttcouple,  -1);
-  ITYPE("nh-chain-length",     ir->opts.nhchainlength, NHCHAINLENGTH);
-  CTYPE ("Groups to couple separately");
-  STYPE ("tc-grps",     tcgrps,         NULL);
-  CTYPE ("Time constant (ps) and reference temperature (K)");
-  STYPE ("tau-t",      tau_t,          NULL);
-  STYPE ("ref-t",      ref_t,          NULL);
-  CTYPE ("pressure coupling");
-  EETYPE("pcoupl",     ir->epc,        epcoupl_names);
-  EETYPE("pcoupltype", ir->epct,       epcoupltype_names);
-  ITYPE ("nstpcouple", ir->nstpcouple,  -1);
-  CTYPE ("Time constant (ps), compressibility (1/bar) and reference P (bar)");
-  RTYPE ("tau-p",      ir->tau_p,      1.0);
-  STYPE ("compressibility",    dumstr[0],      NULL);
-  STYPE ("ref-p",       dumstr[1],      NULL);
-  CTYPE ("Scaling of reference coordinates, No, All or COM");
-  EETYPE ("refcoord-scaling",ir->refcoord_scaling,erefscaling_names);
-
-  CTYPE ("Random seed for Andersen thermostat");
-  ITYPE ("andersen-seed", ir->andersen_seed, 815131);
-
-  /* QMMM */
-  CCTYPE ("OPTIONS FOR QMMM calculations");
-  EETYPE("QMMM", ir->bQMMM, yesno_names);
-  CTYPE ("Groups treated Quantum Mechanically");
-  STYPE ("QMMM-grps",  QMMM,          NULL);
-  CTYPE ("QM method");
-  STYPE("QMmethod",     QMmethod, NULL);
-  CTYPE ("QMMM scheme");
-  EETYPE("QMMMscheme",  ir->QMMMscheme,    eQMMMscheme_names);
-  CTYPE ("QM basisset");
-  STYPE("QMbasis",      QMbasis, NULL);
-  CTYPE ("QM charge");
-  STYPE ("QMcharge",    QMcharge,NULL);
-  CTYPE ("QM multiplicity");
-  STYPE ("QMmult",      QMmult,NULL);
-  CTYPE ("Surface Hopping");
-  STYPE ("SH",          bSH, NULL);
-  CTYPE ("CAS space options");
-  STYPE ("CASorbitals",      CASorbitals,   NULL);
-  STYPE ("CASelectrons",     CASelectrons,  NULL);
-  STYPE ("SAon", SAon, NULL);
-  STYPE ("SAoff",SAoff,NULL);
-  STYPE ("SAsteps",  SAsteps, NULL);
-  CTYPE ("Scale factor for MM charges");
-  RTYPE ("MMChargeScaleFactor", ir->scalefactor, 1.0);
-  CTYPE ("Optimization of QM subsystem");
-  STYPE ("bOPT",          bOPT, NULL);
-  STYPE ("bTS",          bTS, NULL);
-
-  /* Simulated annealing */
-  CCTYPE("SIMULATED ANNEALING");
-  CTYPE ("Type of annealing for each temperature group (no/single/periodic)");
-  STYPE ("annealing",   anneal,      NULL);
-  CTYPE ("Number of time points to use for specifying annealing in each group");
-  STYPE ("annealing-npoints", anneal_npoints, NULL);
-  CTYPE ("List of times at the annealing points for each group");
-  STYPE ("annealing-time",       anneal_time,       NULL);
-  CTYPE ("Temp. at each annealing point, for each group.");
-  STYPE ("annealing-temp",  anneal_temp,  NULL);
-  
-  /* Startup run */
-  CCTYPE ("GENERATE VELOCITIES FOR STARTUP RUN");
-  EETYPE("gen-vel",     opts->bGenVel,  yesno_names);
-  RTYPE ("gen-temp",    opts->tempi,    300.0);
-  ITYPE ("gen-seed",    opts->seed,     173529);
-  
-  /* Shake stuff */
-  CCTYPE ("OPTIONS FOR BONDS");
-  EETYPE("constraints",        opts->nshake,   constraints);
-  CTYPE ("Type of constraint algorithm");
-  EETYPE("constraint-algorithm",  ir->eConstrAlg, econstr_names);
-  CTYPE ("Do not constrain the start configuration");
-  EETYPE("continuation", ir->bContinuation, yesno_names);
-  CTYPE ("Use successive overrelaxation to reduce the number of shake iterations");
-  EETYPE("Shake-SOR", ir->bShakeSOR, yesno_names);
-  CTYPE ("Relative tolerance of shake");
-  RTYPE ("shake-tol", ir->shake_tol, 0.0001);
-  CTYPE ("Highest order in the expansion of the constraint coupling matrix");
-  ITYPE ("lincs-order", ir->nProjOrder, 4);
-  CTYPE ("Number of iterations in the final step of LINCS. 1 is fine for");
-  CTYPE ("normal simulations, but use 2 to conserve energy in NVE runs.");
-  CTYPE ("For energy minimization with constraints it should be 4 to 8.");
-  ITYPE ("lincs-iter", ir->nLincsIter, 1);
-  CTYPE ("Lincs will write a warning to the stderr if in one step a bond"); 
-  CTYPE ("rotates over more degrees than");
-  RTYPE ("lincs-warnangle", ir->LincsWarnAngle, 30.0);
-  CTYPE ("Convert harmonic bonds to morse potentials");
-  EETYPE("morse",       opts->bMorse,yesno_names);
-
-  /* Energy group exclusions */
-  CCTYPE ("ENERGY GROUP EXCLUSIONS");
-  CTYPE ("Pairs of energy groups for which all non-bonded interactions are excluded");
-  STYPE ("energygrp-excl", egpexcl,     NULL);
-  
-  /* Walls */
-  CCTYPE ("WALLS");
-  CTYPE ("Number of walls, type, atom types, densities and box-z scale factor for Ewald");
-  ITYPE ("nwall", ir->nwall, 0);
-  EETYPE("wall-type",     ir->wall_type,   ewt_names);
-  RTYPE ("wall-r-linpot", ir->wall_r_linpot, -1);
-  STYPE ("wall-atomtype", wall_atomtype, NULL);
-  STYPE ("wall-density",  wall_density,  NULL);
-  RTYPE ("wall-ewald-zfac", ir->wall_ewald_zfac, 3);
-  
-  /* COM pulling */
-  CCTYPE("COM PULLING");
-  CTYPE("Pull type: no, umbrella, constraint or constant-force");
-  EETYPE("pull",          ir->ePull, epull_names);
-  if (ir->ePull != epullNO) {
-    snew(ir->pull,1);
-    pull_grp = read_pullparams(&ninp,&inp,ir->pull,&opts->pull_start,wi);
-  }
-
-  /* Refinement */
-  CCTYPE("NMR refinement stuff");
-  CTYPE ("Distance restraints type: No, Simple or Ensemble");
-  EETYPE("disre",       ir->eDisre,     edisre_names);
-  CTYPE ("Force weighting of pairs in one distance restraint: Conservative or Equal");
-  EETYPE("disre-weighting", ir->eDisreWeighting, edisreweighting_names);
-  CTYPE ("Use sqrt of the time averaged times the instantaneous violation");
-  EETYPE("disre-mixed", ir->bDisreMixed, yesno_names);
-  RTYPE ("disre-fc",   ir->dr_fc,      1000.0);
-  RTYPE ("disre-tau",  ir->dr_tau,     0.0);
-  CTYPE ("Output frequency for pair distances to energy file");
-  ITYPE ("nstdisreout", ir->nstdisreout, 100);
-  CTYPE ("Orientation restraints: No or Yes");
-  EETYPE("orire",       opts->bOrire,   yesno_names);
-  CTYPE ("Orientation restraints force constant and tau for time averaging");
-  RTYPE ("orire-fc",   ir->orires_fc,  0.0);
-  RTYPE ("orire-tau",  ir->orires_tau, 0.0);
-  STYPE ("orire-fitgrp",orirefitgrp,    NULL);
-  CTYPE ("Output frequency for trace(SD) and S to energy file");
-  ITYPE ("nstorireout", ir->nstorireout, 100);
-  CTYPE ("Dihedral angle restraints: No or Yes");
-  EETYPE("dihre",       opts->bDihre,   yesno_names);
-  RTYPE ("dihre-fc",   ir->dihre_fc,   1000.0);
-
-  /* Free energy stuff */
-  CCTYPE ("Free energy control stuff");
-  EETYPE("free-energy",        ir->efep, efep_names);
-  RTYPE ("init-lambda",        ir->init_lambda,0.0);
-  RTYPE ("delta-lambda",ir->delta_lambda,0.0);
-  STYPE ("foreign-lambda", foreign_lambda, NULL);
-  RTYPE ("sc-alpha",ir->sc_alpha,0.0);
-  ITYPE ("sc-power",ir->sc_power,0);
-  RTYPE ("sc-sigma",ir->sc_sigma,0.3);
-  ITYPE ("nstdhdl",     ir->nstdhdl, 10);
-  EETYPE("separate-dhdl-file", ir->separate_dhdl_file, 
-                               separate_dhdl_file_names);
-  EETYPE("dhdl-derivatives", ir->dhdl_derivatives, dhdl_derivatives_names);
-  ITYPE ("dh-hist-size", ir->dh_hist_size, 0);
-  RTYPE ("dh-hist-spacing", ir->dh_hist_spacing, 0.1);
-  STYPE ("couple-moltype",  couple_moltype,  NULL);
-  EETYPE("couple-lambda0", opts->couple_lam0, couple_lam);
-  EETYPE("couple-lambda1", opts->couple_lam1, couple_lam);
-  EETYPE("couple-intramol", opts->bCoupleIntra, yesno_names);
-
-  /* Non-equilibrium MD stuff */  
-  CCTYPE("Non-equilibrium MD stuff");
-  STYPE ("acc-grps",    accgrps,        NULL);
-  STYPE ("accelerate",  acc,            NULL);
-  STYPE ("freezegrps",  freeze,         NULL);
-  STYPE ("freezedim",   frdim,          NULL);
-  RTYPE ("cos-acceleration", ir->cos_accel, 0);
-  STYPE ("deform",      deform,         NULL);
-
-  /* Electric fields */
-  CCTYPE("Electric fields");
-  CTYPE ("Format is number of terms (int) and for all terms an amplitude (real)");
-  CTYPE ("and a phase angle (real)");
-  STYPE ("E-x",        efield_x,       NULL);
-  STYPE ("E-xt",       efield_xt,      NULL);
-  STYPE ("E-y",        efield_y,       NULL);
-  STYPE ("E-yt",       efield_yt,      NULL);
-  STYPE ("E-z",        efield_z,       NULL);
-  STYPE ("E-zt",       efield_zt,      NULL);
-  
-  /* User defined thingies */
-  CCTYPE ("User defined thingies");
-  STYPE ("user1-grps",  user1,          NULL);
-  STYPE ("user2-grps",  user2,          NULL);
-  ITYPE ("userint1",    ir->userint1,   0);
-  ITYPE ("userint2",    ir->userint2,   0);
-  ITYPE ("userint3",    ir->userint3,   0);
-  ITYPE ("userint4",    ir->userint4,   0);
-  RTYPE ("userreal1",   ir->userreal1,  0);
-  RTYPE ("userreal2",   ir->userreal2,  0);
-  RTYPE ("userreal3",   ir->userreal3,  0);
-  RTYPE ("userreal4",   ir->userreal4,  0);
-#undef CTYPE
-
-  write_inpfile(mdparout,ninp,inp,FALSE,wi);
-  for (i=0; (i<ninp); i++) {
-    sfree(inp[i].name);
-    sfree(inp[i].value);
-  }
-  sfree(inp);
-
-  /* Process options if necessary */
-  for(m=0; m<2; m++) {
-    for(i=0; i<2*DIM; i++)
-      dumdub[m][i]=0.0;
-    if(ir->epc) {
-      switch (ir->epct) {
-      case epctISOTROPIC:
-       if (sscanf(dumstr[m],"%lf",&(dumdub[m][XX]))!=1) {
-        warning_error(wi,"Pressure coupling not enough values (I need 1)");
-       }
-       dumdub[m][YY]=dumdub[m][ZZ]=dumdub[m][XX];
-       break;
-      case epctSEMIISOTROPIC:
-      case epctSURFACETENSION:
-       if (sscanf(dumstr[m],"%lf%lf",
-                  &(dumdub[m][XX]),&(dumdub[m][ZZ]))!=2) {
-        warning_error(wi,"Pressure coupling not enough values (I need 2)");
-       }
-       dumdub[m][YY]=dumdub[m][XX];
-       break;
-      case epctANISOTROPIC:
-       if (sscanf(dumstr[m],"%lf%lf%lf%lf%lf%lf",
-                  &(dumdub[m][XX]),&(dumdub[m][YY]),&(dumdub[m][ZZ]),
-                  &(dumdub[m][3]),&(dumdub[m][4]),&(dumdub[m][5]))!=6) {
-        warning_error(wi,"Pressure coupling not enough values (I need 6)");
-       }
-       break;
-      default:
-       gmx_fatal(FARGS,"Pressure coupling type %s not implemented yet",
-                   epcoupltype_names[ir->epct]);
-      }
-    }
-  }
-  clear_mat(ir->ref_p);
-  clear_mat(ir->compress);
-  for(i=0; i<DIM; i++) {
-    ir->ref_p[i][i]    = dumdub[1][i];
-    ir->compress[i][i] = dumdub[0][i];
-  }
-  if (ir->epct == epctANISOTROPIC) {
-    ir->ref_p[XX][YY] = dumdub[1][3];
-    ir->ref_p[XX][ZZ] = dumdub[1][4];
-    ir->ref_p[YY][ZZ] = dumdub[1][5];
-    if (ir->ref_p[XX][YY]!=0 && ir->ref_p[XX][ZZ]!=0 && ir->ref_p[YY][ZZ]!=0) {
-      warning(wi,"All off-diagonal reference pressures are non-zero. Are you sure you want to apply a threefold shear stress?\n");
-    }
-    ir->compress[XX][YY] = dumdub[0][3];
-    ir->compress[XX][ZZ] = dumdub[0][4];
-    ir->compress[YY][ZZ] = dumdub[0][5];
-    for(i=0; i<DIM; i++) {
-      for(m=0; m<i; m++) {
-       ir->ref_p[i][m] = ir->ref_p[m][i];
-       ir->compress[i][m] = ir->compress[m][i];
-      }
-    }
-  } 
-  
-  if (ir->comm_mode == ecmNO)
-    ir->nstcomm = 0;
-
-  opts->couple_moltype = NULL;
-  if (strlen(couple_moltype) > 0) {
-    if (ir->efep != efepNO) {
-      opts->couple_moltype = strdup(couple_moltype);
-      if (opts->couple_lam0 == opts->couple_lam1)
-       warning(wi,"The lambda=0 and lambda=1 states for coupling are identical");
-      if (ir->eI == eiMD && (opts->couple_lam0 == ecouplamNONE ||
-                            opts->couple_lam1 == ecouplamNONE)) {
-       warning(wi,"For proper sampling of the (nearly) decoupled state, stochastic dynamics should be used");
-      }
-    } else {
-      warning(wi,"Can not couple a molecule with free-energy = no");
-    }
-  }
-
-  do_wall_params(ir,wall_atomtype,wall_density,opts);
-  
-  if (opts->bOrire && str_nelem(orirefitgrp,MAXPTR,NULL)!=1) {
-      warning_error(wi,"ERROR: Need one orientation restraint fit group\n");
-  }
-
-  clear_mat(ir->deform);
-  for(i=0; i<6; i++)
-    dumdub[0][i] = 0;
-  m = sscanf(deform,"%lf %lf %lf %lf %lf %lf",
-            &(dumdub[0][0]),&(dumdub[0][1]),&(dumdub[0][2]),
-            &(dumdub[0][3]),&(dumdub[0][4]),&(dumdub[0][5]));
-  for(i=0; i<3; i++)
-    ir->deform[i][i] = dumdub[0][i];
-  ir->deform[YY][XX] = dumdub[0][3];
-  ir->deform[ZZ][XX] = dumdub[0][4];
-  ir->deform[ZZ][YY] = dumdub[0][5];
-  if (ir->epc != epcNO) {
-    for(i=0; i<3; i++)
-      for(j=0; j<=i; j++)
-       if (ir->deform[i][j]!=0 && ir->compress[i][j]!=0) {
-        warning_error(wi,"A box element has deform set and compressibility > 0");
-       }
-    for(i=0; i<3; i++)
-      for(j=0; j<i; j++)
-       if (ir->deform[i][j]!=0) {
-         for(m=j; m<DIM; m++)
-           if (ir->compress[m][j]!=0) {
-             sprintf(warn_buf,"An off-diagonal box element has deform set while compressibility > 0 for the same component of another box vector, this might lead to spurious periodicity effects.");
-             warning(wi,warn_buf);
-           }
-       }
-  }
-
-  if (ir->efep != efepNO) {
-    parse_n_double(foreign_lambda,&ir->n_flambda,&ir->flambda);
-    if (ir->n_flambda > 0 && ir->rlist < max(ir->rvdw,ir->rcoulomb)) {
-      warning_note(wi,"For foreign lambda free energy differences it is assumed that the soft-core interactions have no effect beyond the neighborlist cut-off");
-    }
-  } else {
-    ir->n_flambda = 0;
-  }
-
-  sfree(dumstr[0]);
-  sfree(dumstr[1]);
-}
-
-static int search_QMstring(char *s,int ng,const char *gn[])
-{
-  /* same as normal search_string, but this one searches QM strings */
-  int i;
-
-  for(i=0; (i<ng); i++)
-    if (gmx_strcasecmp(s,gn[i]) == 0)
-      return i;
-
-  gmx_fatal(FARGS,"this QM method or basisset (%s) is not implemented\n!",s);
-
-  return -1;
-
-} /* search_QMstring */
-
-
-int search_string(char *s,int ng,char *gn[])
-{
-  int i;
-  
-  for(i=0; (i<ng); i++)
-  {
-    if (gmx_strcasecmp(s,gn[i]) == 0)
-    {
-      return i;
-    }
-  }
-    
-  gmx_fatal(FARGS,"Group %s not found in index file.\nGroup names must match either [moleculetype] names\nor custom index group names,in which case you\nmust supply an index file to the '-n' option of grompp.",s);
-  
-  return -1;
-}
-
-static gmx_bool do_numbering(int natoms,gmx_groups_t *groups,int ng,char *ptrs[],
-                         t_blocka *block,char *gnames[],
-                         int gtype,int restnm,
-                         int grptp,gmx_bool bVerbose,
-                         warninp_t wi)
-{
-    unsigned short *cbuf;
-    t_grps *grps=&(groups->grps[gtype]);
-    int    i,j,gid,aj,ognr,ntot=0;
-    const char *title;
-    gmx_bool   bRest;
-    char   warn_buf[STRLEN];
-
-    if (debug)
-    {
-        fprintf(debug,"Starting numbering %d groups of type %d\n",ng,gtype);
-    }
-  
-    title = gtypes[gtype];
-    
-    snew(cbuf,natoms);
-    /* Mark all id's as not set */
-    for(i=0; (i<natoms); i++)
-    {
-        cbuf[i] = NOGID;
-    }
-  
-    snew(grps->nm_ind,ng+1); /* +1 for possible rest group */
-    for(i=0; (i<ng); i++)
-    {
-        /* Lookup the group name in the block structure */
-        gid = search_string(ptrs[i],block->nr,gnames);
-        if ((grptp != egrptpONE) || (i == 0))
-        {
-            grps->nm_ind[grps->nr++]=gid;
-        }
-        if (debug) 
-        {
-            fprintf(debug,"Found gid %d for group %s\n",gid,ptrs[i]);
-        }
-    
-        /* Now go over the atoms in the group */
-        for(j=block->index[gid]; (j<block->index[gid+1]); j++)
-        {
-
-            aj=block->a[j];
-      
-            /* Range checking */
-            if ((aj < 0) || (aj >= natoms)) 
-            {
-                gmx_fatal(FARGS,"Invalid atom number %d in indexfile",aj);
-            }
-            /* Lookup up the old group number */
-            ognr = cbuf[aj];
-            if (ognr != NOGID)
-            {
-                gmx_fatal(FARGS,"Atom %d in multiple %s groups (%d and %d)",
-                          aj+1,title,ognr+1,i+1);
-            }
-            else
-            {
-                /* Store the group number in buffer */
-                if (grptp == egrptpONE)
-                {
-                    cbuf[aj] = 0;
-                }
-                else
-                {
-                    cbuf[aj] = i;
-                }
-                ntot++;
-            }
-        }
-    }
-    
-    /* Now check whether we have done all atoms */
-    bRest = FALSE;
-    if (ntot != natoms)
-    {
-        if (grptp == egrptpALL)
-        {
-            gmx_fatal(FARGS,"%d atoms are not part of any of the %s groups",
-                      natoms-ntot,title);
-        }
-        else if (grptp == egrptpPART)
-        {
-            sprintf(warn_buf,"%d atoms are not part of any of the %s groups",
-                    natoms-ntot,title);
-            warning_note(wi,warn_buf);
-        }
-        /* Assign all atoms currently unassigned to a rest group */
-        for(j=0; (j<natoms); j++)
-        {
-            if (cbuf[j] == NOGID)
-            {
-                cbuf[j] = grps->nr;
-                bRest = TRUE;
-            }
-        }
-        if (grptp != egrptpPART)
-        {
-            if (bVerbose)
-            {
-                fprintf(stderr,
-                        "Making dummy/rest group for %s containing %d elements\n",
-                        title,natoms-ntot);
-            }
-            /* Add group name "rest" */ 
-            grps->nm_ind[grps->nr] = restnm;
-            
-            /* Assign the rest name to all atoms not currently assigned to a group */
-            for(j=0; (j<natoms); j++)
-            {
-                if (cbuf[j] == NOGID)
-                {
-                    cbuf[j] = grps->nr;
-                }
-            }
-            grps->nr++;
-        }
-    }
-    
-    if (grps->nr == 1)
-    {
-        groups->ngrpnr[gtype] = 0;
-        groups->grpnr[gtype]  = NULL;
-    }
-    else
-    {
-        groups->ngrpnr[gtype] = natoms;
-        snew(groups->grpnr[gtype],natoms);
-        for(j=0; (j<natoms); j++)
-        {
-            groups->grpnr[gtype][j] = cbuf[j];
-        }
-    }
-    
-    sfree(cbuf);
-
-    return (bRest && grptp == egrptpPART);
-}
-
-static void calc_nrdf(gmx_mtop_t *mtop,t_inputrec *ir,char **gnames)
-{
-  t_grpopts *opts;
-  gmx_groups_t *groups;
-  t_pull  *pull;
-  int     natoms,ai,aj,i,j,d,g,imin,jmin,nc;
-  t_iatom *ia;
-  int     *nrdf2,*na_vcm,na_tot;
-  double  *nrdf_tc,*nrdf_vcm,nrdf_uc,n_sub=0;
-  gmx_mtop_atomloop_all_t aloop;
-  t_atom  *atom;
-  int     mb,mol,ftype,as;
-  gmx_molblock_t *molb;
-  gmx_moltype_t *molt;
-
-  /* Calculate nrdf. 
-   * First calc 3xnr-atoms for each group
-   * then subtract half a degree of freedom for each constraint
-   *
-   * Only atoms and nuclei contribute to the degrees of freedom...
-   */
-
-  opts = &ir->opts;
-  
-  groups = &mtop->groups;
-  natoms = mtop->natoms;
-
-  /* Allocate one more for a possible rest group */
-  /* We need to sum degrees of freedom into doubles,
-   * since floats give too low nrdf's above 3 million atoms.
-   */
-  snew(nrdf_tc,groups->grps[egcTC].nr+1);
-  snew(nrdf_vcm,groups->grps[egcVCM].nr+1);
-  snew(na_vcm,groups->grps[egcVCM].nr+1);
-  
-  for(i=0; i<groups->grps[egcTC].nr; i++)
-    nrdf_tc[i] = 0;
-  for(i=0; i<groups->grps[egcVCM].nr+1; i++)
-    nrdf_vcm[i] = 0;
-
-  snew(nrdf2,natoms);
-  aloop = gmx_mtop_atomloop_all_init(mtop);
-  while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
-    nrdf2[i] = 0;
-    if (atom->ptype == eptAtom || atom->ptype == eptNucleus) {
-      g = ggrpnr(groups,egcFREEZE,i);
-      /* Double count nrdf for particle i */
-      for(d=0; d<DIM; d++) {
-       if (opts->nFreeze[g][d] == 0) {
-         nrdf2[i] += 2;
-       }
-      }
-      nrdf_tc [ggrpnr(groups,egcTC ,i)] += 0.5*nrdf2[i];
-      nrdf_vcm[ggrpnr(groups,egcVCM,i)] += 0.5*nrdf2[i];
-    }
-  }
-
-  as = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    molb = &mtop->molblock[mb];
-    molt = &mtop->moltype[molb->type];
-    atom = molt->atoms.atom;
-    for(mol=0; mol<molb->nmol; mol++) {
-      for (ftype=F_CONSTR; ftype<=F_CONSTRNC; ftype++) {
-       ia = molt->ilist[ftype].iatoms;
-       for(i=0; i<molt->ilist[ftype].nr; ) {
-         /* Subtract degrees of freedom for the constraints,
-          * if the particles still have degrees of freedom left.
-          * If one of the particles is a vsite or a shell, then all
-          * constraint motion will go there, but since they do not
-          * contribute to the constraints the degrees of freedom do not
-          * change.
-          */
-         ai = as + ia[1];
-         aj = as + ia[2];
-         if (((atom[ia[1]].ptype == eptNucleus) ||
-              (atom[ia[1]].ptype == eptAtom)) &&
-             ((atom[ia[2]].ptype == eptNucleus) ||
-              (atom[ia[2]].ptype == eptAtom))) {
-           if (nrdf2[ai] > 0) 
-             jmin = 1;
-           else
-             jmin = 2;
-           if (nrdf2[aj] > 0)
-             imin = 1;
-           else
-             imin = 2;
-           imin = min(imin,nrdf2[ai]);
-           jmin = min(jmin,nrdf2[aj]);
-           nrdf2[ai] -= imin;
-           nrdf2[aj] -= jmin;
-           nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
-           nrdf_tc [ggrpnr(groups,egcTC ,aj)] -= 0.5*jmin;
-           nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
-           nrdf_vcm[ggrpnr(groups,egcVCM,aj)] -= 0.5*jmin;
-         }
-         ia += interaction_function[ftype].nratoms+1;
-         i  += interaction_function[ftype].nratoms+1;
-       }
-      }
-      ia = molt->ilist[F_SETTLE].iatoms;
-      for(i=0; i<molt->ilist[F_SETTLE].nr; ) {
-       /* Subtract 1 dof from every atom in the SETTLE */
-       for(ai=as+ia[1]; ai<as+ia[1]+3; ai++) {
-         imin = min(2,nrdf2[ai]);
-         nrdf2[ai] -= imin;
-         nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
-         nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
-       }
-       ia += 2;
-       i  += 2;
-      }
-      as += molt->atoms.nr;
-    }
-  }
-
-  if (ir->ePull == epullCONSTRAINT) {
-    /* Correct nrdf for the COM constraints.
-     * We correct using the TC and VCM group of the first atom
-     * in the reference and pull group. If atoms in one pull group
-     * belong to different TC or VCM groups it is anyhow difficult
-     * to determine the optimal nrdf assignment.
-     */
-    pull = ir->pull;
-    if (pull->eGeom == epullgPOS) {
-      nc = 0;
-      for(i=0; i<DIM; i++) {
-       if (pull->dim[i])
-         nc++;
-      }
-    } else {
-      nc = 1;
-    }
-    for(i=0; i<pull->ngrp; i++) {
-      imin = 2*nc;
-      if (pull->grp[0].nat > 0) {
-       /* Subtract 1/2 dof from the reference group */
-       ai = pull->grp[0].ind[0];
-       if (nrdf_tc[ggrpnr(groups,egcTC,ai)] > 1) {
-         nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5;
-         nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5;
-         imin--;
-       }
-      }
-      /* Subtract 1/2 dof from the pulled group */
-      ai = pull->grp[1+i].ind[0];
-      nrdf_tc [ggrpnr(groups,egcTC ,ai)] -= 0.5*imin;
-      nrdf_vcm[ggrpnr(groups,egcVCM,ai)] -= 0.5*imin;
-      if (nrdf_tc[ggrpnr(groups,egcTC,ai)] < 0)
-       gmx_fatal(FARGS,"Center of mass pulling constraints caused the number of degrees of freedom for temperature coupling group %s to be negative",gnames[groups->grps[egcTC].nm_ind[ggrpnr(groups,egcTC,ai)]]);
-    }
-  }
-  
-  if (ir->nstcomm != 0) {
-    /* Subtract 3 from the number of degrees of freedom in each vcm group
-     * when com translation is removed and 6 when rotation is removed
-     * as well.
-     */
-    switch (ir->comm_mode) {
-    case ecmLINEAR:
-      n_sub = ndof_com(ir);
-      break;
-    case ecmANGULAR:
-      n_sub = 6;
-      break;
-    default:
-      n_sub = 0;
-      gmx_incons("Checking comm_mode");
-    }
-    
-    for(i=0; i<groups->grps[egcTC].nr; i++) {
-      /* Count the number of atoms of TC group i for every VCM group */
-      for(j=0; j<groups->grps[egcVCM].nr+1; j++)
-       na_vcm[j] = 0;
-      na_tot = 0;
-      for(ai=0; ai<natoms; ai++)
-       if (ggrpnr(groups,egcTC,ai) == i) {
-         na_vcm[ggrpnr(groups,egcVCM,ai)]++;
-         na_tot++;
-       }
-      /* Correct for VCM removal according to the fraction of each VCM
-       * group present in this TC group.
-       */
-      nrdf_uc = nrdf_tc[i];
-      if (debug) {
-       fprintf(debug,"T-group[%d] nrdf_uc = %g, n_sub = %g\n",
-               i,nrdf_uc,n_sub);
-      }
-      nrdf_tc[i] = 0;
-      for(j=0; j<groups->grps[egcVCM].nr+1; j++) {
-       if (nrdf_vcm[j] > n_sub) {
-         nrdf_tc[i] += nrdf_uc*((double)na_vcm[j]/(double)na_tot)*
-           (nrdf_vcm[j] - n_sub)/nrdf_vcm[j];
-       }
-       if (debug) {
-         fprintf(debug,"  nrdf_vcm[%d] = %g, nrdf = %g\n",
-                 j,nrdf_vcm[j],nrdf_tc[i]);
-       }
-      }
-    }
-  }
-  for(i=0; (i<groups->grps[egcTC].nr); i++) {
-    opts->nrdf[i] = nrdf_tc[i];
-    if (opts->nrdf[i] < 0)
-      opts->nrdf[i] = 0;
-    fprintf(stderr,
-           "Number of degrees of freedom in T-Coupling group %s is %.2f\n",
-           gnames[groups->grps[egcTC].nm_ind[i]],opts->nrdf[i]);
-  }
-  
-  sfree(nrdf2);
-  sfree(nrdf_tc);
-  sfree(nrdf_vcm);
-  sfree(na_vcm);
-}
-
-static void decode_cos(char *s,t_cosines *cosine,gmx_bool bTime)
-{
-  char   *t;
-  char   format[STRLEN],f1[STRLEN];
-  double a,phi;
-  int    i;
-  
-  t=strdup(s);
-  trim(t);
-  
-  cosine->n=0;
-  cosine->a=NULL;
-  cosine->phi=NULL;
-  if (strlen(t)) {
-    sscanf(t,"%d",&(cosine->n));
-    if (cosine->n <= 0) {
-      cosine->n=0;
-    } else {
-      snew(cosine->a,cosine->n);
-      snew(cosine->phi,cosine->n);
-      
-      sprintf(format,"%%*d");
-      for(i=0; (i<cosine->n); i++) {
-       strcpy(f1,format);
-       strcat(f1,"%lf%lf");
-       if (sscanf(t,f1,&a,&phi) < 2)
-         gmx_fatal(FARGS,"Invalid input for electric field shift: '%s'",t);
-       cosine->a[i]=a;
-       cosine->phi[i]=phi;
-       strcat(format,"%*lf%*lf");
-      }
-    }
-  }
-  sfree(t);
-}
-
-static gmx_bool do_egp_flag(t_inputrec *ir,gmx_groups_t *groups,
-                       const char *option,const char *val,int flag)
-{
-  /* The maximum number of energy group pairs would be MAXPTR*(MAXPTR+1)/2.
-   * But since this is much larger than STRLEN, such a line can not be parsed.
-   * The real maximum is the number of names that fit in a string: STRLEN/2.
-   */
-#define EGP_MAX (STRLEN/2)
-  int  nelem,i,j,k,nr;
-  char *names[EGP_MAX];
-  char ***gnames;
-  gmx_bool bSet;
-
-  gnames = groups->grpname;
-
-  nelem = str_nelem(val,EGP_MAX,names);
-  if (nelem % 2 != 0)
-    gmx_fatal(FARGS,"The number of groups for %s is odd",option);
-  nr = groups->grps[egcENER].nr;
-  bSet = FALSE;
-  for(i=0; i<nelem/2; i++) {
-    j = 0;
-    while ((j < nr) &&
-          gmx_strcasecmp(names[2*i],*(gnames[groups->grps[egcENER].nm_ind[j]])))
-      j++;
-    if (j == nr)
-      gmx_fatal(FARGS,"%s in %s is not an energy group\n",
-                 names[2*i],option);
-    k = 0;
-    while ((k < nr) &&
-          gmx_strcasecmp(names[2*i+1],*(gnames[groups->grps[egcENER].nm_ind[k]])))
-      k++;
-    if (k==nr)
-      gmx_fatal(FARGS,"%s in %s is not an energy group\n",
-             names[2*i+1],option);
-    if ((j < nr) && (k < nr)) {
-      ir->opts.egp_flags[nr*j+k] |= flag;
-      ir->opts.egp_flags[nr*k+j] |= flag;
-      bSet = TRUE;
-    }
-  }
-
-  return bSet;
-}
-
-void do_index(const char* mdparin, const char *ndx,
-              gmx_mtop_t *mtop,
-              gmx_bool bVerbose,
-              t_inputrec *ir,rvec *v,
-              warninp_t wi)
-{
-  t_blocka *grps;
-  gmx_groups_t *groups;
-  int     natoms;
-  t_symtab *symtab;
-  t_atoms atoms_all;
-  char    warnbuf[STRLEN],**gnames;
-  int     nr,ntcg,ntau_t,nref_t,nacc,nofg,nSA,nSA_points,nSA_time,nSA_temp;
-  real    tau_min;
-  int     nstcmin;
-  int     nacg,nfreeze,nfrdim,nenergy,nvcm,nuser;
-  char    *ptr1[MAXPTR],*ptr2[MAXPTR],*ptr3[MAXPTR];
-  int     i,j,k,restnm;
-  real    SAtime;
-  gmx_bool    bExcl,bTable,bSetTCpar,bAnneal,bRest;
-  int     nQMmethod,nQMbasis,nQMcharge,nQMmult,nbSH,nCASorb,nCASelec,
-    nSAon,nSAoff,nSAsteps,nQMg,nbOPT,nbTS;
-  char    warn_buf[STRLEN];
-
-  if (bVerbose)
-    fprintf(stderr,"processing index file...\n");
-  debug_gmx();
-  if (ndx == NULL) {
-    snew(grps,1);
-    snew(grps->index,1);
-    snew(gnames,1);
-    atoms_all = gmx_mtop_global_atoms(mtop);
-    analyse(&atoms_all,grps,&gnames,FALSE,TRUE);
-    free_t_atoms(&atoms_all,FALSE);
-  } else {
-    grps = init_index(ndx,&gnames);
-  }
-
-  groups = &mtop->groups;
-  natoms = mtop->natoms;
-  symtab = &mtop->symtab;
-
-  snew(groups->grpname,grps->nr+1);
-  
-  for(i=0; (i<grps->nr); i++) {
-    groups->grpname[i] = put_symtab(symtab,gnames[i]);
-  }
-  groups->grpname[i] = put_symtab(symtab,"rest");
-  restnm=i;
-  srenew(gnames,grps->nr+1);
-  gnames[restnm] = *(groups->grpname[i]);
-  groups->ngrpname = grps->nr+1;
-
-  set_warning_line(wi,mdparin,-1);
-
-  ntau_t = str_nelem(tau_t,MAXPTR,ptr1);
-  nref_t = str_nelem(ref_t,MAXPTR,ptr2);
-  ntcg   = str_nelem(tcgrps,MAXPTR,ptr3);
-  if ((ntau_t != ntcg) || (nref_t != ntcg)) {
-    gmx_fatal(FARGS,"Invalid T coupling input: %d groups, %d ref-t values and "
-                "%d tau-t values",ntcg,nref_t,ntau_t);
-  }
-
-  bSetTCpar = (ir->etc || EI_SD(ir->eI) || ir->eI==eiBD || EI_TPI(ir->eI));
-  do_numbering(natoms,groups,ntcg,ptr3,grps,gnames,egcTC,
-               restnm,bSetTCpar ? egrptpALL : egrptpALL_GENREST,bVerbose,wi);
-  nr = groups->grps[egcTC].nr;
-  ir->opts.ngtc = nr;
-  snew(ir->opts.nrdf,nr);
-  snew(ir->opts.tau_t,nr);
-  snew(ir->opts.ref_t,nr);
-  if (ir->eI==eiBD && ir->bd_fric==0) {
-    fprintf(stderr,"bd-fric=0, so tau-t will be used as the inverse friction constant(s)\n");
-  }
-
-  if (bSetTCpar)
-  {
-      if (nr != nref_t)
-      {
-          gmx_fatal(FARGS,"Not enough ref-t and tau-t values!");
-      }
-      
-      tau_min = 1e20;
-      for(i=0; (i<nr); i++)
-      {
-          ir->opts.tau_t[i] = strtod(ptr1[i],NULL);
-          if ((ir->eI == eiBD || ir->eI == eiSD2) && ir->opts.tau_t[i] <= 0)
-          {
-              sprintf(warn_buf,"With integrator %s tau-t should be larger than 0",ei_names[ir->eI]);
-              warning_error(wi,warn_buf);
-          }
-          if ((ir->etc == etcVRESCALE && ir->opts.tau_t[i] >= 0) || 
-              (ir->etc != etcVRESCALE && ir->opts.tau_t[i] >  0))
-          {
-              tau_min = min(tau_min,ir->opts.tau_t[i]);
-          }
-      }
-      if (ir->etc != etcNO && ir->nsttcouple == -1)
-      {
-            ir->nsttcouple = ir_optimal_nsttcouple(ir);
-      }
-      if (EI_VV(ir->eI)) 
-      {
-          if ((ir->epc==epcMTTK) && (ir->etc>etcNO))
-          {
-              int mincouple;
-              mincouple = ir->nsttcouple;
-              if (ir->nstpcouple < mincouple)
-              {
-                  mincouple = ir->nstpcouple;
-              }
-              ir->nstpcouple = mincouple;
-              ir->nsttcouple = mincouple;
-              warning_note(wi,"for current Trotter decomposition methods with vv, nsttcouple and nstpcouple must be equal.  Both have been reset to min(nsttcouple,nstpcouple)");
-          }
-      }
-      nstcmin = tcouple_min_integration_steps(ir->etc);
-      if (nstcmin > 1)
-      {
-          if (tau_min/(ir->delta_t*ir->nsttcouple) < nstcmin)
-          {
-              sprintf(warn_buf,"For proper integration of the %s thermostat, tau-t (%g) should be at least %d times larger than nsttcouple*dt (%g)",
-                      ETCOUPLTYPE(ir->etc),
-                      tau_min,nstcmin,
-                      ir->nsttcouple*ir->delta_t);
-              warning(wi,warn_buf);
-          }
-      }
-      for(i=0; (i<nr); i++)
-      {
-          ir->opts.ref_t[i] = strtod(ptr2[i],NULL);
-          if (ir->opts.ref_t[i] < 0)
-          {
-              gmx_fatal(FARGS,"ref-t for group %d negative",i);
-          }
-      }
-  }
-    
-  /* Simulated annealing for each group. There are nr groups */
-  nSA = str_nelem(anneal,MAXPTR,ptr1);
-  if (nSA == 1 && (ptr1[0][0]=='n' || ptr1[0][0]=='N'))
-     nSA = 0;
-  if(nSA>0 && nSA != nr) 
-    gmx_fatal(FARGS,"Not enough annealing values: %d (for %d groups)\n",nSA,nr);
-  else {
-    snew(ir->opts.annealing,nr);
-    snew(ir->opts.anneal_npoints,nr);
-    snew(ir->opts.anneal_time,nr);
-    snew(ir->opts.anneal_temp,nr);
-    for(i=0;i<nr;i++) {
-      ir->opts.annealing[i]=eannNO;
-      ir->opts.anneal_npoints[i]=0;
-      ir->opts.anneal_time[i]=NULL;
-      ir->opts.anneal_temp[i]=NULL;
-    }
-    if (nSA > 0) {
-      bAnneal=FALSE;
-      for(i=0;i<nr;i++) { 
-       if(ptr1[i][0]=='n' || ptr1[i][0]=='N') {
-         ir->opts.annealing[i]=eannNO;
-       } else if(ptr1[i][0]=='s'|| ptr1[i][0]=='S') {
-         ir->opts.annealing[i]=eannSINGLE;
-         bAnneal=TRUE;
-       } else if(ptr1[i][0]=='p'|| ptr1[i][0]=='P') {
-         ir->opts.annealing[i]=eannPERIODIC;
-         bAnneal=TRUE;
-       } 
-      } 
-      if(bAnneal) {
-       /* Read the other fields too */
-       nSA_points = str_nelem(anneal_npoints,MAXPTR,ptr1);
-       if(nSA_points!=nSA) 
-          gmx_fatal(FARGS,"Found %d annealing-npoints values for %d groups\n",nSA_points,nSA);
-       for(k=0,i=0;i<nr;i++) {
-         ir->opts.anneal_npoints[i]=strtol(ptr1[i],NULL,10);
-         if(ir->opts.anneal_npoints[i]==1)
-           gmx_fatal(FARGS,"Please specify at least a start and an end point for annealing\n");
-         snew(ir->opts.anneal_time[i],ir->opts.anneal_npoints[i]);
-         snew(ir->opts.anneal_temp[i],ir->opts.anneal_npoints[i]);
-         k += ir->opts.anneal_npoints[i];
-       }
-
-       nSA_time = str_nelem(anneal_time,MAXPTR,ptr1);
-       if(nSA_time!=k) 
-          gmx_fatal(FARGS,"Found %d annealing-time values, wanter %d\n",nSA_time,k);
-       nSA_temp = str_nelem(anneal_temp,MAXPTR,ptr2);
-       if(nSA_temp!=k) 
-          gmx_fatal(FARGS,"Found %d annealing-temp values, wanted %d\n",nSA_temp,k);
-
-       for(i=0,k=0;i<nr;i++) {
-         
-         for(j=0;j<ir->opts.anneal_npoints[i];j++) {
-           ir->opts.anneal_time[i][j]=strtod(ptr1[k],NULL);
-           ir->opts.anneal_temp[i][j]=strtod(ptr2[k],NULL);
-           if(j==0) {
-             if(ir->opts.anneal_time[i][0] > (ir->init_t+GMX_REAL_EPS))
-               gmx_fatal(FARGS,"First time point for annealing > init_t.\n");      
-           } else { 
-             /* j>0 */
-             if(ir->opts.anneal_time[i][j]<ir->opts.anneal_time[i][j-1])
-               gmx_fatal(FARGS,"Annealing timepoints out of order: t=%f comes after t=%f\n",
-                           ir->opts.anneal_time[i][j],ir->opts.anneal_time[i][j-1]);
-           }
-           if(ir->opts.anneal_temp[i][j]<0) 
-             gmx_fatal(FARGS,"Found negative temperature in annealing: %f\n",ir->opts.anneal_temp[i][j]);    
-           k++;
-         }
-       }
-       /* Print out some summary information, to make sure we got it right */
-       for(i=0,k=0;i<nr;i++) {
-         if(ir->opts.annealing[i]!=eannNO) {
-           j = groups->grps[egcTC].nm_ind[i];
-           fprintf(stderr,"Simulated annealing for group %s: %s, %d timepoints\n",
-                   *(groups->grpname[j]),eann_names[ir->opts.annealing[i]],
-                   ir->opts.anneal_npoints[i]);
-           fprintf(stderr,"Time (ps)   Temperature (K)\n");
-           /* All terms except the last one */
-           for(j=0;j<(ir->opts.anneal_npoints[i]-1);j++) 
-               fprintf(stderr,"%9.1f      %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
-           
-           /* Finally the last one */
-           j = ir->opts.anneal_npoints[i]-1;
-           if(ir->opts.annealing[i]==eannSINGLE)
-             fprintf(stderr,"%9.1f-     %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
-           else {
-             fprintf(stderr,"%9.1f      %5.1f\n",ir->opts.anneal_time[i][j],ir->opts.anneal_temp[i][j]);
-             if(fabs(ir->opts.anneal_temp[i][j]-ir->opts.anneal_temp[i][0])>GMX_REAL_EPS)
-               warning_note(wi,"There is a temperature jump when your annealing loops back.\n");
-           }
-         }
-       } 
-      }
-    }
-  }    
-
-  if (ir->ePull != epullNO) {
-    make_pull_groups(ir->pull,pull_grp,grps,gnames);
-  }
-
-  nacc = str_nelem(acc,MAXPTR,ptr1);
-  nacg = str_nelem(accgrps,MAXPTR,ptr2);
-  if (nacg*DIM != nacc)
-    gmx_fatal(FARGS,"Invalid Acceleration input: %d groups and %d acc. values",
-               nacg,nacc);
-  do_numbering(natoms,groups,nacg,ptr2,grps,gnames,egcACC,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  nr = groups->grps[egcACC].nr;
-  snew(ir->opts.acc,nr);
-  ir->opts.ngacc=nr;
-  
-  for(i=k=0; (i<nacg); i++)
-    for(j=0; (j<DIM); j++,k++)
-      ir->opts.acc[i][j]=strtod(ptr1[k],NULL);
-  for( ;(i<nr); i++)
-    for(j=0; (j<DIM); j++)
-      ir->opts.acc[i][j]=0;
-  
-  nfrdim  = str_nelem(frdim,MAXPTR,ptr1);
-  nfreeze = str_nelem(freeze,MAXPTR,ptr2);
-  if (nfrdim != DIM*nfreeze)
-    gmx_fatal(FARGS,"Invalid Freezing input: %d groups and %d freeze values",
-               nfreeze,nfrdim);
-  do_numbering(natoms,groups,nfreeze,ptr2,grps,gnames,egcFREEZE,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  nr = groups->grps[egcFREEZE].nr;
-  ir->opts.ngfrz=nr;
-  snew(ir->opts.nFreeze,nr);
-  for(i=k=0; (i<nfreeze); i++)
-    for(j=0; (j<DIM); j++,k++) {
-      ir->opts.nFreeze[i][j]=(gmx_strncasecmp(ptr1[k],"Y",1)==0);
-      if (!ir->opts.nFreeze[i][j]) {
-       if (gmx_strncasecmp(ptr1[k],"N",1) != 0) {
-         sprintf(warnbuf,"Please use Y(ES) or N(O) for freezedim only "
-                 "(not %s)", ptr1[k]);
-         warning(wi,warn_buf);
-       }
-      }
-    }
-  for( ; (i<nr); i++)
-    for(j=0; (j<DIM); j++)
-      ir->opts.nFreeze[i][j]=0;
-  
-  nenergy=str_nelem(energy,MAXPTR,ptr1);
-  do_numbering(natoms,groups,nenergy,ptr1,grps,gnames,egcENER,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  add_wall_energrps(groups,ir->nwall,symtab);
-  ir->opts.ngener = groups->grps[egcENER].nr;
-  nvcm=str_nelem(vcm,MAXPTR,ptr1);
-  bRest =
-    do_numbering(natoms,groups,nvcm,ptr1,grps,gnames,egcVCM,
-                 restnm,nvcm==0 ? egrptpALL_GENREST : egrptpPART,bVerbose,wi);
-  if (bRest) {
-    warning(wi,"Some atoms are not part of any center of mass motion removal group.\n"
-           "This may lead to artifacts.\n"
-           "In most cases one should use one group for the whole system.");
-  }
-
-  /* Now we have filled the freeze struct, so we can calculate NRDF */ 
-  calc_nrdf(mtop,ir,gnames);
-
-  if (v && NULL) {
-    real fac,ntot=0;
-    
-    /* Must check per group! */
-    for(i=0; (i<ir->opts.ngtc); i++) 
-      ntot += ir->opts.nrdf[i];
-    if (ntot != (DIM*natoms)) {
-      fac = sqrt(ntot/(DIM*natoms));
-      if (bVerbose)
-       fprintf(stderr,"Scaling velocities by a factor of %.3f to account for constraints\n"
-               "and removal of center of mass motion\n",fac);
-      for(i=0; (i<natoms); i++)
-       svmul(fac,v[i],v[i]);
-    }
-  }
-  
-  nuser=str_nelem(user1,MAXPTR,ptr1);
-  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcUser1,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  nuser=str_nelem(user2,MAXPTR,ptr1);
-  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcUser2,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  nuser=str_nelem(xtc_grps,MAXPTR,ptr1);
-  do_numbering(natoms,groups,nuser,ptr1,grps,gnames,egcXTC,
-               restnm,egrptpONE,bVerbose,wi);
-  nofg = str_nelem(orirefitgrp,MAXPTR,ptr1);
-  do_numbering(natoms,groups,nofg,ptr1,grps,gnames,egcORFIT,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-
-  /* QMMM input processing */
-  nQMg          = str_nelem(QMMM,MAXPTR,ptr1);
-  nQMmethod     = str_nelem(QMmethod,MAXPTR,ptr2);
-  nQMbasis      = str_nelem(QMbasis,MAXPTR,ptr3);
-  if((nQMmethod != nQMg)||(nQMbasis != nQMg)){
-    gmx_fatal(FARGS,"Invalid QMMM input: %d groups %d basissets"
-             " and %d methods\n",nQMg,nQMbasis,nQMmethod);
-  }
-  /* group rest, if any, is always MM! */
-  do_numbering(natoms,groups,nQMg,ptr1,grps,gnames,egcQMMM,
-               restnm,egrptpALL_GENREST,bVerbose,wi);
-  nr = nQMg; /*atoms->grps[egcQMMM].nr;*/
-  ir->opts.ngQM = nQMg;
-  snew(ir->opts.QMmethod,nr);
-  snew(ir->opts.QMbasis,nr);
-  for(i=0;i<nr;i++){
-    /* input consists of strings: RHF CASSCF PM3 .. These need to be
-     * converted to the corresponding enum in names.c
-     */
-    ir->opts.QMmethod[i] = search_QMstring(ptr2[i],eQMmethodNR,
-                                           eQMmethod_names);
-    ir->opts.QMbasis[i]  = search_QMstring(ptr3[i],eQMbasisNR,
-                                           eQMbasis_names);
-
-  }
-  nQMmult   = str_nelem(QMmult,MAXPTR,ptr1);
-  nQMcharge = str_nelem(QMcharge,MAXPTR,ptr2);
-  nbSH      = str_nelem(bSH,MAXPTR,ptr3);
-  snew(ir->opts.QMmult,nr);
-  snew(ir->opts.QMcharge,nr);
-  snew(ir->opts.bSH,nr);
-
-  for(i=0;i<nr;i++){
-    ir->opts.QMmult[i]   = strtol(ptr1[i],NULL,10);
-    ir->opts.QMcharge[i] = strtol(ptr2[i],NULL,10);
-    ir->opts.bSH[i]      = (gmx_strncasecmp(ptr3[i],"Y",1)==0);
-  }
-
-  nCASelec  = str_nelem(CASelectrons,MAXPTR,ptr1);
-  nCASorb   = str_nelem(CASorbitals,MAXPTR,ptr2);
-  snew(ir->opts.CASelectrons,nr);
-  snew(ir->opts.CASorbitals,nr);
-  for(i=0;i<nr;i++){
-    ir->opts.CASelectrons[i]= strtol(ptr1[i],NULL,10);
-    ir->opts.CASorbitals[i] = strtol(ptr2[i],NULL,10);
-  }
-  /* special optimization options */
-
-  nbOPT = str_nelem(bOPT,MAXPTR,ptr1);
-  nbTS = str_nelem(bTS,MAXPTR,ptr2);
-  snew(ir->opts.bOPT,nr);
-  snew(ir->opts.bTS,nr);
-  for(i=0;i<nr;i++){
-    ir->opts.bOPT[i] = (gmx_strncasecmp(ptr1[i],"Y",1)==0);
-    ir->opts.bTS[i]  = (gmx_strncasecmp(ptr2[i],"Y",1)==0);
-  }
-  nSAon     = str_nelem(SAon,MAXPTR,ptr1);
-  nSAoff    = str_nelem(SAoff,MAXPTR,ptr2);
-  nSAsteps  = str_nelem(SAsteps,MAXPTR,ptr3);
-  snew(ir->opts.SAon,nr);
-  snew(ir->opts.SAoff,nr);
-  snew(ir->opts.SAsteps,nr);
-
-  for(i=0;i<nr;i++){
-    ir->opts.SAon[i]    = strtod(ptr1[i],NULL);
-    ir->opts.SAoff[i]   = strtod(ptr2[i],NULL);
-    ir->opts.SAsteps[i] = strtol(ptr3[i],NULL,10);
-  }
-  /* end of QMMM input */
-
-  if (bVerbose)
-    for(i=0; (i<egcNR); i++) {
-      fprintf(stderr,"%-16s has %d element(s):",gtypes[i],groups->grps[i].nr); 
-      for(j=0; (j<groups->grps[i].nr); j++)
-       fprintf(stderr," %s",*(groups->grpname[groups->grps[i].nm_ind[j]]));
-      fprintf(stderr,"\n");
-    }
-
-  nr = groups->grps[egcENER].nr;
-  snew(ir->opts.egp_flags,nr*nr);
-
-  bExcl = do_egp_flag(ir,groups,"energygrp-excl",egpexcl,EGP_EXCL);
-  if (bExcl && EEL_FULL(ir->coulombtype))
-    warning(wi,"Can not exclude the lattice Coulomb energy between energy groups");
-
-  bTable = do_egp_flag(ir,groups,"energygrp-table",egptable,EGP_TABLE);
-  if (bTable && !(ir->vdwtype == evdwUSER) && 
-      !(ir->coulombtype == eelUSER) && !(ir->coulombtype == eelPMEUSER) &&
-      !(ir->coulombtype == eelPMEUSERSWITCH))
-    gmx_fatal(FARGS,"Can only have energy group pair tables in combination with user tables for VdW and/or Coulomb");
-
-  decode_cos(efield_x,&(ir->ex[XX]),FALSE);
-  decode_cos(efield_xt,&(ir->et[XX]),TRUE);
-  decode_cos(efield_y,&(ir->ex[YY]),FALSE);
-  decode_cos(efield_yt,&(ir->et[YY]),TRUE);
-  decode_cos(efield_z,&(ir->ex[ZZ]),FALSE);
-  decode_cos(efield_zt,&(ir->et[ZZ]),TRUE);
-  
-  for(i=0; (i<grps->nr); i++)
-    sfree(gnames[i]);
-  sfree(gnames);
-  done_blocka(grps);
-  sfree(grps);
-
-}
-
-
-
-static void check_disre(gmx_mtop_t *mtop)
-{
-  gmx_ffparams_t *ffparams;
-  t_functype *functype;
-  t_iparams  *ip;
-  int i,ndouble,ftype;
-  int label,old_label;
-  
-  if (gmx_mtop_ftype_count(mtop,F_DISRES) > 0) {
-    ffparams  = &mtop->ffparams;
-    functype  = ffparams->functype;
-    ip        = ffparams->iparams;
-    ndouble   = 0;
-    old_label = -1;
-    for(i=0; i<ffparams->ntypes; i++) {
-      ftype = functype[i];
-      if (ftype == F_DISRES) {
-       label = ip[i].disres.label;
-       if (label == old_label) {
-         fprintf(stderr,"Distance restraint index %d occurs twice\n",label);
-         ndouble++;
-       }
-       old_label = label;
-      }
-    }
-    if (ndouble>0)
-      gmx_fatal(FARGS,"Found %d double distance restraint indices,\n"
-               "probably the parameters for multiple pairs in one restraint "
-               "are not identical\n",ndouble);
-  }
-}
-
-static gmx_bool absolute_reference(t_inputrec *ir,gmx_mtop_t *sys,
-                                   gmx_bool posres_only,
-                                   ivec AbsRef)
-{
-    int d,g,i;
-    gmx_mtop_ilistloop_t iloop;
-    t_ilist *ilist;
-    int nmol;
-    t_iparams *pr;
-
-    clear_ivec(AbsRef);
-
-    if (!posres_only)
-    {
-        /* Check the COM */
-        for(d=0; d<DIM; d++)
-        {
-            AbsRef[d] = (d < ndof_com(ir) ? 0 : 1);
-        }
-        /* Check for freeze groups */
-        for(g=0; g<ir->opts.ngfrz; g++)
-        {
-            for(d=0; d<DIM; d++)
-            {
-                if (ir->opts.nFreeze[g][d] != 0)
-                {
-                    AbsRef[d] = 1;
-                }
-            }
-        }
-    }
-
-    /* Check for position restraints */
-    iloop = gmx_mtop_ilistloop_init(sys);
-    while (gmx_mtop_ilistloop_next(iloop,&ilist,&nmol))
-    {
-        if (nmol > 0 &&
-            (AbsRef[XX] == 0 || AbsRef[YY] == 0 || AbsRef[ZZ] == 0))
-        {
-            for(i=0; i<ilist[F_POSRES].nr; i+=2)
-            {
-                pr = &sys->ffparams.iparams[ilist[F_POSRES].iatoms[i]];
-                for(d=0; d<DIM; d++)
-                {
-                    if (pr->posres.fcA[d] != 0)
-                    {
-                        AbsRef[d] = 1;
-                    }
-                }
-            }
-        }
-    }
-
-    return (AbsRef[XX] != 0 && AbsRef[YY] != 0 && AbsRef[ZZ] != 0);
-}
-
-void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
-                  warninp_t wi)
-{
-  char err_buf[256];
-  int  i,m,g,nmol,npct;
-  gmx_bool bCharge,bAcc;
-  real gdt_max,*mgrp,mt;
-  rvec acc;
-  gmx_mtop_atomloop_block_t aloopb;
-  gmx_mtop_atomloop_all_t aloop;
-  t_atom *atom;
-  ivec AbsRef;
-  char warn_buf[STRLEN];
-
-  set_warning_line(wi,mdparin,-1);
-
-  if (EI_DYNAMICS(ir->eI) && !EI_SD(ir->eI) && ir->eI != eiBD &&
-      ir->comm_mode == ecmNO &&
-      !(absolute_reference(ir,sys,FALSE,AbsRef) || ir->nsteps <= 10)) {
-    warning(wi,"You are not using center of mass motion removal (mdp option comm-mode), numerical rounding errors can lead to build up of kinetic energy of the center of mass");
-  }
-
-    /* Check for pressure coupling with absolute position restraints */
-    if (ir->epc != epcNO && ir->refcoord_scaling == erscNO)
-    {
-        absolute_reference(ir,sys,TRUE,AbsRef);
-        {
-            for(m=0; m<DIM; m++)
-            {
-                if (AbsRef[m] && norm2(ir->compress[m]) > 0)
-                {
-                    warning(wi,"You are using pressure coupling with absolute position restraints, this will give artifacts. Use the refcoord_scaling option.");
-                    break;
-                }
-            }
-        }
-    }
-
-  bCharge = FALSE;
-  aloopb = gmx_mtop_atomloop_block_init(sys);
-  while (gmx_mtop_atomloop_block_next(aloopb,&atom,&nmol)) {
-    if (atom->q != 0 || atom->qB != 0) {
-      bCharge = TRUE;
-    }
-  }
-  
-  if (!bCharge) {
-    if (EEL_FULL(ir->coulombtype)) {
-      sprintf(err_buf,
-             "You are using full electrostatics treatment %s for a system without charges.\n"
-             "This costs a lot of performance for just processing zeros, consider using %s instead.\n",
-             EELTYPE(ir->coulombtype),EELTYPE(eelCUT));
-      warning(wi,err_buf);
-    }
-  } else {
-    if (ir->coulombtype == eelCUT && ir->rcoulomb > 0 && !ir->implicit_solvent) {
-      sprintf(err_buf,
-             "You are using a plain Coulomb cut-off, which might produce artifacts.\n"
-             "You might want to consider using %s electrostatics.\n",
-             EELTYPE(eelPME));
-      warning_note(wi,err_buf);
-    }
-  }
-
-  /* Generalized reaction field */  
-  if (ir->opts.ngtc == 0) {
-    sprintf(err_buf,"No temperature coupling while using coulombtype %s",
-           eel_names[eelGRF]);
-    CHECK(ir->coulombtype == eelGRF);
-  }
-  else {
-    sprintf(err_buf,"When using coulombtype = %s"
-           " ref_t for temperature coupling should be > 0",
-           eel_names[eelGRF]);
-    CHECK((ir->coulombtype == eelGRF) && (ir->opts.ref_t[0] <= 0));
-  }
-    
-  if (ir->eI == eiSD1) {
-    gdt_max = 0;
-    for(i=0; (i<ir->opts.ngtc); i++)
-      gdt_max = max(gdt_max,ir->delta_t/ir->opts.tau_t[i]);
-    if (0.5*gdt_max > 0.0015) {
-      sprintf(warn_buf,"The relative error with integrator %s is 0.5*delta-t/tau-t = %g, you might want to switch to integrator %s\n",
-             ei_names[ir->eI],0.5*gdt_max,ei_names[eiSD2]);
-      warning_note(wi,warn_buf);
-    }
-  }
-
-  bAcc = FALSE;
-  for(i=0; (i<sys->groups.grps[egcACC].nr); i++) {
-    for(m=0; (m<DIM); m++) {
-      if (fabs(ir->opts.acc[i][m]) > 1e-6) {
-       bAcc = TRUE;
-      }
-    }
-  }
-  if (bAcc) {
-    clear_rvec(acc);
-    snew(mgrp,sys->groups.grps[egcACC].nr);
-    aloop = gmx_mtop_atomloop_all_init(sys);
-    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
-      mgrp[ggrpnr(&sys->groups,egcACC,i)] += atom->m;
-    }
-    mt = 0.0;
-    for(i=0; (i<sys->groups.grps[egcACC].nr); i++) {
-      for(m=0; (m<DIM); m++)
-       acc[m] += ir->opts.acc[i][m]*mgrp[i];
-      mt += mgrp[i];
-    }
-    for(m=0; (m<DIM); m++) {
-      if (fabs(acc[m]) > 1e-6) {
-       const char *dim[DIM] = { "X", "Y", "Z" };
-       fprintf(stderr,
-               "Net Acceleration in %s direction, will %s be corrected\n",
-               dim[m],ir->nstcomm != 0 ? "" : "not");
-       if (ir->nstcomm != 0 && m < ndof_com(ir)) {
-         acc[m] /= mt;
-         for (i=0; (i<sys->groups.grps[egcACC].nr); i++)
-           ir->opts.acc[i][m] -= acc[m];
-       }
-      }
-    }
-    sfree(mgrp);
-  }
-
-  if (ir->efep != efepNO && ir->sc_alpha != 0 &&
-      !gmx_within_tol(sys->ffparams.reppow,12.0,10*GMX_DOUBLE_EPS)) {
-    gmx_fatal(FARGS,"Soft-core interactions are only supported with VdW repulsion power 12");
-  }
-
-  if (ir->ePull != epullNO) {
-    if (ir->pull->grp[0].nat == 0) {
-        absolute_reference(ir,sys,FALSE,AbsRef);
-      for(m=0; m<DIM; m++) {
-       if (ir->pull->dim[m] && !AbsRef[m]) {
-         warning(wi,"You are using an absolute reference for pulling, but the rest of the system does not have an absolute reference. This will lead to artifacts.");
-         break;
-       }
-      }
-    }
-
-    if (ir->pull->eGeom == epullgDIRPBC) {
-      for(i=0; i<3; i++) {
-       for(m=0; m<=i; m++) {
-         if ((ir->epc != epcNO && ir->compress[i][m] != 0) ||
-             ir->deform[i][m] != 0) {
-           for(g=1; g<ir->pull->ngrp; g++) {
-             if (ir->pull->grp[g].vec[m] != 0) {
-               gmx_fatal(FARGS,"Can not have dynamic box while using pull geometry '%s' (dim %c)",EPULLGEOM(ir->pull->eGeom),'x'+m);
-             }
-           }
-         }
-       }
-      }
-    }
-  }
-
-  check_disre(sys);
-}
-
-void double_check(t_inputrec *ir,matrix box,gmx_bool bConstr,warninp_t wi)
-{
-  real min_size;
-  gmx_bool bTWIN;
-  char warn_buf[STRLEN];
-  const char *ptr;
-  
-  ptr = check_box(ir->ePBC,box);
-  if (ptr) {
-      warning_error(wi,ptr);
-  }  
-
-  if (bConstr && ir->eConstrAlg == econtSHAKE) {
-    if (ir->shake_tol <= 0.0) {
-      sprintf(warn_buf,"ERROR: shake-tol must be > 0 instead of %g\n",
-              ir->shake_tol);
-      warning_error(wi,warn_buf);
-    }
-
-    if (IR_TWINRANGE(*ir) && ir->nstlist > 1) {
-      sprintf(warn_buf,"With twin-range cut-off's and SHAKE the virial and the pressure are incorrect.");
-      if (ir->epc == epcNO) {
-       warning(wi,warn_buf);
-      } else {
-          warning_error(wi,warn_buf);
-      }
-    }
-  }
-
-  if( (ir->eConstrAlg == econtLINCS) && bConstr) {
-    /* If we have Lincs constraints: */
-    if(ir->eI==eiMD && ir->etc==etcNO &&
-       ir->eConstrAlg==econtLINCS && ir->nLincsIter==1) {
-      sprintf(warn_buf,"For energy conservation with LINCS, lincs_iter should be 2 or larger.\n");
-      warning_note(wi,warn_buf);
-    }
-    
-    if ((ir->eI == eiCG || ir->eI == eiLBFGS) && (ir->nProjOrder<8)) {
-      sprintf(warn_buf,"For accurate %s with LINCS constraints, lincs-order should be 8 or more.",ei_names[ir->eI]);
-      warning_note(wi,warn_buf);
-    }
-    if (ir->epc==epcMTTK) {
-        warning_error(wi,"MTTK not compatible with lincs -- use shake instead.");
-    }
-  }
-
-  if (ir->LincsWarnAngle > 90.0) {
-    sprintf(warn_buf,"lincs-warnangle can not be larger than 90 degrees, setting it to 90.\n");
-    warning(wi,warn_buf);
-    ir->LincsWarnAngle = 90.0;
-  }
-
-  if (ir->ePBC != epbcNONE) {
-    if (ir->nstlist == 0) {
-      warning(wi,"With nstlist=0 atoms are only put into the box at step 0, therefore drifting atoms might cause the simulation to crash.");
-    }
-    bTWIN = (ir->rlistlong > ir->rlist);
-    if (ir->ns_type == ensGRID) {
-      if (sqr(ir->rlistlong) >= max_cutoff2(ir->ePBC,box)) {
-          sprintf(warn_buf,"ERROR: The cut-off length is longer than half the shortest box vector or longer than the smallest box diagonal element. Increase the box size or decrease %s.\n",
-               bTWIN ? (ir->rcoulomb==ir->rlistlong ? "rcoulomb" : "rvdw"):"rlist");
-          warning_error(wi,warn_buf);
-      }
-    } else {
-      min_size = min(box[XX][XX],min(box[YY][YY],box[ZZ][ZZ]));
-      if (2*ir->rlistlong >= min_size) {
-          sprintf(warn_buf,"ERROR: One of the box lengths is smaller than twice the cut-off length. Increase the box size or decrease rlist.");
-          warning_error(wi,warn_buf);
-       if (TRICLINIC(box))
-         fprintf(stderr,"Grid search might allow larger cut-off's than simple search with triclinic boxes.");
-      }
-    }
-  }
-}
-
-void check_chargegroup_radii(const gmx_mtop_t *mtop,const t_inputrec *ir,
-                             rvec *x,
-                             warninp_t wi)
-{
-    real rvdw1,rvdw2,rcoul1,rcoul2;
-    char warn_buf[STRLEN];
-
-    calc_chargegroup_radii(mtop,x,&rvdw1,&rvdw2,&rcoul1,&rcoul2);
-
-    if (rvdw1 > 0)
-    {
-        printf("Largest charge group radii for Van der Waals: %5.3f, %5.3f nm\n",
-               rvdw1,rvdw2);
-    }
-    if (rcoul1 > 0)
-    {
-        printf("Largest charge group radii for Coulomb:       %5.3f, %5.3f nm\n",
-               rcoul1,rcoul2);
-    }
-
-    if (ir->rlist > 0)
-    {
-        if (rvdw1  + rvdw2  > ir->rlist ||
-            rcoul1 + rcoul2 > ir->rlist)
-        {
-            sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than rlist (%f)\n",max(rvdw1+rvdw2,rcoul1+rcoul2),ir->rlist);
-            warning(wi,warn_buf);
-        }
-        else
-        {
-            /* Here we do not use the zero at cut-off macro,
-             * since user defined interactions might purposely
-             * not be zero at the cut-off.
-             */
-            if (EVDW_IS_ZERO_AT_CUTOFF(ir->vdwtype) &&
-                rvdw1 + rvdw2 > ir->rlist - ir->rvdw)
-            {
-                sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than rlist (%f) - rvdw (%f)\n",
-                        rvdw1+rvdw2,
-                        ir->rlist,ir->rvdw);
-                if (ir_NVE(ir))
-                {
-                    warning(wi,warn_buf);
-                }
-                else
-                {
-                    warning_note(wi,warn_buf);
-                }
-            }
-            if (EEL_IS_ZERO_AT_CUTOFF(ir->coulombtype) &&
-                rcoul1 + rcoul2 > ir->rlistlong - ir->rcoulomb)
-            {
-                sprintf(warn_buf,"The sum of the two largest charge group radii (%f) is larger than %s (%f) - rcoulomb (%f)\n",
-                        rcoul1+rcoul2,
-                        ir->rlistlong > ir->rlist ? "rlistlong" : "rlist",
-                        ir->rlistlong,ir->rcoulomb);
-                if (ir_NVE(ir))
-                {
-                    warning(wi,warn_buf);
-                }
-                else
-                {
-                    warning_note(wi,warn_buf);
-                }
-            }
-        }
-    }
-}
diff --git a/src/kernel/readir.h b/src/kernel/readir.h
deleted file mode 100644 (file)
index d9a18e4..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-#ifndef _readir_h
-#define _readir_h
-
-#include "typedefs.h"
-#include "string2.h"
-#include "readinp.h"
-#include "grompp.h"
-
-enum { eshNONE, eshHBONDS, eshALLBONDS, eshHANGLES, eshALLANGLES, eshNR };
-
-static const char *constraints[eshNR+1]    = { 
-  "none", "h-bonds", "all-bonds", "h-angles", "all-angles", NULL 
-};
-
-enum { ecouplamVDWQ, ecouplamVDW, ecouplamQ, ecouplamNONE, ecouplamNR };
-
-static const char *couple_lam[ecouplamNR+1]    = { 
-  "vdw-q", "vdw", "q", "none", NULL 
-};
-
-typedef struct {
-  int warnings;
-  int nshake;
-  real fourierspacing;
-  char *include;
-  char *define;
-  gmx_bool bGenVel;
-  gmx_bool bGenPairs;
-  real tempi;
-  int  seed;
-  gmx_bool bOrire;
-  gmx_bool bDihre;
-  gmx_bool bMorse;
-  char *wall_atomtype[2];
-  gmx_bool pull_start;
-  char *couple_moltype;
-  int  couple_lam0;
-  int  couple_lam1;
-  gmx_bool bCoupleIntra;
-} t_gromppopts;
-
-
-extern void init_ir(t_inputrec *ir, t_gromppopts *opts);
-/* Initiate stuff */
-
-extern void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
-                    warninp_t wi);
-/* Validate inputrec data.
- * Fatal errors will be added to nerror.
- */
-extern int search_string(char *s,int ng,char *gn[]);
-/* Returns the index of string s in the index groups */
-
-extern void double_check(t_inputrec *ir,matrix box,gmx_bool bConstr,
-                        warninp_t wi);
-/* Do more checks */
-
-extern void triple_check(const char *mdparin,t_inputrec *ir,gmx_mtop_t *sys,
-                        warninp_t wi);
-/* Do even more checks */
-
-extern void check_chargegroup_radii(const gmx_mtop_t *mtop,const t_inputrec *ir,
-                                   rvec *x,
-                                   warninp_t wi);
-/* Even more checks, charge group radii vs. cut-off's only. */
-
-extern void get_ir(const char *mdparin,const char *mdparout,
-                  t_inputrec *ir,t_gromppopts *opts,
-                  warninp_t wi);
-/* Read the input file, and retrieve data for inputrec.
- * More data are read, but the are only evaluated when the next
- * function is called. Also prints the input file back to mdparout.
- */
-extern void do_index(const char* mdparin, 
-                    const char *ndx,
-                    gmx_mtop_t *mtop,
-                    gmx_bool bVerbose,
-                    t_inputrec *ir,
-                    rvec *v,
-                    warninp_t wi);
-/* Read the index file and assign grp numbers to atoms.
- * If v is not NULL, the velocities will be scaled to the correct number
- * of degrees of freedom.
- */
-
-/* Routines In readpull.c */
-
-extern char **read_pullparams(int *ninp_p,t_inpfile **inp,
-                             t_pull *pull,gmx_bool *bStart,
-                             warninp_t wi);
-/* Reads the pull parameters, returns a list of the pull group names */
-
-extern void make_pull_groups(t_pull *pull,char **pgnames,
-                            t_blocka *grps,char **gnames);
-/* Process the pull parameters after reading the index groups */
-
-extern void set_pull_init(t_inputrec *ir,gmx_mtop_t *mtop,rvec *x,matrix box,
-                         const output_env_t oenv, gmx_bool bStart);
-/* Prints the initial pull group distances in x.
- * If bStart adds the distance to the initial reference location.
- */
-
-#endif /* _readir_h */
diff --git a/src/kernel/runner.c b/src/kernel/runner.c
deleted file mode 100644 (file)
index 0db72cb..0000000
+++ /dev/null
@@ -1,882 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <signal.h>
-#include <stdlib.h>
-
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-/* _isnan() */
-#include <float.h>
-#endif
-
-#include "typedefs.h"
-#include "smalloc.h"
-#include "sysstuff.h"
-#include "statutil.h"
-#include "mdrun.h"
-#include "network.h"
-#include "pull.h"
-#include "names.h"
-#include "disre.h"
-#include "orires.h"
-#include "dihre.h"
-#include "pppm.h"
-#include "pme.h"
-#include "mdatoms.h"
-#include "repl_ex.h"
-#include "qmmm.h"
-#include "mpelogging.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "coulomb.h"
-#include "constr.h"
-#include "mvdata.h"
-#include "checkpoint.h"
-#include "mtop_util.h"
-#include "sighandler.h"
-#include "tpxio.h"
-#include "txtdump.h"
-
-#include "md_openmm.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#ifdef GMX_FAHCORE
-#include "corewrap.h"
-#endif
-
-#ifdef GMX_OPENMM
-#include "md_openmm.h"
-#endif
-
-
-typedef struct { 
-    gmx_integrator_t *func;
-} gmx_intp_t;
-
-/* The array should match the eI array in include/types/enums.h */
-#ifdef GMX_OPENMM  /* FIXME do_md_openmm needs fixing */
-const gmx_intp_t integrator[eiNR] = { {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm},{do_md_openmm}};
-#else
-const gmx_intp_t integrator[eiNR] = { {do_md}, {do_steep}, {do_cg}, {do_md}, {do_md}, {do_nm}, {do_lbfgs}, {do_tpi}, {do_tpi}, {do_md}, {do_md},{do_md}};
-#endif
-
-gmx_large_int_t     deform_init_init_step_tpx;
-matrix              deform_init_box_tpx;
-#ifdef GMX_THREADS
-tMPI_Thread_mutex_t deform_init_box_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-#endif
-
-
-#ifdef GMX_THREADS
-struct mdrunner_arglist
-{
-    FILE *fplog;
-    t_commrec *cr;
-    int nfile;
-    const t_filenm *fnm;
-    output_env_t oenv;
-    gmx_bool bVerbose;
-    gmx_bool bCompact;
-    int nstglobalcomm;
-    ivec ddxyz;
-    int dd_node_order;
-    real rdd;
-    real rconstr;
-    const char *dddlb_opt;
-    real dlb_scale;
-    const char *ddcsx;
-    const char *ddcsy;
-    const char *ddcsz;
-    int nstepout;
-    int resetstep;
-    int nmultisim;
-    int repl_ex_nst;
-    int repl_ex_seed;
-    real pforce;
-    real cpt_period;
-    real max_hours;
-    const char *deviceOptions;
-    unsigned long Flags;
-    int ret; /* return value */
-};
-
-
-/* The function used for spawning threads. Extracts the mdrunner() 
-   arguments from its one argument and calls mdrunner(), after making
-   a commrec. */
-static void mdrunner_start_fn(void *arg)
-{
-    struct mdrunner_arglist *mda=(struct mdrunner_arglist*)arg;
-    struct mdrunner_arglist mc=*mda; /* copy the arg list to make sure 
-                                        that it's thread-local. This doesn't
-                                        copy pointed-to items, of course,
-                                        but those are all const. */
-    t_commrec *cr;  /* we need a local version of this */
-    FILE *fplog=NULL;
-    t_filenm *fnm;
-
-    fnm = dup_tfn(mc.nfile, mc.fnm);
-
-    cr = init_par_threads(mc.cr);
-
-    if (MASTER(cr))
-    {
-        fplog=mc.fplog;
-    }
-
-    mda->ret=mdrunner(cr->nnodes, fplog, cr, mc.nfile, fnm, mc.oenv, 
-                      mc.bVerbose, mc.bCompact, mc.nstglobalcomm, 
-                      mc.ddxyz, mc.dd_node_order, mc.rdd,
-                      mc.rconstr, mc.dddlb_opt, mc.dlb_scale, 
-                      mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, 
-                      mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce, 
-                      mc.cpt_period, mc.max_hours, mc.deviceOptions, mc.Flags);
-}
-
-/* called by mdrunner() to start a specific number of threads (including 
-   the main thread) for thread-parallel runs. This in turn calls mdrunner()
-   for each thread. 
-   All options besides nthreads are the same as for mdrunner(). */
-static t_commrec *mdrunner_start_threads(int nthreads, 
-              FILE *fplog,t_commrec *cr,int nfile, 
-              const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
-              gmx_bool bCompact, int nstglobalcomm,
-              ivec ddxyz,int dd_node_order,real rdd,real rconstr,
-              const char *dddlb_opt,real dlb_scale,
-              const char *ddcsx,const char *ddcsy,const char *ddcsz,
-              int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
-              int repl_ex_seed, real pforce,real cpt_period, real max_hours, 
-              const char *deviceOptions, unsigned long Flags)
-{
-    int ret;
-    struct mdrunner_arglist *mda;
-    t_commrec *crn; /* the new commrec */
-    t_filenm *fnmn;
-
-    /* first check whether we even need to start tMPI */
-    if (nthreads<2)
-        return cr;
-
-    /* a few small, one-time, almost unavoidable memory leaks: */
-    snew(mda,1);
-    fnmn=dup_tfn(nfile, fnm);
-
-    /* fill the data structure to pass as void pointer to thread start fn */
-    mda->fplog=fplog;
-    mda->cr=cr;
-    mda->nfile=nfile;
-    mda->fnm=fnmn;
-    mda->oenv=oenv;
-    mda->bVerbose=bVerbose;
-    mda->bCompact=bCompact;
-    mda->nstglobalcomm=nstglobalcomm;
-    mda->ddxyz[XX]=ddxyz[XX];
-    mda->ddxyz[YY]=ddxyz[YY];
-    mda->ddxyz[ZZ]=ddxyz[ZZ];
-    mda->dd_node_order=dd_node_order;
-    mda->rdd=rdd;
-    mda->rconstr=rconstr;
-    mda->dddlb_opt=dddlb_opt;
-    mda->dlb_scale=dlb_scale;
-    mda->ddcsx=ddcsx;
-    mda->ddcsy=ddcsy;
-    mda->ddcsz=ddcsz;
-    mda->nstepout=nstepout;
-    mda->resetstep=resetstep;
-    mda->nmultisim=nmultisim;
-    mda->repl_ex_nst=repl_ex_nst;
-    mda->repl_ex_seed=repl_ex_seed;
-    mda->pforce=pforce;
-    mda->cpt_period=cpt_period;
-    mda->max_hours=max_hours;
-    mda->deviceOptions=deviceOptions;
-    mda->Flags=Flags;
-
-    fprintf(stderr, "Starting %d threads\n",nthreads);
-    fflush(stderr);
-    /* now spawn new threads that start mdrunner_start_fn(), while 
-       the main thread returns */
-    ret=tMPI_Init_fn(TRUE, nthreads, mdrunner_start_fn, (void*)(mda) );
-    if (ret!=TMPI_SUCCESS)
-        return NULL;
-
-    /* make a new comm_rec to reflect the new situation */
-    crn=init_par_threads(cr);
-    return crn;
-}
-
-
-/* get the number of threads based on how many there were requested, 
-   which algorithms we're using, and how many particles there are. */
-static int get_nthreads(int nthreads_requested, t_inputrec *inputrec,
-                        gmx_mtop_t *mtop)
-{
-    int nthreads,nthreads_new;
-    int min_atoms_per_thread;
-    char *env;
-
-    nthreads = nthreads_requested;
-
-    /* determine # of hardware threads. */
-    if (nthreads_requested < 1)
-    {
-        if ((env = getenv("GMX_MAX_THREADS")) != NULL)
-        {
-            nthreads = 0;
-            sscanf(env,"%d",&nthreads);
-            if (nthreads < 1)
-            {
-                gmx_fatal(FARGS,"GMX_MAX_THREADS (%d) should be larger than 0",
-                          nthreads);
-            }
-        }
-        else
-        {
-            nthreads = tMPI_Thread_get_hw_number();
-        }
-    }
-
-    if (inputrec->eI == eiNM || EI_TPI(inputrec->eI))
-    {
-        /* Steps are divided over the nodes iso splitting the atoms */
-        min_atoms_per_thread = 0;
-    }
-    else
-    {
-        min_atoms_per_thread = MIN_ATOMS_PER_THREAD;
-    }
-
-    /* Check if an algorithm does not support parallel simulation.  */
-    if (nthreads != 1 && 
-        ( inputrec->eI == eiLBFGS ||
-          inputrec->coulombtype == eelEWALD ) )
-    {
-        fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs. Not starting any threads.\n");
-        nthreads = 1;
-    }
-    else if (nthreads_requested < 1 &&
-             mtop->natoms/nthreads < min_atoms_per_thread)
-    {
-        /* the thread number was chosen automatically, but there are too many
-           threads (too few atoms per thread) */
-        nthreads_new = max(1,mtop->natoms/min_atoms_per_thread);
-
-        if (nthreads_new > 8 || (nthreads == 8 && nthreads_new > 4))
-        {
-            /* Use only multiples of 4 above 8 threads
-             * or with an 8-core processor
-             * (to avoid 6 threads on 8 core processors with 4 real cores).
-             */
-            nthreads_new = (nthreads_new/4)*4;
-        }
-        else if (nthreads_new > 4)
-        {
-            /* Avoid 5 or 7 threads */
-            nthreads_new = (nthreads_new/2)*2;
-        }
-
-        nthreads = nthreads_new;
-
-        fprintf(stderr,"\n");
-        fprintf(stderr,"NOTE: Parallelization is limited by the small number of atoms,\n");
-        fprintf(stderr,"      only starting %d threads.\n",nthreads);
-        fprintf(stderr,"      You can use the -nt option to optimize the number of threads.\n\n");
-    }
-    return nthreads;
-}
-#endif
-
-
-int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
-             const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
-             gmx_bool bCompact, int nstglobalcomm,
-             ivec ddxyz,int dd_node_order,real rdd,real rconstr,
-             const char *dddlb_opt,real dlb_scale,
-             const char *ddcsx,const char *ddcsy,const char *ddcsz,
-             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
-             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
-             const char *deviceOptions, unsigned long Flags)
-{
-    double     nodetime=0,realtime;
-    t_inputrec *inputrec;
-    t_state    *state=NULL;
-    matrix     box;
-    gmx_ddbox_t ddbox={0};
-    int        npme_major,npme_minor;
-    real       tmpr1,tmpr2;
-    t_nrnb     *nrnb;
-    gmx_mtop_t *mtop=NULL;
-    t_mdatoms  *mdatoms=NULL;
-    t_forcerec *fr=NULL;
-    t_fcdata   *fcd=NULL;
-    real       ewaldcoeff=0;
-    gmx_pme_t  *pmedata=NULL;
-    gmx_vsite_t *vsite=NULL;
-    gmx_constr_t constr;
-    int        i,m,nChargePerturbed=-1,status,nalloc;
-    char       *gro;
-    gmx_wallcycle_t wcycle;
-    gmx_bool       bReadRNG,bReadEkin;
-    int        list;
-    gmx_runtime_t runtime;
-    int        rc;
-    gmx_large_int_t reset_counters;
-    gmx_edsam_t ed=NULL;
-    t_commrec   *cr_old=cr; 
-    int         nthreads=1;
-
-    /* CAUTION: threads may be started later on in this function, so
-       cr doesn't reflect the final parallel state right now */
-    snew(inputrec,1);
-    snew(mtop,1);
-
-    if (bVerbose && SIMMASTER(cr))
-    {
-        fprintf(stderr,"Getting Loaded...\n");
-    }
-    
-    if (Flags & MD_APPENDFILES) 
-    {
-        fplog = NULL;
-    }
-
-    snew(state,1);
-    if (MASTER(cr)) 
-    {
-        /* Read (nearly) all data required for the simulation */
-        read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
-
-        /* NOW the threads will be started: */
-#ifdef GMX_THREADS
-        nthreads = get_nthreads(nthreads_requested, inputrec, mtop);
-
-        if (nthreads > 1)
-        {
-            /* now start the threads. */
-            cr=mdrunner_start_threads(nthreads, fplog, cr_old, nfile, fnm, 
-                                      oenv, bVerbose, bCompact, nstglobalcomm, 
-                                      ddxyz, dd_node_order, rdd, rconstr, 
-                                      dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz,
-                                      nstepout, resetstep, nmultisim, 
-                                      repl_ex_nst, repl_ex_seed, pforce, 
-                                      cpt_period, max_hours, deviceOptions, 
-                                      Flags);
-            /* the main thread continues here with a new cr. We don't deallocate
-               the old cr because other threads may still be reading it. */
-            if (cr == NULL)
-            {
-                gmx_comm("Failed to spawn threads");
-            }
-        }
-#endif
-    }
-    /* END OF CAUTION: cr is now reliable */
-
-    if (PAR(cr))
-    {
-        /* now broadcast everything to the non-master nodes/threads: */
-        init_parallel(fplog, cr, inputrec, mtop);
-    }
-    if (fplog != NULL)
-    {
-        pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
-    }
-
-    /* now make sure the state is initialized and propagated */
-    set_state_entries(state,inputrec,cr->nnodes);
-
-    /* A parallel command line option consistency check that we can
-       only do after any threads have started. */
-    if (!PAR(cr) &&
-        (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
-    {
-        gmx_fatal(FARGS,
-                  "The -dd or -npme option request a parallel simulation, "
-#ifndef GMX_MPI
-                  "but mdrun was compiled without threads or MPI enabled"
-#else
-#ifdef GMX_THREADS
-                  "but the number of threads (option -nt) is 1"
-#else
-                  "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec" 
-#endif
-#endif
-            );
-    }
-
-    if ((Flags & MD_RERUN) &&
-        (EI_ENERGY_MINIMIZATION(inputrec->eI) || eiNM == inputrec->eI))
-    {
-        gmx_fatal(FARGS, "The .mdp file specified an energy mininization or normal mode algorithm, and these are not compatible with mdrun -rerun");
-    }
-
-    if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
-    {
-        /* All-vs-all loops do not work with domain decomposition */
-        Flags |= MD_PARTDEC;
-    }
-
-    if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
-    {
-        cr->npmenodes = 0;
-    }
-
-#ifdef GMX_FAHCORE
-    fcRegisterSteps(inputrec->nsteps,inputrec->init_step);
-#endif
-
-    /* NMR restraints must be initialized before load_checkpoint,
-     * since with time averaging the history is added to t_state.
-     * For proper consistency check we therefore need to extend
-     * t_state here.
-     * So the PME-only nodes (if present) will also initialize
-     * the distance restraints.
-     */
-    snew(fcd,1);
-
-    /* This needs to be called before read_checkpoint to extend the state */
-    init_disres(fplog,mtop,inputrec,cr,Flags & MD_PARTDEC,fcd,state);
-
-    if (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0)
-    {
-        if (PAR(cr) && !(Flags & MD_PARTDEC))
-        {
-            gmx_fatal(FARGS,"Orientation restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)");
-        }
-        /* Orientation restraints */
-        if (MASTER(cr))
-        {
-            init_orires(fplog,mtop,state->x,inputrec,cr->ms,&(fcd->orires),
-                        state);
-        }
-    }
-
-    if (DEFORM(*inputrec))
-    {
-        /* Store the deform reference box before reading the checkpoint */
-        if (SIMMASTER(cr))
-        {
-            copy_mat(state->box,box);
-        }
-        if (PAR(cr))
-        {
-            gmx_bcast(sizeof(box),box,cr);
-        }
-        /* Because we do not have the update struct available yet
-         * in which the reference values should be stored,
-         * we store them temporarily in static variables.
-         * This should be thread safe, since they are only written once
-         * and with identical values.
-         */
-#ifdef GMX_THREADS
-        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
-#endif
-        deform_init_init_step_tpx = inputrec->init_step;
-        copy_mat(box,deform_init_box_tpx);
-#ifdef GMX_THREADS
-        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
-#endif
-    }
-
-    if (opt2bSet("-cpi",nfile,fnm)) 
-    {
-        /* Check if checkpoint file exists before doing continuation.
-         * This way we can use identical input options for the first and subsequent runs...
-         */
-        if( gmx_fexist_master(opt2fn_master("-cpi",nfile,fnm,cr),cr) )
-        {
-            load_checkpoint(opt2fn_master("-cpi",nfile,fnm,cr),&fplog,
-                            cr,Flags & MD_PARTDEC,ddxyz,
-                            inputrec,state,&bReadRNG,&bReadEkin,
-                            (Flags & MD_APPENDFILES));
-            
-            if (bReadRNG)
-            {
-                Flags |= MD_READ_RNG;
-            }
-            if (bReadEkin)
-            {
-                Flags |= MD_READ_EKIN;
-            }
-        }
-    }
-
-    if (((MASTER(cr) || (Flags & MD_SEPPOT)) && (Flags & MD_APPENDFILES))
-#ifdef GMX_THREADS
-        /* With thread MPI only the master node/thread exists in mdrun.c,
-         * therefore non-master nodes need to open the "seppot" log file here.
-         */
-        || (!MASTER(cr) && (Flags & MD_SEPPOT))
-#endif
-        )
-    {
-        gmx_log_open(ftp2fn(efLOG,nfile,fnm),cr,!(Flags & MD_SEPPOT),
-                             Flags,&fplog);
-    }
-
-    if (SIMMASTER(cr)) 
-    {
-        copy_mat(state->box,box);
-    }
-
-    if (PAR(cr)) 
-    {
-        gmx_bcast(sizeof(box),box,cr);
-    }
-
-    /* Essential dynamics */
-    if (opt2bSet("-ei",nfile,fnm))
-    {
-        /* Open input and output files, allocate space for ED data structure */
-        ed = ed_open(nfile,fnm,Flags,cr);
-    }
-
-    if (bVerbose && SIMMASTER(cr))
-    {
-        fprintf(stderr,"Loaded with Money\n\n");
-    }
-
-    if (PAR(cr) && !((Flags & MD_PARTDEC) ||
-                     EI_TPI(inputrec->eI) ||
-                     inputrec->eI == eiNM))
-    {
-        cr->dd = init_domain_decomposition(fplog,cr,Flags,ddxyz,rdd,rconstr,
-                                           dddlb_opt,dlb_scale,
-                                           ddcsx,ddcsy,ddcsz,
-                                           mtop,inputrec,
-                                           box,state->x,
-                                           &ddbox,&npme_major,&npme_minor);
-
-        make_dd_communicators(fplog,cr,dd_node_order);
-
-        /* Set overallocation to avoid frequent reallocation of arrays */
-        set_over_alloc_dd(TRUE);
-    }
-    else
-    {
-        /* PME, if used, is done on all nodes with 1D decomposition */
-        cr->npmenodes = 0;
-        cr->duty = (DUTY_PP | DUTY_PME);
-        npme_major = 1;
-        npme_minor = 1;
-        if (!EI_TPI(inputrec->eI))
-        {
-            npme_major = cr->nnodes;
-        }
-        
-        if (inputrec->ePBC == epbcSCREW)
-        {
-            gmx_fatal(FARGS,
-                      "pbc=%s is only implemented with domain decomposition",
-                      epbc_names[inputrec->ePBC]);
-        }
-    }
-
-    if (PAR(cr))
-    {
-        /* After possible communicator splitting in make_dd_communicators.
-         * we can set up the intra/inter node communication.
-         */
-        gmx_setup_nodecomm(fplog,cr);
-    }
-
-    wcycle = wallcycle_init(fplog,resetstep,cr);
-    if (PAR(cr))
-    {
-        /* Master synchronizes its value of reset_counters with all nodes 
-         * including PME only nodes */
-        reset_counters = wcycle_get_reset_counters(wcycle);
-        gmx_bcast_sim(sizeof(reset_counters),&reset_counters,cr);
-        wcycle_set_reset_counters(wcycle, reset_counters);
-    }
-
-
-    snew(nrnb,1);
-    if (cr->duty & DUTY_PP)
-    {
-        /* For domain decomposition we allocate dynamically
-         * in dd_partition_system.
-         */
-        if (DOMAINDECOMP(cr))
-        {
-            bcast_state_setup(cr,state);
-        }
-        else
-        {
-            if (PAR(cr))
-            {
-                bcast_state(cr,state,TRUE);
-            }
-        }
-
-        /* Dihedral Restraints */
-        if (gmx_mtop_ftype_count(mtop,F_DIHRES) > 0)
-        {
-            init_dihres(fplog,mtop,inputrec,fcd);
-        }
-
-        /* Initiate forcerecord */
-        fr = mk_forcerec();
-        init_forcerec(fplog,oenv,fr,fcd,inputrec,mtop,cr,box,FALSE,
-                      opt2fn("-table",nfile,fnm),
-                      opt2fn("-tablep",nfile,fnm),
-                      opt2fn("-tableb",nfile,fnm),FALSE,pforce);
-
-        /* version for PCA_NOT_READ_NODE (see md.c) */
-        /*init_forcerec(fplog,fr,fcd,inputrec,mtop,cr,box,FALSE,
-          "nofile","nofile","nofile",FALSE,pforce);
-          */        
-        fr->bSepDVDL = ((Flags & MD_SEPPOT) == MD_SEPPOT);
-
-        /* Initialize QM-MM */
-        if(fr->bQMMM)
-        {
-            init_QMMMrec(cr,box,mtop,inputrec,fr);
-        }
-
-        /* Initialize the mdatoms structure.
-         * mdatoms is not filled with atom data,
-         * as this can not be done now with domain decomposition.
-         */
-        mdatoms = init_mdatoms(fplog,mtop,inputrec->efep!=efepNO);
-
-        /* Initialize the virtual site communication */
-        vsite = init_vsite(mtop,cr);
-
-        calc_shifts(box,fr->shift_vec);
-
-        /* With periodic molecules the charge groups should be whole at start up
-         * and the virtual sites should not be far from their proper positions.
-         */
-        if (!inputrec->bContinuation && MASTER(cr) &&
-            !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols))
-        {
-            /* Make molecules whole at start of run */
-            if (fr->ePBC != epbcNONE)
-            {
-                do_pbc_first_mtop(fplog,inputrec->ePBC,box,mtop,state->x);
-            }
-            if (vsite)
-            {
-                /* Correct initial vsite positions are required
-                 * for the initial distribution in the domain decomposition
-                 * and for the initial shell prediction.
-                 */
-                construct_vsites_mtop(fplog,vsite,mtop,state->x);
-            }
-        }
-
-        /* Initiate PPPM if necessary */
-        if (fr->eeltype == eelPPPM)
-        {
-            if (mdatoms->nChargePerturbed)
-            {
-                gmx_fatal(FARGS,"Free energy with %s is not implemented",
-                          eel_names[fr->eeltype]);
-            }
-            status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
-                                   getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
-            if (status != 0)
-            {
-                gmx_fatal(FARGS,"Error %d initializing PPPM",status);
-            }
-        }
-
-        if (EEL_PME(fr->eeltype))
-        {
-            ewaldcoeff = fr->ewaldcoeff;
-            pmedata = &fr->pmedata;
-        }
-        else
-        {
-            pmedata = NULL;
-        }
-    }
-    else
-    {
-        /* This is a PME only node */
-
-        /* We don't need the state */
-        done_state(state);
-
-        ewaldcoeff = calc_ewaldcoeff(inputrec->rcoulomb, inputrec->ewald_rtol);
-        snew(pmedata,1);
-    }
-
-    /* Initiate PME if necessary,
-     * either on all nodes or on dedicated PME nodes only. */
-    if (EEL_PME(inputrec->coulombtype))
-    {
-        if (mdatoms)
-        {
-            nChargePerturbed = mdatoms->nChargePerturbed;
-        }
-        if (cr->npmenodes > 0)
-        {
-            /* The PME only nodes need to know nChargePerturbed */
-            gmx_bcast_sim(sizeof(nChargePerturbed),&nChargePerturbed,cr);
-        }
-        if (cr->duty & DUTY_PME)
-        {
-            status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
-                                  mtop ? mtop->natoms : 0,nChargePerturbed,
-                                  (Flags & MD_REPRODUCIBLE));
-            if (status != 0) 
-            {
-                gmx_fatal(FARGS,"Error %d initializing PME",status);
-            }
-        }
-    }
-
-
-    if (integrator[inputrec->eI].func == do_md
-#ifdef GMX_OPENMM
-        ||
-        integrator[inputrec->eI].func == do_md_openmm
-#endif
-        )
-    {
-        /* Turn on signal handling on all nodes */
-        /*
-         * (A user signal from the PME nodes (if any)
-         * is communicated to the PP nodes.
-         */
-        signal_handler_install();
-    }
-
-    if (cr->duty & DUTY_PP)
-    {
-        if (inputrec->ePull != epullNO)
-        {
-            /* Initialize pull code */
-            init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv,
-                      EI_DYNAMICS(inputrec->eI) && MASTER(cr),Flags);
-        }
-
-        constr = init_constraints(fplog,mtop,inputrec,ed,state,cr);
-
-        if (DOMAINDECOMP(cr))
-        {
-            dd_init_bondeds(fplog,cr->dd,mtop,vsite,constr,inputrec,
-                            Flags & MD_DDBONDCHECK,fr->cginfo_mb);
-
-            set_dd_parameters(fplog,cr->dd,dlb_scale,inputrec,fr,&ddbox);
-
-            setup_dd_grid(fplog,cr->dd);
-        }
-
-        /* Now do whatever the user wants us to do (how flexible...) */
-        integrator[inputrec->eI].func(fplog,cr,nfile,fnm,
-                                      oenv,bVerbose,bCompact,
-                                      nstglobalcomm,
-                                      vsite,constr,
-                                      nstepout,inputrec,mtop,
-                                      fcd,state,
-                                      mdatoms,nrnb,wcycle,ed,fr,
-                                      repl_ex_nst,repl_ex_seed,
-                                      cpt_period,max_hours,
-                                      deviceOptions,
-                                      Flags,
-                                      &runtime);
-
-        if (inputrec->ePull != epullNO)
-        {
-            finish_pull(fplog,inputrec->pull);
-        }
-    } 
-    else 
-    {
-        /* do PME only */
-        gmx_pmeonly(*pmedata,cr,nrnb,wcycle,ewaldcoeff,FALSE,inputrec);
-    }
-
-    if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
-    {
-        /* Some timing stats */  
-        if (SIMMASTER(cr))
-        {
-            if (runtime.proc == 0)
-            {
-                runtime.proc = runtime.real;
-            }
-        }
-        else
-        {
-            runtime.real = 0;
-        }
-    }
-
-    wallcycle_stop(wcycle,ewcRUN);
-
-    /* Finish up, write some stuff
-     * if rerunMD, don't write last frame again 
-     */
-    finish_run(fplog,cr,ftp2fn(efSTO,nfile,fnm),
-               inputrec,nrnb,wcycle,&runtime,
-               EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr));
-
-    /* Does what it says */  
-    print_date_and_time(fplog,cr->nodeid,"Finished mdrun",&runtime);
-
-    /* Close logfile already here if we were appending to it */
-    if (MASTER(cr) && (Flags & MD_APPENDFILES))
-    {
-        gmx_log_close(fplog);
-    }  
-
-    rc=(int)gmx_get_stop_condition();
-
-#ifdef GMX_THREADS
-    /* we need to join all threads. The sub-threads join when they
-       exit this function, but the master thread needs to be told to 
-       wait for that. */
-    if (PAR(cr) && MASTER(cr))
-    {
-        tMPI_Finalize();
-    }
-#endif
-
-    return rc;
-}
diff --git a/src/mdlib/.cvsignore b/src/mdlib/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/mdlib/CMakeLists.txt b/src/mdlib/CMakeLists.txt
deleted file mode 100644 (file)
index 18f3a6e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-
-file(GLOB MDLIB_SOURCES *.c)
-
-# Files        called xxx_test.c are test drivers with a main() function for 
-# module xxx.c, so they should not be included in the library
-file(GLOB_RECURSE NOT_MDLIB_SOURCES *_test.c *\#*)
-list(REMOVE_ITEM MDLIB_SOURCES ${NOT_MDLIB_SOURCES})
-
-add_library(md ${MDLIB_SOURCES})
-target_link_libraries(md gmx ${GMX_EXTRA_LIBRARIES} ${FFT_LIBRARIES} ${XML_LIBRARIES})
-set_target_properties(md PROPERTIES OUTPUT_NAME "md${GMX_LIBS_SUFFIX}" SOVERSION ${SOVERSION} INSTALL_NAME_DIR "${LIB_INSTALL_DIR}")
-
-install(TARGETS md DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libmd.pc.cmakein ${CMAKE_CURRENT_BINARY_DIR}/libmd.pc @ONLY)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libmd.pc
-        DESTINATION ${LIB_INSTALL_DIR}/pkgconfig
-        RENAME "libmd${GMX_LIBS_SUFFIX}.pc"
-        COMPONENT development)
diff --git a/src/mdlib/domdec.c b/src/mdlib/domdec.c
deleted file mode 100644 (file)
index abed24f..0000000
+++ /dev/null
@@ -1,8648 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- * This file is part of Gromacs        Copyright (c) 1991-2008
- * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
- *
- * 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.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
- * 
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <time.h>
-#include <math.h>
-#include <string.h>
-#include <stdlib.h>
-#include "typedefs.h"
-#include "smalloc.h"
-#include "vec.h"
-#include "domdec.h"
-#include "domdec_network.h"
-#include "nrnb.h"
-#include "pbc.h"
-#include "chargegroup.h"
-#include "constr.h"
-#include "mdatoms.h"
-#include "names.h"
-#include "pdbio.h"
-#include "futil.h"
-#include "force.h"
-#include "pme.h"
-#include "pull.h"
-#include "gmx_wallcycle.h"
-#include "mdrun.h"
-#include "nsgrid.h"
-#include "shellfc.h"
-#include "mtop_util.h"
-#include "gmxfio.h"
-#include "gmx_ga2la.h"
-#include "gmx_sort.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#define DDRANK(dd,rank)    (rank)
-#define DDMASTERRANK(dd)   (dd->masterrank)
-
-typedef struct gmx_domdec_master
-{
-    /* The cell boundaries */
-    real **cell_x;
-    /* The global charge group division */
-    int  *ncg;     /* Number of home charge groups for each node */
-    int  *index;   /* Index of nnodes+1 into cg */
-    int  *cg;      /* Global charge group index */
-    int  *nat;     /* Number of home atoms for each node. */
-    int  *ibuf;    /* Buffer for communication */
-    rvec *vbuf;    /* Buffer for state scattering and gathering */
-} gmx_domdec_master_t;
-
-typedef struct
-{
-    /* The numbers of charge groups to send and receive for each cell
-     * that requires communication, the last entry contains the total
-     * number of atoms that needs to be communicated.
-     */
-    int nsend[DD_MAXIZONE+2];
-    int nrecv[DD_MAXIZONE+2];
-    /* The charge groups to send */
-    int *index;
-    int nalloc;
-    /* The atom range for non-in-place communication */
-    int cell2at0[DD_MAXIZONE];
-    int cell2at1[DD_MAXIZONE];
-} gmx_domdec_ind_t;
-
-typedef struct
-{
-    int  np;                   /* Number of grid pulses in this dimension */
-    int  np_dlb;               /* For dlb, for use with edlbAUTO          */
-    gmx_domdec_ind_t *ind;     /* The indices to communicate, size np     */
-    int  np_nalloc;
-    gmx_bool bInPlace;             /* Can we communicate in place?            */
-} gmx_domdec_comm_dim_t;
-
-typedef struct
-{
-    gmx_bool *bCellMin;    /* Temp. var.: is this cell size at the limit     */
-    real *cell_f;      /* State var.: cell boundaries, box relative      */
-    real *old_cell_f;  /* Temp. var.: old cell size                      */
-    real *cell_f_max0; /* State var.: max lower boundary, incl neighbors */
-    real *cell_f_min1; /* State var.: min upper boundary, incl neighbors */
-    real *bound_min;   /* Temp. var.: lower limit for cell boundary      */
-    real *bound_max;   /* Temp. var.: upper limit for cell boundary      */
-    gmx_bool bLimited;     /* State var.: is DLB limited in this dim and row */
-    real *buf_ncd;     /* Temp. var.                                     */
-} gmx_domdec_root_t;
-
-#define DD_NLOAD_MAX 9
-
-/* Here floats are accurate enough, since these variables
- * only influence the load balancing, not the actual MD results.
- */
-typedef struct
-{
-    int  nload;
-    float *load;
-    float sum;
-    float max;
-    float sum_m;
-    float cvol_min;
-    float mdf;
-    float pme;
-    int   flags;
-} gmx_domdec_load_t;
-
-typedef struct
-{
-    int  nsc;
-    int  ind_gl;
-    int  ind;
-} gmx_cgsort_t;
-
-typedef struct
-{
-    gmx_cgsort_t *sort1,*sort2;
-    int  sort_nalloc;
-    gmx_cgsort_t *sort_new;
-    int  sort_new_nalloc;
-    int  *ibuf;
-    int  ibuf_nalloc;
-} gmx_domdec_sort_t;
-
-typedef struct
-{
-    rvec *v;
-    int  nalloc;
-} vec_rvec_t;
-
-/* This enum determines the order of the coordinates.
- * ddnatHOME and ddnatZONE should be first and second,
- * the others can be ordered as wanted.
- */
-enum { ddnatHOME, ddnatZONE, ddnatVSITE, ddnatCON, ddnatNR };
-
-enum { edlbAUTO, edlbNO, edlbYES, edlbNR };
-const char *edlb_names[edlbNR] = { "auto", "no", "yes" };
-
-typedef struct
-{
-    int  dim;      /* The dimension                                          */
-    gmx_bool dim_match;/* Tells if DD and PME dims match                         */
-    int  nslab;    /* The number of PME slabs in this dimension              */
-    real *slb_dim_f; /* Cell sizes for determining the PME comm. with SLB    */
-    int  *pp_min;  /* The minimum pp node location, size nslab               */
-    int  *pp_max;  /* The maximum pp node location,size nslab                */
-    int  maxshift; /* The maximum shift for coordinate redistribution in PME */
-} gmx_ddpme_t;
-
-typedef struct
-{
-    real min0;    /* The minimum bottom of this zone                        */
-    real max1;    /* The maximum top of this zone                           */
-    real mch0;    /* The maximum bottom communicaton height for this zone   */
-    real mch1;    /* The maximum top communicaton height for this zone      */
-    real p1_0;    /* The bottom value of the first cell in this zone        */
-    real p1_1;    /* The top value of the first cell in this zone           */
-} gmx_ddzone_t;
-
-typedef struct gmx_domdec_comm
-{
-    /* All arrays are indexed with 0 to dd->ndim (not Cartesian indexing),
-     * unless stated otherwise.
-     */
-
-    /* The number of decomposition dimensions for PME, 0: no PME */
-    int  npmedecompdim;
-    /* The number of nodes doing PME (PP/PME or only PME) */
-    int  npmenodes;
-    int  npmenodes_x;
-    int  npmenodes_y;
-    /* The communication setup including the PME only nodes */
-    gmx_bool bCartesianPP_PME;
-    ivec ntot;
-    int  cartpmedim;
-    int  *pmenodes;          /* size npmenodes                         */
-    int  *ddindex2simnodeid; /* size npmenodes, only with bCartesianPP
-                              * but with bCartesianPP_PME              */
-    gmx_ddpme_t ddpme[2];
-    
-    /* The DD particle-particle nodes only */
-    gmx_bool bCartesianPP;
-    int  *ddindex2ddnodeid; /* size npmenode, only with bCartesianPP_PME */
-    
-    /* The global charge groups */
-    t_block cgs_gl;
-
-    /* Should we sort the cgs */
-    int  nstSortCG;
-    gmx_domdec_sort_t *sort;
-    
-    /* Are there bonded and multi-body interactions between charge groups? */
-    gmx_bool bInterCGBondeds;
-    gmx_bool bInterCGMultiBody;
-
-    /* Data for the optional bonded interaction atom communication range */
-    gmx_bool bBondComm;
-    t_blocka *cglink;
-    char *bLocalCG;
-
-    /* The DLB option */
-    int  eDLB;
-    /* Are we actually using DLB? */
-    gmx_bool bDynLoadBal;
-
-    /* Cell sizes for static load balancing, first index cartesian */
-    real **slb_frac;
-    
-    /* The width of the communicated boundaries */
-    real cutoff_mbody;
-    real cutoff;
-    /* The minimum cell size (including triclinic correction) */
-    rvec cellsize_min;
-    /* For dlb, for use with edlbAUTO */
-    rvec cellsize_min_dlb;
-    /* The lower limit for the DD cell size with DLB */
-    real cellsize_limit;
-    /* Effectively no NB cut-off limit with DLB for systems without PBC? */
-    gmx_bool bVacDLBNoLimit;
-
-    /* tric_dir is only stored here because dd_get_ns_ranges needs it */
-    ivec tric_dir;
-    /* box0 and box_size are required with dim's without pbc and -gcom */
-    rvec box0;
-    rvec box_size;
-    
-    /* The cell boundaries */
-    rvec cell_x0;
-    rvec cell_x1;
-
-    /* The old location of the cell boundaries, to check cg displacements */
-    rvec old_cell_x0;
-    rvec old_cell_x1;
-
-    /* The communication setup and charge group boundaries for the zones */
-    gmx_domdec_zones_t zones;
-    
-    /* The zone limits for DD dimensions 1 and 2 (not 0), determined from
-     * cell boundaries of neighboring cells for dynamic load balancing.
-     */
-    gmx_ddzone_t zone_d1[2];
-    gmx_ddzone_t zone_d2[2][2];
-    
-    /* The coordinate/force communication setup and indices */
-    gmx_domdec_comm_dim_t cd[DIM];
-    /* The maximum number of cells to communicate with in one dimension */
-    int  maxpulse;
-    
-    /* Which cg distribution is stored on the master node */
-    int master_cg_ddp_count;
-    
-    /* The number of cg's received from the direct neighbors */
-    int  zone_ncg1[DD_MAXZONE];
-    
-    /* The atom counts, the range for each type t is nat[t-1] <= at < nat[t] */
-    int  nat[ddnatNR];
-    
-    /* Communication buffer for general use */
-    int  *buf_int;
-    int  nalloc_int;
-
-     /* Communication buffer for general use */
-    vec_rvec_t vbuf;
-    
-    /* Communication buffers only used with multiple grid pulses */
-    int  *buf_int2;
-    int  nalloc_int2;
-    vec_rvec_t vbuf2;
-    
-    /* Communication buffers for local redistribution */
-    int  **cggl_flag;
-    int  cggl_flag_nalloc[DIM*2];
-    rvec **cgcm_state;
-    int  cgcm_state_nalloc[DIM*2];
-    
-    /* Cell sizes for dynamic load balancing */
-    gmx_domdec_root_t **root;
-    real *cell_f_row;
-    real cell_f0[DIM];
-    real cell_f1[DIM];
-    real cell_f_max0[DIM];
-    real cell_f_min1[DIM];
-    
-    /* Stuff for load communication */
-    gmx_bool bRecordLoad;
-    gmx_domdec_load_t *load;
-#ifdef GMX_MPI
-    MPI_Comm *mpi_comm_load;
-#endif
-
-    /* Maximum DLB scaling per load balancing step in percent */
-    int dlb_scale_lim;
-
-    /* Cycle counters */
-    float cycl[ddCyclNr];
-    int   cycl_n[ddCyclNr];
-    float cycl_max[ddCyclNr];
-    /* Flop counter (0=no,1=yes,2=with (eFlop-1)*5% noise */
-    int eFlop;
-    double flop;
-    int    flop_n;
-    /* Have often have did we have load measurements */
-    int    n_load_have;
-    /* Have often have we collected the load measurements */
-    int    n_load_collect;
-    
-    /* Statistics */
-    double sum_nat[ddnatNR-ddnatZONE];
-    int    ndecomp;
-    int    nload;
-    double load_step;
-    double load_sum;
-    double load_max;
-    ivec   load_lim;
-    double load_mdf;
-    double load_pme;
-
-    /* The last partition step */
-    gmx_large_int_t globalcomm_step;
-
-    /* Debugging */
-    int  nstDDDump;
-    int  nstDDDumpGrid;
-    int  DD_debug;
-} gmx_domdec_comm_t;
-
-/* The size per charge group of the cggl_flag buffer in gmx_domdec_comm_t */
-#define DD_CGIBS 2
-
-/* The flags for the cggl_flag buffer in gmx_domdec_comm_t */
-#define DD_FLAG_NRCG  65535
-#define DD_FLAG_FW(d) (1<<(16+(d)*2))
-#define DD_FLAG_BW(d) (1<<(16+(d)*2+1))
-
-/* Zone permutation required to obtain consecutive charge groups
- * for neighbor searching.
- */
-static const int zone_perm[3][4] = { {0,0,0,0},{1,0,0,0},{3,0,1,2} };
-
-/* dd_zo and dd_zp3/dd_zp2 are set up such that i zones with non-zero
- * components see only j zones with that component 0.
- */
-
-/* The DD zone order */
-static const ivec dd_zo[DD_MAXZONE] =
-  {{0,0,0},{1,0,0},{1,1,0},{0,1,0},{0,1,1},{0,0,1},{1,0,1},{1,1,1}};
-
-/* The 3D setup */
-#define dd_z3n  8
-#define dd_zp3n 4
-static const ivec dd_zp3[dd_zp3n] = {{0,0,8},{1,3,6},{2,5,6},{3,5,7}};
-
-/* The 2D setup */
-#define dd_z2n  4
-#define dd_zp2n 2
-static const ivec dd_zp2[dd_zp2n] = {{0,0,4},{1,3,4}};
-
-/* The 1D setup */
-#define dd_z1n  2
-#define dd_zp1n 1
-static const ivec dd_zp1[dd_zp1n] = {{0,0,2}};
-
-/* Factors used to avoid problems due to rounding issues */
-#define DD_CELL_MARGIN       1.0001
-#define DD_CELL_MARGIN2      1.00005
-/* Factor to account for pressure scaling during nstlist steps */
-#define DD_PRES_SCALE_MARGIN 1.02
-
-/* Allowed performance loss before we DLB or warn */
-#define DD_PERF_LOSS 0.05
-
-#define DD_CELL_F_SIZE(dd,di) ((dd)->nc[(dd)->dim[(di)]]+1+(di)*2+1+(di))
-
-/* Use separate MPI send and receive commands
- * when nnodes <= GMX_DD_NNODES_SENDRECV.
- * This saves memory (and some copying for small nnodes).
- * For high parallelization scatter and gather calls are used.
- */
-#define GMX_DD_NNODES_SENDRECV 4
-
-
-/*
-#define dd_index(n,i) ((((i)[ZZ]*(n)[YY] + (i)[YY])*(n)[XX]) + (i)[XX])
-
-static void index2xyz(ivec nc,int ind,ivec xyz)
-{
-  xyz[XX] = ind % nc[XX];
-  xyz[YY] = (ind / nc[XX]) % nc[YY];
-  xyz[ZZ] = ind / (nc[YY]*nc[XX]);
-}
-*/
-
-/* This order is required to minimize the coordinate communication in PME
- * which uses decomposition in the x direction.
- */
-#define dd_index(n,i) ((((i)[XX]*(n)[YY] + (i)[YY])*(n)[ZZ]) + (i)[ZZ])
-
-static void ddindex2xyz(ivec nc,int ind,ivec xyz)
-{
-    xyz[XX] = ind / (nc[YY]*nc[ZZ]);
-    xyz[YY] = (ind / nc[ZZ]) % nc[YY];
-    xyz[ZZ] = ind % nc[ZZ];
-}
-
-static int ddcoord2ddnodeid(gmx_domdec_t *dd,ivec c)
-{
-    int ddindex;
-    int ddnodeid=-1;
-    
-    ddindex = dd_index(dd->nc,c);
-    if (dd->comm->bCartesianPP_PME)
-    {
-        ddnodeid = dd->comm->ddindex2ddnodeid[ddindex];
-    }
-    else if (dd->comm->bCartesianPP)
-    {
-#ifdef GMX_MPI
-        MPI_Cart_rank(dd->mpi_comm_all,c,&ddnodeid);
-#endif
-    }
-    else
-    {
-        ddnodeid = ddindex;
-    }
-    
-    return ddnodeid;
-}
-
-static gmx_bool dynamic_dd_box(gmx_ddbox_t *ddbox,t_inputrec *ir)
-{
-    return (ddbox->nboundeddim < DIM || DYNAMIC_BOX(*ir));
-}
-
-int ddglatnr(gmx_domdec_t *dd,int i)
-{
-    int atnr;
-    
-    if (dd == NULL)
-    {
-        atnr = i + 1;
-    }
-    else
-    {
-        if (i >= dd->comm->nat[ddnatNR-1])
-        {
-            gmx_fatal(FARGS,"glatnr called with %d, which is larger than the local number of atoms (%d)",i,dd->comm->nat[ddnatNR-1]);
-        }
-        atnr = dd->gatindex[i] + 1;
-    }
-    
-    return atnr;
-}
-
-t_block *dd_charge_groups_global(gmx_domdec_t *dd)
-{
-    return &dd->comm->cgs_gl;
-}
-
-static void vec_rvec_init(vec_rvec_t *v)
-{
-    v->nalloc = 0;
-    v->v      = NULL;
-}
-
-static void vec_rvec_check_alloc(vec_rvec_t *v,int n)
-{
-    if (n > v->nalloc)
-    {
-        v->nalloc = over_alloc_dd(n);
-        srenew(v->v,v->nalloc);
-    }
-}
-
-void dd_store_state(gmx_domdec_t *dd,t_state *state)
-{
-    int i;
-    
-    if (state->ddp_count != dd->ddp_count)
-    {
-        gmx_incons("The state does not the domain decomposition state");
-    }
-    
-    state->ncg_gl = dd->ncg_home;
-    if (state->ncg_gl > state->cg_gl_nalloc)
-    {
-        state->cg_gl_nalloc = over_alloc_dd(state->ncg_gl);
-        srenew(state->cg_gl,state->cg_gl_nalloc);
-    }
-    for(i=0; i<state->ncg_gl; i++)
-    {
-        state->cg_gl[i] = dd->index_gl[i];
-    }
-    
-    state->ddp_count_cg_gl = dd->ddp_count;
-}
-
-gmx_domdec_zones_t *domdec_zones(gmx_domdec_t *dd)
-{
-    return &dd->comm->zones;
-}
-
-void dd_get_ns_ranges(gmx_domdec_t *dd,int icg,
-                      int *jcg0,int *jcg1,ivec shift0,ivec shift1)
-{
-    gmx_domdec_zones_t *zones;
-    int izone,d,dim;
-
-    zones = &dd->comm->zones;
-
-    izone = 0;
-    while (icg >= zones->izone[izone].cg1)
-    {
-        izone++;
-    }
-    
-    if (izone == 0)
-    {
-        *jcg0 = icg;
-    }
-    else if (izone < zones->nizone)
-    {
-        *jcg0 = zones->izone[izone].jcg0;
-    }
-    else
-    {
-        gmx_fatal(FARGS,"DD icg %d out of range: izone (%d) >= nizone (%d)",
-                  icg,izone,zones->nizone);
-    }
-        
-    *jcg1 = zones->izone[izone].jcg1;
-    
-    for(d=0; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        shift0[dim] = zones->izone[izone].shift0[dim];
-        shift1[dim] = zones->izone[izone].shift1[dim];
-        if (dd->comm->tric_dir[dim] || (dd->bGridJump && d > 0))
-        {
-            /* A conservative approach, this can be optimized */
-            shift0[dim] -= 1;
-            shift1[dim] += 1;
-        }
-    }
-}
-
-int dd_natoms_vsite(gmx_domdec_t *dd)
-{
-    return dd->comm->nat[ddnatVSITE];
-}
-
-void dd_get_constraint_range(gmx_domdec_t *dd,int *at_start,int *at_end)
-{
-    *at_start = dd->comm->nat[ddnatCON-1];
-    *at_end   = dd->comm->nat[ddnatCON];
-}
-
-void dd_move_x(gmx_domdec_t *dd,matrix box,rvec x[])
-{
-    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
-    int  *index,*cgindex;
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_comm_dim_t *cd;
-    gmx_domdec_ind_t *ind;
-    rvec shift={0,0,0},*buf,*rbuf;
-    gmx_bool bPBC,bScrew;
-    
-    comm = dd->comm;
-    
-    cgindex = dd->cgindex;
-    
-    buf = comm->vbuf.v;
-
-    nzone = 1;
-    nat_tot = dd->nat_home;
-    for(d=0; d<dd->ndim; d++)
-    {
-        bPBC   = (dd->ci[dd->dim[d]] == 0);
-        bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
-        if (bPBC)
-        {
-            copy_rvec(box[dd->dim[d]],shift);
-        }
-        cd = &comm->cd[d];
-        for(p=0; p<cd->np; p++)
-        {
-            ind = &cd->ind[p];
-            index = ind->index;
-            n = 0;
-            if (!bPBC)
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        copy_rvec(x[j],buf[n]);
-                        n++;
-                    }
-                }
-            }
-            else if (!bScrew)
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        /* We need to shift the coordinates */
-                        rvec_add(x[j],shift,buf[n]);
-                        n++;
-                    }
-                }
-            }
-            else
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        /* Shift x */
-                        buf[n][XX] = x[j][XX] + shift[XX];
-                        /* Rotate y and z.
-                         * This operation requires a special shift force
-                         * treatment, which is performed in calc_vir.
-                         */
-                        buf[n][YY] = box[YY][YY] - x[j][YY];
-                        buf[n][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
-                        n++;
-                    }
-                }
-            }
-            
-            if (cd->bInPlace)
-            {
-                rbuf = x + nat_tot;
-            }
-            else
-            {
-                rbuf = comm->vbuf2.v;
-            }
-            /* Send and receive the coordinates */
-            dd_sendrecv_rvec(dd, d, dddirBackward,
-                             buf,  ind->nsend[nzone+1],
-                             rbuf, ind->nrecv[nzone+1]);
-            if (!cd->bInPlace)
-            {
-                j = 0;
-                for(zone=0; zone<nzone; zone++)
-                {
-                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
-                    {
-                        copy_rvec(rbuf[j],x[i]);
-                        j++;
-                    }
-                }
-            }
-            nat_tot += ind->nrecv[nzone+1];
-        }
-        nzone += nzone;
-    }
-}
-
-void dd_move_f(gmx_domdec_t *dd,rvec f[],rvec *fshift)
-{
-    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
-    int  *index,*cgindex;
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_comm_dim_t *cd;
-    gmx_domdec_ind_t *ind;
-    rvec *buf,*sbuf;
-    ivec vis;
-    int  is;
-    gmx_bool bPBC,bScrew;
-    
-    comm = dd->comm;
-    
-    cgindex = dd->cgindex;
-
-    buf = comm->vbuf.v;
-
-    n = 0;
-    nzone = comm->zones.n/2;
-    nat_tot = dd->nat_tot;
-    for(d=dd->ndim-1; d>=0; d--)
-    {
-        bPBC   = (dd->ci[dd->dim[d]] == 0);
-        bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
-        if (fshift == NULL && !bScrew)
-        {
-            bPBC = FALSE;
-        }
-        /* Determine which shift vector we need */
-        clear_ivec(vis);
-        vis[dd->dim[d]] = 1;
-        is = IVEC2IS(vis);
-        
-        cd = &comm->cd[d];
-        for(p=cd->np-1; p>=0; p--) {
-            ind = &cd->ind[p];
-            nat_tot -= ind->nrecv[nzone+1];
-            if (cd->bInPlace)
-            {
-                sbuf = f + nat_tot;
-            }
-            else
-            {
-                sbuf = comm->vbuf2.v;
-                j = 0;
-                for(zone=0; zone<nzone; zone++)
-                {
-                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
-                    {
-                        copy_rvec(f[i],sbuf[j]);
-                        j++;
-                    }
-                }
-            }
-            /* Communicate the forces */
-            dd_sendrecv_rvec(dd, d, dddirForward,
-                             sbuf, ind->nrecv[nzone+1],
-                             buf,  ind->nsend[nzone+1]);
-            index = ind->index;
-            /* Add the received forces */
-            n = 0;
-            if (!bPBC)
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        rvec_inc(f[j],buf[n]);
-                        n++;
-                    }
-                } 
-            }
-            else if (!bScrew)
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        rvec_inc(f[j],buf[n]);
-                        /* Add this force to the shift force */
-                        rvec_inc(fshift[is],buf[n]);
-                        n++;
-                    }
-                }
-            }
-            else
-            {
-                for(i=0; i<ind->nsend[nzone]; i++)
-                {
-                    at0 = cgindex[index[i]];
-                    at1 = cgindex[index[i]+1];
-                    for(j=at0; j<at1; j++)
-                    {
-                        /* Rotate the force */
-                        f[j][XX] += buf[n][XX];
-                        f[j][YY] -= buf[n][YY];
-                        f[j][ZZ] -= buf[n][ZZ];
-                        if (fshift)
-                        {
-                            /* Add this force to the shift force */
-                            rvec_inc(fshift[is],buf[n]);
-                        }
-                        n++;
-                    }
-                }
-            }
-        }
-        nzone /= 2;
-    }
-}
-
-void dd_atom_spread_real(gmx_domdec_t *dd,real v[])
-{
-    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
-    int  *index,*cgindex;
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_comm_dim_t *cd;
-    gmx_domdec_ind_t *ind;
-    real *buf,*rbuf;
-    
-    comm = dd->comm;
-    
-    cgindex = dd->cgindex;
-    
-    buf = &comm->vbuf.v[0][0];
-
-    nzone = 1;
-    nat_tot = dd->nat_home;
-    for(d=0; d<dd->ndim; d++)
-    {
-        cd = &comm->cd[d];
-        for(p=0; p<cd->np; p++)
-        {
-            ind = &cd->ind[p];
-            index = ind->index;
-            n = 0;
-            for(i=0; i<ind->nsend[nzone]; i++)
-            {
-                at0 = cgindex[index[i]];
-                at1 = cgindex[index[i]+1];
-                for(j=at0; j<at1; j++)
-                {
-                    buf[n] = v[j];
-                    n++;
-                }
-            }
-            
-            if (cd->bInPlace)
-            {
-                rbuf = v + nat_tot;
-            }
-            else
-            {
-                rbuf = &comm->vbuf2.v[0][0];
-            }
-            /* Send and receive the coordinates */
-            dd_sendrecv_real(dd, d, dddirBackward,
-                             buf,  ind->nsend[nzone+1],
-                             rbuf, ind->nrecv[nzone+1]);
-            if (!cd->bInPlace)
-            {
-                j = 0;
-                for(zone=0; zone<nzone; zone++)
-                {
-                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
-                    {
-                        v[i] = rbuf[j];
-                        j++;
-                    }
-                }
-            }
-            nat_tot += ind->nrecv[nzone+1];
-        }
-        nzone += nzone;
-    }
-}
-
-void dd_atom_sum_real(gmx_domdec_t *dd,real v[])
-{
-    int  nzone,nat_tot,n,d,p,i,j,at0,at1,zone;
-    int  *index,*cgindex;
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_comm_dim_t *cd;
-    gmx_domdec_ind_t *ind;
-    real *buf,*sbuf;
-    
-    comm = dd->comm;
-    
-    cgindex = dd->cgindex;
-
-    buf = &comm->vbuf.v[0][0];
-
-    n = 0;
-    nzone = comm->zones.n/2;
-    nat_tot = dd->nat_tot;
-    for(d=dd->ndim-1; d>=0; d--)
-    {
-        cd = &comm->cd[d];
-        for(p=cd->np-1; p>=0; p--) {
-            ind = &cd->ind[p];
-            nat_tot -= ind->nrecv[nzone+1];
-            if (cd->bInPlace)
-            {
-                sbuf = v + nat_tot;
-            }
-            else
-            {
-                sbuf = &comm->vbuf2.v[0][0];
-                j = 0;
-                for(zone=0; zone<nzone; zone++)
-                {
-                    for(i=ind->cell2at0[zone]; i<ind->cell2at1[zone]; i++)
-                    {
-                        sbuf[j] = v[i];
-                        j++;
-                    }
-                }
-            }
-            /* Communicate the forces */
-            dd_sendrecv_real(dd, d, dddirForward,
-                             sbuf, ind->nrecv[nzone+1],
-                             buf,  ind->nsend[nzone+1]);
-            index = ind->index;
-            /* Add the received forces */
-            n = 0;
-            for(i=0; i<ind->nsend[nzone]; i++)
-            {
-                at0 = cgindex[index[i]];
-                at1 = cgindex[index[i]+1];
-                for(j=at0; j<at1; j++)
-                {
-                    v[j] += buf[n];
-                    n++;
-                }
-            } 
-        }
-        nzone /= 2;
-    }
-}
-
-static void print_ddzone(FILE *fp,int d,int i,int j,gmx_ddzone_t *zone)
-{
-    fprintf(fp,"zone d0 %d d1 %d d2 %d  min0 %6.3f max1 %6.3f mch0 %6.3f mch1 %6.3f p1_0 %6.3f p1_1 %6.3f\n",
-            d,i,j,
-            zone->min0,zone->max1,
-            zone->mch0,zone->mch0,
-            zone->p1_0,zone->p1_1);
-}
-
-static void dd_sendrecv_ddzone(const gmx_domdec_t *dd,
-                               int ddimind,int direction,
-                               gmx_ddzone_t *buf_s,int n_s,
-                               gmx_ddzone_t *buf_r,int n_r)
-{
-    rvec vbuf_s[5*2],vbuf_r[5*2];
-    int i;
-
-    for(i=0; i<n_s; i++)
-    {
-        vbuf_s[i*2  ][0] = buf_s[i].min0;
-        vbuf_s[i*2  ][1] = buf_s[i].max1;
-        vbuf_s[i*2  ][2] = buf_s[i].mch0;
-        vbuf_s[i*2+1][0] = buf_s[i].mch1;
-        vbuf_s[i*2+1][1] = buf_s[i].p1_0;
-        vbuf_s[i*2+1][2] = buf_s[i].p1_1;
-    }
-
-    dd_sendrecv_rvec(dd, ddimind, direction,
-                     vbuf_s, n_s*2,
-                     vbuf_r, n_r*2);
-
-    for(i=0; i<n_r; i++)
-    {
-        buf_r[i].min0 = vbuf_r[i*2  ][0];
-        buf_r[i].max1 = vbuf_r[i*2  ][1];
-        buf_r[i].mch0 = vbuf_r[i*2  ][2];
-        buf_r[i].mch1 = vbuf_r[i*2+1][0];
-        buf_r[i].p1_0 = vbuf_r[i*2+1][1];
-        buf_r[i].p1_1 = vbuf_r[i*2+1][2];
-    }
-}
-
-static void dd_move_cellx(gmx_domdec_t *dd,gmx_ddbox_t *ddbox,
-                          rvec cell_ns_x0,rvec cell_ns_x1)
-{
-    int  d,d1,dim,dim1,pos,buf_size,i,j,k,p,npulse,npulse_min;
-    gmx_ddzone_t *zp,buf_s[5],buf_r[5],buf_e[5];
-    rvec extr_s[2],extr_r[2];
-    rvec dh;
-    real dist_d,c=0,det;
-    gmx_domdec_comm_t *comm;
-    gmx_bool bPBC,bUse;
-
-    comm = dd->comm;
-
-    for(d=1; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        zp = (d == 1) ? &comm->zone_d1[0] : &comm->zone_d2[0][0];
-        zp->min0 = cell_ns_x0[dim];
-        zp->max1 = cell_ns_x1[dim];
-        zp->mch0 = cell_ns_x0[dim];
-        zp->mch1 = cell_ns_x1[dim];
-        zp->p1_0 = cell_ns_x0[dim];
-        zp->p1_1 = cell_ns_x1[dim];
-    }
-    
-    for(d=dd->ndim-2; d>=0; d--)
-    {
-        dim  = dd->dim[d];
-        bPBC = (dim < ddbox->npbcdim);
-
-        /* Use an rvec to store two reals */
-        extr_s[d][0] = comm->cell_f0[d+1];
-        extr_s[d][1] = comm->cell_f1[d+1];
-        extr_s[d][2] = 0;
-
-        pos = 0;
-        /* Store the extremes in the backward sending buffer,
-         * so the get updated separately from the forward communication.
-         */
-        for(d1=d; d1<dd->ndim-1; d1++)
-        {
-            /* We invert the order to be able to use the same loop for buf_e */
-            buf_s[pos].min0 = extr_s[d1][1];
-            buf_s[pos].max1 = extr_s[d1][0];
-            buf_s[pos].mch0 = 0;
-            buf_s[pos].mch1 = 0;
-            /* Store the cell corner of the dimension we communicate along */
-            buf_s[pos].p1_0 = comm->cell_x0[dim];
-            buf_s[pos].p1_1 = 0;
-            pos++;
-        }
-
-        buf_s[pos] = (dd->ndim == 2) ? comm->zone_d1[0] : comm->zone_d2[0][0];
-        pos++;
-
-        if (dd->ndim == 3 && d == 0)
-        {
-            buf_s[pos] = comm->zone_d2[0][1];
-            pos++;
-            buf_s[pos] = comm->zone_d1[0];
-            pos++;
-        }
-
-        /* We only need to communicate the extremes
-         * in the forward direction
-         */
-        npulse = comm->cd[d].np;
-        if (bPBC)
-        {
-            /* Take the minimum to avoid double communication */
-            npulse_min = min(npulse,dd->nc[dim]-1-npulse);
-        }
-        else
-        {
-            /* Without PBC we should really not communicate over
-             * the boundaries, but implementing that complicates
-             * the communication setup and therefore we simply
-             * do all communication, but ignore some data.
-             */
-            npulse_min = npulse;
-        }
-        for(p=0; p<npulse_min; p++)
-        {
-            /* Communicate the extremes forward */
-            bUse = (bPBC || dd->ci[dim] > 0);
-
-            dd_sendrecv_rvec(dd, d, dddirForward,
-                             extr_s+d, dd->ndim-d-1,
-                             extr_r+d, dd->ndim-d-1);
-
-            if (bUse)
-            {
-                for(d1=d; d1<dd->ndim-1; d1++)
-                {
-                    extr_s[d1][0] = max(extr_s[d1][0],extr_r[d1][0]);
-                    extr_s[d1][1] = min(extr_s[d1][1],extr_r[d1][1]);
-                }
-            }
-        }
-
-        buf_size = pos;
-        for(p=0; p<npulse; p++)
-        {
-            /* Communicate all the zone information backward */
-            bUse = (bPBC || dd->ci[dim] < dd->nc[dim] - 1);
-
-            dd_sendrecv_ddzone(dd, d, dddirBackward,
-                               buf_s, buf_size,
-                               buf_r, buf_size);
-
-            clear_rvec(dh);
-            if (p > 0)
-            {
-                for(d1=d+1; d1<dd->ndim; d1++)
-                {
-                    /* Determine the decrease of maximum required
-                     * communication height along d1 due to the distance along d,
-                     * this avoids a lot of useless atom communication.
-                     */
-                    dist_d = comm->cell_x1[dim] - buf_r[0].p1_0;
-
-                    if (ddbox->tric_dir[dim])
-                    {
-                        /* c is the off-diagonal coupling between the cell planes
-                         * along directions d and d1.
-                         */
-                        c = ddbox->v[dim][dd->dim[d1]][dim];
-                    }
-                    else
-                    {
-                        c = 0;
-                    }
-                    det = (1 + c*c)*comm->cutoff*comm->cutoff - dist_d*dist_d;
-                    if (det > 0)
-                    {
-                        dh[d1] = comm->cutoff - (c*dist_d + sqrt(det))/(1 + c*c);
-                    }
-                    else
-                    {
-                        /* A negative value signals out of range */
-                        dh[d1] = -1;
-                    }
-                }
-            }
-
-            /* Accumulate the extremes over all pulses */
-            for(i=0; i<buf_size; i++)
-            {
-                if (p == 0)
-                {
-                    buf_e[i] = buf_r[i];
-                }
-                else
-                {
-                    if (bUse)
-                    {
-                        buf_e[i].min0 = min(buf_e[i].min0,buf_r[i].min0);
-                        buf_e[i].max1 = max(buf_e[i].max1,buf_r[i].max1);
-                    }
-
-                    if (dd->ndim == 3 && d == 0 && i == buf_size - 1)
-                    {
-                        d1 = 1;
-                    }
-                    else
-                    {
-                        d1 = d + 1;
-                    }
-                    if (bUse && dh[d1] >= 0)
-                    {
-                        buf_e[i].mch0 = max(buf_e[i].mch0,buf_r[i].mch0-dh[d1]);
-                        buf_e[i].mch1 = max(buf_e[i].mch1,buf_r[i].mch1-dh[d1]);
-                    }
-                }
-                /* Copy the received buffer to the send buffer,
-                 * to pass the data through with the next pulse.
-                 */
-                buf_s[i] = buf_r[i];
-            }
-            if (((bPBC || dd->ci[dim]+npulse < dd->nc[dim]) && p == npulse-1) ||
-                (!bPBC && dd->ci[dim]+1+p == dd->nc[dim]-1))
-            {
-                /* Store the extremes */ 
-                pos = 0;
-
-                for(d1=d; d1<dd->ndim-1; d1++)
-                {
-                    extr_s[d1][1] = min(extr_s[d1][1],buf_e[pos].min0);
-                    extr_s[d1][0] = max(extr_s[d1][0],buf_e[pos].max1);
-                    pos++;
-                }
-
-                if (d == 1 || (d == 0 && dd->ndim == 3))
-                {
-                    for(i=d; i<2; i++)
-                    {
-                        comm->zone_d2[1-d][i] = buf_e[pos];
-                        pos++;
-                    }
-                }
-                if (d == 0)
-                {
-                    comm->zone_d1[1] = buf_e[pos];
-                    pos++;
-                }
-            }
-        }
-    }
-    
-    if (dd->ndim >= 2)
-    {
-        dim = dd->dim[1];
-        for(i=0; i<2; i++)
-        {
-            if (debug)
-            {
-                print_ddzone(debug,1,i,0,&comm->zone_d1[i]);
-            }
-            cell_ns_x0[dim] = min(cell_ns_x0[dim],comm->zone_d1[i].min0);
-            cell_ns_x1[dim] = max(cell_ns_x1[dim],comm->zone_d1[i].max1);
-        }
-    }
-    if (dd->ndim >= 3)
-    {
-        dim = dd->dim[2];
-        for(i=0; i<2; i++)
-        {
-            for(j=0; j<2; j++)
-            {
-                if (debug)
-                {
-                    print_ddzone(debug,2,i,j,&comm->zone_d2[i][j]);
-                }
-                cell_ns_x0[dim] = min(cell_ns_x0[dim],comm->zone_d2[i][j].min0);
-                cell_ns_x1[dim] = max(cell_ns_x1[dim],comm->zone_d2[i][j].max1);
-            }
-        }
-    }
-    for(d=1; d<dd->ndim; d++)
-    {
-        comm->cell_f_max0[d] = extr_s[d-1][0];
-        comm->cell_f_min1[d] = extr_s[d-1][1];
-        if (debug)
-        {
-            fprintf(debug,"Cell fraction d %d, max0 %f, min1 %f\n",
-                    d,comm->cell_f_max0[d],comm->cell_f_min1[d]);
-        }
-    }
-}
-
-static void dd_collect_cg(gmx_domdec_t *dd,
-                          t_state *state_local)
-{
-    gmx_domdec_master_t *ma=NULL;
-    int buf2[2],*ibuf,i,ncg_home=0,*cg=NULL,nat_home=0;
-    t_block *cgs_gl;
-
-    if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
-    {
-        /* The master has the correct distribution */
-        return;
-    }
-    
-    if (state_local->ddp_count == dd->ddp_count)
-    {
-        ncg_home = dd->ncg_home;
-        cg       = dd->index_gl;
-        nat_home = dd->nat_home;
-    } 
-    else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
-    {
-        cgs_gl = &dd->comm->cgs_gl;
-
-        ncg_home = state_local->ncg_gl;
-        cg       = state_local->cg_gl;
-        nat_home = 0;
-        for(i=0; i<ncg_home; i++)
-        {
-            nat_home += cgs_gl->index[cg[i]+1] - cgs_gl->index[cg[i]];
-        }
-    }
-    else
-    {
-        gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
-    }
-    
-    buf2[0] = dd->ncg_home;
-    buf2[1] = dd->nat_home;
-    if (DDMASTER(dd))
-    {
-        ma = dd->ma;
-        ibuf = ma->ibuf;
-    }
-    else
-    {
-        ibuf = NULL;
-    }
-    /* Collect the charge group and atom counts on the master */
-    dd_gather(dd,2*sizeof(int),buf2,ibuf);
-    
-    if (DDMASTER(dd))
-    {
-        ma->index[0] = 0;
-        for(i=0; i<dd->nnodes; i++)
-        {
-            ma->ncg[i] = ma->ibuf[2*i];
-            ma->nat[i] = ma->ibuf[2*i+1];
-            ma->index[i+1] = ma->index[i] + ma->ncg[i];
-            
-        }
-        /* Make byte counts and indices */
-        for(i=0; i<dd->nnodes; i++)
-        {
-            ma->ibuf[i] = ma->ncg[i]*sizeof(int);
-            ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
-        }
-        if (debug)
-        {
-            fprintf(debug,"Initial charge group distribution: ");
-            for(i=0; i<dd->nnodes; i++)
-                fprintf(debug," %d",ma->ncg[i]);
-            fprintf(debug,"\n");
-        }
-    }
-    
-    /* Collect the charge group indices on the master */
-    dd_gatherv(dd,
-               dd->ncg_home*sizeof(int),dd->index_gl,
-               DDMASTER(dd) ? ma->ibuf : NULL,
-               DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
-               DDMASTER(dd) ? ma->cg : NULL);
-    
-    dd->comm->master_cg_ddp_count = state_local->ddp_count;
-}
-
-static void dd_collect_vec_sendrecv(gmx_domdec_t *dd,
-                                    rvec *lv,rvec *v)
-{
-    gmx_domdec_master_t *ma;
-    int  n,i,c,a,nalloc=0;
-    rvec *buf=NULL;
-    t_block *cgs_gl;
-
-    ma = dd->ma;
-    
-    if (!DDMASTER(dd))
-    {
-#ifdef GMX_MPI
-        MPI_Send(lv,dd->nat_home*sizeof(rvec),MPI_BYTE,DDMASTERRANK(dd),
-                 dd->rank,dd->mpi_comm_all);
-#endif
-    } else {
-        /* Copy the master coordinates to the global array */
-        cgs_gl = &dd->comm->cgs_gl;
-
-        n = DDMASTERRANK(dd);
-        a = 0;
-        for(i=ma->index[n]; i<ma->index[n+1]; i++)
-        {
-            for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
-            {
-                copy_rvec(lv[a++],v[c]);
-            }
-        }
-        
-        for(n=0; n<dd->nnodes; n++)
-        {
-            if (n != dd->rank)
-            {
-                if (ma->nat[n] > nalloc)
-                {
-                    nalloc = over_alloc_dd(ma->nat[n]);
-                    srenew(buf,nalloc);
-                }
-#ifdef GMX_MPI
-                MPI_Recv(buf,ma->nat[n]*sizeof(rvec),MPI_BYTE,DDRANK(dd,n),
-                         n,dd->mpi_comm_all,MPI_STATUS_IGNORE);
-#endif
-                a = 0;
-                for(i=ma->index[n]; i<ma->index[n+1]; i++)
-                {
-                    for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
-                    {
-                        copy_rvec(buf[a++],v[c]);
-                    }
-                }
-            }
-        }
-        sfree(buf);
-    }
-}
-
-static void get_commbuffer_counts(gmx_domdec_t *dd,
-                                  int **counts,int **disps)
-{
-    gmx_domdec_master_t *ma;
-    int n;
-
-    ma = dd->ma;
-    
-    /* Make the rvec count and displacment arrays */
-    *counts  = ma->ibuf;
-    *disps   = ma->ibuf + dd->nnodes;
-    for(n=0; n<dd->nnodes; n++)
-    {
-        (*counts)[n] = ma->nat[n]*sizeof(rvec);
-        (*disps)[n]  = (n == 0 ? 0 : (*disps)[n-1] + (*counts)[n-1]);
-    }
-}
-
-static void dd_collect_vec_gatherv(gmx_domdec_t *dd,
-                                   rvec *lv,rvec *v)
-{
-    gmx_domdec_master_t *ma;
-    int  *rcounts=NULL,*disps=NULL;
-    int  n,i,c,a;
-    rvec *buf=NULL;
-    t_block *cgs_gl;
-    
-    ma = dd->ma;
-    
-    if (DDMASTER(dd))
-    {
-        get_commbuffer_counts(dd,&rcounts,&disps);
-
-        buf = ma->vbuf;
-    }
-    
-    dd_gatherv(dd,dd->nat_home*sizeof(rvec),lv,rcounts,disps,buf);
-
-    if (DDMASTER(dd))
-    {
-        cgs_gl = &dd->comm->cgs_gl;
-
-        a = 0;
-        for(n=0; n<dd->nnodes; n++)
-        {
-            for(i=ma->index[n]; i<ma->index[n+1]; i++)
-            {
-                for(c=cgs_gl->index[ma->cg[i]]; c<cgs_gl->index[ma->cg[i]+1]; c++)
-                {
-                    copy_rvec(buf[a++],v[c]);
-                }
-            }
-        }
-    }
-}
-
-void dd_collect_vec(gmx_domdec_t *dd,
-                    t_state *state_local,rvec *lv,rvec *v)
-{
-    gmx_domdec_master_t *ma;
-    int  n,i,c,a,nalloc=0;
-    rvec *buf=NULL;
-    
-    dd_collect_cg(dd,state_local);
-
-    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
-    {
-        dd_collect_vec_sendrecv(dd,lv,v);
-    }
-    else
-    {
-        dd_collect_vec_gatherv(dd,lv,v);
-    }
-}
-
-
-void dd_collect_state(gmx_domdec_t *dd,
-                      t_state *state_local,t_state *state)
-{
-    int est,i,j,nh;
-
-    nh = state->nhchainlength;
-
-    if (DDMASTER(dd))
-    {
-        state->lambda = state_local->lambda;
-        state->veta = state_local->veta;
-        state->vol0 = state_local->vol0;
-        copy_mat(state_local->box,state->box);
-        copy_mat(state_local->boxv,state->boxv);
-        copy_mat(state_local->svir_prev,state->svir_prev);
-        copy_mat(state_local->fvir_prev,state->fvir_prev);
-        copy_mat(state_local->pres_prev,state->pres_prev);
-
-
-        for(i=0; i<state_local->ngtc; i++)
-        {
-            for(j=0; j<nh; j++) {
-                state->nosehoover_xi[i*nh+j]        = state_local->nosehoover_xi[i*nh+j];
-                state->nosehoover_vxi[i*nh+j]       = state_local->nosehoover_vxi[i*nh+j];
-            }
-            state->therm_integral[i] = state_local->therm_integral[i];            
-        }
-        for(i=0; i<state_local->nnhpres; i++) 
-        {
-            for(j=0; j<nh; j++) {
-                state->nhpres_xi[i*nh+j]        = state_local->nhpres_xi[i*nh+j];
-                state->nhpres_vxi[i*nh+j]       = state_local->nhpres_vxi[i*nh+j];
-            }
-        }
-    }
-    for(est=0; est<estNR; est++)
-    {
-        if (EST_DISTR(est) && (state_local->flags & (1<<est)))
-        {
-            switch (est) {
-            case estX:
-                dd_collect_vec(dd,state_local,state_local->x,state->x);
-                break;
-            case estV:
-                dd_collect_vec(dd,state_local,state_local->v,state->v);
-                break;
-            case estSDX:
-                dd_collect_vec(dd,state_local,state_local->sd_X,state->sd_X);
-                break;
-            case estCGP:
-                dd_collect_vec(dd,state_local,state_local->cg_p,state->cg_p);
-                break;
-            case estLD_RNG:
-                if (state->nrngi == 1)
-                {
-                    if (DDMASTER(dd))
-                    {
-                        for(i=0; i<state_local->nrng; i++)
-                        {
-                            state->ld_rng[i] = state_local->ld_rng[i];
-                        }
-                    }
-                }
-                else
-                {
-                    dd_gather(dd,state_local->nrng*sizeof(state->ld_rng[0]),
-                              state_local->ld_rng,state->ld_rng);
-                }
-                break;
-            case estLD_RNGI:
-                if (state->nrngi == 1)
-                {
-                   if (DDMASTER(dd))
-                    {
-                        state->ld_rngi[0] = state_local->ld_rngi[0];
-                    } 
-                }
-                else
-                {
-                    dd_gather(dd,sizeof(state->ld_rngi[0]),
-                              state_local->ld_rngi,state->ld_rngi);
-                }
-                break;
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                break;
-            default:
-                gmx_incons("Unknown state entry encountered in dd_collect_state");
-            }
-        }
-    }
-}
-
-static void dd_realloc_fr_cg(t_forcerec *fr,int nalloc)
-{
-    if (debug)
-    {
-        fprintf(debug,"Reallocating forcerec: currently %d, required %d, allocating %d\n",fr->cg_nalloc,nalloc,over_alloc_dd(nalloc));
-    }
-    fr->cg_nalloc = over_alloc_dd(nalloc);
-    srenew(fr->cg_cm,fr->cg_nalloc);
-    srenew(fr->cginfo,fr->cg_nalloc);
-}
-
-static void dd_realloc_state(t_state *state,rvec **f,int nalloc)
-{
-    int est;
-
-    if (debug)
-    {
-        fprintf(debug,"Reallocating state: currently %d, required %d, allocating %d\n",state->nalloc,nalloc,over_alloc_dd(nalloc));
-    }
-
-    state->nalloc = over_alloc_dd(nalloc);
-    
-    for(est=0; est<estNR; est++)
-    {
-        if (EST_DISTR(est) && (state->flags & (1<<est)))
-        {
-            switch(est) {
-            case estX:
-                srenew(state->x,state->nalloc);
-                break;
-            case estV:
-                srenew(state->v,state->nalloc);
-                break;
-            case estSDX:
-                srenew(state->sd_X,state->nalloc);
-                break;
-            case estCGP:
-                srenew(state->cg_p,state->nalloc);
-                break;
-            case estLD_RNG:
-            case estLD_RNGI:
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                /* No reallocation required */
-                break;
-            default:
-                gmx_incons("Unknown state entry encountered in dd_realloc_state");            
-            }
-        }
-    }
-    
-    if (f != NULL)
-    {
-        srenew(*f,state->nalloc);
-    }
-}
-
-static void dd_distribute_vec_sendrecv(gmx_domdec_t *dd,t_block *cgs,
-                                       rvec *v,rvec *lv)
-{
-    gmx_domdec_master_t *ma;
-    int  n,i,c,a,nalloc=0;
-    rvec *buf=NULL;
-    
-    if (DDMASTER(dd))
-    {
-        ma  = dd->ma;
-        
-        for(n=0; n<dd->nnodes; n++)
-        {
-            if (n != dd->rank)
-            {
-                if (ma->nat[n] > nalloc)
-                {
-                    nalloc = over_alloc_dd(ma->nat[n]);
-                    srenew(buf,nalloc);
-                }
-                /* Use lv as a temporary buffer */
-                a = 0;
-                for(i=ma->index[n]; i<ma->index[n+1]; i++)
-                {
-                    for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
-                    {
-                        copy_rvec(v[c],buf[a++]);
-                    }
-                }
-                if (a != ma->nat[n])
-                {
-                    gmx_fatal(FARGS,"Internal error a (%d) != nat (%d)",
-                              a,ma->nat[n]);
-                }
-                
-#ifdef GMX_MPI
-                MPI_Send(buf,ma->nat[n]*sizeof(rvec),MPI_BYTE,
-                         DDRANK(dd,n),n,dd->mpi_comm_all);
-#endif
-            }
-        }
-        sfree(buf);
-        n = DDMASTERRANK(dd);
-        a = 0;
-        for(i=ma->index[n]; i<ma->index[n+1]; i++)
-        {
-            for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
-            {
-                copy_rvec(v[c],lv[a++]);
-            }
-        }
-    }
-    else
-    {
-#ifdef GMX_MPI
-        MPI_Recv(lv,dd->nat_home*sizeof(rvec),MPI_BYTE,DDMASTERRANK(dd),
-                 MPI_ANY_TAG,dd->mpi_comm_all,MPI_STATUS_IGNORE);
-#endif
-    }
-}
-
-static void dd_distribute_vec_scatterv(gmx_domdec_t *dd,t_block *cgs,
-                                       rvec *v,rvec *lv)
-{
-    gmx_domdec_master_t *ma;
-    int  *scounts=NULL,*disps=NULL;
-    int  n,i,c,a,nalloc=0;
-    rvec *buf=NULL;
-    
-    if (DDMASTER(dd))
-    {
-        ma  = dd->ma;
-     
-        get_commbuffer_counts(dd,&scounts,&disps);
-
-        buf = ma->vbuf;
-        a = 0;
-        for(n=0; n<dd->nnodes; n++)
-        {
-            for(i=ma->index[n]; i<ma->index[n+1]; i++)
-            {
-                for(c=cgs->index[ma->cg[i]]; c<cgs->index[ma->cg[i]+1]; c++)
-                {
-                    copy_rvec(v[c],buf[a++]);
-                }
-            }
-        }
-    }
-
-    dd_scatterv(dd,scounts,disps,buf,dd->nat_home*sizeof(rvec),lv);
-}
-
-static void dd_distribute_vec(gmx_domdec_t *dd,t_block *cgs,rvec *v,rvec *lv)
-{
-    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
-    {
-        dd_distribute_vec_sendrecv(dd,cgs,v,lv);
-    }
-    else
-    {
-        dd_distribute_vec_scatterv(dd,cgs,v,lv);
-    }
-}
-
-static void dd_distribute_state(gmx_domdec_t *dd,t_block *cgs,
-                                t_state *state,t_state *state_local,
-                                rvec **f)
-{
-    int  i,j,ngtch,ngtcp,nh;
-
-    nh = state->nhchainlength;
-
-    if (DDMASTER(dd))
-    {
-        state_local->lambda = state->lambda;
-        state_local->veta   = state->veta;
-        state_local->vol0   = state->vol0;
-        copy_mat(state->box,state_local->box);
-        copy_mat(state->box_rel,state_local->box_rel);
-        copy_mat(state->boxv,state_local->boxv);
-        copy_mat(state->svir_prev,state_local->svir_prev);
-        copy_mat(state->fvir_prev,state_local->fvir_prev);
-        for(i=0; i<state_local->ngtc; i++)
-        {
-            for(j=0; j<nh; j++) {
-                state_local->nosehoover_xi[i*nh+j]        = state->nosehoover_xi[i*nh+j];
-                state_local->nosehoover_vxi[i*nh+j]       = state->nosehoover_vxi[i*nh+j];
-            }
-            state_local->therm_integral[i] = state->therm_integral[i];
-        }
-        for(i=0; i<state_local->nnhpres; i++)
-        {
-            for(j=0; j<nh; j++) {
-                state_local->nhpres_xi[i*nh+j]        = state->nhpres_xi[i*nh+j];
-                state_local->nhpres_vxi[i*nh+j]       = state->nhpres_vxi[i*nh+j];
-            }
-        }
-    }
-    dd_bcast(dd,sizeof(real),&state_local->lambda);
-    dd_bcast(dd,sizeof(real),&state_local->veta);
-    dd_bcast(dd,sizeof(real),&state_local->vol0);
-    dd_bcast(dd,sizeof(state_local->box),state_local->box);
-    dd_bcast(dd,sizeof(state_local->box_rel),state_local->box_rel);
-    dd_bcast(dd,sizeof(state_local->boxv),state_local->boxv);
-    dd_bcast(dd,sizeof(state_local->svir_prev),state_local->svir_prev);
-    dd_bcast(dd,sizeof(state_local->fvir_prev),state_local->fvir_prev);
-    dd_bcast(dd,((state_local->ngtc*nh)*sizeof(double)),state_local->nosehoover_xi);
-    dd_bcast(dd,((state_local->ngtc*nh)*sizeof(double)),state_local->nosehoover_vxi);
-    dd_bcast(dd,state_local->ngtc*sizeof(double),state_local->therm_integral);
-    dd_bcast(dd,((state_local->nnhpres*nh)*sizeof(double)),state_local->nhpres_xi);
-    dd_bcast(dd,((state_local->nnhpres*nh)*sizeof(double)),state_local->nhpres_vxi);
-
-    if (dd->nat_home > state_local->nalloc)
-    {
-        dd_realloc_state(state_local,f,dd->nat_home);
-    }
-    for(i=0; i<estNR; i++)
-    {
-        if (EST_DISTR(i) && (state_local->flags & (1<<i)))
-        {
-            switch (i) {
-            case estX:
-                dd_distribute_vec(dd,cgs,state->x,state_local->x);
-                break;
-            case estV:
-                dd_distribute_vec(dd,cgs,state->v,state_local->v);
-                break;
-            case estSDX:
-                dd_distribute_vec(dd,cgs,state->sd_X,state_local->sd_X);
-                break;
-            case estCGP:
-                dd_distribute_vec(dd,cgs,state->cg_p,state_local->cg_p);
-                break;
-            case estLD_RNG:
-                if (state->nrngi == 1)
-                {
-                    dd_bcastc(dd,
-                              state_local->nrng*sizeof(state_local->ld_rng[0]),
-                              state->ld_rng,state_local->ld_rng);
-                }
-                else
-                {
-                    dd_scatter(dd,
-                               state_local->nrng*sizeof(state_local->ld_rng[0]),
-                               state->ld_rng,state_local->ld_rng);
-                }
-                break;
-            case estLD_RNGI:
-                if (state->nrngi == 1)
-                {
-                    dd_bcastc(dd,sizeof(state_local->ld_rngi[0]),
-                              state->ld_rngi,state_local->ld_rngi);
-                }
-                else
-                {
-                     dd_scatter(dd,sizeof(state_local->ld_rngi[0]),
-                               state->ld_rngi,state_local->ld_rngi);
-                }   
-                break;
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                /* Not implemented yet */
-                break;
-            default:
-                gmx_incons("Unknown state entry encountered in dd_distribute_state");
-            }
-        }
-    }
-}
-
-static char dim2char(int dim)
-{
-    char c='?';
-    
-    switch (dim)
-    {
-    case XX: c = 'X'; break;
-    case YY: c = 'Y'; break;
-    case ZZ: c = 'Z'; break;
-    default: gmx_fatal(FARGS,"Unknown dim %d",dim);
-    }
-    
-    return c;
-}
-
-static void write_dd_grid_pdb(const char *fn,gmx_large_int_t step,
-                              gmx_domdec_t *dd,matrix box,gmx_ddbox_t *ddbox)
-{
-    rvec grid_s[2],*grid_r=NULL,cx,r;
-    char fname[STRLEN],format[STRLEN],buf[22];
-    FILE *out;
-    int  a,i,d,z,y,x;
-    matrix tric;
-    real vol;
-
-    copy_rvec(dd->comm->cell_x0,grid_s[0]);
-    copy_rvec(dd->comm->cell_x1,grid_s[1]);
-    
-    if (DDMASTER(dd))
-    {
-        snew(grid_r,2*dd->nnodes);
-    }
-    
-    dd_gather(dd,2*sizeof(rvec),grid_s[0],DDMASTER(dd) ? grid_r[0] : NULL);
-    
-    if (DDMASTER(dd))
-    {
-        for(d=0; d<DIM; d++)
-        {
-            for(i=0; i<DIM; i++)
-            {
-                if (d == i)
-                {
-                    tric[d][i] = 1;
-                }
-                else
-                {
-                    if (dd->nc[d] > 1 && d < ddbox->npbcdim)
-                    {
-                        tric[d][i] = box[i][d]/box[i][i];
-                    }
-                    else
-                    {
-                        tric[d][i] = 0;
-                    }
-                }
-            }
-        }
-        sprintf(fname,"%s_%s.pdb",fn,gmx_step_str(step,buf));
-        sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
-        out = gmx_fio_fopen(fname,"w");
-        gmx_write_pdb_box(out,dd->bScrewPBC ? epbcSCREW : epbcXYZ,box);
-        a = 1;
-        for(i=0; i<dd->nnodes; i++)
-        {
-            vol = dd->nnodes/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
-            for(d=0; d<DIM; d++)
-            {
-                vol *= grid_r[i*2+1][d] - grid_r[i*2][d];
-            }
-            for(z=0; z<2; z++)
-            {
-                for(y=0; y<2; y++)
-                {
-                    for(x=0; x<2; x++)
-                    {
-                        cx[XX] = grid_r[i*2+x][XX];
-                        cx[YY] = grid_r[i*2+y][YY];
-                        cx[ZZ] = grid_r[i*2+z][ZZ];
-                        mvmul(tric,cx,r);
-                        fprintf(out,format,"ATOM",a++,"CA","GLY",' ',1+i,
-                                10*r[XX],10*r[YY],10*r[ZZ],1.0,vol);
-                    }
-                }
-            }
-            for(d=0; d<DIM; d++)
-            {
-                for(x=0; x<4; x++)
-                {
-                    switch(d)
-                    {
-                    case 0: y = 1 + i*8 + 2*x; break;
-                    case 1: y = 1 + i*8 + 2*x - (x % 2); break;
-                    case 2: y = 1 + i*8 + x; break;
-                    }
-                    fprintf(out,"%6s%5d%5d\n","CONECT",y,y+(1<<d));
-                }
-            }
-        }
-        gmx_fio_fclose(out);
-        sfree(grid_r);
-    }
-}
-
-void write_dd_pdb(const char *fn,gmx_large_int_t step,const char *title,
-                  gmx_mtop_t *mtop,t_commrec *cr,
-                  int natoms,rvec x[],matrix box)
-{
-    char fname[STRLEN],format[STRLEN],format4[STRLEN],buf[22];
-    FILE *out;
-    int  i,ii,resnr,c;
-    char *atomname,*resname;
-    real b;
-    gmx_domdec_t *dd;
-    
-    dd = cr->dd;
-    if (natoms == -1)
-    {
-        natoms = dd->comm->nat[ddnatVSITE];
-    }
-    
-    sprintf(fname,"%s_%s_n%d.pdb",fn,gmx_step_str(step,buf),cr->sim_nodeid);
-    
-    sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
-    sprintf(format4,"%s%s\n",pdbformat4,"%6.2f%6.2f");
-    
-    out = gmx_fio_fopen(fname,"w");
-    
-    fprintf(out,"TITLE     %s\n",title);
-    gmx_write_pdb_box(out,dd->bScrewPBC ? epbcSCREW : epbcXYZ,box);
-    for(i=0; i<natoms; i++)
-    {
-        ii = dd->gatindex[i];
-        gmx_mtop_atominfo_global(mtop,ii,&atomname,&resnr,&resname);
-        if (i < dd->comm->nat[ddnatZONE])
-        {
-            c = 0;
-            while (i >= dd->cgindex[dd->comm->zones.cg_range[c+1]])
-            {
-                c++;
-            }
-            b = c;
-        }
-        else if (i < dd->comm->nat[ddnatVSITE])
-        {
-            b = dd->comm->zones.n;
-        }
-        else
-        {
-            b = dd->comm->zones.n + 1;
-        }
-        fprintf(out,strlen(atomname)<4 ? format : format4,
-                "ATOM",(ii+1)%100000,
-                atomname,resname,' ',resnr%10000,' ',
-                10*x[i][XX],10*x[i][YY],10*x[i][ZZ],1.0,b);
-    }
-    fprintf(out,"TER\n");
-    
-    gmx_fio_fclose(out);
-}
-
-real dd_cutoff_mbody(gmx_domdec_t *dd)
-{
-    gmx_domdec_comm_t *comm;
-    int  di;
-    real r;
-
-    comm = dd->comm;
-
-    r = -1;
-    if (comm->bInterCGBondeds)
-    {
-        if (comm->cutoff_mbody > 0)
-        {
-            r = comm->cutoff_mbody;
-        }
-        else
-        {
-            /* cutoff_mbody=0 means we do not have DLB */
-            r = comm->cellsize_min[dd->dim[0]];
-            for(di=1; di<dd->ndim; di++)
-            {
-                r = min(r,comm->cellsize_min[dd->dim[di]]);
-            }
-            if (comm->bBondComm)
-            {
-                r = max(r,comm->cutoff_mbody);
-            }
-            else
-            {
-                r = min(r,comm->cutoff);
-            }
-        }
-    }
-
-    return r;
-}
-
-real dd_cutoff_twobody(gmx_domdec_t *dd)
-{
-    real r_mb;
-
-    r_mb = dd_cutoff_mbody(dd);
-
-    return max(dd->comm->cutoff,r_mb);
-}
-
-
-static void dd_cart_coord2pmecoord(gmx_domdec_t *dd,ivec coord,ivec coord_pme)
-{
-    int nc,ntot;
-    
-    nc   = dd->nc[dd->comm->cartpmedim];
-    ntot = dd->comm->ntot[dd->comm->cartpmedim];
-    copy_ivec(coord,coord_pme);
-    coord_pme[dd->comm->cartpmedim] =
-        nc + (coord[dd->comm->cartpmedim]*(ntot - nc) + (ntot - nc)/2)/nc;
-}
-
-static int low_ddindex2pmeindex(int ndd,int npme,int ddindex)
-{
-    /* Here we assign a PME node to communicate with this DD node
-     * by assuming that the major index of both is x.
-     * We add cr->npmenodes/2 to obtain an even distribution.
-     */
-    return (ddindex*npme + npme/2)/ndd;
-}
-
-static int ddindex2pmeindex(const gmx_domdec_t *dd,int ddindex)
-{
-    return low_ddindex2pmeindex(dd->nnodes,dd->comm->npmenodes,ddindex);
-}
-
-static int cr_ddindex2pmeindex(const t_commrec *cr,int ddindex)
-{
-    return low_ddindex2pmeindex(cr->dd->nnodes,cr->npmenodes,ddindex);
-}
-
-static int *dd_pmenodes(t_commrec *cr)
-{
-    int *pmenodes;
-    int n,i,p0,p1;
-    
-    snew(pmenodes,cr->npmenodes);
-    n = 0;
-    for(i=0; i<cr->dd->nnodes; i++) {
-        p0 = cr_ddindex2pmeindex(cr,i);
-        p1 = cr_ddindex2pmeindex(cr,i+1);
-        if (i+1 == cr->dd->nnodes || p1 > p0) {
-            if (debug)
-                fprintf(debug,"pmenode[%d] = %d\n",n,i+1+n);
-            pmenodes[n] = i + 1 + n;
-            n++;
-        }
-    }
-
-    return pmenodes;
-}
-
-static int gmx_ddcoord2pmeindex(t_commrec *cr,int x,int y,int z)
-{
-    gmx_domdec_t *dd;
-    ivec coords,coords_pme,nc;
-    int  slab;
-    
-    dd = cr->dd;
-    /*
-      if (dd->comm->bCartesian) {
-      gmx_ddindex2xyz(dd->nc,ddindex,coords);
-      dd_coords2pmecoords(dd,coords,coords_pme);
-      copy_ivec(dd->ntot,nc);
-      nc[dd->cartpmedim]         -= dd->nc[dd->cartpmedim];
-      coords_pme[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
-      
-      slab = (coords_pme[XX]*nc[YY] + coords_pme[YY])*nc[ZZ] + coords_pme[ZZ];
-      } else {
-      slab = (ddindex*cr->npmenodes + cr->npmenodes/2)/dd->nnodes;
-      }
-    */
-    coords[XX] = x;
-    coords[YY] = y;
-    coords[ZZ] = z;
-    slab = ddindex2pmeindex(dd,dd_index(dd->nc,coords));
-    
-    return slab;
-}
-
-static int ddcoord2simnodeid(t_commrec *cr,int x,int y,int z)
-{
-    gmx_domdec_comm_t *comm;
-    ivec coords;
-    int  ddindex,nodeid=-1;
-    
-    comm = cr->dd->comm;
-    
-    coords[XX] = x;
-    coords[YY] = y;
-    coords[ZZ] = z;
-    if (comm->bCartesianPP_PME)
-    {
-#ifdef GMX_MPI
-        MPI_Cart_rank(cr->mpi_comm_mysim,coords,&nodeid);
-#endif
-    }
-    else
-    {
-        ddindex = dd_index(cr->dd->nc,coords);
-        if (comm->bCartesianPP)
-        {
-            nodeid = comm->ddindex2simnodeid[ddindex];
-        }
-        else
-        {
-            if (comm->pmenodes)
-            {
-                nodeid = ddindex + gmx_ddcoord2pmeindex(cr,x,y,z);
-            }
-            else
-            {
-                nodeid = ddindex;
-            }
-        }
-    }
-  
-    return nodeid;
-}
-
-static int dd_simnode2pmenode(t_commrec *cr,int sim_nodeid)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    ivec coord,coord_pme;
-    int  i;
-    int  pmenode=-1;
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-    /* This assumes a uniform x domain decomposition grid cell size */
-    if (comm->bCartesianPP_PME)
-    {
-#ifdef GMX_MPI
-        MPI_Cart_coords(cr->mpi_comm_mysim,sim_nodeid,DIM,coord);
-        if (coord[comm->cartpmedim] < dd->nc[comm->cartpmedim])
-        {
-            /* This is a PP node */
-            dd_cart_coord2pmecoord(dd,coord,coord_pme);
-            MPI_Cart_rank(cr->mpi_comm_mysim,coord_pme,&pmenode);
-        }
-#endif
-    }
-    else if (comm->bCartesianPP)
-    {
-        if (sim_nodeid < dd->nnodes)
-        {
-            pmenode = dd->nnodes + ddindex2pmeindex(dd,sim_nodeid);
-        }
-    }
-    else
-    {
-        /* This assumes DD cells with identical x coordinates
-         * are numbered sequentially.
-         */
-        if (dd->comm->pmenodes == NULL)
-        {
-            if (sim_nodeid < dd->nnodes)
-            {
-                /* The DD index equals the nodeid */
-                pmenode = dd->nnodes + ddindex2pmeindex(dd,sim_nodeid);
-            }
-        }
-        else
-        {
-            i = 0;
-            while (sim_nodeid > dd->comm->pmenodes[i])
-            {
-                i++;
-            }
-            if (sim_nodeid < dd->comm->pmenodes[i])
-            {
-                pmenode = dd->comm->pmenodes[i];
-            }
-        }
-    }
-    
-    return pmenode;
-}
-
-gmx_bool gmx_pmeonlynode(t_commrec *cr,int sim_nodeid)
-{
-    gmx_bool bPMEOnlyNode;
-    
-    if (DOMAINDECOMP(cr))
-    {
-        bPMEOnlyNode = (dd_simnode2pmenode(cr,sim_nodeid) == -1);
-    }
-    else
-    {
-        bPMEOnlyNode = FALSE;
-    }
-    
-    return bPMEOnlyNode;
-}
-
-void get_pme_ddnodes(t_commrec *cr,int pmenodeid,
-                     int *nmy_ddnodes,int **my_ddnodes,int *node_peer)
-{
-    gmx_domdec_t *dd;
-    int x,y,z;
-    ivec coord,coord_pme;
-    
-    dd = cr->dd;
-    
-    snew(*my_ddnodes,(dd->nnodes+cr->npmenodes-1)/cr->npmenodes);
-    
-    *nmy_ddnodes = 0;
-    for(x=0; x<dd->nc[XX]; x++)
-    {
-        for(y=0; y<dd->nc[YY]; y++)
-        {
-            for(z=0; z<dd->nc[ZZ]; z++)
-            {
-                if (dd->comm->bCartesianPP_PME)
-                {
-                    coord[XX] = x;
-                    coord[YY] = y;
-                    coord[ZZ] = z;
-                    dd_cart_coord2pmecoord(dd,coord,coord_pme);
-                    if (dd->ci[XX] == coord_pme[XX] &&
-                        dd->ci[YY] == coord_pme[YY] &&
-                        dd->ci[ZZ] == coord_pme[ZZ])
-                        (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr,x,y,z);
-                }
-                else
-                {
-                    /* The slab corresponds to the nodeid in the PME group */
-                    if (gmx_ddcoord2pmeindex(cr,x,y,z) == pmenodeid)
-                    {
-                        (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr,x,y,z);
-                    }
-                }
-            }
-        }
-    }
-    
-    /* The last PP-only node is the peer node */
-    *node_peer = (*my_ddnodes)[*nmy_ddnodes-1];
-    
-    if (debug)
-    {
-        fprintf(debug,"Receive coordinates from PP nodes:");
-        for(x=0; x<*nmy_ddnodes; x++)
-        {
-            fprintf(debug," %d",(*my_ddnodes)[x]);
-        }
-        fprintf(debug,"\n");
-    }
-}
-
-static gmx_bool receive_vir_ener(t_commrec *cr)
-{
-    gmx_domdec_comm_t *comm;
-    int  pmenode,coords[DIM],rank;
-    gmx_bool bReceive;
-    
-    bReceive = TRUE;
-    if (cr->npmenodes < cr->dd->nnodes)
-    {
-        comm = cr->dd->comm;
-        if (comm->bCartesianPP_PME)
-        {
-            pmenode = dd_simnode2pmenode(cr,cr->sim_nodeid);
-#ifdef GMX_MPI
-            MPI_Cart_coords(cr->mpi_comm_mysim,cr->sim_nodeid,DIM,coords);
-            coords[comm->cartpmedim]++;
-            if (coords[comm->cartpmedim] < cr->dd->nc[comm->cartpmedim])
-            {
-                MPI_Cart_rank(cr->mpi_comm_mysim,coords,&rank);
-                if (dd_simnode2pmenode(cr,rank) == pmenode)
-                {
-                    /* This is not the last PP node for pmenode */
-                    bReceive = FALSE;
-                }
-            }
-#endif  
-        }
-        else
-        {
-            pmenode = dd_simnode2pmenode(cr,cr->sim_nodeid);
-            if (cr->sim_nodeid+1 < cr->nnodes &&
-                dd_simnode2pmenode(cr,cr->sim_nodeid+1) == pmenode)
-            {
-                /* This is not the last PP node for pmenode */
-                bReceive = FALSE;
-            }
-        }
-    }
-    
-    return bReceive;
-}
-
-static void set_zones_ncg_home(gmx_domdec_t *dd)
-{
-    gmx_domdec_zones_t *zones;
-    int i;
-
-    zones = &dd->comm->zones;
-
-    zones->cg_range[0] = 0;
-    for(i=1; i<zones->n+1; i++)
-    {
-        zones->cg_range[i] = dd->ncg_home;
-    }
-}
-
-static void rebuild_cgindex(gmx_domdec_t *dd,int *gcgs_index,t_state *state)
-{
-    int nat,i,*ind,*dd_cg_gl,*cgindex,cg_gl;
-    
-    ind = state->cg_gl;
-    dd_cg_gl = dd->index_gl;
-    cgindex  = dd->cgindex;
-    nat = 0;
-    cgindex[0] = nat;
-    for(i=0; i<state->ncg_gl; i++)
-    {
-        cgindex[i] = nat;
-        cg_gl = ind[i];
-        dd_cg_gl[i] = cg_gl;
-        nat += gcgs_index[cg_gl+1] - gcgs_index[cg_gl];
-    }
-    cgindex[i] = nat;
-    
-    dd->ncg_home = state->ncg_gl;
-    dd->nat_home = nat;
-
-    set_zones_ncg_home(dd);
-}
-
-static int ddcginfo(const cginfo_mb_t *cginfo_mb,int cg)
-{
-    while (cg >= cginfo_mb->cg_end)
-    {
-        cginfo_mb++;
-    }
-
-    return cginfo_mb->cginfo[(cg - cginfo_mb->cg_start) % cginfo_mb->cg_mod];
-}
-
-static void dd_set_cginfo(int *index_gl,int cg0,int cg1,
-                          t_forcerec *fr,char *bLocalCG)
-{
-    cginfo_mb_t *cginfo_mb;
-    int *cginfo;
-    int cg;
-
-    if (fr != NULL)
-    {
-        cginfo_mb = fr->cginfo_mb;
-        cginfo    = fr->cginfo;
-
-        for(cg=cg0; cg<cg1; cg++)
-        {
-            cginfo[cg] = ddcginfo(cginfo_mb,index_gl[cg]);
-        }
-    }
-
-    if (bLocalCG != NULL)
-    {
-        for(cg=cg0; cg<cg1; cg++)
-        {
-            bLocalCG[index_gl[cg]] = TRUE;
-        }
-    }
-}
-
-static void make_dd_indices(gmx_domdec_t *dd,int *gcgs_index,int cg_start)
-{
-    int nzone,zone,zone1,cg0,cg,cg_gl,a,a_gl;
-    int *zone2cg,*zone_ncg1,*index_gl,*gatindex;
-    gmx_ga2la_t *ga2la;
-    char *bLocalCG;
-
-    bLocalCG = dd->comm->bLocalCG;
-
-    if (dd->nat_tot > dd->gatindex_nalloc)
-    {
-        dd->gatindex_nalloc = over_alloc_dd(dd->nat_tot);
-        srenew(dd->gatindex,dd->gatindex_nalloc);
-    }
-
-    nzone      = dd->comm->zones.n;
-    zone2cg    = dd->comm->zones.cg_range;
-    zone_ncg1  = dd->comm->zone_ncg1;
-    index_gl   = dd->index_gl;
-    gatindex   = dd->gatindex;
-
-    if (zone2cg[1] != dd->ncg_home)
-    {
-        gmx_incons("dd->ncg_zone is not up to date");
-    }
-    
-    /* Make the local to global and global to local atom index */
-    a = dd->cgindex[cg_start];
-    for(zone=0; zone<nzone; zone++)
-    {
-        if (zone == 0)
-        {
-            cg0 = cg_start;
-        }
-        else
-        {
-            cg0 = zone2cg[zone];
-        }
-        for(cg=cg0; cg<zone2cg[zone+1]; cg++)
-        {
-            zone1 = zone;
-            if (cg - cg0 >= zone_ncg1[zone])
-            {
-                /* Signal that this cg is from more than one zone away */
-                zone1 += nzone;
-            }
-            cg_gl = index_gl[cg];
-            for(a_gl=gcgs_index[cg_gl]; a_gl<gcgs_index[cg_gl+1]; a_gl++)
-            {
-                gatindex[a] = a_gl;
-                ga2la_set(dd->ga2la,a_gl,a,zone1);
-                a++;
-            }
-        }
-    }
-}
-
-static int check_bLocalCG(gmx_domdec_t *dd,int ncg_sys,const char *bLocalCG,
-                          const char *where)
-{
-    int ncg,i,ngl,nerr;
-
-    nerr = 0;
-    if (bLocalCG == NULL)
-    {
-        return nerr;
-    }
-    for(i=0; i<dd->ncg_tot; i++)
-    {
-        if (!bLocalCG[dd->index_gl[i]])
-        {
-            fprintf(stderr,
-                    "DD node %d, %s: cg %d, global cg %d is not marked in bLocalCG (ncg_home %d)\n",dd->rank,where,i+1,dd->index_gl[i]+1,dd->ncg_home);
-            nerr++;
-        }
-    }
-    ngl = 0;
-    for(i=0; i<ncg_sys; i++)
-    {
-        if (bLocalCG[i])
-        {
-            ngl++;
-        }
-    }
-    if (ngl != dd->ncg_tot)
-    {
-        fprintf(stderr,"DD node %d, %s: In bLocalCG %d cgs are marked as local, whereas there are %d\n",dd->rank,where,ngl,dd->ncg_tot);
-        nerr++;
-    }
-
-    return nerr;
-}
-
-static void check_index_consistency(gmx_domdec_t *dd,
-                                    int natoms_sys,int ncg_sys,
-                                    const char *where)
-{
-    int  nerr,ngl,i,a,cell;
-    int  *have;
-
-    nerr = 0;
-
-    if (dd->comm->DD_debug > 1)
-    {
-        snew(have,natoms_sys);
-        for(a=0; a<dd->nat_tot; a++)
-        {
-            if (have[dd->gatindex[a]] > 0)
-            {
-                fprintf(stderr,"DD node %d: global atom %d occurs twice: index %d and %d\n",dd->rank,dd->gatindex[a]+1,have[dd->gatindex[a]],a+1);
-            }
-            else
-            {
-                have[dd->gatindex[a]] = a + 1;
-            }
-        }
-        sfree(have);
-    }
-
-    snew(have,dd->nat_tot);
-
-    ngl  = 0;
-    for(i=0; i<natoms_sys; i++)
-    {
-        if (ga2la_get(dd->ga2la,i,&a,&cell))
-        {
-            if (a >= dd->nat_tot)
-            {
-                fprintf(stderr,"DD node %d: global atom %d marked as local atom %d, which is larger than nat_tot (%d)\n",dd->rank,i+1,a+1,dd->nat_tot);
-                nerr++;
-            }
-            else
-            {
-                have[a] = 1;
-                if (dd->gatindex[a] != i)
-                {
-                    fprintf(stderr,"DD node %d: global atom %d marked as local atom %d, which has global atom index %d\n",dd->rank,i+1,a+1,dd->gatindex[a]+1);
-                    nerr++;
-                }
-            }
-            ngl++;
-        }
-    }
-    if (ngl != dd->nat_tot)
-    {
-        fprintf(stderr,
-                "DD node %d, %s: %d global atom indices, %d local atoms\n",
-                dd->rank,where,ngl,dd->nat_tot);
-    }
-    for(a=0; a<dd->nat_tot; a++)
-    {
-        if (have[a] == 0)
-        {
-            fprintf(stderr,
-                    "DD node %d, %s: local atom %d, global %d has no global index\n",
-                    dd->rank,where,a+1,dd->gatindex[a]+1);
-        }
-    }
-    sfree(have);
-
-    nerr += check_bLocalCG(dd,ncg_sys,dd->comm->bLocalCG,where);
-
-    if (nerr > 0) {
-        gmx_fatal(FARGS,"DD node %d, %s: %d atom/cg index inconsistencies",
-                  dd->rank,where,nerr);
-    }
-}
-
-static void clear_dd_indices(gmx_domdec_t *dd,int cg_start,int a_start)
-{
-    int  i;
-    char *bLocalCG;
-
-    if (a_start == 0)
-    {
-        /* Clear the whole list without searching */
-        ga2la_clear(dd->ga2la);
-    }
-    else
-    {
-        for(i=a_start; i<dd->nat_tot; i++)
-        {
-            ga2la_del(dd->ga2la,dd->gatindex[i]);
-        }
-    }
-
-    bLocalCG = dd->comm->bLocalCG;
-    if (bLocalCG)
-    {
-        for(i=cg_start; i<dd->ncg_tot; i++)
-        {
-            bLocalCG[dd->index_gl[i]] = FALSE;
-        }
-    }
-
-    dd_clear_local_vsite_indices(dd);
-    
-    if (dd->constraints)
-    {
-        dd_clear_local_constraint_indices(dd);
-    }
-}
-
-static real grid_jump_limit(gmx_domdec_comm_t *comm,int dim_ind)
-{
-    real grid_jump_limit;
-
-    /* The distance between the boundaries of cells at distance
-     * x+-1,y+-1 or y+-1,z+-1 is limited by the cut-off restrictions
-     * and by the fact that cells should not be shifted by more than
-     * half their size, such that cg's only shift by one cell
-     * at redecomposition.
-     */
-    grid_jump_limit = comm->cellsize_limit;
-    if (!comm->bVacDLBNoLimit)
-    {
-        grid_jump_limit = max(grid_jump_limit,
-                              comm->cutoff/comm->cd[dim_ind].np);
-    }
-
-    return grid_jump_limit;
-}
-
-static void check_grid_jump(gmx_large_int_t step,gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
-{
-    gmx_domdec_comm_t *comm;
-    int  d,dim;
-    real limit,bfac;
-    
-    comm = dd->comm;
-    
-    for(d=1; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        limit = grid_jump_limit(comm,d);
-        bfac = ddbox->box_size[dim];
-        if (ddbox->tric_dir[dim])
-        {
-            bfac *= ddbox->skew_fac[dim];
-        }
-        if ((comm->cell_f1[d] - comm->cell_f_max0[d])*bfac <  limit ||
-            (comm->cell_f0[d] - comm->cell_f_min1[d])*bfac > -limit)
-        {
-            char buf[22];
-            gmx_fatal(FARGS,"Step %s: The domain decomposition grid has shifted too much in the %c-direction around cell %d %d %d\n",
-                      gmx_step_str(step,buf),
-                      dim2char(dim),dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-        }
-    }
-}
-
-static int dd_load_count(gmx_domdec_comm_t *comm)
-{
-    return (comm->eFlop ? comm->flop_n : comm->cycl_n[ddCyclF]);
-}
-
-static float dd_force_load(gmx_domdec_comm_t *comm)
-{
-    float load;
-    
-    if (comm->eFlop)
-    {
-        load = comm->flop;
-        if (comm->eFlop > 1)
-        {
-            load *= 1.0 + (comm->eFlop - 1)*(0.1*rand()/RAND_MAX - 0.05);
-        }
-    } 
-    else
-    {
-        load = comm->cycl[ddCyclF];
-        if (comm->cycl_n[ddCyclF] > 1)
-        {
-            /* Subtract the maximum of the last n cycle counts
-             * to get rid of possible high counts due to other soures,
-             * for instance system activity, that would otherwise
-             * affect the dynamic load balancing.
-             */
-            load -= comm->cycl_max[ddCyclF];
-        }
-    }
-    
-    return load;
-}
-
-static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dim,real **dim_f)
-{
-    gmx_domdec_comm_t *comm;
-    int i;
-    
-    comm = dd->comm;
-    
-    snew(*dim_f,dd->nc[dim]+1);
-    (*dim_f)[0] = 0;
-    for(i=1; i<dd->nc[dim]; i++)
-    {
-        if (comm->slb_frac[dim])
-        {
-            (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
-        }
-        else
-        {
-            (*dim_f)[i] = (real)i/(real)dd->nc[dim];
-        }
-    }
-    (*dim_f)[dd->nc[dim]] = 1;
-}
-
-static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,int dimind)
-{
-    int         pmeindex,slab,nso,i;
-    ivec xyz;
-    
-    if (dimind == 0 && dd->dim[0] == YY && dd->comm->npmenodes_x == 1)
-    {
-        ddpme->dim = YY;
-    }
-    else
-    {
-        ddpme->dim = dimind;
-    }
-    ddpme->dim_match = (ddpme->dim == dd->dim[dimind]);
-    
-    ddpme->nslab = (ddpme->dim == 0 ?
-                    dd->comm->npmenodes_x :
-                    dd->comm->npmenodes_y);
-
-    if (ddpme->nslab <= 1)
-    {
-        return;
-    }
-
-    nso = dd->comm->npmenodes/ddpme->nslab;
-    /* Determine for each PME slab the PP location range for dimension dim */
-    snew(ddpme->pp_min,ddpme->nslab);
-    snew(ddpme->pp_max,ddpme->nslab);
-    for(slab=0; slab<ddpme->nslab; slab++) {
-        ddpme->pp_min[slab] = dd->nc[dd->dim[dimind]] - 1;
-        ddpme->pp_max[slab] = 0;
-    }
-    for(i=0; i<dd->nnodes; i++) {
-        ddindex2xyz(dd->nc,i,xyz);
-        /* For y only use our y/z slab.
-         * This assumes that the PME x grid size matches the DD grid size.
-         */
-        if (dimind == 0 || xyz[XX] == dd->ci[XX]) {
-            pmeindex = ddindex2pmeindex(dd,i);
-            if (dimind == 0) {
-                slab = pmeindex/nso;
-            } else {
-                slab = pmeindex % ddpme->nslab;
-            }
-            ddpme->pp_min[slab] = min(ddpme->pp_min[slab],xyz[dimind]);
-            ddpme->pp_max[slab] = max(ddpme->pp_max[slab],xyz[dimind]);
-        }
-    }
-
-    set_slb_pme_dim_f(dd,ddpme->dim,&ddpme->slb_dim_f);
-}
-
-int dd_pme_maxshift_x(gmx_domdec_t *dd)
-{
-    if (dd->comm->ddpme[0].dim == XX)
-    {
-        return dd->comm->ddpme[0].maxshift;
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-int dd_pme_maxshift_y(gmx_domdec_t *dd)
-{
-    if (dd->comm->ddpme[0].dim == YY)
-    {
-        return dd->comm->ddpme[0].maxshift;
-    }
-    else if (dd->comm->npmedecompdim >= 2 && dd->comm->ddpme[1].dim == YY)
-    {
-        return dd->comm->ddpme[1].maxshift;
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
-                             gmx_bool bUniform,gmx_ddbox_t *ddbox,real *cell_f)
-{
-    gmx_domdec_comm_t *comm;
-    int  nc,ns,s;
-    int  *xmin,*xmax;
-    real range,pme_boundary;
-    int  sh;
-    
-    comm = dd->comm;
-    nc  = dd->nc[ddpme->dim];
-    ns  = ddpme->nslab;
-    
-    if (!ddpme->dim_match)
-    {
-        /* PP decomposition is not along dim: the worst situation */
-        sh = ns/2;
-    }
-    else if (ns <= 3 || (bUniform && ns == nc))
-    {
-        /* The optimal situation */
-        sh = 1;
-    }
-    else
-    {
-        /* We need to check for all pme nodes which nodes they
-         * could possibly need to communicate with.
-         */
-        xmin = ddpme->pp_min;
-        xmax = ddpme->pp_max;
-        /* Allow for atoms to be maximally 2/3 times the cut-off
-         * out of their DD cell. This is a reasonable balance between
-         * between performance and support for most charge-group/cut-off
-         * combinations.
-         */
-        range  = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
-        /* Avoid extra communication when we are exactly at a boundary */
-        range *= 0.999;
-        
-        sh = 1;
-        for(s=0; s<ns; s++)
-        {
-            /* PME slab s spreads atoms between box frac. s/ns and (s+1)/ns */
-            pme_boundary = (real)s/ns;
-            while (sh+1 < ns &&
-                   ((s-(sh+1) >= 0 &&
-                     cell_f[xmax[s-(sh+1)   ]+1]     + range > pme_boundary) ||
-                    (s-(sh+1) <  0 &&
-                     cell_f[xmax[s-(sh+1)+ns]+1] - 1 + range > pme_boundary)))
-            {
-                sh++;
-            }
-            pme_boundary = (real)(s+1)/ns;
-            while (sh+1 < ns &&
-                   ((s+(sh+1) <  ns &&
-                     cell_f[xmin[s+(sh+1)   ]  ]     - range < pme_boundary) ||
-                    (s+(sh+1) >= ns &&
-                     cell_f[xmin[s+(sh+1)-ns]  ] + 1 - range < pme_boundary)))
-            {
-                sh++;
-            }
-        }
-    }
-    
-    ddpme->maxshift = sh;
-    
-    if (debug)
-    {
-        fprintf(debug,"PME slab communication range for dim %d is %d\n",
-                ddpme->dim,ddpme->maxshift);
-    }
-}
-
-static void check_box_size(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
-{
-    int d,dim;
-    
-    for(d=0; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        if (dim < ddbox->nboundeddim &&
-            ddbox->box_size[dim]*ddbox->skew_fac[dim] <
-            dd->nc[dim]*dd->comm->cellsize_limit*DD_CELL_MARGIN)
-        {
-            gmx_fatal(FARGS,"The %c-size of the box (%f) times the triclinic skew factor (%f) is smaller than the number of DD cells (%d) times the smallest allowed cell size (%f)\n",
-                      dim2char(dim),ddbox->box_size[dim],ddbox->skew_fac[dim],
-                      dd->nc[dim],dd->comm->cellsize_limit);
-        }
-    }
-}
-
-static void set_dd_cell_sizes_slb(gmx_domdec_t *dd,gmx_ddbox_t *ddbox,
-                                  gmx_bool bMaster,ivec npulse)
-{
-    gmx_domdec_comm_t *comm;
-    int  d,j;
-    rvec cellsize_min;
-    real *cell_x,cell_dx,cellsize;
-    
-    comm = dd->comm;
-    
-    for(d=0; d<DIM; d++)
-    {
-        cellsize_min[d] = ddbox->box_size[d]*ddbox->skew_fac[d];
-        npulse[d] = 1;
-        if (dd->nc[d] == 1 || comm->slb_frac[d] == NULL)
-        {
-            /* Uniform grid */
-            cell_dx = ddbox->box_size[d]/dd->nc[d];
-            if (bMaster)
-            {
-                for(j=0; j<dd->nc[d]+1; j++)
-                {
-                    dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
-                }
-            }
-            else
-            {
-                comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d]  )*cell_dx;
-                comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
-            }
-            cellsize = cell_dx*ddbox->skew_fac[d];
-            while (cellsize*npulse[d] < comm->cutoff && npulse[d] < dd->nc[d]-1)
-            {
-                npulse[d]++;
-            }
-            cellsize_min[d] = cellsize;
-        }
-        else
-        {
-            /* Statically load balanced grid */
-            /* Also when we are not doing a master distribution we determine
-             * all cell borders in a loop to obtain identical values
-             * to the master distribution case and to determine npulse.
-             */
-            if (bMaster)
-            {
-                cell_x = dd->ma->cell_x[d];
-            }
-            else
-            {
-                snew(cell_x,dd->nc[d]+1);
-            }
-            cell_x[0] = ddbox->box0[d];
-            for(j=0; j<dd->nc[d]; j++)
-            {
-                cell_dx = ddbox->box_size[d]*comm->slb_frac[d][j];
-                cell_x[j+1] = cell_x[j] + cell_dx;
-                cellsize = cell_dx*ddbox->skew_fac[d];
-                while (cellsize*npulse[d] < comm->cutoff &&
-                       npulse[d] < dd->nc[d]-1)
-                {
-                    npulse[d]++;
-                }
-                cellsize_min[d] = min(cellsize_min[d],cellsize);
-            }
-            if (!bMaster)
-            {
-                comm->cell_x0[d] = cell_x[dd->ci[d]];
-                comm->cell_x1[d] = cell_x[dd->ci[d]+1];
-                sfree(cell_x);
-            }
-        }
-        /* The following limitation is to avoid that a cell would receive
-         * some of its own home charge groups back over the periodic boundary.
-         * Double charge groups cause trouble with the global indices.
-         */
-        if (d < ddbox->npbcdim &&
-            dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
-        {
-            gmx_fatal_collective(FARGS,NULL,dd,
-                                 "The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
-                                 dim2char(d),ddbox->box_size[d],ddbox->skew_fac[d],
-                                 comm->cutoff,
-                                 dd->nc[d],dd->nc[d],
-                                 dd->nnodes > dd->nc[d] ? "cells" : "processors");
-        }
-    }
-    
-    if (!comm->bDynLoadBal)
-    {
-        copy_rvec(cellsize_min,comm->cellsize_min);
-    }
-   
-    for(d=0; d<comm->npmedecompdim; d++)
-    {
-        set_pme_maxshift(dd,&comm->ddpme[d],
-                         comm->slb_frac[dd->dim[d]]==NULL,ddbox,
-                         comm->ddpme[d].slb_dim_f);
-    }
-}
-
-
-static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
-                                       int d,int dim,gmx_domdec_root_t *root,
-                                       gmx_ddbox_t *ddbox,
-                                       gmx_bool bUniform,gmx_large_int_t step, real cellsize_limit_f, int range[])
-{
-    gmx_domdec_comm_t *comm;
-    int  ncd,i,j,nmin,nmin_old;
-    gmx_bool bLimLo,bLimHi;
-    real *cell_size;
-    real fac,halfway,cellsize_limit_f_i,region_size;
-    gmx_bool bPBC,bLastHi=FALSE;
-    int nrange[]={range[0],range[1]};
-
-    region_size= root->cell_f[range[1]]-root->cell_f[range[0]];  
-
-    comm = dd->comm;
-
-    ncd = dd->nc[dim];
-
-    bPBC = (dim < ddbox->npbcdim);
-
-    cell_size = root->buf_ncd;
-
-    if (debug) 
-    {
-        fprintf(debug,"enforce_limits: %d %d\n",range[0],range[1]);
-    }
-
-    /* First we need to check if the scaling does not make cells
-     * smaller than the smallest allowed size.
-     * We need to do this iteratively, since if a cell is too small,
-     * it needs to be enlarged, which makes all the other cells smaller,
-     * which could in turn make another cell smaller than allowed.
-     */
-    for(i=range[0]; i<range[1]; i++)
-    {
-        root->bCellMin[i] = FALSE;
-    }
-    nmin = 0;
-    do
-    {
-        nmin_old = nmin;
-        /* We need the total for normalization */
-        fac = 0;
-        for(i=range[0]; i<range[1]; i++)
-        {
-            if (root->bCellMin[i] == FALSE)
-            {
-                fac += cell_size[i];
-            }
-        }
-        fac = ( region_size - nmin*cellsize_limit_f)/fac; /* substracting cells already set to cellsize_limit_f */
-        /* Determine the cell boundaries */
-        for(i=range[0]; i<range[1]; i++)
-        {
-            if (root->bCellMin[i] == FALSE)
-            {
-                cell_size[i] *= fac;
-                if (!bPBC && (i == 0 || i == dd->nc[dim] -1))
-                {
-                    cellsize_limit_f_i = 0;
-                }
-                else
-                {
-                    cellsize_limit_f_i = cellsize_limit_f;
-                }
-                if (cell_size[i] < cellsize_limit_f_i)
-                {
-                    root->bCellMin[i] = TRUE;
-                    cell_size[i] = cellsize_limit_f_i;
-                    nmin++;
-                }
-            }
-            root->cell_f[i+1] = root->cell_f[i] + cell_size[i];
-        }
-    }
-    while (nmin > nmin_old);
-    
-    i=range[1]-1;
-    cell_size[i] = root->cell_f[i+1] - root->cell_f[i];
-    /* For this check we should not use DD_CELL_MARGIN,
-     * but a slightly smaller factor,
-     * since rounding could get use below the limit.
-     */
-    if (bPBC && cell_size[i] < cellsize_limit_f*DD_CELL_MARGIN2/DD_CELL_MARGIN)
-    {
-        char buf[22];
-        gmx_fatal(FARGS,"Step %s: the dynamic load balancing could not balance dimension %c: box size %f, triclinic skew factor %f, #cells %d, minimum cell size %f\n",
-                  gmx_step_str(step,buf),
-                  dim2char(dim),ddbox->box_size[dim],ddbox->skew_fac[dim],
-                  ncd,comm->cellsize_min[dim]);
-    }
-    
-    root->bLimited = (nmin > 0) || (range[0]>0) || (range[1]<ncd);
-    
-    if (!bUniform)
-    {
-        /* Check if the boundary did not displace more than halfway
-         * each of the cells it bounds, as this could cause problems,
-         * especially when the differences between cell sizes are large.
-         * If changes are applied, they will not make cells smaller
-         * than the cut-off, as we check all the boundaries which
-         * might be affected by a change and if the old state was ok,
-         * the cells will at most be shrunk back to their old size.
-         */
-        for(i=range[0]+1; i<range[1]; i++)
-        {
-            halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i-1]);
-            if (root->cell_f[i] < halfway)
-            {
-                root->cell_f[i] = halfway;
-                /* Check if the change also causes shifts of the next boundaries */
-                for(j=i+1; j<range[1]; j++)
-                {
-                    if (root->cell_f[j] < root->cell_f[j-1] + cellsize_limit_f)
-                        root->cell_f[j] =  root->cell_f[j-1] + cellsize_limit_f;
-                }
-            }
-            halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i+1]);
-            if (root->cell_f[i] > halfway)
-            {
-                root->cell_f[i] = halfway;
-                /* Check if the change also causes shifts of the next boundaries */
-                for(j=i-1; j>=range[0]+1; j--)
-                {
-                    if (root->cell_f[j] > root->cell_f[j+1] - cellsize_limit_f)
-                        root->cell_f[j] = root->cell_f[j+1] - cellsize_limit_f;
-                }
-            }
-        }
-    }
-    
-    /* nrange is defined as [lower, upper) range for new call to enforce_limits */
-    /* find highest violation of LimLo (a) and the following violation of LimHi (thus the lowest following) (b)
-     * then call enforce_limits for (oldb,a), (a,b). In the next step: (b,nexta). oldb and nexta can be the boundaries.
-     * for a and b nrange is used */
-    if (d > 0)
-    {
-        /* Take care of the staggering of the cell boundaries */
-        if (bUniform)
-        {
-            for(i=range[0]; i<range[1]; i++)
-            {
-                root->cell_f_max0[i] = root->cell_f[i];
-                root->cell_f_min1[i] = root->cell_f[i+1];
-            }
-        }
-        else
-        {
-            for(i=range[0]+1; i<range[1]; i++)
-            {
-                bLimLo = (root->cell_f[i] < root->bound_min[i]);
-                bLimHi = (root->cell_f[i] > root->bound_max[i]);
-                if (bLimLo && bLimHi)
-                {
-                    /* Both limits violated, try the best we can */
-                    /* For this case we split the original range (range) in two parts and care about the other limitiations in the next iteration. */
-                    root->cell_f[i] = 0.5*(root->bound_min[i] + root->bound_max[i]);
-                    nrange[0]=range[0];
-                    nrange[1]=i;
-                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-
-                    nrange[0]=i;
-                    nrange[1]=range[1];
-                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-
-                    return;
-                }
-                else if (bLimLo)
-                {
-                    /* root->cell_f[i] = root->bound_min[i]; */
-                    nrange[1]=i;  /* only store violation location. There could be a LimLo violation following with an higher index */
-                    bLastHi=FALSE;
-                }
-                else if (bLimHi && !bLastHi)
-                {
-                    bLastHi=TRUE;
-                    if (nrange[1] < range[1])   /* found a LimLo before */
-                    {
-                        root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
-                        dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-                        nrange[0]=nrange[1];
-                    }
-                    root->cell_f[i] = root->bound_max[i];
-                    nrange[1]=i; 
-                    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-                    nrange[0]=i;
-                    nrange[1]=range[1];
-                }
-            }
-            if (nrange[1] < range[1])   /* found last a LimLo */
-            {
-                root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
-                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-                nrange[0]=nrange[1];
-                nrange[1]=range[1];
-                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-            } 
-            else if (nrange[0] > range[0]) /* found at least one LimHi */
-            {
-                dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
-            }
-        }
-    }
-}
-
-
-static void set_dd_cell_sizes_dlb_root(gmx_domdec_t *dd,
-                                       int d,int dim,gmx_domdec_root_t *root,
-                                       gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
-                                       gmx_bool bUniform,gmx_large_int_t step)
-{
-    gmx_domdec_comm_t *comm;
-    int  ncd,d1,i,j,pos;
-    real *cell_size;
-    real load_aver,load_i,imbalance,change,change_max,sc;
-    real cellsize_limit_f,dist_min_f,dist_min_f_hard,space;
-    real change_limit;
-    real relax = 0.5;
-    gmx_bool bPBC;
-    int range[] = { 0, 0 };
-
-    comm = dd->comm;
-
-    /* Convert the maximum change from the input percentage to a fraction */
-    change_limit = comm->dlb_scale_lim*0.01;
-
-    ncd = dd->nc[dim];
-
-    bPBC = (dim < ddbox->npbcdim);
-
-    cell_size = root->buf_ncd;
-
-    /* Store the original boundaries */
-    for(i=0; i<ncd+1; i++)
-    {
-        root->old_cell_f[i] = root->cell_f[i];
-    }
-    if (bUniform) {
-        for(i=0; i<ncd; i++)
-        {
-            cell_size[i] = 1.0/ncd;
-        }
-    }
-    else if (dd_load_count(comm))
-    {
-        load_aver = comm->load[d].sum_m/ncd;
-        change_max = 0;
-        for(i=0; i<ncd; i++)
-        {
-            /* Determine the relative imbalance of cell i */
-            load_i = comm->load[d].load[i*comm->load[d].nload+2];
-            imbalance = (load_i - load_aver)/(load_aver>0 ? load_aver : 1);
-            /* Determine the change of the cell size using underrelaxation */
-            change = -relax*imbalance;
-            change_max = max(change_max,max(change,-change));
-        }
-        /* Limit the amount of scaling.
-         * We need to use the same rescaling for all cells in one row,
-         * otherwise the load balancing might not converge.
-         */
-        sc = relax;
-        if (change_max > change_limit)
-        {
-            sc *= change_limit/change_max;
-        }
-        for(i=0; i<ncd; i++)
-        {
-            /* Determine the relative imbalance of cell i */
-            load_i = comm->load[d].load[i*comm->load[d].nload+2];
-            imbalance = (load_i - load_aver)/(load_aver>0 ? load_aver : 1);
-            /* Determine the change of the cell size using underrelaxation */
-            change = -sc*imbalance;
-            cell_size[i] = (root->cell_f[i+1]-root->cell_f[i])*(1 + change);
-        }
-    }
-    
-    cellsize_limit_f  = comm->cellsize_min[dim]/ddbox->box_size[dim];
-    cellsize_limit_f *= DD_CELL_MARGIN;
-    dist_min_f_hard        = grid_jump_limit(comm,d)/ddbox->box_size[dim];
-    dist_min_f       = dist_min_f_hard * DD_CELL_MARGIN;
-    if (ddbox->tric_dir[dim])
-    {
-        cellsize_limit_f /= ddbox->skew_fac[dim];
-        dist_min_f       /= ddbox->skew_fac[dim];
-    }
-    if (bDynamicBox && d > 0)
-    {
-        dist_min_f *= DD_PRES_SCALE_MARGIN;
-    }
-    if (d > 0 && !bUniform)
-    {
-        /* Make sure that the grid is not shifted too much */
-        for(i=1; i<ncd; i++) {
-            if (root->cell_f_min1[i] - root->cell_f_max0[i-1] < 2 * dist_min_f_hard) 
-            {
-                gmx_incons("Inconsistent DD boundary staggering limits!");
-            }
-            root->bound_min[i] = root->cell_f_max0[i-1] + dist_min_f;
-            space = root->cell_f[i] - (root->cell_f_max0[i-1] + dist_min_f);
-            if (space > 0) {
-                root->bound_min[i] += 0.5*space;
-            }
-            root->bound_max[i] = root->cell_f_min1[i] - dist_min_f;
-            space = root->cell_f[i] - (root->cell_f_min1[i] - dist_min_f);
-            if (space < 0) {
-                root->bound_max[i] += 0.5*space;
-            }
-            if (debug)
-            {
-                fprintf(debug,
-                        "dim %d boundary %d %.3f < %.3f < %.3f < %.3f < %.3f\n",
-                        d,i,
-                        root->cell_f_max0[i-1] + dist_min_f,
-                        root->bound_min[i],root->cell_f[i],root->bound_max[i],
-                        root->cell_f_min1[i] - dist_min_f);
-            }
-        }
-    }
-    range[1]=ncd;
-    root->cell_f[0] = 0;
-    root->cell_f[ncd] = 1;
-    dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, range);
-
-
-    /* After the checks above, the cells should obey the cut-off
-     * restrictions, but it does not hurt to check.
-     */
-    for(i=0; i<ncd; i++)
-    {
-        if (debug)
-        {
-            fprintf(debug,"Relative bounds dim %d  cell %d: %f %f\n",
-                    dim,i,root->cell_f[i],root->cell_f[i+1]);
-        }
-
-        if ((bPBC || (i != 0 && i != dd->nc[dim]-1)) &&
-            root->cell_f[i+1] - root->cell_f[i] <
-            cellsize_limit_f/DD_CELL_MARGIN)
-        {
-            char buf[22];
-            fprintf(stderr,
-                    "\nWARNING step %s: direction %c, cell %d too small: %f\n",
-                    gmx_step_str(step,buf),dim2char(dim),i,
-                    (root->cell_f[i+1] - root->cell_f[i])
-                    *ddbox->box_size[dim]*ddbox->skew_fac[dim]);
-        }
-    }
-    
-    pos = ncd + 1;
-    /* Store the cell boundaries of the lower dimensions at the end */
-    for(d1=0; d1<d; d1++)
-    {
-        root->cell_f[pos++] = comm->cell_f0[d1];
-        root->cell_f[pos++] = comm->cell_f1[d1];
-    }
-    
-    if (d < comm->npmedecompdim)
-    {
-        /* The master determines the maximum shift for
-         * the coordinate communication between separate PME nodes.
-         */
-        set_pme_maxshift(dd,&comm->ddpme[d],bUniform,ddbox,root->cell_f);
-    }
-    root->cell_f[pos++] = comm->ddpme[0].maxshift;
-    if (d >= 1)
-    {
-        root->cell_f[pos++] = comm->ddpme[1].maxshift;
-    }
-}    
-
-static void relative_to_absolute_cell_bounds(gmx_domdec_t *dd,
-                                             gmx_ddbox_t *ddbox,int dimind)
-{
-    gmx_domdec_comm_t *comm;
-    int dim;
-
-    comm = dd->comm;
-
-    /* Set the cell dimensions */
-    dim = dd->dim[dimind];
-    comm->cell_x0[dim] = comm->cell_f0[dimind]*ddbox->box_size[dim];
-    comm->cell_x1[dim] = comm->cell_f1[dimind]*ddbox->box_size[dim];
-    if (dim >= ddbox->nboundeddim)
-    {
-        comm->cell_x0[dim] += ddbox->box0[dim];
-        comm->cell_x1[dim] += ddbox->box0[dim];
-    }
-}
-
-static void distribute_dd_cell_sizes_dlb(gmx_domdec_t *dd,
-                                         int d,int dim,real *cell_f_row,
-                                         gmx_ddbox_t *ddbox)
-{
-    gmx_domdec_comm_t *comm;
-    int d1,dim1,pos;
-
-    comm = dd->comm;
-
-#ifdef GMX_MPI
-    /* Each node would only need to know two fractions,
-     * but it is probably cheaper to broadcast the whole array.
-     */
-    MPI_Bcast(cell_f_row,DD_CELL_F_SIZE(dd,d)*sizeof(real),MPI_BYTE,
-              0,comm->mpi_comm_load[d]);
-#endif
-    /* Copy the fractions for this dimension from the buffer */
-    comm->cell_f0[d] = cell_f_row[dd->ci[dim]  ];
-    comm->cell_f1[d] = cell_f_row[dd->ci[dim]+1];
-    /* The whole array was communicated, so set the buffer position */
-    pos = dd->nc[dim] + 1;
-    for(d1=0; d1<=d; d1++)
-    {
-        if (d1 < d)
-        {
-            /* Copy the cell fractions of the lower dimensions */
-            comm->cell_f0[d1] = cell_f_row[pos++];
-            comm->cell_f1[d1] = cell_f_row[pos++];
-        }
-        relative_to_absolute_cell_bounds(dd,ddbox,d1);
-    }
-    /* Convert the communicated shift from float to int */
-    comm->ddpme[0].maxshift = (int)(cell_f_row[pos++] + 0.5);
-    if (d >= 1)
-    {
-        comm->ddpme[1].maxshift = (int)(cell_f_row[pos++] + 0.5);
-    }
-}
-
-static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
-                                         gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
-                                         gmx_bool bUniform,gmx_large_int_t step)
-{
-    gmx_domdec_comm_t *comm;
-    int d,dim,d1;
-    gmx_bool bRowMember,bRowRoot;
-    real *cell_f_row;
-    
-    comm = dd->comm;
-
-    for(d=0; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        bRowMember = TRUE;
-        bRowRoot = TRUE;
-        for(d1=d; d1<dd->ndim; d1++)
-        {
-            if (dd->ci[dd->dim[d1]] > 0)
-            {
-                if (d1 > d)
-                {
-                    bRowMember = FALSE;
-                }
-                bRowRoot = FALSE;
-            }
-        }
-        if (bRowMember)
-        {
-            if (bRowRoot)
-            {
-                set_dd_cell_sizes_dlb_root(dd,d,dim,comm->root[d],
-                                           ddbox,bDynamicBox,bUniform,step);
-                cell_f_row = comm->root[d]->cell_f;
-            }
-            else
-            {
-                cell_f_row = comm->cell_f_row;
-            }
-            distribute_dd_cell_sizes_dlb(dd,d,dim,cell_f_row,ddbox);
-        }
-    }
-}    
-
-static void set_dd_cell_sizes_dlb_nochange(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
-{
-    int d;
-
-    /* This function assumes the box is static and should therefore
-     * not be called when the box has changed since the last
-     * call to dd_partition_system.
-     */
-    for(d=0; d<dd->ndim; d++)
-    {
-        relative_to_absolute_cell_bounds(dd,ddbox,d); 
-    }
-}
-
-
-
-static void set_dd_cell_sizes_dlb(gmx_domdec_t *dd,
-                                  gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
-                                  gmx_bool bUniform,gmx_bool bDoDLB,gmx_large_int_t step,
-                                  gmx_wallcycle_t wcycle)
-{
-    gmx_domdec_comm_t *comm;
-    int dim;
-
-    comm = dd->comm;
-    
-    if (bDoDLB)
-    {
-        wallcycle_start(wcycle,ewcDDCOMMBOUND);
-        set_dd_cell_sizes_dlb_change(dd,ddbox,bDynamicBox,bUniform,step);
-        wallcycle_stop(wcycle,ewcDDCOMMBOUND);
-    }
-    else if (bDynamicBox)
-    {
-        set_dd_cell_sizes_dlb_nochange(dd,ddbox);
-    }
-    
-    /* Set the dimensions for which no DD is used */
-    for(dim=0; dim<DIM; dim++) {
-        if (dd->nc[dim] == 1) {
-            comm->cell_x0[dim] = 0;
-            comm->cell_x1[dim] = ddbox->box_size[dim];
-            if (dim >= ddbox->nboundeddim)
-            {
-                comm->cell_x0[dim] += ddbox->box0[dim];
-                comm->cell_x1[dim] += ddbox->box0[dim];
-            }
-        }
-    }
-}
-
-static void realloc_comm_ind(gmx_domdec_t *dd,ivec npulse)
-{
-    int d,np,i;
-    gmx_domdec_comm_dim_t *cd;
-    
-    for(d=0; d<dd->ndim; d++)
-    {
-        cd = &dd->comm->cd[d];
-        np = npulse[dd->dim[d]];
-        if (np > cd->np_nalloc)
-        {
-            if (debug)
-            {
-                fprintf(debug,"(Re)allocing cd for %c to %d pulses\n",
-                        dim2char(dd->dim[d]),np);
-            }
-            if (DDMASTER(dd) && cd->np_nalloc > 0)
-            {
-                fprintf(stderr,"\nIncreasing the number of cell to communicate in dimension %c to %d for the first time\n",dim2char(dd->dim[d]),np);
-            }
-            srenew(cd->ind,np);
-            for(i=cd->np_nalloc; i<np; i++)
-            {
-                cd->ind[i].index  = NULL;
-                cd->ind[i].nalloc = 0;
-            }
-            cd->np_nalloc = np;
-        }
-        cd->np = np;
-    }
-}
-
-
-static void set_dd_cell_sizes(gmx_domdec_t *dd,
-                              gmx_ddbox_t *ddbox,gmx_bool bDynamicBox,
-                              gmx_bool bUniform,gmx_bool bDoDLB,gmx_large_int_t step,
-                              gmx_wallcycle_t wcycle)
-{
-    gmx_domdec_comm_t *comm;
-    int  d;
-    ivec npulse;
-    
-    comm = dd->comm;
-
-    /* Copy the old cell boundaries for the cg displacement check */
-    copy_rvec(comm->cell_x0,comm->old_cell_x0);
-    copy_rvec(comm->cell_x1,comm->old_cell_x1);
-    
-    if (comm->bDynLoadBal)
-    {
-        if (DDMASTER(dd))
-        {
-            check_box_size(dd,ddbox);
-        }
-        set_dd_cell_sizes_dlb(dd,ddbox,bDynamicBox,bUniform,bDoDLB,step,wcycle);
-    }
-    else
-    {
-        set_dd_cell_sizes_slb(dd,ddbox,FALSE,npulse);
-        realloc_comm_ind(dd,npulse);
-    }
-    
-    if (debug)
-    {
-        for(d=0; d<DIM; d++)
-        {
-            fprintf(debug,"cell_x[%d] %f - %f skew_fac %f\n",
-                    d,comm->cell_x0[d],comm->cell_x1[d],ddbox->skew_fac[d]);
-        }
-    }
-}
-
-static void comm_dd_ns_cell_sizes(gmx_domdec_t *dd,
-                                  gmx_ddbox_t *ddbox,
-                                  rvec cell_ns_x0,rvec cell_ns_x1,
-                                  gmx_large_int_t step)
-{
-    gmx_domdec_comm_t *comm;
-    int dim_ind,dim;
-    
-    comm = dd->comm;
-
-    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
-    {
-        dim = dd->dim[dim_ind];
-        
-        /* Without PBC we don't have restrictions on the outer cells */
-        if (!(dim >= ddbox->npbcdim && 
-              (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1)) &&
-            comm->bDynLoadBal &&
-            (comm->cell_x1[dim] - comm->cell_x0[dim])*ddbox->skew_fac[dim] <
-            comm->cellsize_min[dim])
-        {
-            char buf[22];
-            gmx_fatal(FARGS,"Step %s: The %c-size (%f) times the triclinic skew factor (%f) is smaller than the smallest allowed cell size (%f) for domain decomposition grid cell %d %d %d",
-                      gmx_step_str(step,buf),dim2char(dim),
-                      comm->cell_x1[dim] - comm->cell_x0[dim],
-                      ddbox->skew_fac[dim],
-                      dd->comm->cellsize_min[dim],
-                      dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-        }
-    }
-    
-    if ((dd->bGridJump && dd->ndim > 1) || ddbox->nboundeddim < DIM)
-    {
-        /* Communicate the boundaries and update cell_ns_x0/1 */
-        dd_move_cellx(dd,ddbox,cell_ns_x0,cell_ns_x1);
-        if (dd->bGridJump && dd->ndim > 1)
-        {
-            check_grid_jump(step,dd,ddbox);
-        }
-    }
-}
-
-static void make_tric_corr_matrix(int npbcdim,matrix box,matrix tcm)
-{
-    if (YY < npbcdim)
-    {
-        tcm[YY][XX] = -box[YY][XX]/box[YY][YY];
-    }
-    else
-    {
-        tcm[YY][XX] = 0;
-    }
-    if (ZZ < npbcdim)
-    {
-        tcm[ZZ][XX] = -(box[ZZ][YY]*tcm[YY][XX] + box[ZZ][XX])/box[ZZ][ZZ];
-        tcm[ZZ][YY] = -box[ZZ][YY]/box[ZZ][ZZ];
-    }
-    else
-    {
-        tcm[ZZ][XX] = 0;
-        tcm[ZZ][YY] = 0;
-    }
-}
-
-static void check_screw_box(matrix box)
-{
-    /* Mathematical limitation */
-    if (box[YY][XX] != 0 || box[ZZ][XX] != 0)
-    {
-        gmx_fatal(FARGS,"With screw pbc the unit cell can not have non-zero off-diagonal x-components");
-    }
-    
-    /* Limitation due to the asymmetry of the eighth shell method */
-    if (box[ZZ][YY] != 0)
-    {
-        gmx_fatal(FARGS,"pbc=screw with non-zero box_zy is not supported");
-    }
-}
-
-static void distribute_cg(FILE *fplog,gmx_large_int_t step,
-                          matrix box,ivec tric_dir,t_block *cgs,rvec pos[],
-                          gmx_domdec_t *dd)
-{
-    gmx_domdec_master_t *ma;
-    int **tmp_ind=NULL,*tmp_nalloc=NULL;
-    int  i,icg,j,k,k0,k1,d,npbcdim;
-    matrix tcm;
-    rvec box_size,cg_cm;
-    ivec ind;
-    real nrcg,inv_ncg,pos_d;
-    atom_id *cgindex;
-    gmx_bool bUnbounded,bScrew;
-
-    ma = dd->ma;
-    
-    if (tmp_ind == NULL)
-    {
-        snew(tmp_nalloc,dd->nnodes);
-        snew(tmp_ind,dd->nnodes);
-        for(i=0; i<dd->nnodes; i++)
-        {
-            tmp_nalloc[i] = over_alloc_large(cgs->nr/dd->nnodes+1);
-            snew(tmp_ind[i],tmp_nalloc[i]);
-        }
-    }
-    
-    /* Clear the count */
-    for(i=0; i<dd->nnodes; i++)
-    {
-        ma->ncg[i] = 0;
-        ma->nat[i] = 0;
-    }
-    
-    make_tric_corr_matrix(dd->npbcdim,box,tcm);
-    
-    cgindex = cgs->index;
-    
-    /* Compute the center of geometry for all charge groups */
-    for(icg=0; icg<cgs->nr; icg++)
-    {
-        k0      = cgindex[icg];
-        k1      = cgindex[icg+1];
-        nrcg    = k1 - k0;
-        if (nrcg == 1)
-        {
-            copy_rvec(pos[k0],cg_cm);
-        }
-        else
-        {
-            inv_ncg = 1.0/nrcg;
-            
-            clear_rvec(cg_cm);
-            for(k=k0; (k<k1); k++)
-            {
-                rvec_inc(cg_cm,pos[k]);
-            }
-            for(d=0; (d<DIM); d++)
-            {
-                cg_cm[d] *= inv_ncg;
-            }
-        }
-        /* Put the charge group in the box and determine the cell index */
-        for(d=DIM-1; d>=0; d--) {
-            pos_d = cg_cm[d];
-            if (d < dd->npbcdim)
-            {
-                bScrew = (dd->bScrewPBC && d == XX);
-                if (tric_dir[d] && dd->nc[d] > 1)
-                {
-                    /* Use triclinic coordintates for this dimension */
-                    for(j=d+1; j<DIM; j++)
-                    {
-                        pos_d += cg_cm[j]*tcm[j][d];
-                    }
-                }
-                while(pos_d >= box[d][d])
-                {
-                    pos_d -= box[d][d];
-                    rvec_dec(cg_cm,box[d]);
-                    if (bScrew)
-                    {
-                        cg_cm[YY] = box[YY][YY] - cg_cm[YY];
-                        cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
-                    }
-                    for(k=k0; (k<k1); k++)
-                    {
-                        rvec_dec(pos[k],box[d]);
-                        if (bScrew)
-                        {
-                            pos[k][YY] = box[YY][YY] - pos[k][YY];
-                            pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
-                        }
-                    }
-                }
-                while(pos_d < 0)
-                {
-                    pos_d += box[d][d];
-                    rvec_inc(cg_cm,box[d]);
-                    if (bScrew)
-                    {
-                        cg_cm[YY] = box[YY][YY] - cg_cm[YY];
-                        cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
-                    }
-                    for(k=k0; (k<k1); k++)
-                    {
-                        rvec_inc(pos[k],box[d]);
-                        if (bScrew) {
-                            pos[k][YY] = box[YY][YY] - pos[k][YY];
-                            pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
-                        }
-                    }
-                }
-            }
-            /* This could be done more efficiently */
-            ind[d] = 0;
-            while(ind[d]+1 < dd->nc[d] && pos_d >= ma->cell_x[d][ind[d]+1])
-            {
-                ind[d]++;
-            }
-        }
-        i = dd_index(dd->nc,ind);
-        if (ma->ncg[i] == tmp_nalloc[i])
-        {
-            tmp_nalloc[i] = over_alloc_large(ma->ncg[i]+1);
-            srenew(tmp_ind[i],tmp_nalloc[i]);
-        }
-        tmp_ind[i][ma->ncg[i]] = icg;
-        ma->ncg[i]++;
-        ma->nat[i] += cgindex[icg+1] - cgindex[icg];
-    }
-    
-    k1 = 0;
-    for(i=0; i<dd->nnodes; i++)
-    {
-        ma->index[i] = k1;
-        for(k=0; k<ma->ncg[i]; k++)
-        {
-            ma->cg[k1++] = tmp_ind[i][k];
-        }
-    }
-    ma->index[dd->nnodes] = k1;
-    
-    for(i=0; i<dd->nnodes; i++)
-    {
-        sfree(tmp_ind[i]);
-    }
-    sfree(tmp_ind);
-    sfree(tmp_nalloc);
-    
-    if (fplog)
-    {
-        char buf[22];
-        fprintf(fplog,"Charge group distribution at step %s:",
-                gmx_step_str(step,buf));
-        for(i=0; i<dd->nnodes; i++)
-        {
-            fprintf(fplog," %d",ma->ncg[i]);
-        }
-        fprintf(fplog,"\n");
-    }
-}
-
-static void get_cg_distribution(FILE *fplog,gmx_large_int_t step,gmx_domdec_t *dd,
-                                t_block *cgs,matrix box,gmx_ddbox_t *ddbox,
-                                rvec pos[])
-{
-    gmx_domdec_master_t *ma=NULL;
-    ivec npulse;
-    int  i,cg_gl;
-    int  *ibuf,buf2[2] = { 0, 0 };
-    
-    if (DDMASTER(dd))
-    {
-        ma = dd->ma;
-        
-        if (dd->bScrewPBC)
-        {
-            check_screw_box(box);
-        }
-    
-        set_dd_cell_sizes_slb(dd,ddbox,TRUE,npulse);
-    
-        distribute_cg(fplog,step,box,ddbox->tric_dir,cgs,pos,dd);
-        for(i=0; i<dd->nnodes; i++)
-        {
-            ma->ibuf[2*i]   = ma->ncg[i];
-            ma->ibuf[2*i+1] = ma->nat[i];
-        }
-        ibuf = ma->ibuf;
-    }
-    else
-    {
-        ibuf = NULL;
-    }
-    dd_scatter(dd,2*sizeof(int),ibuf,buf2);
-    
-    dd->ncg_home = buf2[0];
-    dd->nat_home = buf2[1];
-    dd->ncg_tot  = dd->ncg_home;
-    dd->nat_tot  = dd->nat_home;
-    if (dd->ncg_home > dd->cg_nalloc || dd->cg_nalloc == 0)
-    {
-        dd->cg_nalloc = over_alloc_dd(dd->ncg_home);
-        srenew(dd->index_gl,dd->cg_nalloc);
-        srenew(dd->cgindex,dd->cg_nalloc+1);
-    }
-    if (DDMASTER(dd))
-    {
-        for(i=0; i<dd->nnodes; i++)
-        {
-            ma->ibuf[i] = ma->ncg[i]*sizeof(int);
-            ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
-        }
-    }
-    
-    dd_scatterv(dd,
-                DDMASTER(dd) ? ma->ibuf : NULL,
-                DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
-                DDMASTER(dd) ? ma->cg : NULL,
-                dd->ncg_home*sizeof(int),dd->index_gl);
-    
-    /* Determine the home charge group sizes */
-    dd->cgindex[0] = 0;
-    for(i=0; i<dd->ncg_home; i++)
-    {
-        cg_gl = dd->index_gl[i];
-        dd->cgindex[i+1] =
-            dd->cgindex[i] + cgs->index[cg_gl+1] - cgs->index[cg_gl];
-    }
-    
-    if (debug)
-    {
-        fprintf(debug,"Home charge groups:\n");
-        for(i=0; i<dd->ncg_home; i++)
-        {
-            fprintf(debug," %d",dd->index_gl[i]);
-            if (i % 10 == 9) 
-                fprintf(debug,"\n");
-        }
-        fprintf(debug,"\n");
-    }
-}
-
-static int compact_and_copy_vec_at(int ncg,int *move,
-                                   int *cgindex,
-                                   int nvec,int vec,
-                                   rvec *src,gmx_domdec_comm_t *comm,
-                                   gmx_bool bCompact)
-{
-    int m,icg,i,i0,i1,nrcg;
-    int home_pos;
-    int pos_vec[DIM*2];
-    
-    home_pos = 0;
-
-    for(m=0; m<DIM*2; m++)
-    {
-        pos_vec[m] = 0;
-    }
-    
-    i0 = 0;
-    for(icg=0; icg<ncg; icg++)
-    {
-        i1 = cgindex[icg+1];
-        m = move[icg];
-        if (m == -1)
-        {
-            if (bCompact)
-            {
-                /* Compact the home array in place */
-                for(i=i0; i<i1; i++)
-                {
-                    copy_rvec(src[i],src[home_pos++]);
-                }
-            }
-        }
-        else
-        {
-            /* Copy to the communication buffer */
-            nrcg = i1 - i0;
-            pos_vec[m] += 1 + vec*nrcg;
-            for(i=i0; i<i1; i++)
-            {
-                copy_rvec(src[i],comm->cgcm_state[m][pos_vec[m]++]);
-            }
-            pos_vec[m] += (nvec - vec - 1)*nrcg;
-        }
-        if (!bCompact)
-        {
-            home_pos += i1 - i0;
-        }
-        i0 = i1;
-    }
-    
-    return home_pos;
-}
-
-static int compact_and_copy_vec_cg(int ncg,int *move,
-                                   int *cgindex,
-                                   int nvec,rvec *src,gmx_domdec_comm_t *comm,
-                                   gmx_bool bCompact)
-{
-    int m,icg,i0,i1,nrcg;
-    int home_pos;
-    int pos_vec[DIM*2];
-    
-    home_pos = 0;
-    
-    for(m=0; m<DIM*2; m++)
-    {
-        pos_vec[m] = 0;
-    }
-    
-    i0 = 0;
-    for(icg=0; icg<ncg; icg++)
-    {
-        i1 = cgindex[icg+1];
-        m = move[icg];
-        if (m == -1)
-        {
-            if (bCompact)
-            {
-                /* Compact the home array in place */
-                copy_rvec(src[icg],src[home_pos++]);
-            }
-        }
-        else
-        {
-            nrcg = i1 - i0;
-            /* Copy to the communication buffer */
-            copy_rvec(src[icg],comm->cgcm_state[m][pos_vec[m]]);
-            pos_vec[m] += 1 + nrcg*nvec;
-        }
-        i0 = i1;
-    }
-    if (!bCompact)
-    {
-        home_pos = ncg;
-    }
-    
-    return home_pos;
-}
-
-static int compact_ind(int ncg,int *move,
-                       int *index_gl,int *cgindex,
-                       int *gatindex,
-                       gmx_ga2la_t ga2la,char *bLocalCG,
-                       int *cginfo)
-{
-    int cg,nat,a0,a1,a,a_gl;
-    int home_pos;
-
-    home_pos = 0;
-    nat = 0;
-    for(cg=0; cg<ncg; cg++)
-    {
-        a0 = cgindex[cg];
-        a1 = cgindex[cg+1];
-        if (move[cg] == -1)
-        {
-            /* Compact the home arrays in place.
-             * Anything that can be done here avoids access to global arrays.
-             */
-            cgindex[home_pos] = nat;
-            for(a=a0; a<a1; a++)
-            {
-                a_gl = gatindex[a];
-                gatindex[nat] = a_gl;
-                /* The cell number stays 0, so we don't need to set it */
-                ga2la_change_la(ga2la,a_gl,nat);
-                nat++;
-            }
-            index_gl[home_pos] = index_gl[cg];
-            cginfo[home_pos]   = cginfo[cg];
-            /* The charge group remains local, so bLocalCG does not change */
-            home_pos++;
-        }
-        else
-        {
-            /* Clear the global indices */
-            for(a=a0; a<a1; a++)
-            {
-                ga2la_del(ga2la,gatindex[a]);
-            }
-            if (bLocalCG)
-            {
-                bLocalCG[index_gl[cg]] = FALSE;
-            }
-        }
-    }
-    cgindex[home_pos] = nat;
-    
-    return home_pos;
-}
-
-static void clear_and_mark_ind(int ncg,int *move,
-                               int *index_gl,int *cgindex,int *gatindex,
-                               gmx_ga2la_t ga2la,char *bLocalCG,
-                               int *cell_index)
-{
-    int cg,a0,a1,a;
-    
-    for(cg=0; cg<ncg; cg++)
-    {
-        if (move[cg] >= 0)
-        {
-            a0 = cgindex[cg];
-            a1 = cgindex[cg+1];
-            /* Clear the global indices */
-            for(a=a0; a<a1; a++)
-            {
-                ga2la_del(ga2la,gatindex[a]);
-            }
-            if (bLocalCG)
-            {
-                bLocalCG[index_gl[cg]] = FALSE;
-            }
-            /* Signal that this cg has moved using the ns cell index.
-             * Here we set it to -1.
-             * fill_grid will change it from -1 to 4*grid->ncells.
-             */
-            cell_index[cg] = -1;
-        }
-    }
-}
-
-static void print_cg_move(FILE *fplog,
-                          gmx_domdec_t *dd,
-                          gmx_large_int_t step,int cg,int dim,int dir,
-                          gmx_bool bHaveLimitdAndCMOld,real limitd,
-                          rvec cm_old,rvec cm_new,real pos_d)
-{
-    gmx_domdec_comm_t *comm;
-    char buf[22];
-
-    comm = dd->comm;
-
-    fprintf(fplog,"\nStep %s:\n",gmx_step_str(step,buf));
-    if (bHaveLimitdAndCMOld)
-    {
-        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
-                ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
-    }
-    else
-    {
-        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition in direction %c\n",
-                ddglatnr(dd,dd->cgindex[cg]),dim2char(dim));
-    }
-    fprintf(fplog,"distance out of cell %f\n",
-            dir==1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
-    if (bHaveLimitdAndCMOld)
-    {
-        fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
-                cm_old[XX],cm_old[YY],cm_old[ZZ]);
-    }
-    fprintf(fplog,"New coordinates: %8.3f %8.3f %8.3f\n",
-            cm_new[XX],cm_new[YY],cm_new[ZZ]);
-    fprintf(fplog,"Old cell boundaries in direction %c: %8.3f %8.3f\n",
-            dim2char(dim),
-            comm->old_cell_x0[dim],comm->old_cell_x1[dim]);
-    fprintf(fplog,"New cell boundaries in direction %c: %8.3f %8.3f\n",
-            dim2char(dim),
-            comm->cell_x0[dim],comm->cell_x1[dim]);
-}
-
-static void cg_move_error(FILE *fplog,
-                          gmx_domdec_t *dd,
-                          gmx_large_int_t step,int cg,int dim,int dir,
-                          gmx_bool bHaveLimitdAndCMOld,real limitd,
-                          rvec cm_old,rvec cm_new,real pos_d)
-{
-    if (fplog)
-    {
-        print_cg_move(fplog, dd,step,cg,dim,dir,
-                      bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
-    }
-    print_cg_move(stderr,dd,step,cg,dim,dir,
-                  bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
-    gmx_fatal(FARGS,
-              "A charge group moved too far between two domain decomposition steps\n"
-              "This usually means that your system is not well equilibrated");
-}
-
-static void rotate_state_atom(t_state *state,int a)
-{
-    int est;
-
-    for(est=0; est<estNR; est++)
-    {
-        if (EST_DISTR(est) && (state->flags & (1<<est))) {
-            switch (est) {
-            case estX:
-                /* Rotate the complete state; for a rectangular box only */
-                state->x[a][YY] = state->box[YY][YY] - state->x[a][YY];
-                state->x[a][ZZ] = state->box[ZZ][ZZ] - state->x[a][ZZ];
-                break;
-            case estV:
-                state->v[a][YY] = -state->v[a][YY];
-                state->v[a][ZZ] = -state->v[a][ZZ];
-                break;
-            case estSDX:
-                state->sd_X[a][YY] = -state->sd_X[a][YY];
-                state->sd_X[a][ZZ] = -state->sd_X[a][ZZ];
-                break;
-            case estCGP:
-                state->cg_p[a][YY] = -state->cg_p[a][YY];
-                state->cg_p[a][ZZ] = -state->cg_p[a][ZZ];
-                break;
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                /* These are distances, so not affected by rotation */
-                break;
-            default:
-                gmx_incons("Unknown state entry encountered in rotate_state_atom");            
-            }
-        }
-    }
-}
-
-static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
-                              gmx_domdec_t *dd,ivec tric_dir,
-                              t_state *state,rvec **f,
-                              t_forcerec *fr,t_mdatoms *md,
-                              gmx_bool bCompact,
-                              t_nrnb *nrnb)
-{
-    int  *move;
-    int  npbcdim;
-    int  ncg[DIM*2],nat[DIM*2];
-    int  c,i,cg,k,k0,k1,d,dim,dim2,dir,d2,d3,d4,cell_d;
-    int  mc,cdd,nrcg,ncg_recv,nat_recv,nvs,nvr,nvec,vec;
-    int  sbuf[2],rbuf[2];
-    int  home_pos_cg,home_pos_at,ncg_stay_home,buf_pos;
-    int  flag;
-    gmx_bool bV=FALSE,bSDX=FALSE,bCGP=FALSE;
-    gmx_bool bScrew;
-    ivec dev;
-    real inv_ncg,pos_d;
-    matrix tcm;
-    rvec *cg_cm,cell_x0,cell_x1,limitd,limit0,limit1,cm_new;
-    atom_id *cgindex;
-    cginfo_mb_t *cginfo_mb;
-    gmx_domdec_comm_t *comm;
-    
-    if (dd->bScrewPBC)
-    {
-        check_screw_box(state->box);
-    }
-    
-    comm  = dd->comm;
-    cg_cm = fr->cg_cm;
-    
-    for(i=0; i<estNR; i++)
-    {
-        if (EST_DISTR(i))
-        {
-            switch (i)
-            {
-            case estX:   /* Always present */            break;
-            case estV:   bV   = (state->flags & (1<<i)); break;
-            case estSDX: bSDX = (state->flags & (1<<i)); break;
-            case estCGP: bCGP = (state->flags & (1<<i)); break;
-            case estLD_RNG:
-            case estLD_RNGI:
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                /* No processing required */
-                break;
-            default:
-            gmx_incons("Unknown state entry encountered in dd_redistribute_cg");
-            }
-        }
-    }
-    
-    if (dd->ncg_tot > comm->nalloc_int)
-    {
-        comm->nalloc_int = over_alloc_dd(dd->ncg_tot);
-        srenew(comm->buf_int,comm->nalloc_int);
-    }
-    move = comm->buf_int;
-    
-    /* Clear the count */
-    for(c=0; c<dd->ndim*2; c++)
-    {
-        ncg[c] = 0;
-        nat[c] = 0;
-    }
-
-    npbcdim = dd->npbcdim;
-
-    for(d=0; (d<DIM); d++)
-    {
-        limitd[d] = dd->comm->cellsize_min[d];
-        if (d >= npbcdim && dd->ci[d] == 0)
-        {
-            cell_x0[d] = -GMX_FLOAT_MAX;
-        }
-        else
-        {
-            cell_x0[d] = comm->cell_x0[d];
-        }
-        if (d >= npbcdim && dd->ci[d] == dd->nc[d] - 1)
-        {
-            cell_x1[d] = GMX_FLOAT_MAX;
-        }
-        else
-        {
-            cell_x1[d] = comm->cell_x1[d];
-        }
-        if (d < npbcdim)
-        {
-            limit0[d] = comm->old_cell_x0[d] - limitd[d];
-            limit1[d] = comm->old_cell_x1[d] + limitd[d];
-        }
-        else
-        {
-            /* We check after communication if a charge group moved
-             * more than one cell. Set the pre-comm check limit to float_max.
-             */
-            limit0[d] = -GMX_FLOAT_MAX;
-            limit1[d] =  GMX_FLOAT_MAX;
-        }
-    }
-    
-    make_tric_corr_matrix(npbcdim,state->box,tcm);
-    
-    cgindex = dd->cgindex;
-    
-    /* Compute the center of geometry for all home charge groups
-     * and put them in the box and determine where they should go.
-     */
-    for(cg=0; cg<dd->ncg_home; cg++)
-    {
-        k0   = cgindex[cg];
-        k1   = cgindex[cg+1];
-        nrcg = k1 - k0;
-        if (nrcg == 1)
-        {
-            copy_rvec(state->x[k0],cm_new);
-        }
-        else
-        {
-            inv_ncg = 1.0/nrcg;
-            
-            clear_rvec(cm_new);
-            for(k=k0; (k<k1); k++)
-            {
-                rvec_inc(cm_new,state->x[k]);
-            }
-            for(d=0; (d<DIM); d++)
-            {
-                cm_new[d] = inv_ncg*cm_new[d];
-            }
-        }
-        
-        clear_ivec(dev);
-        /* Do pbc and check DD cell boundary crossings */
-        for(d=DIM-1; d>=0; d--)
-        {
-            if (dd->nc[d] > 1)
-            {
-                bScrew = (dd->bScrewPBC && d == XX);
-                /* Determine the location of this cg in lattice coordinates */
-                pos_d = cm_new[d];
-                if (tric_dir[d])
-                {
-                    for(d2=d+1; d2<DIM; d2++)
-                    {
-                        pos_d += cm_new[d2]*tcm[d2][d];
-                    }
-                }
-                /* Put the charge group in the triclinic unit-cell */
-                if (pos_d >= cell_x1[d])
-                {
-                    if (pos_d >= limit1[d])
-                    {
-                        cg_move_error(fplog,dd,step,cg,d,1,TRUE,limitd[d],
-                                      cg_cm[cg],cm_new,pos_d);
-                    }
-                    dev[d] = 1;
-                    if (dd->ci[d] == dd->nc[d] - 1)
-                    {
-                        rvec_dec(cm_new,state->box[d]);
-                        if (bScrew)
-                        {
-                            cm_new[YY] = state->box[YY][YY] - cm_new[YY];
-                            cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
-                        }
-                        for(k=k0; (k<k1); k++)
-                        {
-                            rvec_dec(state->x[k],state->box[d]);
-                            if (bScrew)
-                            {
-                                rotate_state_atom(state,k);
-                            }
-                        }
-                    }
-                }
-                else if (pos_d < cell_x0[d])
-                {
-                    if (pos_d < limit0[d])
-                    {
-                        cg_move_error(fplog,dd,step,cg,d,-1,TRUE,limitd[d],
-                                      cg_cm[cg],cm_new,pos_d);
-                    }
-                    dev[d] = -1;
-                    if (dd->ci[d] == 0)
-                    {
-                        rvec_inc(cm_new,state->box[d]);
-                        if (bScrew)
-                        {
-                            cm_new[YY] = state->box[YY][YY] - cm_new[YY];
-                            cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
-                        }
-                        for(k=k0; (k<k1); k++)
-                        {
-                            rvec_inc(state->x[k],state->box[d]);
-                            if (bScrew)
-                            {
-                                rotate_state_atom(state,k);
-                            }
-                        }
-                    }
-                }
-            }
-            else if (d < npbcdim)
-            {
-                /* Put the charge group in the rectangular unit-cell */
-                while (cm_new[d] >= state->box[d][d])
-                {
-                    rvec_dec(cm_new,state->box[d]);
-                    for(k=k0; (k<k1); k++)
-                    {
-                        rvec_dec(state->x[k],state->box[d]);
-                    }
-                }
-                while (cm_new[d] < 0)
-                {
-                    rvec_inc(cm_new,state->box[d]);
-                    for(k=k0; (k<k1); k++)
-                    {
-                        rvec_inc(state->x[k],state->box[d]);
-                    }
-                }
-            }
-        }
-    
-        copy_rvec(cm_new,cg_cm[cg]);
-        
-        /* Determine where this cg should go */
-        flag = 0;
-        mc = -1;
-        for(d=0; d<dd->ndim; d++)
-        {
-            dim = dd->dim[d];
-            if (dev[dim] == 1)
-            {
-                flag |= DD_FLAG_FW(d);
-                if (mc == -1)
-                {
-                    mc = d*2;
-                }
-            }
-            else if (dev[dim] == -1)
-            {
-                flag |= DD_FLAG_BW(d);
-                if (mc == -1) {
-                    if (dd->nc[dim] > 2)
-                    {
-                        mc = d*2 + 1;
-                    }
-                    else
-                    {
-                        mc = d*2;
-                    }
-                }
-            }
-        }
-        move[cg] = mc;
-        if (mc >= 0)
-        {
-            if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
-            {
-                comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
-                srenew(comm->cggl_flag[mc],comm->cggl_flag_nalloc[mc]*DD_CGIBS);
-            }
-            comm->cggl_flag[mc][ncg[mc]*DD_CGIBS  ] = dd->index_gl[cg];
-            /* We store the cg size in the lower 16 bits
-             * and the place where the charge group should go
-             * in the next 6 bits. This saves some communication volume.
-             */
-            comm->cggl_flag[mc][ncg[mc]*DD_CGIBS+1] = nrcg | flag;
-            ncg[mc] += 1;
-            nat[mc] += nrcg;
-        }
-    }
-    
-    inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
-    inc_nrnb(nrnb,eNR_RESETX,dd->ncg_home);
-    
-    nvec = 1;
-    if (bV)
-    {
-        nvec++;
-    }
-    if (bSDX)
-    {
-        nvec++;
-    }
-    if (bCGP)
-    {
-        nvec++;
-    }
-    
-    /* Make sure the communication buffers are large enough */
-    for(mc=0; mc<dd->ndim*2; mc++)
-    {
-        nvr = ncg[mc] + nat[mc]*nvec;
-        if (nvr > comm->cgcm_state_nalloc[mc])
-        {
-            comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr);
-            srenew(comm->cgcm_state[mc],comm->cgcm_state_nalloc[mc]);
-        }
-    }
-    
-    /* Recalculating cg_cm might be cheaper than communicating,
-     * but that could give rise to rounding issues.
-     */
-    home_pos_cg =
-        compact_and_copy_vec_cg(dd->ncg_home,move,cgindex,
-                                nvec,cg_cm,comm,bCompact);
-    
-    vec = 0;
-    home_pos_at =
-        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
-                                nvec,vec++,state->x,comm,bCompact);
-    if (bV)
-    {
-        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
-                                nvec,vec++,state->v,comm,bCompact);
-    }
-    if (bSDX)
-    {
-        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
-                                nvec,vec++,state->sd_X,comm,bCompact);
-    }
-    if (bCGP)
-    {
-        compact_and_copy_vec_at(dd->ncg_home,move,cgindex,
-                                nvec,vec++,state->cg_p,comm,bCompact);
-    }
-    
-    if (bCompact)
-    {
-        compact_ind(dd->ncg_home,move,
-                    dd->index_gl,dd->cgindex,dd->gatindex,
-                    dd->ga2la,comm->bLocalCG,
-                    fr->cginfo);
-    }
-    else
-    {
-        clear_and_mark_ind(dd->ncg_home,move,
-                           dd->index_gl,dd->cgindex,dd->gatindex,
-                           dd->ga2la,comm->bLocalCG,
-                           fr->ns.grid->cell_index);
-    }
-    
-    cginfo_mb = fr->cginfo_mb;
-
-    ncg_stay_home = home_pos_cg;
-    for(d=0; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        ncg_recv = 0;
-        nat_recv = 0;
-        nvr      = 0;
-        for(dir=0; dir<(dd->nc[dim]==2 ? 1 : 2); dir++)
-        {
-            cdd = d*2 + dir;
-            /* Communicate the cg and atom counts */
-            sbuf[0] = ncg[cdd];
-            sbuf[1] = nat[cdd];
-            if (debug)
-            {
-                fprintf(debug,"Sending ddim %d dir %d: ncg %d nat %d\n",
-                        d,dir,sbuf[0],sbuf[1]);
-            }
-            dd_sendrecv_int(dd, d, dir, sbuf, 2, rbuf, 2);
-            
-            if ((ncg_recv+rbuf[0])*DD_CGIBS > comm->nalloc_int)
-            {
-                comm->nalloc_int = over_alloc_dd((ncg_recv+rbuf[0])*DD_CGIBS);
-                srenew(comm->buf_int,comm->nalloc_int);
-            }
-            
-            /* Communicate the charge group indices, sizes and flags */
-            dd_sendrecv_int(dd, d, dir,
-                            comm->cggl_flag[cdd], sbuf[0]*DD_CGIBS,
-                            comm->buf_int+ncg_recv*DD_CGIBS, rbuf[0]*DD_CGIBS);
-            
-            nvs = ncg[cdd] + nat[cdd]*nvec;
-            i   = rbuf[0]  + rbuf[1] *nvec;
-            vec_rvec_check_alloc(&comm->vbuf,nvr+i);
-            
-            /* Communicate cgcm and state */
-            dd_sendrecv_rvec(dd, d, dir,
-                             comm->cgcm_state[cdd], nvs,
-                             comm->vbuf.v+nvr, i);
-            ncg_recv += rbuf[0];
-            nat_recv += rbuf[1];
-            nvr      += i;
-        }
-        
-        /* Process the received charge groups */
-        buf_pos = 0;
-        for(cg=0; cg<ncg_recv; cg++)
-        {
-            flag = comm->buf_int[cg*DD_CGIBS+1];
-
-            if (dim >= npbcdim && dd->nc[dim] > 2)
-            {
-                /* No pbc in this dim and more than one domain boundary.
-                 * We to a separate check if a charge did not move too far.
-                 */
-                if (((flag & DD_FLAG_FW(d)) &&
-                     comm->vbuf.v[buf_pos][d] > cell_x1[dim]) ||
-                    ((flag & DD_FLAG_BW(d)) &&
-                     comm->vbuf.v[buf_pos][d] < cell_x0[dim]))
-                {
-                    cg_move_error(fplog,dd,step,cg,d,
-                                  (flag & DD_FLAG_FW(d)) ? 1 : 0,
-                                   FALSE,0,
-                                   comm->vbuf.v[buf_pos],
-                                   comm->vbuf.v[buf_pos],
-                                   comm->vbuf.v[buf_pos][d]);
-                }
-            }
-
-            mc = -1;
-            if (d < dd->ndim-1)
-            {
-                /* Check which direction this cg should go */
-                for(d2=d+1; (d2<dd->ndim && mc==-1); d2++)
-                {
-                    if (dd->bGridJump)
-                    {
-                        /* The cell boundaries for dimension d2 are not equal
-                         * for each cell row of the lower dimension(s),
-                         * therefore we might need to redetermine where
-                         * this cg should go.
-                         */
-                        dim2 = dd->dim[d2];
-                        /* If this cg crosses the box boundary in dimension d2
-                         * we can use the communicated flag, so we do not
-                         * have to worry about pbc.
-                         */
-                        if (!((dd->ci[dim2] == dd->nc[dim2]-1 &&
-                               (flag & DD_FLAG_FW(d2))) ||
-                              (dd->ci[dim2] == 0 &&
-                               (flag & DD_FLAG_BW(d2)))))
-                        {
-                            /* Clear the two flags for this dimension */
-                            flag &= ~(DD_FLAG_FW(d2) | DD_FLAG_BW(d2));
-                            /* Determine the location of this cg
-                             * in lattice coordinates
-                             */
-                            pos_d = comm->vbuf.v[buf_pos][dim2];
-                            if (tric_dir[dim2])
-                            {
-                                for(d3=dim2+1; d3<DIM; d3++)
-                                {
-                                    pos_d +=
-                                        comm->vbuf.v[buf_pos][d3]*tcm[d3][dim2];
-                                }
-                            }
-                            /* Check of we are not at the box edge.
-                             * pbc is only handled in the first step above,
-                             * but this check could move over pbc while
-                             * the first step did not due to different rounding.
-                             */
-                            if (pos_d >= cell_x1[dim2] &&
-                                dd->ci[dim2] != dd->nc[dim2]-1)
-                            {
-                                flag |= DD_FLAG_FW(d2);
-                            }
-                            else if (pos_d < cell_x0[dim2] &&
-                                     dd->ci[dim2] != 0)
-                            {
-                                flag |= DD_FLAG_BW(d2);
-                            }
-                            comm->buf_int[cg*DD_CGIBS+1] = flag;
-                        }
-                    }
-                    /* Set to which neighboring cell this cg should go */
-                    if (flag & DD_FLAG_FW(d2))
-                    {
-                        mc = d2*2;
-                    }
-                    else if (flag & DD_FLAG_BW(d2))
-                    {
-                        if (dd->nc[dd->dim[d2]] > 2)
-                        {
-                            mc = d2*2+1;
-                        }
-                        else
-                        {
-                            mc = d2*2;
-                        }
-                    }
-                }
-            }
-            
-            nrcg = flag & DD_FLAG_NRCG;
-            if (mc == -1)
-            {
-                if (home_pos_cg+1 > dd->cg_nalloc)
-                {
-                    dd->cg_nalloc = over_alloc_dd(home_pos_cg+1);
-                    srenew(dd->index_gl,dd->cg_nalloc);
-                    srenew(dd->cgindex,dd->cg_nalloc+1);
-                }
-                /* Set the global charge group index and size */
-                dd->index_gl[home_pos_cg] = comm->buf_int[cg*DD_CGIBS];
-                dd->cgindex[home_pos_cg+1] = dd->cgindex[home_pos_cg] + nrcg;
-                /* Copy the state from the buffer */
-                if (home_pos_cg >= fr->cg_nalloc)
-                {
-                    dd_realloc_fr_cg(fr,home_pos_cg+1);
-                    cg_cm = fr->cg_cm;
-                }
-                copy_rvec(comm->vbuf.v[buf_pos++],cg_cm[home_pos_cg]);
-                /* Set the cginfo */
-                fr->cginfo[home_pos_cg] = ddcginfo(cginfo_mb,
-                                                   dd->index_gl[home_pos_cg]);
-                if (comm->bLocalCG)
-                {
-                    comm->bLocalCG[dd->index_gl[home_pos_cg]] = TRUE;
-                }
-
-                if (home_pos_at+nrcg > state->nalloc)
-                {
-                    dd_realloc_state(state,f,home_pos_at+nrcg);
-                }
-                for(i=0; i<nrcg; i++)
-                {
-                    copy_rvec(comm->vbuf.v[buf_pos++],
-                              state->x[home_pos_at+i]);
-                }
-                if (bV)
-                {
-                    for(i=0; i<nrcg; i++)
-                    {
-                        copy_rvec(comm->vbuf.v[buf_pos++],
-                                  state->v[home_pos_at+i]);
-                    }
-                }
-                if (bSDX)
-                {
-                    for(i=0; i<nrcg; i++)
-                    {
-                        copy_rvec(comm->vbuf.v[buf_pos++],
-                                  state->sd_X[home_pos_at+i]);
-                    }
-                }
-                if (bCGP)
-                {
-                    for(i=0; i<nrcg; i++)
-                    {
-                        copy_rvec(comm->vbuf.v[buf_pos++],
-                                  state->cg_p[home_pos_at+i]);
-                    }
-                }
-                home_pos_cg += 1;
-                home_pos_at += nrcg;
-            }
-            else
-            {
-                /* Reallocate the buffers if necessary  */
-                if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
-                {
-                    comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
-                    srenew(comm->cggl_flag[mc],comm->cggl_flag_nalloc[mc]*DD_CGIBS);
-                }
-                nvr = ncg[mc] + nat[mc]*nvec;
-                if (nvr + 1 + nrcg*nvec > comm->cgcm_state_nalloc[mc])
-                {
-                    comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr + 1 + nrcg*nvec);
-                    srenew(comm->cgcm_state[mc],comm->cgcm_state_nalloc[mc]);
-                }
-                /* Copy from the receive to the send buffers */
-                memcpy(comm->cggl_flag[mc] + ncg[mc]*DD_CGIBS,
-                       comm->buf_int + cg*DD_CGIBS,
-                       DD_CGIBS*sizeof(int));
-                memcpy(comm->cgcm_state[mc][nvr],
-                       comm->vbuf.v[buf_pos],
-                       (1+nrcg*nvec)*sizeof(rvec));
-                buf_pos += 1 + nrcg*nvec;
-                ncg[mc] += 1;
-                nat[mc] += nrcg;
-            }
-        }
-    }
-    
-    /* With sorting (!bCompact) the indices are now only partially up to date
-     * and ncg_home and nat_home are not the real count, since there are
-     * "holes" in the arrays for the charge groups that moved to neighbors.
-     */
-    dd->ncg_home = home_pos_cg;
-    dd->nat_home = home_pos_at;
-
-    if (debug)
-    {
-        fprintf(debug,"Finished repartitioning\n");
-    }
-
-    return ncg_stay_home;
-}
-
-void dd_cycles_add(gmx_domdec_t *dd,float cycles,int ddCycl)
-{
-    dd->comm->cycl[ddCycl] += cycles;
-    dd->comm->cycl_n[ddCycl]++;
-    if (cycles > dd->comm->cycl_max[ddCycl])
-    {
-        dd->comm->cycl_max[ddCycl] = cycles;
-    }
-}
-
-static double force_flop_count(t_nrnb *nrnb)
-{
-    int i;
-    double sum;
-    const char *name;
-
-    sum = 0;
-    for(i=eNR_NBKERNEL010; i<eNR_NBKERNEL_FREE_ENERGY; i++)
-    {
-        /* To get closer to the real timings, we half the count
-         * for the normal loops and again half it for water loops.
-         */
-        name = nrnb_str(i);
-        if (strstr(name,"W3") != NULL || strstr(name,"W4") != NULL)
-        {
-            sum += nrnb->n[i]*0.25*cost_nrnb(i);
-        }
-        else
-        {
-            sum += nrnb->n[i]*0.50*cost_nrnb(i);
-        }
-    }
-    for(i=eNR_NBKERNEL_FREE_ENERGY; i<=eNR_NB14; i++)
-    {
-        name = nrnb_str(i);
-        if (strstr(name,"W3") != NULL || strstr(name,"W4") != NULL)
-        sum += nrnb->n[i]*cost_nrnb(i);
-    }
-    for(i=eNR_BONDS; i<=eNR_WALLS; i++)
-    {
-        sum += nrnb->n[i]*cost_nrnb(i);
-    }
-
-    return sum;
-}
-
-void dd_force_flop_start(gmx_domdec_t *dd,t_nrnb *nrnb)
-{
-    if (dd->comm->eFlop)
-    {
-        dd->comm->flop -= force_flop_count(nrnb);
-    }
-}
-void dd_force_flop_stop(gmx_domdec_t *dd,t_nrnb *nrnb)
-{
-    if (dd->comm->eFlop)
-    {
-        dd->comm->flop += force_flop_count(nrnb);
-        dd->comm->flop_n++;
-    }
-}  
-
-static void clear_dd_cycle_counts(gmx_domdec_t *dd)
-{
-    int i;
-    
-    for(i=0; i<ddCyclNr; i++)
-    {
-        dd->comm->cycl[i] = 0;
-        dd->comm->cycl_n[i] = 0;
-        dd->comm->cycl_max[i] = 0;
-    }
-    dd->comm->flop = 0;
-    dd->comm->flop_n = 0;
-}
-
-static void get_load_distribution(gmx_domdec_t *dd,gmx_wallcycle_t wcycle)
-{
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_load_t *load;
-    gmx_domdec_root_t *root=NULL;
-    int  d,dim,cid,i,pos;
-    float cell_frac=0,sbuf[DD_NLOAD_MAX];
-    gmx_bool bSepPME;
-    
-    if (debug)
-    {
-        fprintf(debug,"get_load_distribution start\n");
-    }
-
-    wallcycle_start(wcycle,ewcDDCOMMLOAD);
-    
-    comm = dd->comm;
-    
-    bSepPME = (dd->pme_nodeid >= 0);
-    
-    for(d=dd->ndim-1; d>=0; d--)
-    {
-        dim = dd->dim[d];
-        /* Check if we participate in the communication in this dimension */
-        if (d == dd->ndim-1 || 
-            (dd->ci[dd->dim[d+1]]==0 && dd->ci[dd->dim[dd->ndim-1]]==0))
-        {
-            load = &comm->load[d];
-            if (dd->bGridJump)
-            {
-                cell_frac = comm->cell_f1[d] - comm->cell_f0[d];
-            }
-            pos = 0;
-            if (d == dd->ndim-1)
-            {
-                sbuf[pos++] = dd_force_load(comm);
-                sbuf[pos++] = sbuf[0];
-                if (dd->bGridJump)
-                {
-                    sbuf[pos++] = sbuf[0];
-                    sbuf[pos++] = cell_frac;
-                    if (d > 0)
-                    {
-                        sbuf[pos++] = comm->cell_f_max0[d];
-                        sbuf[pos++] = comm->cell_f_min1[d];
-                    }
-                }
-                if (bSepPME)
-                {
-                    sbuf[pos++] = comm->cycl[ddCyclPPduringPME];
-                    sbuf[pos++] = comm->cycl[ddCyclPME];
-                }
-            }
-            else
-            {
-                sbuf[pos++] = comm->load[d+1].sum;
-                sbuf[pos++] = comm->load[d+1].max;
-                if (dd->bGridJump)
-                {
-                    sbuf[pos++] = comm->load[d+1].sum_m;
-                    sbuf[pos++] = comm->load[d+1].cvol_min*cell_frac;
-                    sbuf[pos++] = comm->load[d+1].flags;
-                    if (d > 0)
-                    {
-                        sbuf[pos++] = comm->cell_f_max0[d];
-                        sbuf[pos++] = comm->cell_f_min1[d];
-                    }
-                }
-                if (bSepPME)
-                {
-                    sbuf[pos++] = comm->load[d+1].mdf;
-                    sbuf[pos++] = comm->load[d+1].pme;
-                }
-            }
-            load->nload = pos;
-            /* Communicate a row in DD direction d.
-             * The communicators are setup such that the root always has rank 0.
-             */
-#ifdef GMX_MPI
-            MPI_Gather(sbuf      ,load->nload*sizeof(float),MPI_BYTE,
-                       load->load,load->nload*sizeof(float),MPI_BYTE,
-                       0,comm->mpi_comm_load[d]);
-#endif
-            if (dd->ci[dim] == dd->master_ci[dim])
-            {
-                /* We are the root, process this row */
-                if (comm->bDynLoadBal)
-                {
-                    root = comm->root[d];
-                }
-                load->sum = 0;
-                load->max = 0;
-                load->sum_m = 0;
-                load->cvol_min = 1;
-                load->flags = 0;
-                load->mdf = 0;
-                load->pme = 0;
-                pos = 0;
-                for(i=0; i<dd->nc[dim]; i++)
-                {
-                    load->sum += load->load[pos++];
-                    load->max = max(load->max,load->load[pos]);
-                    pos++;
-                    if (dd->bGridJump)
-                    {
-                        if (root->bLimited)
-                        {
-                            /* This direction could not be load balanced properly,
-                             * therefore we need to use the maximum iso the average load.
-                             */
-                            load->sum_m = max(load->sum_m,load->load[pos]);
-                        }
-                        else
-                        {
-                            load->sum_m += load->load[pos];
-                        }
-                        pos++;
-                        load->cvol_min = min(load->cvol_min,load->load[pos]);
-                        pos++;
-                        if (d < dd->ndim-1)
-                        {
-                            load->flags = (int)(load->load[pos++] + 0.5);
-                        }
-                        if (d > 0)
-                        {
-                            root->cell_f_max0[i] = load->load[pos++];
-                            root->cell_f_min1[i] = load->load[pos++];
-                        }
-                    }
-                    if (bSepPME)
-                    {
-                        load->mdf = max(load->mdf,load->load[pos]);
-                        pos++;
-                        load->pme = max(load->pme,load->load[pos]);
-                        pos++;
-                    }
-                }
-                if (comm->bDynLoadBal && root->bLimited)
-                {
-                    load->sum_m *= dd->nc[dim];
-                    load->flags |= (1<<d);
-                }
-            }
-        }
-    }
-
-    if (DDMASTER(dd))
-    {
-        comm->nload      += dd_load_count(comm);
-        comm->load_step  += comm->cycl[ddCyclStep];
-        comm->load_sum   += comm->load[0].sum;
-        comm->load_max   += comm->load[0].max;
-        if (comm->bDynLoadBal)
-        {
-            for(d=0; d<dd->ndim; d++)
-            {
-                if (comm->load[0].flags & (1<<d))
-                {
-                    comm->load_lim[d]++;
-                }
-            }
-        }
-        if (bSepPME)
-        {
-            comm->load_mdf += comm->load[0].mdf;
-            comm->load_pme += comm->load[0].pme;
-        }
-    }
-
-    wallcycle_stop(wcycle,ewcDDCOMMLOAD);
-    
-    if (debug)
-    {
-        fprintf(debug,"get_load_distribution finished\n");
-    }
-}
-
-static float dd_force_imb_perf_loss(gmx_domdec_t *dd)
-{
-    /* Return the relative performance loss on the total run time
-     * due to the force calculation load imbalance.
-     */
-    if (dd->comm->nload > 0)
-    {
-        return
-            (dd->comm->load_max*dd->nnodes - dd->comm->load_sum)/
-            (dd->comm->load_step*dd->nnodes);
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-static void print_dd_load_av(FILE *fplog,gmx_domdec_t *dd)
-{
-    char  buf[STRLEN];
-    int   npp,npme,nnodes,d,limp;
-    float imbal,pme_f_ratio,lossf,lossp=0;
-    gmx_bool  bLim;
-    gmx_domdec_comm_t *comm;
-
-    comm = dd->comm;
-    if (DDMASTER(dd) && comm->nload > 0)
-    {
-        npp    = dd->nnodes;
-        npme   = (dd->pme_nodeid >= 0) ? comm->npmenodes : 0;
-        nnodes = npp + npme;
-        imbal = comm->load_max*npp/comm->load_sum - 1;
-        lossf = dd_force_imb_perf_loss(dd);
-        sprintf(buf," Average load imbalance: %.1f %%\n",imbal*100);
-        fprintf(fplog,"%s",buf);
-        fprintf(stderr,"\n");
-        fprintf(stderr,"%s",buf);
-        sprintf(buf," Part of the total run time spent waiting due to load imbalance: %.1f %%\n",lossf*100);
-        fprintf(fplog,"%s",buf);
-        fprintf(stderr,"%s",buf);
-        bLim = FALSE;
-        if (comm->bDynLoadBal)
-        {
-            sprintf(buf," Steps where the load balancing was limited by -rdd, -rcon and/or -dds:");
-            for(d=0; d<dd->ndim; d++)
-            {
-                limp = (200*comm->load_lim[d]+1)/(2*comm->nload);
-                sprintf(buf+strlen(buf)," %c %d %%",dim2char(dd->dim[d]),limp);
-                if (limp >= 50)
-                {
-                    bLim = TRUE;
-                }
-            }
-            sprintf(buf+strlen(buf),"\n");
-            fprintf(fplog,"%s",buf);
-            fprintf(stderr,"%s",buf);
-        }
-        if (npme > 0)
-        {
-            pme_f_ratio = comm->load_pme/comm->load_mdf;
-            lossp = (comm->load_pme -comm->load_mdf)/comm->load_step;
-            if (lossp <= 0)
-            {
-                lossp *= (float)npme/(float)nnodes;
-            }
-            else
-            {
-                lossp *= (float)npp/(float)nnodes;
-            }
-            sprintf(buf," Average PME mesh/force load: %5.3f\n",pme_f_ratio);
-            fprintf(fplog,"%s",buf);
-            fprintf(stderr,"%s",buf);
-            sprintf(buf," Part of the total run time spent waiting due to PP/PME imbalance: %.1f %%\n",fabs(lossp)*100);
-            fprintf(fplog,"%s",buf);
-            fprintf(stderr,"%s",buf);
-        }
-        fprintf(fplog,"\n");
-        fprintf(stderr,"\n");
-        
-        if (lossf >= DD_PERF_LOSS)
-        {
-            sprintf(buf,
-                    "NOTE: %.1f %% performance was lost due to load imbalance\n"
-                    "      in the domain decomposition.\n",lossf*100);
-            if (!comm->bDynLoadBal)
-            {
-                sprintf(buf+strlen(buf),"      You might want to use dynamic load balancing (option -dlb.)\n");
-            }
-            else if (bLim)
-            {
-                sprintf(buf+strlen(buf),"      You might want to decrease the cell size limit (options -rdd, -rcon and/or -dds).\n");
-            }
-            fprintf(fplog,"%s\n",buf);
-            fprintf(stderr,"%s\n",buf);
-        }
-        if (npme > 0 && fabs(lossp) >= DD_PERF_LOSS)
-        {
-            sprintf(buf,
-                    "NOTE: %.1f %% performance was lost because the PME nodes\n"
-                    "      had %s work to do than the PP nodes.\n"
-                    "      You might want to %s the number of PME nodes\n"
-                    "      or %s the cut-off and the grid spacing.\n",
-                    fabs(lossp*100),
-                    (lossp < 0) ? "less"     : "more",
-                    (lossp < 0) ? "decrease" : "increase",
-                    (lossp < 0) ? "decrease" : "increase");
-            fprintf(fplog,"%s\n",buf);
-            fprintf(stderr,"%s\n",buf);
-        }
-    }
-}
-
-static float dd_vol_min(gmx_domdec_t *dd)
-{
-    return dd->comm->load[0].cvol_min*dd->nnodes;
-}
-
-static gmx_bool dd_load_flags(gmx_domdec_t *dd)
-{
-    return dd->comm->load[0].flags;
-}
-
-static float dd_f_imbal(gmx_domdec_t *dd)
-{
-    return dd->comm->load[0].max*dd->nnodes/dd->comm->load[0].sum - 1;
-}
-
-static float dd_pme_f_ratio(gmx_domdec_t *dd)
-{
-    return dd->comm->load[0].pme/dd->comm->load[0].mdf;
-}
-
-static void dd_print_load(FILE *fplog,gmx_domdec_t *dd,gmx_large_int_t step)
-{
-    int flags,d;
-    char buf[22];
-    
-    flags = dd_load_flags(dd);
-    if (flags)
-    {
-        fprintf(fplog,
-                "DD  load balancing is limited by minimum cell size in dimension");
-        for(d=0; d<dd->ndim; d++)
-        {
-            if (flags & (1<<d))
-            {
-                fprintf(fplog," %c",dim2char(dd->dim[d]));
-            }
-        }
-        fprintf(fplog,"\n");
-    }
-    fprintf(fplog,"DD  step %s",gmx_step_str(step,buf));
-    if (dd->comm->bDynLoadBal)
-    {
-        fprintf(fplog,"  vol min/aver %5.3f%c",
-                dd_vol_min(dd),flags ? '!' : ' ');
-    }
-    fprintf(fplog," load imb.: force %4.1f%%",dd_f_imbal(dd)*100);
-    if (dd->comm->cycl_n[ddCyclPME])
-    {
-        fprintf(fplog,"  pme mesh/force %5.3f",dd_pme_f_ratio(dd));
-    }
-    fprintf(fplog,"\n\n");
-}
-
-static void dd_print_load_verbose(gmx_domdec_t *dd)
-{
-    if (dd->comm->bDynLoadBal)
-    {
-        fprintf(stderr,"vol %4.2f%c ",
-                dd_vol_min(dd),dd_load_flags(dd) ? '!' : ' ');
-    }
-    fprintf(stderr,"imb F %2d%% ",(int)(dd_f_imbal(dd)*100+0.5));
-    if (dd->comm->cycl_n[ddCyclPME])
-    {
-        fprintf(stderr,"pme/F %4.2f ",dd_pme_f_ratio(dd));
-    }
-}
-
-#ifdef GMX_MPI
-static void make_load_communicator(gmx_domdec_t *dd,MPI_Group g_all,
-                                   int dim_ind,ivec loc)
-{
-    MPI_Group g_row = MPI_GROUP_EMPTY;
-    MPI_Comm  c_row;
-    int  dim,i,*rank;
-    ivec loc_c;
-    gmx_domdec_root_t *root;
-    gmx_bool bPartOfGroup = FALSE;
-    
-    dim = dd->dim[dim_ind];
-    copy_ivec(loc,loc_c);
-    snew(rank,dd->nc[dim]);
-    for(i=0; i<dd->nc[dim]; i++)
-    {
-        loc_c[dim] = i;
-        rank[i] = dd_index(dd->nc,loc_c);
-        if (rank[i] == dd->rank)
-        {
-            /* This process is part of the group */
-            bPartOfGroup = TRUE;
-        }
-    }
-    if (bPartOfGroup)
-    {
-        MPI_Group_incl(g_all,dd->nc[dim],rank,&g_row);
-    }
-    MPI_Comm_create(dd->mpi_comm_all,g_row,&c_row);
-    if (bPartOfGroup)
-    {
-        dd->comm->mpi_comm_load[dim_ind] = c_row;
-        if (dd->comm->eDLB != edlbNO)
-        {
-            if (dd->ci[dim] == dd->master_ci[dim])
-            {
-                /* This is the root process of this row */
-                snew(dd->comm->root[dim_ind],1);
-                root = dd->comm->root[dim_ind];
-                snew(root->cell_f,DD_CELL_F_SIZE(dd,dim_ind));
-                snew(root->old_cell_f,dd->nc[dim]+1);
-                snew(root->bCellMin,dd->nc[dim]);
-                if (dim_ind > 0)
-                {
-                    snew(root->cell_f_max0,dd->nc[dim]);
-                    snew(root->cell_f_min1,dd->nc[dim]);
-                    snew(root->bound_min,dd->nc[dim]);
-                    snew(root->bound_max,dd->nc[dim]);
-                }
-                snew(root->buf_ncd,dd->nc[dim]);
-            }
-            else
-            {
-                /* This is not a root process, we only need to receive cell_f */
-                snew(dd->comm->cell_f_row,DD_CELL_F_SIZE(dd,dim_ind));
-            }
-        }
-        if (dd->ci[dim] == dd->master_ci[dim])
-        {
-            snew(dd->comm->load[dim_ind].load,dd->nc[dim]*DD_NLOAD_MAX);
-        }
-    }
-    sfree(rank);
-}
-#endif
-
-static void make_load_communicators(gmx_domdec_t *dd)
-{
-#ifdef GMX_MPI
-  MPI_Group g_all;
-  int  dim0,dim1,i,j;
-  ivec loc;
-
-  if (debug)
-    fprintf(debug,"Making load communicators\n");
-
-  MPI_Comm_group(dd->mpi_comm_all,&g_all);
-  
-  snew(dd->comm->load,dd->ndim);
-  snew(dd->comm->mpi_comm_load,dd->ndim);
-  
-  clear_ivec(loc);
-  make_load_communicator(dd,g_all,0,loc);
-  if (dd->ndim > 1) {
-    dim0 = dd->dim[0];
-    for(i=0; i<dd->nc[dim0]; i++) {
-      loc[dim0] = i;
-      make_load_communicator(dd,g_all,1,loc);
-    }
-  }
-  if (dd->ndim > 2) {
-    dim0 = dd->dim[0];
-    for(i=0; i<dd->nc[dim0]; i++) {
-      loc[dim0] = i;
-      dim1 = dd->dim[1];
-      for(j=0; j<dd->nc[dim1]; j++) {
-         loc[dim1] = j;
-         make_load_communicator(dd,g_all,2,loc);
-      }
-    }
-  }
-
-  MPI_Group_free(&g_all);
-
-  if (debug)
-    fprintf(debug,"Finished making load communicators\n");
-#endif
-}
-
-void setup_dd_grid(FILE *fplog,gmx_domdec_t *dd)
-{
-    gmx_bool bZYX;
-    int  d,dim,i,j,m;
-    ivec tmp,s;
-    int  nzone,nzonep;
-    ivec dd_zp[DD_MAXIZONE];
-    gmx_domdec_zones_t *zones;
-    gmx_domdec_ns_ranges_t *izone;
-    
-    for(d=0; d<dd->ndim; d++)
-    {
-        dim = dd->dim[d];
-        copy_ivec(dd->ci,tmp);
-        tmp[dim] = (tmp[dim] + 1) % dd->nc[dim];
-        dd->neighbor[d][0] = ddcoord2ddnodeid(dd,tmp);
-        copy_ivec(dd->ci,tmp);
-        tmp[dim] = (tmp[dim] - 1 + dd->nc[dim]) % dd->nc[dim];
-        dd->neighbor[d][1] = ddcoord2ddnodeid(dd,tmp);
-        if (debug)
-        {
-            fprintf(debug,"DD rank %d neighbor ranks in dir %d are + %d - %d\n",
-                    dd->rank,dim,
-                    dd->neighbor[d][0],
-                    dd->neighbor[d][1]);
-        }
-    }
-    
-    if (DDMASTER(dd))
-    {
-        fprintf(stderr,"Making %dD domain decomposition %d x %d x %d\n",
-           dd->ndim,dd->nc[XX],dd->nc[YY],dd->nc[ZZ]);
-    }
-    if (fplog)
-    {
-        fprintf(fplog,"\nMaking %dD domain decomposition grid %d x %d x %d, home cell index %d %d %d\n\n",
-                dd->ndim,
-                dd->nc[XX],dd->nc[YY],dd->nc[ZZ],
-                dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-    }
-    switch (dd->ndim)
-    {
-    case 3:
-        nzone  = dd_z3n;
-        nzonep = dd_zp3n;
-        for(i=0; i<nzonep; i++)
-        {
-            copy_ivec(dd_zp3[i],dd_zp[i]);
-        }
-        break;
-    case 2:
-        nzone  = dd_z2n;
-        nzonep = dd_zp2n;
-        for(i=0; i<nzonep; i++)
-        {
-            copy_ivec(dd_zp2[i],dd_zp[i]);
-        }
-        break;
-    case 1:
-        nzone  = dd_z1n;
-        nzonep = dd_zp1n;
-        for(i=0; i<nzonep; i++)
-        {
-            copy_ivec(dd_zp1[i],dd_zp[i]);
-        }
-        break;
-    default:
-        gmx_fatal(FARGS,"Can only do 1, 2 or 3D domain decomposition");
-        nzone = 0;
-        nzonep = 0;
-    }
-
-    zones = &dd->comm->zones;
-
-    for(i=0; i<nzone; i++)
-    {
-        m = 0;
-        clear_ivec(zones->shift[i]);
-        for(d=0; d<dd->ndim; d++)
-        {
-            zones->shift[i][dd->dim[d]] = dd_zo[i][m++];
-        }
-    }
-    
-    zones->n = nzone;
-    for(i=0; i<nzone; i++)
-    {
-        for(d=0; d<DIM; d++)
-        {
-            s[d] = dd->ci[d] - zones->shift[i][d];
-            if (s[d] < 0)
-            {
-                s[d] += dd->nc[d];
-            }
-            else if (s[d] >= dd->nc[d])
-            {
-                s[d] -= dd->nc[d];
-            }
-        }
-    }
-    zones->nizone = nzonep;
-    for(i=0; i<zones->nizone; i++)
-    {
-        if (dd_zp[i][0] != i)
-        {
-            gmx_fatal(FARGS,"Internal inconsistency in the dd grid setup");
-        }
-        izone = &zones->izone[i];
-        izone->j0 = dd_zp[i][1];
-        izone->j1 = dd_zp[i][2];
-        for(dim=0; dim<DIM; dim++)
-        {
-            if (dd->nc[dim] == 1)
-            {
-                /* All shifts should be allowed */
-                izone->shift0[dim] = -1;
-                izone->shift1[dim] = 1;
-            }
-            else
-            {
-                /*
-                  izone->shift0[d] = 0;
-                  izone->shift1[d] = 0;
-                  for(j=izone->j0; j<izone->j1; j++) {
-                  if (dd->shift[j][d] > dd->shift[i][d])
-                  izone->shift0[d] = -1;
-                  if (dd->shift[j][d] < dd->shift[i][d])
-                  izone->shift1[d] = 1;
-                  }
-                */
-                
-                int shift_diff;
-                
-                /* Assume the shift are not more than 1 cell */
-                izone->shift0[dim] = 1;
-                izone->shift1[dim] = -1;
-                for(j=izone->j0; j<izone->j1; j++)
-                {
-                    shift_diff = zones->shift[j][dim] - zones->shift[i][dim];
-                    if (shift_diff < izone->shift0[dim])
-                    {
-                        izone->shift0[dim] = shift_diff;
-                    }
-                    if (shift_diff > izone->shift1[dim])
-                    {
-                        izone->shift1[dim] = shift_diff;
-                    }
-                }
-            }
-        }
-    }
-    
-    if (dd->comm->eDLB != edlbNO)
-    {
-        snew(dd->comm->root,dd->ndim);
-    }
-    
-    if (dd->comm->bRecordLoad)
-    {
-        make_load_communicators(dd);
-    }
-}
-
-static void make_pp_communicator(FILE *fplog,t_commrec *cr,int reorder)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    int  i,rank,*buf;
-    ivec periods;
-#ifdef GMX_MPI
-    MPI_Comm comm_cart;
-#endif
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-#ifdef GMX_MPI
-    if (comm->bCartesianPP)
-    {
-        /* Set up cartesian communication for the particle-particle part */
-        if (fplog)
-        {
-            fprintf(fplog,"Will use a Cartesian communicator: %d x %d x %d\n",
-                    dd->nc[XX],dd->nc[YY],dd->nc[ZZ]);
-        }
-        
-        for(i=0; i<DIM; i++)
-        {
-            periods[i] = TRUE;
-        }
-        MPI_Cart_create(cr->mpi_comm_mygroup,DIM,dd->nc,periods,reorder,
-                        &comm_cart);
-        /* We overwrite the old communicator with the new cartesian one */
-        cr->mpi_comm_mygroup = comm_cart;
-    }
-    
-    dd->mpi_comm_all = cr->mpi_comm_mygroup;
-    MPI_Comm_rank(dd->mpi_comm_all,&dd->rank);
-    
-    if (comm->bCartesianPP_PME)
-    {
-        /* Since we want to use the original cartesian setup for sim,
-         * and not the one after split, we need to make an index.
-         */
-        snew(comm->ddindex2ddnodeid,dd->nnodes);
-        comm->ddindex2ddnodeid[dd_index(dd->nc,dd->ci)] = dd->rank;
-        gmx_sumi(dd->nnodes,comm->ddindex2ddnodeid,cr);
-        /* Get the rank of the DD master,
-         * above we made sure that the master node is a PP node.
-         */
-        if (MASTER(cr))
-        {
-            rank = dd->rank;
-        }
-        else
-        {
-            rank = 0;
-        }
-        MPI_Allreduce(&rank,&dd->masterrank,1,MPI_INT,MPI_SUM,dd->mpi_comm_all);
-    }
-    else if (comm->bCartesianPP)
-    {
-        if (cr->npmenodes == 0)
-        {
-            /* The PP communicator is also
-             * the communicator for this simulation
-             */
-            cr->mpi_comm_mysim = cr->mpi_comm_mygroup;
-        }
-        cr->nodeid = dd->rank;
-        
-        MPI_Cart_coords(dd->mpi_comm_all,dd->rank,DIM,dd->ci);
-        
-        /* We need to make an index to go from the coordinates
-         * to the nodeid of this simulation.
-         */
-        snew(comm->ddindex2simnodeid,dd->nnodes);
-        snew(buf,dd->nnodes);
-        if (cr->duty & DUTY_PP)
-        {
-            buf[dd_index(dd->nc,dd->ci)] = cr->sim_nodeid;
-        }
-        /* Communicate the ddindex to simulation nodeid index */
-        MPI_Allreduce(buf,comm->ddindex2simnodeid,dd->nnodes,MPI_INT,MPI_SUM,
-                      cr->mpi_comm_mysim);
-        sfree(buf);
-        
-        /* Determine the master coordinates and rank.
-         * The DD master should be the same node as the master of this sim.
-         */
-        for(i=0; i<dd->nnodes; i++)
-        {
-            if (comm->ddindex2simnodeid[i] == 0)
-            {
-                ddindex2xyz(dd->nc,i,dd->master_ci);
-                MPI_Cart_rank(dd->mpi_comm_all,dd->master_ci,&dd->masterrank);
-            }
-        }
-        if (debug)
-        {
-            fprintf(debug,"The master rank is %d\n",dd->masterrank);
-        }
-    }
-    else
-    {
-        /* No Cartesian communicators */
-        /* We use the rank in dd->comm->all as DD index */
-        ddindex2xyz(dd->nc,dd->rank,dd->ci);
-        /* The simulation master nodeid is 0, so the DD master rank is also 0 */
-        dd->masterrank = 0;
-        clear_ivec(dd->master_ci);
-    }
-#endif
-  
-    if (fplog)
-    {
-        fprintf(fplog,
-                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
-                dd->rank,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-    }
-    if (debug)
-    {
-        fprintf(debug,
-                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
-                dd->rank,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-    }
-}
-
-static void receive_ddindex2simnodeid(t_commrec *cr)
-{
-    gmx_domdec_t *dd;
-    
-    gmx_domdec_comm_t *comm;
-    int  *buf;
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-#ifdef GMX_MPI
-    if (!comm->bCartesianPP_PME && comm->bCartesianPP)
-    {
-        snew(comm->ddindex2simnodeid,dd->nnodes);
-        snew(buf,dd->nnodes);
-        if (cr->duty & DUTY_PP)
-        {
-            buf[dd_index(dd->nc,dd->ci)] = cr->sim_nodeid;
-        }
-#ifdef GMX_MPI
-        /* Communicate the ddindex to simulation nodeid index */
-        MPI_Allreduce(buf,comm->ddindex2simnodeid,dd->nnodes,MPI_INT,MPI_SUM,
-                      cr->mpi_comm_mysim);
-#endif
-        sfree(buf);
-    }
-#endif
-}
-
-static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
-                                                     int ncg,int natoms)
-{
-    gmx_domdec_master_t *ma;
-    int i;
-
-    snew(ma,1);
-    
-    snew(ma->ncg,dd->nnodes);
-    snew(ma->index,dd->nnodes+1);
-    snew(ma->cg,ncg);
-    snew(ma->nat,dd->nnodes);
-    snew(ma->ibuf,dd->nnodes*2);
-    snew(ma->cell_x,DIM);
-    for(i=0; i<DIM; i++)
-    {
-        snew(ma->cell_x[i],dd->nc[i]+1);
-    }
-
-    if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
-    {
-        ma->vbuf = NULL;
-    }
-    else
-    {
-        snew(ma->vbuf,natoms);
-    }
-
-    return ma;
-}
-
-static void split_communicator(FILE *fplog,t_commrec *cr,int dd_node_order,
-                               int reorder)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    int  i,rank;
-    gmx_bool bDiv[DIM];
-    ivec periods;
-#ifdef GMX_MPI
-    MPI_Comm comm_cart;
-#endif
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-    if (comm->bCartesianPP)
-    {
-        for(i=1; i<DIM; i++)
-        {
-            bDiv[i] = ((cr->npmenodes*dd->nc[i]) % (dd->nnodes) == 0);
-        }
-        if (bDiv[YY] || bDiv[ZZ])
-        {
-            comm->bCartesianPP_PME = TRUE;
-            /* If we have 2D PME decomposition, which is always in x+y,
-             * we stack the PME only nodes in z.
-             * Otherwise we choose the direction that provides the thinnest slab
-             * of PME only nodes as this will have the least effect
-             * on the PP communication.
-             * But for the PME communication the opposite might be better.
-             */
-            if (bDiv[ZZ] && (comm->npmenodes_y > 1 ||
-                             !bDiv[YY] ||
-                             dd->nc[YY] > dd->nc[ZZ]))
-            {
-                comm->cartpmedim = ZZ;
-            }
-            else
-            {
-                comm->cartpmedim = YY;
-            }
-            comm->ntot[comm->cartpmedim]
-                += (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
-        }
-        else if (fplog)
-        {
-            fprintf(fplog,"#pmenodes (%d) is not a multiple of nx*ny (%d*%d) or nx*nz (%d*%d)\n",cr->npmenodes,dd->nc[XX],dd->nc[YY],dd->nc[XX],dd->nc[ZZ]);
-            fprintf(fplog,
-                    "Will not use a Cartesian communicator for PP <-> PME\n\n");
-        }
-    }
-    
-#ifdef GMX_MPI
-    if (comm->bCartesianPP_PME)
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"Will use a Cartesian communicator for PP <-> PME: %d x %d x %d\n",comm->ntot[XX],comm->ntot[YY],comm->ntot[ZZ]);
-        }
-        
-        for(i=0; i<DIM; i++)
-        {
-            periods[i] = TRUE;
-        }
-        MPI_Cart_create(cr->mpi_comm_mysim,DIM,comm->ntot,periods,reorder,
-                        &comm_cart);
-        
-        MPI_Comm_rank(comm_cart,&rank);
-        if (MASTERNODE(cr) && rank != 0)
-        {
-            gmx_fatal(FARGS,"MPI rank 0 was renumbered by MPI_Cart_create, we do not allow this");
-        }
-        
-        /* With this assigment we loose the link to the original communicator
-         * which will usually be MPI_COMM_WORLD, unless have multisim.
-         */
-        cr->mpi_comm_mysim = comm_cart;
-        cr->sim_nodeid = rank;
-        
-        MPI_Cart_coords(cr->mpi_comm_mysim,cr->sim_nodeid,DIM,dd->ci);
-        
-        if (fplog)
-        {
-            fprintf(fplog,"Cartesian nodeid %d, coordinates %d %d %d\n\n",
-                    cr->sim_nodeid,dd->ci[XX],dd->ci[YY],dd->ci[ZZ]);
-        }
-        
-        if (dd->ci[comm->cartpmedim] < dd->nc[comm->cartpmedim])
-        {
-            cr->duty = DUTY_PP;
-        }
-        if (cr->npmenodes == 0 ||
-            dd->ci[comm->cartpmedim] >= dd->nc[comm->cartpmedim])
-        {
-            cr->duty = DUTY_PME;
-        }
-        
-        /* Split the sim communicator into PP and PME only nodes */
-        MPI_Comm_split(cr->mpi_comm_mysim,
-                       cr->duty,
-                       dd_index(comm->ntot,dd->ci),
-                       &cr->mpi_comm_mygroup);
-    }
-    else
-    {
-        switch (dd_node_order)
-        {
-        case ddnoPP_PME:
-            if (fplog)
-            {
-                fprintf(fplog,"Order of the nodes: PP first, PME last\n");
-            }
-            break;
-        case ddnoINTERLEAVE:
-            /* Interleave the PP-only and PME-only nodes,
-             * as on clusters with dual-core machines this will double
-             * the communication bandwidth of the PME processes
-             * and thus speed up the PP <-> PME and inter PME communication.
-             */
-            if (fplog)
-            {
-                fprintf(fplog,"Interleaving PP and PME nodes\n");
-            }
-            comm->pmenodes = dd_pmenodes(cr);
-            break;
-        case ddnoCARTESIAN:
-            break;
-        default:
-            gmx_fatal(FARGS,"Unknown dd_node_order=%d",dd_node_order);
-        }
-    
-        if (dd_simnode2pmenode(cr,cr->sim_nodeid) == -1)
-        {
-            cr->duty = DUTY_PME;
-        }
-        else
-        {
-            cr->duty = DUTY_PP;
-        }
-        
-        /* Split the sim communicator into PP and PME only nodes */
-        MPI_Comm_split(cr->mpi_comm_mysim,
-                       cr->duty,
-                       cr->nodeid,
-                       &cr->mpi_comm_mygroup);
-        MPI_Comm_rank(cr->mpi_comm_mygroup,&cr->nodeid);
-    }
-#endif
-
-    if (fplog)
-    {
-        fprintf(fplog,"This is a %s only node\n\n",
-                (cr->duty & DUTY_PP) ? "particle-particle" : "PME-mesh");
-    }
-}
-
-void make_dd_communicators(FILE *fplog,t_commrec *cr,int dd_node_order)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    int CartReorder;
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-    copy_ivec(dd->nc,comm->ntot);
-    
-    comm->bCartesianPP = (dd_node_order == ddnoCARTESIAN);
-    comm->bCartesianPP_PME = FALSE;
-    
-    /* Reorder the nodes by default. This might change the MPI ranks.
-     * Real reordering is only supported on very few architectures,
-     * Blue Gene is one of them.
-     */
-    CartReorder = (getenv("GMX_NO_CART_REORDER") == NULL);
-    
-    if (cr->npmenodes > 0)
-    {
-        /* Split the communicator into a PP and PME part */
-        split_communicator(fplog,cr,dd_node_order,CartReorder);
-        if (comm->bCartesianPP_PME)
-        {
-            /* We (possibly) reordered the nodes in split_communicator,
-             * so it is no longer required in make_pp_communicator.
-             */
-            CartReorder = FALSE;
-        }
-    }
-    else
-    {
-        /* All nodes do PP and PME */
-#ifdef GMX_MPI    
-        /* We do not require separate communicators */
-        cr->mpi_comm_mygroup = cr->mpi_comm_mysim;
-#endif
-    }
-    
-    if (cr->duty & DUTY_PP)
-    {
-        /* Copy or make a new PP communicator */
-        make_pp_communicator(fplog,cr,CartReorder);
-    }
-    else
-    {
-        receive_ddindex2simnodeid(cr);
-    }
-    
-    if (!(cr->duty & DUTY_PME))
-    {
-        /* Set up the commnuication to our PME node */
-        dd->pme_nodeid = dd_simnode2pmenode(cr,cr->sim_nodeid);
-        dd->pme_receive_vir_ener = receive_vir_ener(cr);
-        if (debug)
-        {
-            fprintf(debug,"My pme_nodeid %d receive ener %d\n",
-                    dd->pme_nodeid,dd->pme_receive_vir_ener);
-        }
-    }
-    else
-    {
-        dd->pme_nodeid = -1;
-    }
-
-    if (DDMASTER(dd))
-    {
-        dd->ma = init_gmx_domdec_master_t(dd,
-                                          comm->cgs_gl.nr,
-                                          comm->cgs_gl.index[comm->cgs_gl.nr]);
-    }
-}
-
-static real *get_slb_frac(FILE *fplog,const char *dir,int nc,const char *size_string)
-{
-    real *slb_frac,tot;
-    int  i,n;
-    double dbl;
-    
-    slb_frac = NULL;
-    if (nc > 1 && size_string != NULL)
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"Using static load balancing for the %s direction\n",
-                    dir);
-        }
-        snew(slb_frac,nc);
-        tot = 0;
-        for (i=0; i<nc; i++)
-        {
-            dbl = 0;
-            sscanf(size_string,"%lf%n",&dbl,&n);
-            if (dbl == 0)
-            {
-                gmx_fatal(FARGS,"Incorrect or not enough DD cell size entries for direction %s: '%s'",dir,size_string);
-            }
-            slb_frac[i] = dbl;
-            size_string += n;
-            tot += slb_frac[i];
-        }
-        /* Normalize */
-        if (fplog)
-        {
-            fprintf(fplog,"Relative cell sizes:");
-        }
-        for (i=0; i<nc; i++)
-        {
-            slb_frac[i] /= tot;
-            if (fplog)
-            {
-                fprintf(fplog," %5.3f",slb_frac[i]);
-            }
-        }
-        if (fplog)
-        {
-            fprintf(fplog,"\n");
-        }
-    }
-    
-    return slb_frac;
-}
-
-static int multi_body_bondeds_count(gmx_mtop_t *mtop)
-{
-    int n,nmol,ftype;
-    gmx_mtop_ilistloop_t iloop;
-    t_ilist *il;
-    
-    n = 0;
-    iloop = gmx_mtop_ilistloop_init(mtop);
-    while (gmx_mtop_ilistloop_next(iloop,&il,&nmol))
-    {
-        for(ftype=0; ftype<F_NRE; ftype++)
-        {
-            if ((interaction_function[ftype].flags & IF_BOND) &&
-                NRAL(ftype) >  2)
-            {
-                n += nmol*il[ftype].nr/(1 + NRAL(ftype));
-            }
-        }
-  }
-
-  return n;
-}
-
-static int dd_nst_env(FILE *fplog,const char *env_var,int def)
-{
-    char *val;
-    int  nst;
-    
-    nst = def;
-    val = getenv(env_var);
-    if (val)
-    {
-        if (sscanf(val,"%d",&nst) <= 0)
-        {
-            nst = 1;
-        }
-        if (fplog)
-        {
-            fprintf(fplog,"Found env.var. %s = %s, using value %d\n",
-                    env_var,val,nst);
-        }
-    }
-    
-    return nst;
-}
-
-static void dd_warning(t_commrec *cr,FILE *fplog,const char *warn_string)
-{
-    if (MASTER(cr))
-    {
-        fprintf(stderr,"\n%s\n",warn_string);
-    }
-    if (fplog)
-    {
-        fprintf(fplog,"\n%s\n",warn_string);
-    }
-}
-
-static void check_dd_restrictions(t_commrec *cr,gmx_domdec_t *dd,
-                                  t_inputrec *ir,FILE *fplog)
-{
-    if (ir->ePBC == epbcSCREW &&
-        (dd->nc[XX] == 1 || dd->nc[YY] > 1 || dd->nc[ZZ] > 1))
-    {
-        gmx_fatal(FARGS,"With pbc=%s can only do domain decomposition in the x-direction",epbc_names[ir->ePBC]);
-    }
-
-    if (ir->ns_type == ensSIMPLE)
-    {
-        gmx_fatal(FARGS,"Domain decomposition does not support simple neighbor searching, use grid searching or use particle decomposition");
-    }
-
-    if (ir->nstlist == 0)
-    {
-        gmx_fatal(FARGS,"Domain decomposition does not work with nstlist=0");
-    }
-
-    if (ir->comm_mode == ecmANGULAR && ir->ePBC != epbcNONE)
-    {
-        dd_warning(cr,fplog,"comm-mode angular will give incorrect results when the comm group partially crosses a periodic boundary");
-    }
-}
-
-static real average_cellsize_min(gmx_domdec_t *dd,gmx_ddbox_t *ddbox)
-{
-    int  di,d;
-    real r;
-
-    r = ddbox->box_size[XX];
-    for(di=0; di<dd->ndim; di++)
-    {
-        d = dd->dim[di];
-        /* Check using the initial average cell size */
-        r = min(r,ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
-    }
-
-    return r;
-}
-
-static int check_dlb_support(FILE *fplog,t_commrec *cr,
-                             const char *dlb_opt,gmx_bool bRecordLoad,
-                             unsigned long Flags,t_inputrec *ir)
-{
-    gmx_domdec_t *dd;
-    int  eDLB=-1;
-    char buf[STRLEN];
-
-    switch (dlb_opt[0])
-    {
-    case 'a': eDLB = edlbAUTO; break;
-    case 'n': eDLB = edlbNO;   break;
-    case 'y': eDLB = edlbYES;  break;
-    default: gmx_incons("Unknown dlb_opt");
-    }
-
-    if (Flags & MD_RERUN)
-    {
-        return edlbNO;
-    }
-
-    if (!EI_DYNAMICS(ir->eI))
-    {
-        if (eDLB == edlbYES)
-        {
-            sprintf(buf,"NOTE: dynamic load balancing is only supported with dynamics, not with integrator '%s'\n",EI(ir->eI));
-            dd_warning(cr,fplog,buf);
-        }
-            
-        return edlbNO;
-    }
-
-    if (!bRecordLoad)
-    {
-        dd_warning(cr,fplog,"NOTE: Cycle counting is not supported on this architecture, will not use dynamic load balancing\n");
-
-        return edlbNO;
-    }
-
-    if (Flags & MD_REPRODUCIBLE)
-    {
-        switch (eDLB)
-        {
-                       case edlbNO: 
-                               break;
-                       case edlbAUTO:
-                               dd_warning(cr,fplog,"NOTE: reproducibility requested, will not use dynamic load balancing\n");
-                               eDLB = edlbNO;
-                               break;
-                       case edlbYES:
-                               dd_warning(cr,fplog,"WARNING: reproducibility requested with dynamic load balancing, the simulation will NOT be binary reproducible\n");
-                               break;
-                       default:
-                               gmx_fatal(FARGS,"Death horror: undefined case (%d) for load balancing choice",eDLB);
-                               break;
-        }
-    }
-
-    return eDLB;
-}
-
-static void set_dd_dim(FILE *fplog,gmx_domdec_t *dd)
-{
-    int dim;
-
-    dd->ndim = 0;
-    if (getenv("GMX_DD_ORDER_ZYX") != NULL)
-    {
-        /* Decomposition order z,y,x */
-        if (fplog)
-        {
-            fprintf(fplog,"Using domain decomposition order z, y, x\n");
-        }
-        for(dim=DIM-1; dim>=0; dim--)
-        {
-            if (dd->nc[dim] > 1)
-            {
-                dd->dim[dd->ndim++] = dim;
-            }
-        }
-    }
-    else
-    {
-        /* Decomposition order x,y,z */
-        for(dim=0; dim<DIM; dim++)
-        {
-            if (dd->nc[dim] > 1)
-            {
-                dd->dim[dd->ndim++] = dim;
-            }
-        }
-    }
-}
-
-static gmx_domdec_comm_t *init_dd_comm()
-{
-    gmx_domdec_comm_t *comm;
-    int  i;
-
-    snew(comm,1);
-    snew(comm->cggl_flag,DIM*2);
-    snew(comm->cgcm_state,DIM*2);
-    for(i=0; i<DIM*2; i++)
-    {
-        comm->cggl_flag_nalloc[i]  = 0;
-        comm->cgcm_state_nalloc[i] = 0;
-    }
-    
-    comm->nalloc_int = 0;
-    comm->buf_int    = NULL;
-
-    vec_rvec_init(&comm->vbuf);
-
-    comm->n_load_have    = 0;
-    comm->n_load_collect = 0;
-
-    for(i=0; i<ddnatNR-ddnatZONE; i++)
-    {
-        comm->sum_nat[i] = 0;
-    }
-    comm->ndecomp = 0;
-    comm->nload   = 0;
-    comm->load_step = 0;
-    comm->load_sum  = 0;
-    comm->load_max  = 0;
-    clear_ivec(comm->load_lim);
-    comm->load_mdf  = 0;
-    comm->load_pme  = 0;
-
-    return comm;
-}
-
-gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
-                                        unsigned long Flags,
-                                        ivec nc,
-                                        real comm_distance_min,real rconstr,
-                                        const char *dlb_opt,real dlb_scale,
-                                        const char *sizex,const char *sizey,const char *sizez,
-                                        gmx_mtop_t *mtop,t_inputrec *ir,
-                                        matrix box,rvec *x,
-                                        gmx_ddbox_t *ddbox,
-                                        int *npme_x,int *npme_y)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    int  recload;
-    int  d,i,j;
-    real r_2b,r_mb,r_bonded=-1,r_bonded_limit=-1,limit,acs;
-    gmx_bool bC;
-    char buf[STRLEN];
-    
-    if (fplog)
-    {
-        fprintf(fplog,
-                "\nInitializing Domain Decomposition on %d nodes\n",cr->nnodes);
-    }
-    
-    snew(dd,1);
-
-    dd->comm = init_dd_comm();
-    comm = dd->comm;
-    snew(comm->cggl_flag,DIM*2);
-    snew(comm->cgcm_state,DIM*2);
-
-    dd->npbcdim   = ePBC2npbcdim(ir->ePBC);
-    dd->bScrewPBC = (ir->ePBC == epbcSCREW);
-    
-    dd->bSendRecv2      = dd_nst_env(fplog,"GMX_DD_SENDRECV2",0);
-    comm->dlb_scale_lim = dd_nst_env(fplog,"GMX_DLB_MAX",10);
-    comm->eFlop         = dd_nst_env(fplog,"GMX_DLB_FLOP",0);
-    recload             = dd_nst_env(fplog,"GMX_DD_LOAD",1);
-    comm->nstSortCG     = dd_nst_env(fplog,"GMX_DD_SORT",1);
-    comm->nstDDDump     = dd_nst_env(fplog,"GMX_DD_DUMP",0);
-    comm->nstDDDumpGrid = dd_nst_env(fplog,"GMX_DD_DUMP_GRID",0);
-    comm->DD_debug      = dd_nst_env(fplog,"GMX_DD_DEBUG",0);
-
-    dd->pme_recv_f_alloc = 0;
-    dd->pme_recv_f_buf = NULL;
-
-    if (dd->bSendRecv2 && fplog)
-    {
-        fprintf(fplog,"Will use two sequential MPI_Sendrecv calls instead of two simultaneous non-blocking MPI_Irecv and MPI_Isend pairs for constraint and vsite communication\n");
-    }
-    if (comm->eFlop)
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"Will load balance based on FLOP count\n");
-        }
-        if (comm->eFlop > 1)
-        {
-            srand(1+cr->nodeid);
-        }
-        comm->bRecordLoad = TRUE;
-    }
-    else
-    {
-        comm->bRecordLoad = (wallcycle_have_counter() && recload > 0);
-                             
-    }
-    
-    comm->eDLB = check_dlb_support(fplog,cr,dlb_opt,comm->bRecordLoad,Flags,ir);
-    
-    comm->bDynLoadBal = (comm->eDLB == edlbYES);
-    if (fplog)
-    {
-        fprintf(fplog,"Dynamic load balancing: %s\n",edlb_names[comm->eDLB]);
-    }
-    dd->bGridJump = comm->bDynLoadBal;
-    
-    if (comm->nstSortCG)
-    {
-        if (fplog)
-        {
-            if (comm->nstSortCG == 1)
-            {
-                fprintf(fplog,"Will sort the charge groups at every domain (re)decomposition\n");
-            }
-            else
-            {
-                fprintf(fplog,"Will sort the charge groups every %d steps\n",
-                        comm->nstSortCG);
-            }
-        }
-        snew(comm->sort,1);
-    }
-    else
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"Will not sort the charge groups\n");
-        }
-    }
-    
-    comm->bInterCGBondeds = (ncg_mtop(mtop) > mtop->mols.nr);
-    if (comm->bInterCGBondeds)
-    {
-        comm->bInterCGMultiBody = (multi_body_bondeds_count(mtop) > 0);
-    }
-    else
-    {
-        comm->bInterCGMultiBody = FALSE;
-    }
-    
-    dd->bInterCGcons = inter_charge_group_constraints(mtop);
-
-    if (ir->rlistlong == 0)
-    {
-        /* Set the cut-off to some very large value,
-         * so we don't need if statements everywhere in the code.
-         * We use sqrt, since the cut-off is squared in some places.
-         */
-        comm->cutoff   = GMX_CUTOFF_INF;
-    }
-    else
-    {
-        comm->cutoff   = ir->rlistlong;
-    }
-    comm->cutoff_mbody = 0;
-    
-    comm->cellsize_limit = 0;
-    comm->bBondComm = FALSE;
-
-    if (comm->bInterCGBondeds)
-    {
-        if (comm_distance_min > 0)
-        {
-            comm->cutoff_mbody = comm_distance_min;
-            if (Flags & MD_DDBONDCOMM)
-            {
-                comm->bBondComm = (comm->cutoff_mbody > comm->cutoff);
-            }
-            else
-            {
-                comm->cutoff = max(comm->cutoff,comm->cutoff_mbody);
-            }
-            r_bonded_limit = comm->cutoff_mbody;
-        }
-        else if (ir->bPeriodicMols)
-        {
-            /* Can not easily determine the required cut-off */
-            dd_warning(cr,fplog,"NOTE: Periodic molecules: can not easily determine the required minimum bonded cut-off, using half the non-bonded cut-off\n");
-            comm->cutoff_mbody = comm->cutoff/2;
-            r_bonded_limit = comm->cutoff_mbody;
-        }
-        else
-        {
-            if (MASTER(cr))
-            {
-                dd_bonded_cg_distance(fplog,dd,mtop,ir,x,box,
-                                      Flags & MD_DDBONDCHECK,&r_2b,&r_mb);
-            }
-            gmx_bcast(sizeof(r_2b),&r_2b,cr);
-            gmx_bcast(sizeof(r_mb),&r_mb,cr);
-
-            /* We use an initial margin of 10% for the minimum cell size,
-             * except when we are just below the non-bonded cut-off.
-             */
-            if (Flags & MD_DDBONDCOMM)
-            {
-                if (max(r_2b,r_mb) > comm->cutoff)
-                {
-                    r_bonded       = max(r_2b,r_mb);
-                    r_bonded_limit = 1.1*r_bonded;
-                    comm->bBondComm = TRUE;
-                }
-                else
-                {
-                    r_bonded       = r_mb;
-                    r_bonded_limit = min(1.1*r_bonded,comm->cutoff);
-                }
-                /* We determine cutoff_mbody later */
-            }
-            else
-            {
-                /* No special bonded communication,
-                 * simply increase the DD cut-off.
-                 */
-                r_bonded_limit     = 1.1*max(r_2b,r_mb);
-                comm->cutoff_mbody = r_bonded_limit;
-                comm->cutoff       = max(comm->cutoff,comm->cutoff_mbody);
-            }
-        }
-        comm->cellsize_limit = max(comm->cellsize_limit,r_bonded_limit);
-        if (fplog)
-        {
-            fprintf(fplog,
-                    "Minimum cell size due to bonded interactions: %.3f nm\n",
-                    comm->cellsize_limit);
-        }
-    }
-
-    if (dd->bInterCGcons && rconstr <= 0)
-    {
-        /* There is a cell size limit due to the constraints (P-LINCS) */
-        rconstr = constr_r_max(fplog,mtop,ir);
-        if (fplog)
-        {
-            fprintf(fplog,
-                    "Estimated maximum distance required for P-LINCS: %.3f nm\n",
-                    rconstr);
-            if (rconstr > comm->cellsize_limit)
-            {
-                fprintf(fplog,"This distance will limit the DD cell size, you can override this with -rcon\n");
-            }
-        }
-    }
-    else if (rconstr > 0 && fplog)
-    {
-        /* Here we do not check for dd->bInterCGcons,
-         * because one can also set a cell size limit for virtual sites only
-         * and at this point we don't know yet if there are intercg v-sites.
-         */
-        fprintf(fplog,
-                "User supplied maximum distance required for P-LINCS: %.3f nm\n",
-                rconstr);
-    }
-    comm->cellsize_limit = max(comm->cellsize_limit,rconstr);
-
-    comm->cgs_gl = gmx_mtop_global_cgs(mtop);
-
-    if (nc[XX] > 0)
-    {
-        copy_ivec(nc,dd->nc);
-        set_dd_dim(fplog,dd);
-        set_ddbox_cr(cr,&dd->nc,ir,box,&comm->cgs_gl,x,ddbox);
-
-        if (cr->npmenodes == -1)
-        {
-            cr->npmenodes = 0;
-        }
-        acs = average_cellsize_min(dd,ddbox);
-        if (acs < comm->cellsize_limit)
-        {
-            if (fplog)
-            {
-                fprintf(fplog,"ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n",acs,comm->cellsize_limit);
-            }
-            gmx_fatal_collective(FARGS,cr,NULL,
-                                 "The initial cell size (%f) is smaller than the cell size limit (%f), change options -dd, -rdd or -rcon, see the log file for details",
-                                 acs,comm->cellsize_limit);
-        }
-    }
-    else
-    {
-        set_ddbox_cr(cr,NULL,ir,box,&comm->cgs_gl,x,ddbox);
-
-        /* We need to choose the optimal DD grid and possibly PME nodes */
-        limit = dd_choose_grid(fplog,cr,dd,ir,mtop,box,ddbox,
-                               comm->eDLB!=edlbNO,dlb_scale,
-                               comm->cellsize_limit,comm->cutoff,
-                               comm->bInterCGBondeds,comm->bInterCGMultiBody);
-        
-        if (dd->nc[XX] == 0)
-        {
-            bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
-            sprintf(buf,"Change the number of nodes or mdrun option %s%s%s",
-                    !bC ? "-rdd" : "-rcon",
-                    comm->eDLB!=edlbNO ? " or -dds" : "",
-                    bC ? " or your LINCS settings" : "");
-
-            gmx_fatal_collective(FARGS,cr,NULL,
-                                 "There is no domain decomposition for %d nodes that is compatible with the given box and a minimum cell size of %g nm\n"
-                                 "%s\n"
-                                 "Look in the log file for details on the domain decomposition",
-                                 cr->nnodes-cr->npmenodes,limit,buf);
-        }
-        set_dd_dim(fplog,dd);
-    }
-
-    if (fplog)
-    {
-        fprintf(fplog,
-                "Domain decomposition grid %d x %d x %d, separate PME nodes %d\n",
-                dd->nc[XX],dd->nc[YY],dd->nc[ZZ],cr->npmenodes);
-    }
-    
-    dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
-    if (cr->nnodes - dd->nnodes != cr->npmenodes)
-    {
-        gmx_fatal_collective(FARGS,cr,NULL,
-                             "The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
-                             dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
-    }
-    if (cr->npmenodes > dd->nnodes)
-    {
-        gmx_fatal_collective(FARGS,cr,NULL,
-                             "The number of separate PME nodes (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
-    }
-    if (cr->npmenodes > 0)
-    {
-        comm->npmenodes = cr->npmenodes;
-    }
-    else
-    {
-        comm->npmenodes = dd->nnodes;
-    }
-
-    if (EEL_PME(ir->coulombtype))
-    {
-        /* The following choices should match those
-         * in comm_cost_est in domdec_setup.c.
-         * Note that here the checks have to take into account
-         * that the decomposition might occur in a different order than xyz
-         * (for instance through the env.var. GMX_DD_ORDER_ZYX),
-         * in which case they will not match those in comm_cost_est,
-         * but since that is mainly for testing purposes that's fine.
-         */
-        if (dd->ndim >= 2 && dd->dim[0] == XX && dd->dim[1] == YY &&
-            comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
-            getenv("GMX_PMEONEDD") == NULL)
-        {
-            comm->npmedecompdim = 2;
-            comm->npmenodes_x   = dd->nc[XX];
-            comm->npmenodes_y   = comm->npmenodes/comm->npmenodes_x;
-        }
-        else
-        {
-            /* In case nc is 1 in both x and y we could still choose to
-             * decompose pme in y instead of x, but we use x for simplicity.
-             */
-            comm->npmedecompdim = 1;
-            if (dd->dim[0] == YY)
-            {
-                comm->npmenodes_x = 1;
-                comm->npmenodes_y = comm->npmenodes;
-            }
-            else
-            {
-                comm->npmenodes_x = comm->npmenodes;
-                comm->npmenodes_y = 1;
-            }
-        }    
-        if (fplog)
-        {
-            fprintf(fplog,"PME domain decomposition: %d x %d x %d\n",
-                    comm->npmenodes_x,comm->npmenodes_y,1);
-        }
-    }
-    else
-    {
-        comm->npmedecompdim = 0;
-        comm->npmenodes_x   = 0;
-        comm->npmenodes_y   = 0;
-    }
-    
-    /* Technically we don't need both of these,
-     * but it simplifies code not having to recalculate it.
-     */
-    *npme_x = comm->npmenodes_x;
-    *npme_y = comm->npmenodes_y;
-        
-    snew(comm->slb_frac,DIM);
-    if (comm->eDLB == edlbNO)
-    {
-        comm->slb_frac[XX] = get_slb_frac(fplog,"x",dd->nc[XX],sizex);
-        comm->slb_frac[YY] = get_slb_frac(fplog,"y",dd->nc[YY],sizey);
-        comm->slb_frac[ZZ] = get_slb_frac(fplog,"z",dd->nc[ZZ],sizez);
-    }
-
-    if (comm->bInterCGBondeds && comm->cutoff_mbody == 0)
-    {
-        if (comm->bBondComm || comm->eDLB != edlbNO)
-        {
-            /* Set the bonded communication distance to halfway
-             * the minimum and the maximum,
-             * since the extra communication cost is nearly zero.
-             */
-            acs = average_cellsize_min(dd,ddbox);
-            comm->cutoff_mbody = 0.5*(r_bonded + acs);
-            if (comm->eDLB != edlbNO)
-            {
-                /* Check if this does not limit the scaling */
-                comm->cutoff_mbody = min(comm->cutoff_mbody,dlb_scale*acs);
-            }
-            if (!comm->bBondComm)
-            {
-                /* Without bBondComm do not go beyond the n.b. cut-off */
-                comm->cutoff_mbody = min(comm->cutoff_mbody,comm->cutoff);
-                if (comm->cellsize_limit >= comm->cutoff)
-                {
-                    /* We don't loose a lot of efficieny
-                     * when increasing it to the n.b. cut-off.
-                     * It can even be slightly faster, because we need
-                     * less checks for the communication setup.
-                     */
-                    comm->cutoff_mbody = comm->cutoff;
-                }
-            }
-            /* Check if we did not end up below our original limit */
-            comm->cutoff_mbody = max(comm->cutoff_mbody,r_bonded_limit);
-
-            if (comm->cutoff_mbody > comm->cellsize_limit)
-            {
-                comm->cellsize_limit = comm->cutoff_mbody;
-            }
-        }
-        /* Without DLB and cutoff_mbody<cutoff, cutoff_mbody is dynamic */
-    }
-
-    if (debug)
-    {
-        fprintf(debug,"Bonded atom communication beyond the cut-off: %d\n"
-                "cellsize limit %f\n",
-                comm->bBondComm,comm->cellsize_limit);
-    }
-    
-    if (MASTER(cr))
-    {
-        check_dd_restrictions(cr,dd,ir,fplog);
-    }
-
-    comm->globalcomm_step = INT_MIN;
-    dd->ddp_count = 0;
-
-    clear_dd_cycle_counts(dd);
-
-    return dd;
-}
-
-static void set_dlb_limits(gmx_domdec_t *dd)
-
-{
-    int d;
-
-    for(d=0; d<dd->ndim; d++)
-    {
-        dd->comm->cd[d].np = dd->comm->cd[d].np_dlb;
-        dd->comm->cellsize_min[dd->dim[d]] =
-            dd->comm->cellsize_min_dlb[dd->dim[d]];
-    }
-}
-
-
-static void turn_on_dlb(FILE *fplog,t_commrec *cr,gmx_large_int_t step)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    real cellsize_min;
-    int  d,nc,i;
-    char buf[STRLEN];
-    
-    dd = cr->dd;
-    comm = dd->comm;
-    
-    if (fplog)
-    {
-        fprintf(fplog,"At step %s the performance loss due to force load imbalance is %.1f %%\n",gmx_step_str(step,buf),dd_force_imb_perf_loss(dd)*100);
-    }
-
-    cellsize_min = comm->cellsize_min[dd->dim[0]];
-    for(d=1; d<dd->ndim; d++)
-    {
-        cellsize_min = min(cellsize_min,comm->cellsize_min[dd->dim[d]]);
-    }
-
-    if (cellsize_min < comm->cellsize_limit*1.05)
-    {
-        dd_warning(cr,fplog,"NOTE: the minimum cell size is smaller than 1.05 times the cell size limit, will not turn on dynamic load balancing\n");
-
-        /* Change DLB from "auto" to "no". */
-        comm->eDLB = edlbNO;
-
-        return;
-    }
-
-    dd_warning(cr,fplog,"NOTE: Turning on dynamic load balancing\n");
-    comm->bDynLoadBal = TRUE;
-    dd->bGridJump = TRUE;
-    
-    set_dlb_limits(dd);
-
-    /* We can set the required cell size info here,
-     * so we do not need to communicate this.
-     * The grid is completely uniform.
-     */
-    for(d=0; d<dd->ndim; d++)
-    {
-        if (comm->root[d])
-        {
-            comm->load[d].sum_m = comm->load[d].sum;
-
-            nc = dd->nc[dd->dim[d]];
-            for(i=0; i<nc; i++)
-            {
-                comm->root[d]->cell_f[i]    = i/(real)nc;
-                if (d > 0)
-                {
-                    comm->root[d]->cell_f_max0[i] =  i   /(real)nc;
-                    comm->root[d]->cell_f_min1[i] = (i+1)/(real)nc;
-                }
-            }
-            comm->root[d]->cell_f[nc] = 1.0;
-        }
-    }
-}
-
-static char *init_bLocalCG(gmx_mtop_t *mtop)
-{
-    int  ncg,cg;
-    char *bLocalCG;
-    
-    ncg = ncg_mtop(mtop);
-    snew(bLocalCG,ncg);
-    for(cg=0; cg<ncg; cg++)
-    {
-        bLocalCG[cg] = FALSE;
-    }
-
-    return bLocalCG;
-}
-
-void dd_init_bondeds(FILE *fplog,
-                     gmx_domdec_t *dd,gmx_mtop_t *mtop,
-                     gmx_vsite_t *vsite,gmx_constr_t constr,
-                     t_inputrec *ir,gmx_bool bBCheck,cginfo_mb_t *cginfo_mb)
-{
-    gmx_domdec_comm_t *comm;
-    gmx_bool bBondComm;
-    int  d;
-
-    dd_make_reverse_top(fplog,dd,mtop,vsite,constr,ir,bBCheck);
-
-    comm = dd->comm;
-
-    if (comm->bBondComm)
-    {
-        /* Communicate atoms beyond the cut-off for bonded interactions */
-        comm = dd->comm;
-
-        comm->cglink = make_charge_group_links(mtop,dd,cginfo_mb);
-
-        comm->bLocalCG = init_bLocalCG(mtop);
-    }
-    else
-    {
-        /* Only communicate atoms based on cut-off */
-        comm->cglink   = NULL;
-        comm->bLocalCG = NULL;
-    }
-}
-
-static void print_dd_settings(FILE *fplog,gmx_domdec_t *dd,
-                              t_inputrec *ir,
-                              gmx_bool bDynLoadBal,real dlb_scale,
-                              gmx_ddbox_t *ddbox)
-{
-    gmx_domdec_comm_t *comm;
-    int  d;
-    ivec np;
-    real limit,shrink;
-    char buf[64];
-
-    if (fplog == NULL)
-    {
-        return;
-    }
-
-    comm = dd->comm;
-
-    if (bDynLoadBal)
-    {
-        fprintf(fplog,"The maximum number of communication pulses is:");
-        for(d=0; d<dd->ndim; d++)
-        {
-            fprintf(fplog," %c %d",dim2char(dd->dim[d]),comm->cd[d].np_dlb);
-        }
-        fprintf(fplog,"\n");
-        fprintf(fplog,"The minimum size for domain decomposition cells is %.3f nm\n",comm->cellsize_limit);
-        fprintf(fplog,"The requested allowed shrink of DD cells (option -dds) is: %.2f\n",dlb_scale);
-        fprintf(fplog,"The allowed shrink of domain decomposition cells is:");
-        for(d=0; d<DIM; d++)
-        {
-            if (dd->nc[d] > 1)
-            {
-                if (d >= ddbox->npbcdim && dd->nc[d] == 2)
-                {
-                    shrink = 0;
-                }
-                else
-                {
-                    shrink =
-                        comm->cellsize_min_dlb[d]/
-                        (ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
-                }
-                fprintf(fplog," %c %.2f",dim2char(d),shrink);
-            }
-        }
-        fprintf(fplog,"\n");
-    }
-    else
-    {
-        set_dd_cell_sizes_slb(dd,ddbox,FALSE,np);
-        fprintf(fplog,"The initial number of communication pulses is:");
-        for(d=0; d<dd->ndim; d++)
-        {
-            fprintf(fplog," %c %d",dim2char(dd->dim[d]),np[dd->dim[d]]);
-        }
-        fprintf(fplog,"\n");
-        fprintf(fplog,"The initial domain decomposition cell size is:");
-        for(d=0; d<DIM; d++) {
-            if (dd->nc[d] > 1)
-            {
-                fprintf(fplog," %c %.2f nm",
-                        dim2char(d),dd->comm->cellsize_min[d]);
-            }
-        }
-        fprintf(fplog,"\n\n");
-    }
-    
-    if (comm->bInterCGBondeds || dd->vsite_comm || dd->constraint_comm)
-    {
-        fprintf(fplog,"The maximum allowed distance for charge groups involved in interactions is:\n");
-        fprintf(fplog,"%40s  %-7s %6.3f nm\n",
-                "non-bonded interactions","",comm->cutoff);
-
-        if (bDynLoadBal)
-        {
-            limit = dd->comm->cellsize_limit;
-        }
-        else
-        {
-            if (dynamic_dd_box(ddbox,ir))
-            {
-                fprintf(fplog,"(the following are initial values, they could change due to box deformation)\n");
-            }
-            limit = dd->comm->cellsize_min[XX];
-            for(d=1; d<DIM; d++)
-            {
-                limit = min(limit,dd->comm->cellsize_min[d]);
-            }
-        }
-
-        if (comm->bInterCGBondeds)
-        {
-            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
-                    "two-body bonded interactions","(-rdd)",
-                    max(comm->cutoff,comm->cutoff_mbody));
-            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
-                    "multi-body bonded interactions","(-rdd)",
-                    (comm->bBondComm || dd->bGridJump) ? comm->cutoff_mbody : min(comm->cutoff,limit));
-        }
-        if (dd->vsite_comm)
-        {
-            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
-                    "virtual site constructions","(-rcon)",limit);
-        }
-        if (dd->constraint_comm)
-        {
-            sprintf(buf,"atoms separated by up to %d constraints",
-                    1+ir->nProjOrder);
-            fprintf(fplog,"%40s  %-7s %6.3f nm\n",
-                    buf,"(-rcon)",limit);
-        }
-        fprintf(fplog,"\n");
-    }
-    
-    fflush(fplog);
-}
-
-void set_dd_parameters(FILE *fplog,gmx_domdec_t *dd,real dlb_scale,
-                       t_inputrec *ir,t_forcerec *fr,
-                       gmx_ddbox_t *ddbox)
-{
-    gmx_domdec_comm_t *comm;
-    int  d,dim,npulse,npulse_d_max,npulse_d;
-    gmx_bool bNoCutOff;
-    int  natoms_tot;
-    real vol_frac;
-
-    comm = dd->comm;
-
-    bNoCutOff = (ir->rvdw == 0 || ir->rcoulomb == 0);
-
-    if (EEL_PME(ir->coulombtype))
-    {
-        init_ddpme(dd,&comm->ddpme[0],0);
-        if (comm->npmedecompdim >= 2)
-        {
-            init_ddpme(dd,&comm->ddpme[1],1);
-        }
-    }
-    else
-    {
-        comm->npmenodes = 0;
-        if (dd->pme_nodeid >= 0)
-        {
-            gmx_fatal_collective(FARGS,NULL,dd,
-                                 "Can not have separate PME nodes without PME electrostatics");
-        }
-    }
-    
-    /* If each molecule is a single charge group
-     * or we use domain decomposition for each periodic dimension,
-     * we do not need to take pbc into account for the bonded interactions.
-     */
-    if (fr->ePBC == epbcNONE || !comm->bInterCGBondeds ||
-        (dd->nc[XX]>1 && dd->nc[YY]>1 && (dd->nc[ZZ]>1 || fr->ePBC==epbcXY)))
-    {
-        fr->bMolPBC = FALSE;
-    }
-    else
-    {
-        fr->bMolPBC = TRUE;
-    }
-        
-    if (debug)
-    {
-        fprintf(debug,"The DD cut-off is %f\n",comm->cutoff);
-    }
-    if (comm->eDLB != edlbNO)
-    {
-        /* Determine the maximum number of comm. pulses in one dimension */
-        
-        comm->cellsize_limit = max(comm->cellsize_limit,comm->cutoff_mbody);
-        
-        /* Determine the maximum required number of grid pulses */
-        if (comm->cellsize_limit >= comm->cutoff)
-        {
-            /* Only a single pulse is required */
-            npulse = 1;
-        }
-        else if (!bNoCutOff && comm->cellsize_limit > 0)
-        {
-            /* We round down slightly here to avoid overhead due to the latency
-             * of extra communication calls when the cut-off
-             * would be only slightly longer than the cell size.
-             * Later cellsize_limit is redetermined,
-             * so we can not miss interactions due to this rounding.
-             */
-            npulse = (int)(0.96 + comm->cutoff/comm->cellsize_limit);
-        }
-        else
-        {
-            /* There is no cell size limit */
-            npulse = max(dd->nc[XX]-1,max(dd->nc[YY]-1,dd->nc[ZZ]-1));
-        }
-
-        if (!bNoCutOff && npulse > 1)
-        {
-            /* See if we can do with less pulses, based on dlb_scale */
-            npulse_d_max = 0;
-            for(d=0; d<dd->ndim; d++)
-            {
-                dim = dd->dim[d];
-                npulse_d = (int)(1 + dd->nc[dim]*comm->cutoff
-                                 /(ddbox->box_size[dim]*ddbox->skew_fac[dim]*dlb_scale));
-                npulse_d_max = max(npulse_d_max,npulse_d);
-            }
-            npulse = min(npulse,npulse_d_max);
-        }
-        
-        /* This env var can override npulse */
-        d = dd_nst_env(fplog,"GMX_DD_NPULSE",0);
-        if (d > 0)
-        {
-            npulse = d;
-        }
-
-        comm->maxpulse = 1;
-        comm->bVacDLBNoLimit = (ir->ePBC == epbcNONE);
-        for(d=0; d<dd->ndim; d++)
-        {
-            comm->cd[d].np_dlb = min(npulse,dd->nc[dd->dim[d]]-1);
-            comm->cd[d].np_nalloc = comm->cd[d].np_dlb;
-            snew(comm->cd[d].ind,comm->cd[d].np_nalloc);
-            comm->maxpulse = max(comm->maxpulse,comm->cd[d].np_dlb);
-            if (comm->cd[d].np_dlb < dd->nc[dd->dim[d]]-1)
-            {
-                comm->bVacDLBNoLimit = FALSE;
-            }
-        }
-        
-        /* cellsize_limit is set for LINCS in init_domain_decomposition */
-        if (!comm->bVacDLBNoLimit)
-        {
-            comm->cellsize_limit = max(comm->cellsize_limit,
-                                       comm->cutoff/comm->maxpulse);
-        }
-        comm->cellsize_limit = max(comm->cellsize_limit,comm->cutoff_mbody);
-        /* Set the minimum cell size for each DD dimension */
-        for(d=0; d<dd->ndim; d++)
-        {
-            if (comm->bVacDLBNoLimit ||
-                comm->cd[d].np_dlb*comm->cellsize_limit >= comm->cutoff)
-            {
-                comm->cellsize_min_dlb[dd->dim[d]] = comm->cellsize_limit;
-            }
-            else
-            {
-                comm->cellsize_min_dlb[dd->dim[d]] =
-                    comm->cutoff/comm->cd[d].np_dlb;
-            }
-        }
-        if (comm->cutoff_mbody <= 0)
-        {
-            comm->cutoff_mbody = min(comm->cutoff,comm->cellsize_limit);
-        }
-        if (comm->bDynLoadBal)
-        {
-            set_dlb_limits(dd);
-        }
-    }
-    
-    print_dd_settings(fplog,dd,ir,comm->bDynLoadBal,dlb_scale,ddbox);
-    if (comm->eDLB == edlbAUTO)
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"When dynamic load balancing gets turned on, these settings will change to:\n");
-        }
-        print_dd_settings(fplog,dd,ir,TRUE,dlb_scale,ddbox);
-    }
-
-    if (ir->ePBC == epbcNONE)
-    {
-        vol_frac = 1 - 1/(double)dd->nnodes;
-    }
-    else
-    {
-        vol_frac =
-            (1 + comm_box_frac(dd->nc,comm->cutoff,ddbox))/(double)dd->nnodes;
-    }
-    if (debug)
-    {
-        fprintf(debug,"Volume fraction for all DD zones: %f\n",vol_frac);
-    }
-    natoms_tot = comm->cgs_gl.index[comm->cgs_gl.nr];
-   
-    dd->ga2la = ga2la_init(natoms_tot,vol_frac*natoms_tot);
-}
-
-static void merge_cg_buffers(int ncell,
-                             gmx_domdec_comm_dim_t *cd, int pulse,
-                             int  *ncg_cell,
-                             int  *index_gl, int  *recv_i,
-                             rvec *cg_cm,    rvec *recv_vr,
-                             int *cgindex,
-                             cginfo_mb_t *cginfo_mb,int *cginfo)
-{
-    gmx_domdec_ind_t *ind,*ind_p;
-    int p,cell,c,cg,cg0,cg1,cg_gl,nat;
-    int shift,shift_at;
-    
-    ind = &cd->ind[pulse];
-    
-    /* First correct the already stored data */
-    shift = ind->nrecv[ncell];
-    for(cell=ncell-1; cell>=0; cell--)
-    {
-        shift -= ind->nrecv[cell];
-        if (shift > 0)
-        {
-            /* Move the cg's present from previous grid pulses */
-            cg0 = ncg_cell[ncell+cell];
-            cg1 = ncg_cell[ncell+cell+1];
-            cgindex[cg1+shift] = cgindex[cg1];
-            for(cg=cg1-1; cg>=cg0; cg--)
-            {
-                index_gl[cg+shift] = index_gl[cg];
-                copy_rvec(cg_cm[cg],cg_cm[cg+shift]);
-                cgindex[cg+shift] = cgindex[cg];
-                cginfo[cg+shift] = cginfo[cg];
-            }
-            /* Correct the already stored send indices for the shift */
-            for(p=1; p<=pulse; p++)
-            {
-                ind_p = &cd->ind[p];
-                cg0 = 0;
-                for(c=0; c<cell; c++)
-                {
-                    cg0 += ind_p->nsend[c];
-                }
-                cg1 = cg0 + ind_p->nsend[cell];
-                for(cg=cg0; cg<cg1; cg++)
-                {
-                    ind_p->index[cg] += shift;
-                }
-            }
-        }
-    }
-
-    /* Merge in the communicated buffers */
-    shift = 0;
-    shift_at = 0;
-    cg0 = 0;
-    for(cell=0; cell<ncell; cell++)
-    {
-        cg1 = ncg_cell[ncell+cell+1] + shift;
-        if (shift_at > 0)
-        {
-            /* Correct the old cg indices */
-            for(cg=ncg_cell[ncell+cell]; cg<cg1; cg++)
-            {
-                cgindex[cg+1] += shift_at;
-            }
-        }
-        for(cg=0; cg<ind->nrecv[cell]; cg++)
-        {
-            /* Copy this charge group from the buffer */
-            index_gl[cg1] = recv_i[cg0];
-            copy_rvec(recv_vr[cg0],cg_cm[cg1]);
-            /* Add it to the cgindex */
-            cg_gl = index_gl[cg1];
-            cginfo[cg1] = ddcginfo(cginfo_mb,cg_gl);
-            nat = GET_CGINFO_NATOMS(cginfo[cg1]);
-            cgindex[cg1+1] = cgindex[cg1] + nat;
-            cg0++;
-            cg1++;
-            shift_at += nat;
-        }
-        shift += ind->nrecv[cell];
-        ncg_cell[ncell+cell+1] = cg1;
-    }
-}
-
-static void make_cell2at_index(gmx_domdec_comm_dim_t *cd,
-                               int nzone,int cg0,const int *cgindex)
-{
-    int cg,zone,p;
-    
-    /* Store the atom block boundaries for easy copying of communication buffers
-     */
-    cg = cg0;
-    for(zone=0; zone<nzone; zone++)
-    {
-        for(p=0; p<cd->np; p++) {
-            cd->ind[p].cell2at0[zone] = cgindex[cg];
-            cg += cd->ind[p].nrecv[zone];
-            cd->ind[p].cell2at1[zone] = cgindex[cg];
-        }
-    }
-}
-
-static gmx_bool missing_link(t_blocka *link,int cg_gl,char *bLocalCG)
-{
-    int  i;
-    gmx_bool bMiss;
-
-    bMiss = FALSE;
-    for(i=link->index[cg_gl]; i<link->index[cg_gl+1]; i++)
-    {
-        if (!bLocalCG[link->a[i]])
-        {
-            bMiss = TRUE;
-        }
-    }
-
-    return bMiss;
-}
-
-static void setup_dd_communication(gmx_domdec_t *dd,
-                                   matrix box,gmx_ddbox_t *ddbox,t_forcerec *fr)
-{
-    int dim_ind,dim,dim0,dim1=-1,dim2=-1,dimd,p,nat_tot;
-    int nzone,nzone_send,zone,zonei,cg0,cg1;
-    int c,i,j,cg,cg_gl,nrcg;
-    int *zone_cg_range,pos_cg,*index_gl,*cgindex,*recv_i;
-    gmx_domdec_comm_t *comm;
-    gmx_domdec_zones_t *zones;
-    gmx_domdec_comm_dim_t *cd;
-    gmx_domdec_ind_t *ind;
-    cginfo_mb_t *cginfo_mb;
-    gmx_bool bBondComm,bDist2B,bDistMB,bDistMB_pulse,bDistBonded,bScrew;
-    real r_mb,r_comm2,r_scomm2,r_bcomm2,r,r_0,r_1,r2,rb2,r2inc,inv_ncg,tric_sh;
-    rvec rb,rn;
-    real corner[DIM][4],corner_round_0=0,corner_round_1[4];
-    real bcorner[DIM],bcorner_round_1=0;
-    ivec tric_dist;
-    rvec *cg_cm,*normal,*v_d,*v_0=NULL,*v_1=NULL,*recv_vr;
-    real skew_fac2_d,skew_fac_01;
-    rvec sf2_round;
-    int  nsend,nat;
-    
-    if (debug)
-    {
-        fprintf(debug,"Setting up DD communication\n");
-    }
-    
-    comm  = dd->comm;
-    cg_cm = fr->cg_cm;
-
-    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
-    {
-        dim = dd->dim[dim_ind];
-
-        /* Check if we need to use triclinic distances */
-        tric_dist[dim_ind] = 0;
-        for(i=0; i<=dim_ind; i++)
-        {
-            if (ddbox->tric_dir[dd->dim[i]])
-            {
-                tric_dist[dim_ind] = 1;
-            }
-        }
-    }
-
-    bBondComm = comm->bBondComm;
-
-    /* Do we need to determine extra distances for multi-body bondeds? */
-    bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
-    
-    /* Do we need to determine extra distances for only two-body bondeds? */
-    bDist2B = (bBondComm && !bDistMB);
-
-    r_comm2  = sqr(comm->cutoff);
-    r_bcomm2 = sqr(comm->cutoff_mbody);
-
-    if (debug)
-    {
-        fprintf(debug,"bBondComm %d, r_bc %f\n",bBondComm,sqrt(r_bcomm2));
-    }
-
-    zones = &comm->zones;
-    
-    dim0 = dd->dim[0];
-    /* The first dimension is equal for all cells */
-    corner[0][0] = comm->cell_x0[dim0];
-    if (bDistMB)
-    {
-        bcorner[0] = corner[0][0];
-    }
-    if (dd->ndim >= 2)
-    {
-        dim1 = dd->dim[1];
-        /* This cell row is only seen from the first row */
-        corner[1][0] = comm->cell_x0[dim1];
-        /* All rows can see this row */
-        corner[1][1] = comm->cell_x0[dim1];
-        if (dd->bGridJump)
-        {
-            corner[1][1] = max(comm->cell_x0[dim1],comm->zone_d1[1].mch0);
-            if (bDistMB)
-            {
-                /* For the multi-body distance we need the maximum */
-                bcorner[1] = max(comm->cell_x0[dim1],comm->zone_d1[1].p1_0);
-            }
-        }
-        /* Set the upper-right corner for rounding */
-        corner_round_0 = comm->cell_x1[dim0];
-        
-        if (dd->ndim >= 3)
-        {
-            dim2 = dd->dim[2];
-            for(j=0; j<4; j++)
-            {
-                corner[2][j] = comm->cell_x0[dim2];
-            }
-            if (dd->bGridJump)
-            {
-                /* Use the maximum of the i-cells that see a j-cell */
-                for(i=0; i<zones->nizone; i++)
-                {
-                    for(j=zones->izone[i].j0; j<zones->izone[i].j1; j++)
-                    {
-                        if (j >= 4)
-                        {
-                            corner[2][j-4] =
-                                max(corner[2][j-4],
-                                    comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0);
-                        }
-                    }
-                }
-                if (bDistMB)
-                {
-                    /* For the multi-body distance we need the maximum */
-                    bcorner[2] = comm->cell_x0[dim2];
-                    for(i=0; i<2; i++)
-                    {
-                        for(j=0; j<2; j++)
-                        {
-                            bcorner[2] = max(bcorner[2],
-                                             comm->zone_d2[i][j].p1_0);
-                        }
-                    }
-                }
-            }
-            
-            /* Set the upper-right corner for rounding */
-            /* Cell (0,0,0) and cell (1,0,0) can see cell 4 (0,1,1)
-             * Only cell (0,0,0) can see cell 7 (1,1,1)
-             */
-            corner_round_1[0] = comm->cell_x1[dim1];
-            corner_round_1[3] = comm->cell_x1[dim1];
-            if (dd->bGridJump)
-            {
-                corner_round_1[0] = max(comm->cell_x1[dim1],
-                                        comm->zone_d1[1].mch1);
-                if (bDistMB)
-                {
-                    /* For the multi-body distance we need the maximum */
-                    bcorner_round_1 = max(comm->cell_x1[dim1],
-                                          comm->zone_d1[1].p1_1);
-                }
-            }
-        }
-    }
-    
-    /* Triclinic stuff */
-    normal = ddbox->normal;
-    skew_fac_01 = 0;
-    if (dd->ndim >= 2)
-    {
-        v_0 = ddbox->v[dim0];
-        if (ddbox->tric_dir[dim0] && ddbox->tric_dir[dim1])
-        {
-            /* Determine the coupling coefficient for the distances
-             * to the cell planes along dim0 and dim1 through dim2.
-             * This is required for correct rounding.
-             */
-            skew_fac_01 =
-                ddbox->v[dim0][dim1+1][dim0]*ddbox->v[dim1][dim1+1][dim1];
-            if (debug)
-            {
-                fprintf(debug,"\nskew_fac_01 %f\n",skew_fac_01);
-            }
-        }
-    }
-    if (dd->ndim >= 3)
-    {
-        v_1 = ddbox->v[dim1];
-    }
-    
-    zone_cg_range = zones->cg_range;
-    index_gl = dd->index_gl;
-    cgindex  = dd->cgindex;
-    cginfo_mb = fr->cginfo_mb;
-    
-    zone_cg_range[0]   = 0;
-    zone_cg_range[1]   = dd->ncg_home;
-    comm->zone_ncg1[0] = dd->ncg_home;
-    pos_cg             = dd->ncg_home;
-    
-    nat_tot = dd->nat_home;
-    nzone = 1;
-    for(dim_ind=0; dim_ind<dd->ndim; dim_ind++)
-    {
-        dim = dd->dim[dim_ind];
-        cd = &comm->cd[dim_ind];
-        
-        if (dim >= ddbox->npbcdim && dd->ci[dim] == 0)
-        {
-            /* No pbc in this dimension, the first node should not comm. */
-            nzone_send = 0;
-        }
-        else
-        {
-            nzone_send = nzone;
-        }
-
-        bScrew = (dd->bScrewPBC && dim == XX);
-        
-        v_d = ddbox->v[dim];
-        skew_fac2_d = sqr(ddbox->skew_fac[dim]);
-
-        cd->bInPlace = TRUE;
-        for(p=0; p<cd->np; p++)
-        {
-            /* Only atoms communicated in the first pulse are used
-             * for multi-body bonded interactions or for bBondComm.
-             */
-            bDistBonded   = ((bDistMB || bDist2B) && p == 0);
-            bDistMB_pulse = (bDistMB && bDistBonded);
-
-            ind = &cd->ind[p];
-            nsend = 0;
-            nat = 0;
-            for(zone=0; zone<nzone_send; zone++)
-            {
-                if (tric_dist[dim_ind] && dim_ind > 0)
-                {
-                    /* Determine slightly more optimized skew_fac's
-                     * for rounding.
-                     * This reduces the number of communicated atoms
-                     * by about 10% for 3D DD of rhombic dodecahedra.
-                     */
-                    for(dimd=0; dimd<dim; dimd++)
-                    {
-                        sf2_round[dimd] = 1;
-                        if (ddbox->tric_dir[dimd])
-                        {
-                            for(i=dd->dim[dimd]+1; i<DIM; i++)
-                            {
-                                /* If we are shifted in dimension i
-                                 * and the cell plane is tilted forward
-                                 * in dimension i, skip this coupling.
-                                 */
-                                if (!(zones->shift[nzone+zone][i] &&
-                                      ddbox->v[dimd][i][dimd] >= 0))
-                                {
-                                    sf2_round[dimd] +=
-                                        sqr(ddbox->v[dimd][i][dimd]);
-                                }
-                            }
-                            sf2_round[dimd] = 1/sf2_round[dimd];
-                        }
-                    }
-                }
-
-                zonei = zone_perm[dim_ind][zone];
-                if (p == 0)
-                {
-                    /* Here we permutate the zones to obtain a convenient order
-                     * for neighbor searching
-                     */
-                    cg0 = zone_cg_range[zonei];
-                    cg1 = zone_cg_range[zonei+1];
-                }
-                else
-                {
-                    /* Look only at the cg's received in the previous grid pulse
-                     */
-                    cg1 = zone_cg_range[nzone+zone+1];
-                    cg0 = cg1 - cd->ind[p-1].nrecv[zone];
-                }
-                ind->nsend[zone] = 0;
-                for(cg=cg0; cg<cg1; cg++)
-                {
-                    r2  = 0;
-                    rb2 = 0;
-                    if (tric_dist[dim_ind] == 0)
-                    {
-                        /* Rectangular direction, easy */
-                        r = cg_cm[cg][dim] - corner[dim_ind][zone];
-                        if (r > 0)
-                        {
-                            r2 += r*r;
-                        }
-                        if (bDistMB_pulse)
-                        {
-                            r = cg_cm[cg][dim] - bcorner[dim_ind];
-                            if (r > 0)
-                            {
-                                rb2 += r*r;
-                            }
-                        }
-                        /* Rounding gives at most a 16% reduction
-                         * in communicated atoms
-                         */
-                        if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
-                        {
-                            r = cg_cm[cg][dim0] - corner_round_0;
-                            /* This is the first dimension, so always r >= 0 */
-                            r2 += r*r;
-                            if (bDistMB_pulse)
-                            {
-                                rb2 += r*r;
-                            }
-                        }
-                        if (dim_ind == 2 && (zonei == 2 || zonei == 3))
-                        {
-                            r = cg_cm[cg][dim1] - corner_round_1[zone];
-                            if (r > 0)
-                            {
-                                r2 += r*r;
-                            }
-                            if (bDistMB_pulse)
-                            {
-                                r = cg_cm[cg][dim1] - bcorner_round_1;
-                                if (r > 0)
-                                {
-                                    rb2 += r*r;
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        /* Triclinic direction, more complicated */
-                        clear_rvec(rn);
-                        clear_rvec(rb);
-                        /* Rounding, conservative as the skew_fac multiplication
-                         * will slightly underestimate the distance.
-                         */
-                        if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
-                        {
-                            rn[dim0] = cg_cm[cg][dim0] - corner_round_0;
-                            for(i=dim0+1; i<DIM; i++)
-                            {
-                                rn[dim0] -= cg_cm[cg][i]*v_0[i][dim0];
-                            }
-                            r2 = rn[dim0]*rn[dim0]*sf2_round[dim0];
-                            if (bDistMB_pulse)
-                            {
-                                rb[dim0] = rn[dim0];
-                                rb2 = r2;
-                            }
-                            /* Take care that the cell planes along dim0 might not
-                             * be orthogonal to those along dim1 and dim2.
-                             */
-                            for(i=1; i<=dim_ind; i++)
-                            {
-                                dimd = dd->dim[i];
-                                if (normal[dim0][dimd] > 0)
-                                {
-                                    rn[dimd] -= rn[dim0]*normal[dim0][dimd];
-                                    if (bDistMB_pulse)
-                                    {
-                                        rb[dimd] -= rb[dim0]*normal[dim0][dimd];
-                                    }
-                                }
-                            }
-                        }
-                        if (dim_ind == 2 && (zonei == 2 || zonei == 3))
-                        {
-                            rn[dim1] += cg_cm[cg][dim1] - corner_round_1[zone];
-                            tric_sh = 0;
-                            for(i=dim1+1; i<DIM; i++)
-                            {
-                                tric_sh -= cg_cm[cg][i]*v_1[i][dim1];
-                            }
-                            rn[dim1] += tric_sh;
-                            if (rn[dim1] > 0)
-                            {
-                                r2 += rn[dim1]*rn[dim1]*sf2_round[dim1];
-                                /* Take care of coupling of the distances
-                                 * to the planes along dim0 and dim1 through dim2.
-                                 */
-                                r2 -= rn[dim0]*rn[dim1]*skew_fac_01;
-                                /* Take care that the cell planes along dim1
-                                 * might not be orthogonal to that along dim2.
-                                 */
-                                if (normal[dim1][dim2] > 0)
-                                {
-                                    rn[dim2] -= rn[dim1]*normal[dim1][dim2];
-                                }
-                            }
-                            if (bDistMB_pulse)
-                            {
-                                rb[dim1] +=
-                                    cg_cm[cg][dim1] - bcorner_round_1 + tric_sh;
-                                if (rb[dim1] > 0)
-                                {
-                                    rb2 += rb[dim1]*rb[dim1]*sf2_round[dim1];
-                                    /* Take care of coupling of the distances
-                                     * to the planes along dim0 and dim1 through dim2.
-                                     */
-                                    rb2 -= rb[dim0]*rb[dim1]*skew_fac_01;
-                                    /* Take care that the cell planes along dim1
-                                     * might not be orthogonal to that along dim2.
-                                     */
-                                    if (normal[dim1][dim2] > 0)
-                                    {
-                                        rb[dim2] -= rb[dim1]*normal[dim1][dim2];
-                                    }
-                                }
-                            }
-                        }
-                        /* The distance along the communication direction */
-                        rn[dim] += cg_cm[cg][dim] - corner[dim_ind][zone];
-                        tric_sh = 0;
-                        for(i=dim+1; i<DIM; i++)
-                        {
-                            tric_sh -= cg_cm[cg][i]*v_d[i][dim];
-                        }
-                        rn[dim] += tric_sh;
-                        if (rn[dim] > 0)
-                        {
-                            r2 += rn[dim]*rn[dim]*skew_fac2_d;
-                            /* Take care of coupling of the distances
-                             * to the planes along dim0 and dim1 through dim2.
-                             */
-                            if (dim_ind == 1 && zonei == 1)
-                            {
-                                r2 -= rn[dim0]*rn[dim]*skew_fac_01;
-                            }
-                        }
-                        if (bDistMB_pulse)
-                        {
-                            clear_rvec(rb);
-                            rb[dim] += cg_cm[cg][dim] - bcorner[dim_ind] + tric_sh;
-                            if (rb[dim] > 0)
-                            {
-                                rb2 += rb[dim]*rb[dim]*skew_fac2_d;
-                                /* Take care of coupling of the distances
-                                 * to the planes along dim0 and dim1 through dim2.
-                                 */
-                                if (dim_ind == 1 && zonei == 1)
-                                {
-                                    rb2 -= rb[dim0]*rb[dim]*skew_fac_01;
-                                }
-                            }
-                        }
-                    }
-                    
-                    if (r2 < r_comm2 ||
-                        (bDistBonded &&
-                         ((bDistMB && rb2 < r_bcomm2) ||
-                          (bDist2B && r2  < r_bcomm2)) &&
-                         (!bBondComm ||
-                          (GET_CGINFO_BOND_INTER(fr->cginfo[cg]) &&
-                           missing_link(comm->cglink,index_gl[cg],
-                                        comm->bLocalCG)))))
-                    {
-                        /* Make an index to the local charge groups */
-                        if (nsend+1 > ind->nalloc)
-                        {
-                            ind->nalloc = over_alloc_large(nsend+1);
-                            srenew(ind->index,ind->nalloc);
-                        }
-                        if (nsend+1 > comm->nalloc_int)
-                        {
-                            comm->nalloc_int = over_alloc_large(nsend+1);
-                            srenew(comm->buf_int,comm->nalloc_int);
-                        }
-                        ind->index[nsend] = cg;
-                        comm->buf_int[nsend] = index_gl[cg];
-                        ind->nsend[zone]++;
-                        vec_rvec_check_alloc(&comm->vbuf,nsend+1);
-
-                        if (dd->ci[dim] == 0)
-                        {
-                            /* Correct cg_cm for pbc */
-                            rvec_add(cg_cm[cg],box[dim],comm->vbuf.v[nsend]);
-                            if (bScrew)
-                            {
-                                comm->vbuf.v[nsend][YY] =
-                                    box[YY][YY]-comm->vbuf.v[nsend][YY];
-                                comm->vbuf.v[nsend][ZZ] =
-                                    box[ZZ][ZZ]-comm->vbuf.v[nsend][ZZ];
-                            }
-                        }
-                        else
-                        {
-                            copy_rvec(cg_cm[cg],comm->vbuf.v[nsend]);
-                        }
-                        nsend++;
-                        nat += cgindex[cg+1] - cgindex[cg];
-                    }
-                }
-            }
-            /* Clear the counts in case we do not have pbc */
-            for(zone=nzone_send; zone<nzone; zone++)
-            {
-                ind->nsend[zone] = 0;
-            }
-            ind->nsend[nzone]   = nsend;
-            ind->nsend[nzone+1] = nat;
-            /* Communicate the number of cg's and atoms to receive */
-            dd_sendrecv_int(dd, dim_ind, dddirBackward,
-                            ind->nsend, nzone+2,
-                            ind->nrecv, nzone+2);
-            
-            /* The rvec buffer is also required for atom buffers of size nsend
-             * in dd_move_x and dd_move_f.
-             */
-            vec_rvec_check_alloc(&comm->vbuf,ind->nsend[nzone+1]);
-
-            if (p > 0)
-            {
-                /* We can receive in place if only the last zone is not empty */
-                for(zone=0; zone<nzone-1; zone++)
-                {
-                    if (ind->nrecv[zone] > 0)
-                    {
-                        cd->bInPlace = FALSE;
-                    }
-                }
-                if (!cd->bInPlace)
-                {
-                    /* The int buffer is only required here for the cg indices */
-                    if (ind->nrecv[nzone] > comm->nalloc_int2)
-                    {
-                        comm->nalloc_int2 = over_alloc_dd(ind->nrecv[nzone]);
-                        srenew(comm->buf_int2,comm->nalloc_int2);
-                    }
-                    /* The rvec buffer is also required for atom buffers
-                     * of size nrecv in dd_move_x and dd_move_f.
-                     */
-                    i = max(cd->ind[0].nrecv[nzone+1],ind->nrecv[nzone+1]);
-                    vec_rvec_check_alloc(&comm->vbuf2,i);
-                }
-            }
-            
-            /* Make space for the global cg indices */
-            if (pos_cg + ind->nrecv[nzone] > dd->cg_nalloc
-                || dd->cg_nalloc == 0)
-            {
-                dd->cg_nalloc = over_alloc_dd(pos_cg + ind->nrecv[nzone]);
-                srenew(index_gl,dd->cg_nalloc);
-                srenew(cgindex,dd->cg_nalloc+1);
-            }
-            /* Communicate the global cg indices */
-            if (cd->bInPlace)
-            {
-                recv_i = index_gl + pos_cg;
-            }
-            else
-            {
-                recv_i = comm->buf_int2;
-            }
-            dd_sendrecv_int(dd, dim_ind, dddirBackward,
-                            comm->buf_int, nsend,
-                            recv_i,        ind->nrecv[nzone]);
-
-            /* Make space for cg_cm */
-            if (pos_cg + ind->nrecv[nzone] > fr->cg_nalloc)
-            {
-                dd_realloc_fr_cg(fr,pos_cg + ind->nrecv[nzone]);
-                cg_cm = fr->cg_cm;
-            }
-            /* Communicate cg_cm */
-            if (cd->bInPlace)
-            {
-                recv_vr = cg_cm + pos_cg;
-            }
-            else
-            {
-                recv_vr = comm->vbuf2.v;
-            }
-            dd_sendrecv_rvec(dd, dim_ind, dddirBackward,
-                             comm->vbuf.v, nsend,
-                             recv_vr,      ind->nrecv[nzone]);
-            
-            /* Make the charge group index */
-            if (cd->bInPlace)
-            {
-                zone = (p == 0 ? 0 : nzone - 1);
-                while (zone < nzone)
-                {
-                    for(cg=0; cg<ind->nrecv[zone]; cg++)
-                    {
-                        cg_gl = index_gl[pos_cg];
-                        fr->cginfo[pos_cg] = ddcginfo(cginfo_mb,cg_gl);
-                        nrcg = GET_CGINFO_NATOMS(fr->cginfo[pos_cg]);
-                        cgindex[pos_cg+1] = cgindex[pos_cg] + nrcg;
-                        if (bBondComm)
-                        {
-                            /* Update the charge group presence,
-                             * so we can use it in the next pass of the loop.
-                             */
-                            comm->bLocalCG[cg_gl] = TRUE;
-                        }
-                        pos_cg++;
-                    }
-                    if (p == 0)
-                    {
-                        comm->zone_ncg1[nzone+zone] = ind->nrecv[zone];
-                    }
-                    zone++;
-                    zone_cg_range[nzone+zone] = pos_cg;
-                }
-            }
-            else
-            {
-                /* This part of the code is never executed with bBondComm. */
-                merge_cg_buffers(nzone,cd,p,zone_cg_range,
-                                 index_gl,recv_i,cg_cm,recv_vr,
-                                 cgindex,fr->cginfo_mb,fr->cginfo);
-                pos_cg += ind->nrecv[nzone];
-            }
-            nat_tot += ind->nrecv[nzone+1];
-        }
-        if (!cd->bInPlace)
-        {
-            /* Store the atom block for easy copying of communication buffers */
-            make_cell2at_index(cd,nzone,zone_cg_range[nzone],cgindex);
-        }
-        nzone += nzone;
-    }
-    dd->index_gl = index_gl;
-    dd->cgindex  = cgindex;
-    
-    dd->ncg_tot = zone_cg_range[zones->n];
-    dd->nat_tot = nat_tot;
-    comm->nat[ddnatHOME] = dd->nat_home;
-    for(i=ddnatZONE; i<ddnatNR; i++)
-    {
-        comm->nat[i] = dd->nat_tot;
-    }
-
-    if (!bBondComm)
-    {
-        /* We don't need to update cginfo, since that was alrady done above.
-         * So we pass NULL for the forcerec.
-         */
-        dd_set_cginfo(dd->index_gl,dd->ncg_home,dd->ncg_tot,
-                      NULL,comm->bLocalCG);
-    }
-
-    if (debug)
-    {
-        fprintf(debug,"Finished setting up DD communication, zones:");
-        for(c=0; c<zones->n; c++)
-        {
-            fprintf(debug," %d",zones->cg_range[c+1]-zones->cg_range[c]);
-        }
-        fprintf(debug,"\n");
-    }
-}
-
-static void set_cg_boundaries(gmx_domdec_zones_t *zones)
-{
-    int c;
-    
-    for(c=0; c<zones->nizone; c++)
-    {
-        zones->izone[c].cg1  = zones->cg_range[c+1];
-        zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0];
-        zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1];
-    }
-}
-
-static int comp_cgsort(const void *a,const void *b)
-{
-    int comp;
-    
-    gmx_cgsort_t *cga,*cgb;
-    cga = (gmx_cgsort_t *)a;
-    cgb = (gmx_cgsort_t *)b;
-    
-    comp = cga->nsc - cgb->nsc;
-    if (comp == 0)
-    {
-        comp = cga->ind_gl - cgb->ind_gl;
-    }
-    
-    return comp;
-}
-
-static void order_int_cg(int n,gmx_cgsort_t *sort,
-                         int *a,int *buf)
-{
-    int i;
-    
-    /* Order the data */
-    for(i=0; i<n; i++)
-    {
-        buf[i] = a[sort[i].ind];
-    }
-    
-    /* Copy back to the original array */
-    for(i=0; i<n; i++)
-    {
-        a[i] = buf[i];
-    }
-}
-
-static void order_vec_cg(int n,gmx_cgsort_t *sort,
-                         rvec *v,rvec *buf)
-{
-    int i;
-    
-    /* Order the data */
-    for(i=0; i<n; i++)
-    {
-        copy_rvec(v[sort[i].ind],buf[i]);
-    }
-    
-    /* Copy back to the original array */
-    for(i=0; i<n; i++)
-    {
-        copy_rvec(buf[i],v[i]);
-    }
-}
-
-static void order_vec_atom(int ncg,int *cgindex,gmx_cgsort_t *sort,
-                           rvec *v,rvec *buf)
-{
-    int a,atot,cg,cg0,cg1,i;
-    
-    /* Order the data */
-    a = 0;
-    for(cg=0; cg<ncg; cg++)
-    {
-        cg0 = cgindex[sort[cg].ind];
-        cg1 = cgindex[sort[cg].ind+1];
-        for(i=cg0; i<cg1; i++)
-        {
-            copy_rvec(v[i],buf[a]);
-            a++;
-        }
-    }
-    atot = a;
-    
-    /* Copy back to the original array */
-    for(a=0; a<atot; a++)
-    {
-        copy_rvec(buf[a],v[a]);
-    }
-}
-
-static void ordered_sort(int nsort2,gmx_cgsort_t *sort2,
-                         int nsort_new,gmx_cgsort_t *sort_new,
-                         gmx_cgsort_t *sort1)
-{
-    int i1,i2,i_new;
-    
-    /* The new indices are not very ordered, so we qsort them */
-    qsort_threadsafe(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
-    
-    /* sort2 is already ordered, so now we can merge the two arrays */
-    i1 = 0;
-    i2 = 0;
-    i_new = 0;
-    while(i2 < nsort2 || i_new < nsort_new)
-    {
-        if (i2 == nsort2)
-        {
-            sort1[i1++] = sort_new[i_new++];
-        }
-        else if (i_new == nsort_new)
-        {
-            sort1[i1++] = sort2[i2++];
-        }
-        else if (sort2[i2].nsc < sort_new[i_new].nsc ||
-                 (sort2[i2].nsc == sort_new[i_new].nsc &&
-                  sort2[i2].ind_gl < sort_new[i_new].ind_gl))
-        {
-            sort1[i1++] = sort2[i2++];
-        }
-        else
-        {
-            sort1[i1++] = sort_new[i_new++];
-        }
-    }
-}
-
-static void dd_sort_state(gmx_domdec_t *dd,int ePBC,
-                          rvec *cgcm,t_forcerec *fr,t_state *state,
-                          int ncg_home_old)
-{
-    gmx_domdec_sort_t *sort;
-    gmx_cgsort_t *cgsort,*sort_i;
-    int  ncg_new,nsort2,nsort_new,i,cell_index,*ibuf,cgsize;
-    rvec *vbuf;
-    
-    sort = dd->comm->sort;
-    
-    if (dd->ncg_home > sort->sort_nalloc)
-    {
-        sort->sort_nalloc = over_alloc_dd(dd->ncg_home);
-        srenew(sort->sort1,sort->sort_nalloc);
-        srenew(sort->sort2,sort->sort_nalloc);
-    }
-    
-    if (ncg_home_old >= 0)
-    {
-        /* The charge groups that remained in the same ns grid cell
-         * are completely ordered. So we can sort efficiently by sorting
-         * the charge groups that did move into the stationary list.
-         */
-        ncg_new = 0;
-        nsort2 = 0;
-        nsort_new = 0;
-        for(i=0; i<dd->ncg_home; i++)
-        {
-            /* Check if this cg did not move to another node */
-            cell_index = fr->ns.grid->cell_index[i];
-            if (cell_index !=  4*fr->ns.grid->ncells)
-            {
-                if (i >= ncg_home_old || cell_index != sort->sort1[i].nsc)
-                {
-                    /* This cg is new on this node or moved ns grid cell */
-                    if (nsort_new >= sort->sort_new_nalloc)
-                    {
-                        sort->sort_new_nalloc = over_alloc_dd(nsort_new+1);
-                        srenew(sort->sort_new,sort->sort_new_nalloc);
-                    }
-                    sort_i = &(sort->sort_new[nsort_new++]);
-                }
-                else
-                {
-                    /* This cg did not move */
-                    sort_i = &(sort->sort2[nsort2++]);
-                }
-                /* Sort on the ns grid cell indices
-                 * and the global topology index
-                 */
-                sort_i->nsc    = cell_index;
-                sort_i->ind_gl = dd->index_gl[i];
-                sort_i->ind    = i;
-                ncg_new++;
-            }
-        }
-        if (debug)
-        {
-            fprintf(debug,"ordered sort cgs: stationary %d moved %d\n",
-                    nsort2,nsort_new);
-        }
-        /* Sort efficiently */
-        ordered_sort(nsort2,sort->sort2,nsort_new,sort->sort_new,sort->sort1);
-    }
-    else
-    {
-        cgsort = sort->sort1;
-        ncg_new = 0;
-        for(i=0; i<dd->ncg_home; i++)
-        {
-            /* Sort on the ns grid cell indices
-             * and the global topology index
-             */
-            cgsort[i].nsc    = fr->ns.grid->cell_index[i];
-            cgsort[i].ind_gl = dd->index_gl[i];
-            cgsort[i].ind    = i;
-            if (cgsort[i].nsc != 4*fr->ns.grid->ncells)
-            {
-                ncg_new++;
-            }
-        }
-        if (debug)
-        {
-            fprintf(debug,"qsort cgs: %d new home %d\n",dd->ncg_home,ncg_new);
-        }
-        /* Determine the order of the charge groups using qsort */
-        qsort_threadsafe(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
-    }
-    cgsort = sort->sort1;
-    
-    /* We alloc with the old size, since cgindex is still old */
-    vec_rvec_check_alloc(&dd->comm->vbuf,dd->cgindex[dd->ncg_home]);
-    vbuf = dd->comm->vbuf.v;
-    
-    /* Remove the charge groups which are no longer at home here */
-    dd->ncg_home = ncg_new;
-    
-    /* Reorder the state */
-    for(i=0; i<estNR; i++)
-    {
-        if (EST_DISTR(i) && (state->flags & (1<<i)))
-        {
-            switch (i)
-            {
-            case estX:
-                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->x,vbuf);
-                break;
-            case estV:
-                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->v,vbuf);
-                break;
-            case estSDX:
-                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->sd_X,vbuf);
-                break;
-            case estCGP:
-                order_vec_atom(dd->ncg_home,dd->cgindex,cgsort,state->cg_p,vbuf);
-                break;
-            case estLD_RNG:
-            case estLD_RNGI:
-            case estDISRE_INITF:
-            case estDISRE_RM3TAV:
-            case estORIRE_INITF:
-            case estORIRE_DTAV:
-                /* No ordering required */
-                break;
-            default:
-                gmx_incons("Unknown state entry encountered in dd_sort_state");
-                break;
-            }
-        }
-    }
-    /* Reorder cgcm */
-    order_vec_cg(dd->ncg_home,cgsort,cgcm,vbuf);
-    
-    if (dd->ncg_home+1 > sort->ibuf_nalloc)
-    {
-        sort->ibuf_nalloc = over_alloc_dd(dd->ncg_home+1);
-        srenew(sort->ibuf,sort->ibuf_nalloc);
-    }
-    ibuf = sort->ibuf;
-    /* Reorder the global cg index */
-    order_int_cg(dd->ncg_home,cgsort,dd->index_gl,ibuf);
-    /* Reorder the cginfo */
-    order_int_cg(dd->ncg_home,cgsort,fr->cginfo,ibuf);
-    /* Rebuild the local cg index */
-    ibuf[0] = 0;
-    for(i=0; i<dd->ncg_home; i++)
-    {
-        cgsize = dd->cgindex[cgsort[i].ind+1] - dd->cgindex[cgsort[i].ind];
-        ibuf[i+1] = ibuf[i] + cgsize;
-    }
-    for(i=0; i<dd->ncg_home+1; i++)
-    {
-        dd->cgindex[i] = ibuf[i];
-    }
-    /* Set the home atom number */
-    dd->nat_home = dd->cgindex[dd->ncg_home];
-    
-    /* Copy the sorted ns cell indices back to the ns grid struct */
-    for(i=0; i<dd->ncg_home; i++)
-    {
-        fr->ns.grid->cell_index[i] = cgsort[i].nsc;
-    }
-    fr->ns.grid->nr = dd->ncg_home;
-}
-
-static void add_dd_statistics(gmx_domdec_t *dd)
-{
-    gmx_domdec_comm_t *comm;
-    int ddnat;
-    
-    comm = dd->comm;
-    
-    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
-    {
-        comm->sum_nat[ddnat-ddnatZONE] +=
-            comm->nat[ddnat] - comm->nat[ddnat-1];
-    }
-    comm->ndecomp++;
-}
-
-void reset_dd_statistics_counters(gmx_domdec_t *dd)
-{
-    gmx_domdec_comm_t *comm;
-    int ddnat;
-    
-    comm = dd->comm;
-
-    /* Reset all the statistics and counters for total run counting */
-    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
-    {
-        comm->sum_nat[ddnat-ddnatZONE] = 0;
-    }
-    comm->ndecomp = 0;
-    comm->nload = 0;
-    comm->load_step = 0;
-    comm->load_sum = 0;
-    comm->load_max = 0;
-    clear_ivec(comm->load_lim);
-    comm->load_mdf = 0;
-    comm->load_pme = 0;
-}
-
-void print_dd_statistics(t_commrec *cr,t_inputrec *ir,FILE *fplog)
-{
-    gmx_domdec_comm_t *comm;
-    int ddnat;
-    double av;
-   
-    comm = cr->dd->comm;
-    
-    gmx_sumd(ddnatNR-ddnatZONE,comm->sum_nat,cr);
-    
-    if (fplog == NULL)
-    {
-        return;
-    }
-    
-    fprintf(fplog,"\n    D O M A I N   D E C O M P O S I T I O N   S T A T I S T I C S\n\n");
-            
-    for(ddnat=ddnatZONE; ddnat<ddnatNR; ddnat++)
-    {
-        av = comm->sum_nat[ddnat-ddnatZONE]/comm->ndecomp;
-        switch(ddnat)
-        {
-        case ddnatZONE:
-            fprintf(fplog,
-                    " av. #atoms communicated per step for force:  %d x %.1f\n",
-                    2,av);
-            break;
-        case ddnatVSITE:
-            if (cr->dd->vsite_comm)
-            {
-                fprintf(fplog,
-                        " av. #atoms communicated per step for vsites: %d x %.1f\n",
-                        (EEL_PME(ir->coulombtype) || ir->coulombtype==eelEWALD) ? 3 : 2,
-                        av);
-            }
-            break;
-        case ddnatCON:
-            if (cr->dd->constraint_comm)
-            {
-                fprintf(fplog,
-                        " av. #atoms communicated per step for LINCS:  %d x %.1f\n",
-                        1 + ir->nLincsIter,av);
-            }
-            break;
-        default:
-            gmx_incons(" Unknown type for DD statistics");
-        }
-    }
-    fprintf(fplog,"\n");
-    
-    if (comm->bRecordLoad && EI_DYNAMICS(ir->eI))
-    {
-        print_dd_load_av(fplog,cr->dd);
-    }
-}
-
-void dd_partition_system(FILE            *fplog,
-                         gmx_large_int_t      step,
-                         t_commrec       *cr,
-                         gmx_bool            bMasterState,
-                         int             nstglobalcomm,
-                         t_state         *state_global,
-                         gmx_mtop_t      *top_global,
-                         t_inputrec      *ir,
-                         t_state         *state_local,
-                         rvec            **f,
-                         t_mdatoms       *mdatoms,
-                         gmx_localtop_t  *top_local,
-                         t_forcerec      *fr,
-                         gmx_vsite_t     *vsite,
-                         gmx_shellfc_t   shellfc,
-                         gmx_constr_t    constr,
-                         t_nrnb          *nrnb,
-                         gmx_wallcycle_t wcycle,
-                         gmx_bool            bVerbose)
-{
-    gmx_domdec_t *dd;
-    gmx_domdec_comm_t *comm;
-    gmx_ddbox_t ddbox={0};
-    t_block *cgs_gl;
-    gmx_large_int_t step_pcoupl;
-    rvec cell_ns_x0,cell_ns_x1;
-    int  i,j,n,cg0=0,ncg_home_old=-1,nat_f_novirsum;
-    gmx_bool bBoxChanged,bNStGlobalComm,bDoDLB,bCheckDLB,bTurnOnDLB,bLogLoad;
-    gmx_bool bRedist,bSortCG,bResortAll;
-    ivec ncells_old,np;
-    real grid_density;
-    char sbuf[22];
-       
-    dd = cr->dd;
-    comm = dd->comm;
-
-    bBoxChanged = (bMasterState || DEFORM(*ir));
-    if (ir->epc != epcNO)
-    {
-        /* With nstpcouple > 1 pressure coupling happens.
-         * one step after calculating the pressure.
-         * Box scaling happens at the end of the MD step,
-         * after the DD partitioning.
-         * We therefore have to do DLB in the first partitioning
-         * after an MD step where P-coupling occured.
-         * We need to determine the last step in which p-coupling occurred.
-         * MRS -- need to validate this for vv?
-         */
-        n = ir->nstpcouple;
-        if (n == 1)
-        {
-            step_pcoupl = step - 1;
-        }
-        else
-        {
-            step_pcoupl = ((step - 1)/n)*n + 1;
-        }
-        if (step_pcoupl >= comm->globalcomm_step)
-        {
-            bBoxChanged = TRUE;
-        }
-    }
-
-    bNStGlobalComm = (step >= comm->globalcomm_step + nstglobalcomm);
-
-    if (!comm->bDynLoadBal)
-    {
-        bDoDLB = FALSE;
-    }
-    else
-    {
-        /* Should we do dynamic load balacing this step?
-         * Since it requires (possibly expensive) global communication,
-         * we might want to do DLB less frequently.
-         */
-        if (bBoxChanged || ir->epc != epcNO)
-        {
-            bDoDLB = bBoxChanged;
-        }
-        else
-        {
-            bDoDLB = bNStGlobalComm;
-        }
-    }
-
-    /* Check if we have recorded loads on the nodes */
-    if (comm->bRecordLoad && dd_load_count(comm))
-    {
-        if (comm->eDLB == edlbAUTO && !comm->bDynLoadBal)
-        {
-            /* Check if we should use DLB at the second partitioning
-             * and every 100 partitionings,
-             * so the extra communication cost is negligible.
-             */
-            n = max(100,nstglobalcomm);
-            bCheckDLB = (comm->n_load_collect == 0 ||
-                         comm->n_load_have % n == n-1);
-        }
-        else
-        {
-            bCheckDLB = FALSE;
-        }
-        
-        /* Print load every nstlog, first and last step to the log file */
-        bLogLoad = ((ir->nstlog > 0 && step % ir->nstlog == 0) ||
-                    comm->n_load_collect == 0 ||
-                    (ir->nsteps >= 0 &&
-                     (step + ir->nstlist > ir->init_step + ir->nsteps)));
-
-        /* Avoid extra communication due to verbose screen output
-         * when nstglobalcomm is set.
-         */
-        if (bDoDLB || bLogLoad || bCheckDLB ||
-            (bVerbose && (ir->nstlist == 0 || nstglobalcomm <= ir->nstlist)))
-        {
-            get_load_distribution(dd,wcycle);
-            if (DDMASTER(dd))
-            {
-                if (bLogLoad)
-                {
-                    dd_print_load(fplog,dd,step-1);
-                }
-                if (bVerbose)
-                {
-                    dd_print_load_verbose(dd);
-                }
-            }
-            comm->n_load_collect++;
-
-            if (bCheckDLB) {
-                /* Since the timings are node dependent, the master decides */
-                if (DDMASTER(dd))
-                {
-                    bTurnOnDLB =
-                        (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS);
-                    if (debug)
-                    {
-                        fprintf(debug,"step %s, imb loss %f\n",
-                                gmx_step_str(step,sbuf),
-                                dd_force_imb_perf_loss(dd));
-                    }
-                }
-                dd_bcast(dd,sizeof(bTurnOnDLB),&bTurnOnDLB);
-                if (bTurnOnDLB)
-                {
-                    turn_on_dlb(fplog,cr,step);
-                    bDoDLB = TRUE;
-                }
-            }
-        }
-        comm->n_load_have++;
-    }
-
-    cgs_gl = &comm->cgs_gl;
-
-    bRedist = FALSE;
-    if (bMasterState)
-    {
-        /* Clear the old state */
-        clear_dd_indices(dd,0,0);
-
-        set_ddbox(dd,bMasterState,cr,ir,state_global->box,
-                  TRUE,cgs_gl,state_global->x,&ddbox);
-    
-        get_cg_distribution(fplog,step,dd,cgs_gl,
-                            state_global->box,&ddbox,state_global->x);
-        
-        dd_distribute_state(dd,cgs_gl,
-                            state_global,state_local,f);
-        
-        dd_make_local_cgs(dd,&top_local->cgs);
-        
-        if (dd->ncg_home > fr->cg_nalloc)
-        {
-            dd_realloc_fr_cg(fr,dd->ncg_home);
-        }
-        calc_cgcm(fplog,0,dd->ncg_home,
-                  &top_local->cgs,state_local->x,fr->cg_cm);
-        
-        inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
-        
-        dd_set_cginfo(dd->index_gl,0,dd->ncg_home,fr,comm->bLocalCG);
-
-        cg0 = 0;
-    }
-    else if (state_local->ddp_count != dd->ddp_count)
-    {
-        if (state_local->ddp_count > dd->ddp_count)
-        {
-            gmx_fatal(FARGS,"Internal inconsistency state_local->ddp_count (%d) > dd->ddp_count (%d)",state_local->ddp_count,dd->ddp_count);
-        }
-        
-        if (state_local->ddp_count_cg_gl != state_local->ddp_count)
-        {
-            gmx_fatal(FARGS,"Internal inconsistency state_local->ddp_count_cg_gl (%d) != state_local->ddp_count (%d)",state_local->ddp_count_cg_gl,state_local->ddp_count);
-        }
-        
-        /* Clear the old state */
-        clear_dd_indices(dd,0,0);
-        
-        /* Build the new indices */
-        rebuild_cgindex(dd,cgs_gl->index,state_local);
-        make_dd_indices(dd,cgs_gl->index,0);
-        
-        /* Redetermine the cg COMs */
-        calc_cgcm(fplog,0,dd->ncg_home,
-                  &top_local->cgs,state_local->x,fr->cg_cm);
-        
-        inc_nrnb(nrnb,eNR_CGCM,dd->nat_home);
-
-        dd_set_cginfo(dd->index_gl,0,dd->ncg_home,fr,comm->bLocalCG);
-
-        set_ddbox(dd,bMasterState,cr,ir,state_local->box,
-                  TRUE,&top_local->cgs,state_local->x,&ddbox);
-
-        bRedist = comm->bDynLoadBal;
-    }
-    else
-    {
-        /* We have the full state, only redistribute the cgs */
-
-        /* Clear the non-home indices */
-        clear_dd_indices(dd,dd->ncg_home,dd->nat_home);
-
-        /* Avoid global communication for dim's without pbc and -gcom */
-        if (!bNStGlobalComm)
-        {
-            copy_rvec(comm->box0    ,ddbox.box0    );
-            copy_rvec(comm->box_size,ddbox.box_size);
-        }
-        set_ddbox(dd,bMasterState,cr,ir,state_local->box,
-                  bNStGlobalComm,&top_local->cgs,state_local->x,&ddbox);
-
-        bBoxChanged = TRUE;
-        bRedist = TRUE;
-    }
-    /* For dim's without pbc and -gcom */
-    copy_rvec(ddbox.box0    ,comm->box0    );
-    copy_rvec(ddbox.box_size,comm->box_size);
-    
-    set_dd_cell_sizes(dd,&ddbox,dynamic_dd_box(&ddbox,ir),bMasterState,bDoDLB,
-                      step,wcycle);
-    
-    if (comm->nstDDDumpGrid > 0 && step % comm->nstDDDumpGrid == 0)
-    {
-        write_dd_grid_pdb("dd_grid",step,dd,state_local->box,&ddbox);
-    }
-    
-    /* Check if we should sort the charge groups */
-    if (comm->nstSortCG > 0)
-    {
-        bSortCG = (bMasterState ||
-                   (bRedist && (step % comm->nstSortCG == 0)));
-    }
-    else
-    {
-        bSortCG = FALSE;
-    }
-
-    ncg_home_old = dd->ncg_home;
-
-    if (bRedist)
-    {
-        cg0 = dd_redistribute_cg(fplog,step,dd,ddbox.tric_dir,
-                                 state_local,f,fr,mdatoms,
-                                 !bSortCG,nrnb);
-    }
-    
-    get_nsgrid_boundaries(fr->ns.grid,dd,
-                          state_local->box,&ddbox,&comm->cell_x0,&comm->cell_x1,
-                          dd->ncg_home,fr->cg_cm,
-                          cell_ns_x0,cell_ns_x1,&grid_density);
-
-    if (bBoxChanged)
-    {
-        comm_dd_ns_cell_sizes(dd,&ddbox,cell_ns_x0,cell_ns_x1,step);
-    }
-
-    copy_ivec(fr->ns.grid->n,ncells_old);
-    grid_first(fplog,fr->ns.grid,dd,&ddbox,fr->ePBC,
-               state_local->box,cell_ns_x0,cell_ns_x1,
-               fr->rlistlong,grid_density);
-    /* We need to store tric_dir for dd_get_ns_ranges called from ns.c */
-    copy_ivec(ddbox.tric_dir,comm->tric_dir);
-
-    if (bSortCG)
-    {
-        /* Sort the state on charge group position.
-         * This enables exact restarts from this step.
-         * It also improves performance by about 15% with larger numbers
-         * of atoms per node.
-         */
-        
-        /* Fill the ns grid with the home cell,
-         * so we can sort with the indices.
-         */
-        set_zones_ncg_home(dd);
-        fill_grid(fplog,&comm->zones,fr->ns.grid,dd->ncg_home,
-                  0,dd->ncg_home,fr->cg_cm);
-        
-        /* Check if we can user the old order and ns grid cell indices
-         * of the charge groups to sort the charge groups efficiently.
-         */
-        bResortAll = (bMasterState ||
-                      fr->ns.grid->n[XX] != ncells_old[XX] ||
-                      fr->ns.grid->n[YY] != ncells_old[YY] ||
-                      fr->ns.grid->n[ZZ] != ncells_old[ZZ]);
-
-        if (debug)
-        {
-            fprintf(debug,"Step %s, sorting the %d home charge groups\n",
-                    gmx_step_str(step,sbuf),dd->ncg_home);
-        }
-        dd_sort_state(dd,ir->ePBC,fr->cg_cm,fr,state_local,
-                      bResortAll ? -1 : ncg_home_old);
-        /* Rebuild all the indices */
-        cg0 = 0;
-        ga2la_clear(dd->ga2la);
-    }
-    
-    /* Setup up the communication and communicate the coordinates */
-    setup_dd_communication(dd,state_local->box,&ddbox,fr);
-    
-    /* Set the indices */
-    make_dd_indices(dd,cgs_gl->index,cg0);
-
-    /* Set the charge group boundaries for neighbor searching */
-    set_cg_boundaries(&comm->zones);
-    
-    /*
-    write_dd_pdb("dd_home",step,"dump",top_global,cr,
-                 -1,state_local->x,state_local->box);
-    */
-    
-    /* Extract a local topology from the global topology */
-    for(i=0; i<dd->ndim; i++)
-    {
-        np[dd->dim[i]] = comm->cd[i].np;
-    }
-    dd_make_local_top(fplog,dd,&comm->zones,dd->npbcdim,state_local->box,
-                      comm->cellsize_min,np,
-                      fr,vsite,top_global,top_local);
-    
-    /* Set up the special atom communication */
-    n = comm->nat[ddnatZONE];
-    for(i=ddnatZONE+1; i<ddnatNR; i++)
-    {
-        switch(i)
-        {
-        case ddnatVSITE:
-            if (vsite && vsite->n_intercg_vsite)
-            {
-                n = dd_make_local_vsites(dd,n,top_local->idef.il);
-            }
-            break;
-        case ddnatCON:
-            if (dd->bInterCGcons)
-            {
-                /* Only for inter-cg constraints we need special code */
-                n = dd_make_local_constraints(dd,n,top_global,
-                                              constr,ir->nProjOrder,
-                                              &top_local->idef.il[F_CONSTR]);
-            }
-            break;
-        default:
-            gmx_incons("Unknown special atom type setup");
-        }
-        comm->nat[i] = n;
-    }
-    
-    /* Make space for the extra coordinates for virtual site
-     * or constraint communication.
-     */
-    state_local->natoms = comm->nat[ddnatNR-1];
-    if (state_local->natoms > state_local->nalloc)
-    {
-        dd_realloc_state(state_local,f,state_local->natoms);
-    }
-
-    if (fr->bF_NoVirSum)
-    {
-        if (vsite && vsite->n_intercg_vsite)
-        {
-            nat_f_novirsum = comm->nat[ddnatVSITE];
-        }
-        else
-        {
-            if (EEL_FULL(ir->coulombtype) && dd->n_intercg_excl > 0)
-            {
-                nat_f_novirsum = dd->nat_tot;
-            }
-            else
-            {
-                nat_f_novirsum = dd->nat_home;
-            }
-        }
-    }
-    else
-    {
-        nat_f_novirsum = 0;
-    }
-
-    /* Set the number of atoms required for the force calculation.
-     * Forces need to be constrained when using a twin-range setup
-     * or with energy minimization. For simple simulations we could
-     * avoid some allocation, zeroing and copying, but this is
-     * probably not worth the complications ande checking.
-     */
-    forcerec_set_ranges(fr,dd->ncg_home,dd->ncg_tot,
-                        dd->nat_tot,comm->nat[ddnatCON],nat_f_novirsum);
-
-    /* We make the all mdatoms up to nat_tot_con.
-     * We could save some work by only setting invmass
-     * between nat_tot and nat_tot_con.
-     */
-    /* This call also sets the new number of home particles to dd->nat_home */
-    atoms2md(top_global,ir,
-             comm->nat[ddnatCON],dd->gatindex,0,dd->nat_home,mdatoms);
-
-    /* Now we have the charges we can sort the FE interactions */
-    dd_sort_local_top(dd,mdatoms,top_local);
-
-    if (shellfc)
-    {
-        /* Make the local shell stuff, currently no communication is done */
-        make_local_shells(cr,mdatoms,shellfc);
-    }
-    
-       if (ir->implicit_solvent)
-    {
-        make_local_gb(cr,fr->born,ir->gb_algorithm);
-    }
-       
-    if (!(cr->duty & DUTY_PME))
-    {
-        /* Send the charges to our PME only node */
-        gmx_pme_send_q(cr,mdatoms->nChargePerturbed,
-                       mdatoms->chargeA,mdatoms->chargeB,
-                       dd_pme_maxshift_x(dd),dd_pme_maxshift_y(dd));
-    }
-    
-    if (constr)
-    {
-        set_constraints(constr,top_local,ir,mdatoms,cr);
-    }
-    
-    if (ir->ePull != epullNO)
-    {
-        /* Update the local pull groups */
-        dd_make_local_pull_groups(dd,ir->pull,mdatoms);
-    }
-
-    add_dd_statistics(dd);
-    
-    /* Make sure we only count the cycles for this DD partitioning */
-    clear_dd_cycle_counts(dd);
-    
-    /* Because the order of the atoms might have changed since
-     * the last vsite construction, we need to communicate the constructing
-     * atom coordinates again (for spreading the forces this MD step).
-     */
-    dd_move_x_vsites(dd,state_local->box,state_local->x);
-    
-    if (comm->nstDDDump > 0 && step % comm->nstDDDump == 0)
-    {
-        dd_move_x(dd,state_local->box,state_local->x);
-        write_dd_pdb("dd_dump",step,"dump",top_global,cr,
-                     -1,state_local->x,state_local->box);
-    }
-
-    if (bNStGlobalComm)
-    {
-        /* Store the global communication step */
-        comm->globalcomm_step = step;
-    }
-    
-    /* Increase the DD partitioning counter */
-    dd->ddp_count++;
-    /* The state currently matches this DD partitioning count, store it */
-    state_local->ddp_count = dd->ddp_count;
-    if (bMasterState)
-    {
-        /* The DD master node knows the complete cg distribution,
-         * store the count so we can possibly skip the cg info communication.
-         */
-        comm->master_cg_ddp_count = (bSortCG ? 0 : dd->ddp_count);
-    }
-
-    if (comm->DD_debug > 0)
-    {
-        /* Set the env var GMX_DD_DEBUG if you suspect corrupted indices */
-        check_index_consistency(dd,top_global->natoms,ncg_mtop(top_global),
-                                "after partitioning");
-    }
-}
diff --git a/src/mdlib/edsam.c b/src/mdlib/edsam.c
deleted file mode 100644 (file)
index 8359863..0000000
+++ /dev/null
@@ -1,2594 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- *
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <time.h>
-#include "typedefs.h"
-#include "string2.h"
-#include "smalloc.h"
-#include "names.h"
-#include "confio.h"
-#include "mvdata.h"
-#include "txtdump.h"
-#include "vec.h"
-#include "time.h"
-#include "nrnb.h"
-#include "mshift.h"
-#include "mdrun.h"
-#include "update.h"
-#include "physics.h"
-#include "nrjac.h"
-#include "mtop_util.h"
-#include "edsam.h"
-#include "mpelogging.h"
-#include "gmxfio.h"
-#include "groupcoord.h"
-
-
-/* We use the same defines as in mvdata.c here */
-#define  block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
-#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
-#define   snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
-
-
-/* enum to identify the type of ED: none, normal ED, flooding */
-enum {eEDnone, eEDedsam, eEDflood, eEDnr};
-
-/* enum to identify operations on reference, average, origin, target structures */
-enum {eedREF, eedAV, eedORI, eedTAR, eedNR};
-
-
-typedef struct
-{
-    int    neig;     /* nr of eigenvectors             */
-    int   *ieig;     /* index nrs of eigenvectors      */
-    real  *stpsz;    /* stepsizes (per eigenvector)    */
-    rvec  **vec;     /* eigenvector components         */
-    real  *xproj;    /* instantaneous x projections    */
-    real  *fproj;    /* instantaneous f projections    */
-    real  radius;    /* instantaneous radius           */
-    real  *refproj;  /* starting or target projecions  */
-    /* When using flooding as harmonic restraint: The current reference projection
-     * is at each step calculated from the initial refproj0 and the slope. */
-    real  *refproj0,*refprojslope;
-} t_eigvec;
-
-
-typedef struct
-{
-    t_eigvec      mon;            /* only monitored, no constraints       */
-    t_eigvec      linfix;         /* fixed linear constraints             */
-    t_eigvec      linacc;         /* acceptance linear constraints        */
-    t_eigvec      radfix;         /* fixed radial constraints (exp)       */
-    t_eigvec      radacc;         /* acceptance radial constraints (exp)  */
-    t_eigvec      radcon;         /* acceptance rad. contraction constr.  */
-} t_edvecs;
-
-
-typedef struct
-{
-    real deltaF0;
-    gmx_bool bHarmonic;           /* Use flooding for harmonic restraint on
-                                     the eigenvector                          */
-    gmx_bool bConstForce;         /* Do not calculate a flooding potential,
-                                     instead flood with a constant force      */
-    real tau;
-    real deltaF;
-    real Efl;
-    real kT;
-    real Vfl;
-    real dt;
-    real constEfl;
-    real alpha2;
-    int flood_id;
-    rvec *forces_cartesian;
-    t_eigvec vecs;         /* use flooding for these */
-} t_edflood;
-
-
-/* This type is for the average, reference, target, and origin structure    */
-typedef struct gmx_edx
-{
-    int           nr;             /* number of atoms this structure contains  */
-    int           nr_loc;         /* number of atoms on local node            */
-    int           *anrs;          /* atom index numbers                       */
-    int           *anrs_loc;      /* local atom index numbers                 */
-    int           nalloc_loc;     /* allocation size of anrs_loc              */
-    int           *c_ind;         /* at which position of the whole anrs
-                                   * array is a local atom?, i.e.
-                                   * c_ind[0...nr_loc-1] gives the atom index
-                                   * with respect to the collective
-                                   * anrs[0...nr-1] array                     */
-    rvec          *x;             /* positions for this structure             */
-    rvec          *x_old;         /* used to keep track of the shift vectors
-                                     such that the ED molecule can always be
-                                     made whole in the parallel case          */
-    real          *m;             /* masses                                   */
-    real          mtot;           /* total mass (only used in sref)           */
-    real          *sqrtm;         /* sqrt of the masses used for mass-
-                                   * weighting of analysis (only used in sav) */
-} t_gmx_edx;
-
-
-typedef struct edpar
-{
-    int            nini;           /* total Nr of atoms                    */
-    gmx_bool       fitmas;         /* true if trans fit with cm            */
-    gmx_bool       pcamas;         /* true if mass-weighted PCA            */
-    int            presteps;       /* number of steps to run without any
-                                    *    perturbations ... just monitoring */
-    int            outfrq;         /* freq (in steps) of writing to edo    */
-    int            maxedsteps;     /* max nr of steps per cycle            */
-
-    /* all gmx_edx datasets are copied to all nodes in the parallel case   */
-    struct gmx_edx sref;           /* reference positions, to these fitting
-                                    * will be done                         */
-    gmx_bool       bRefEqAv;       /* If true, reference & average indices
-                                    * are the same. Used for optimization  */
-    struct gmx_edx sav;            /* average positions                    */
-    struct gmx_edx star;           /* target positions                     */
-    struct gmx_edx sori;           /* origin positions                     */
-
-    t_edvecs       vecs;           /* eigenvectors                         */
-    real           slope;          /* minimal slope in acceptance radexp   */
-
-    gmx_bool       bNeedDoEdsam;   /* if any of the options mon, linfix, ...
-                                    * is used (i.e. apart from flooding)   */
-    t_edflood      flood;          /* parameters especially for flooding   */
-    struct t_ed_buffer *buf;       /* handle to local buffers              */
-    struct edpar   *next_edi;      /* Pointer to another ed dataset        */
-} t_edpar;
-
-
-typedef struct gmx_edsam
-{
-    int           eEDtype;        /* Type of ED: see enums above          */
-    const char    *edinam;        /* name of ED sampling input file       */
-    const char    *edonam;        /*                     output           */
-    FILE          *edo;           /* output file pointer                  */
-    t_edpar       *edpar;
-    gmx_bool      bFirst;
-    gmx_bool      bStartFromCpt;
-} t_gmx_edsam;
-
-
-struct t_do_edsam
-{
-    matrix old_rotmat;
-    real oldrad;
-    rvec old_transvec,older_transvec,transvec_compact;
-    rvec *xcoll;         /* Positions from all nodes, this is the
-                            collective set we work on.
-                            These are the positions of atoms with
-                            average structure indices */
-    rvec *xc_ref;        /* same but with reference structure indices */
-    ivec *shifts_xcoll;        /* Shifts for xcoll  */
-    ivec *extra_shifts_xcoll;  /* xcoll shift changes since last NS step */
-    ivec *shifts_xc_ref;       /* Shifts for xc_ref */
-    ivec *extra_shifts_xc_ref; /* xc_ref shift changes since last NS step */
-    gmx_bool bUpdateShifts;    /* TRUE in NS steps to indicate that the
-                                  ED shifts for this ED dataset need to
-                                  be updated */
-};
-
-
-/* definition of ED buffer structure */
-struct t_ed_buffer
-{
-    struct t_fit_to_ref *           fit_to_ref;
-    struct t_do_edfit *             do_edfit;
-    struct t_do_edsam *             do_edsam;
-    struct t_do_radcon *            do_radcon;
-};
-
-
-/* Function declarations */
-static void fit_to_reference(rvec *xcoll,rvec transvec,matrix rotmat,t_edpar *edi);
-
-static void translate_and_rotate(rvec *x,int nat,rvec transvec,matrix rotmat);
-/* End function declarations */
-
-
-/* Does not subtract average positions, projection on single eigenvector is returned
- * used by: do_linfix, do_linacc, do_radfix, do_radacc, do_radcon
- * Average position is subtracted in ed_apply_constraints prior to calling projectx
- */
-static real projectx(t_edpar *edi, rvec *xcoll, rvec *vec)
-{
-    int  i;
-    real proj=0.0;
-
-
-    for (i=0; i<edi->sav.nr; i++)
-        proj += edi->sav.sqrtm[i]*iprod(vec[i], xcoll[i]);
-
-    return proj;
-}
-
-
-/* Specialized: projection is stored in vec->refproj
- * -> used for radacc, radfix, radcon  and center of flooding potential
- * subtracts average positions, projects vector x */
-static void rad_project(t_edpar *edi, rvec *x, t_eigvec *vec, t_commrec *cr)
-{
-    int i;
-    real rad=0.0;
-
-    /* Subtract average positions */
-    for (i = 0; i < edi->sav.nr; i++)
-        rvec_dec(x[i], edi->sav.x[i]);
-
-    for (i = 0; i < vec->neig; i++)
-    {
-        vec->refproj[i] = projectx(edi,x,vec->vec[i]);
-        rad += pow((vec->refproj[i]-vec->xproj[i]),2);
-    }
-    vec->radius=sqrt(rad);
-
-    /* Add average positions */
-    for (i = 0; i < edi->sav.nr; i++)
-        rvec_inc(x[i], edi->sav.x[i]);
-}
-
-
-/* Project vector x, subtract average positions prior to projection and add
- * them afterwards to retain the unchanged vector. Store in xproj. Mass-weighting
- * is applied. */
-static void project_to_eigvectors(rvec       *x,    /* The positions to project to an eigenvector */
-                                  t_eigvec   *vec,  /* The eigenvectors */
-                                  t_edpar    *edi)
-{
-    int  i;
-
-
-    if (!vec->neig) return;
-
-    /* Subtract average positions */
-    for (i=0; i<edi->sav.nr; i++)
-        rvec_dec(x[i], edi->sav.x[i]);
-
-    for (i=0; i<vec->neig; i++)
-        vec->xproj[i] = projectx(edi, x, vec->vec[i]);
-
-    /* Add average positions */
-    for (i=0; i<edi->sav.nr; i++)
-        rvec_inc(x[i], edi->sav.x[i]);
-}
-
-
-/* Project vector x onto all edi->vecs (mon, linfix,...) */
-static void project(rvec      *x,     /* positions to project */
-                    t_edpar   *edi)   /* edi data set */
-{
-    /* It is not more work to subtract the average position in every
-     * subroutine again, because these routines are rarely used simultanely */
-    project_to_eigvectors(x, &edi->vecs.mon   , edi);
-    project_to_eigvectors(x, &edi->vecs.linfix, edi);
-    project_to_eigvectors(x, &edi->vecs.linacc, edi);
-    project_to_eigvectors(x, &edi->vecs.radfix, edi);
-    project_to_eigvectors(x, &edi->vecs.radacc, edi);
-    project_to_eigvectors(x, &edi->vecs.radcon, edi);
-}
-
-
-static real calc_radius(t_eigvec *vec)
-{
-    int i;
-    real rad=0.0;
-
-
-    for (i=0; i<vec->neig; i++)
-        rad += pow((vec->refproj[i]-vec->xproj[i]),2);
-
-    return rad=sqrt(rad);
-}
-
-
-/* Debug helper */
-#ifdef DEBUGHELPERS
-static void dump_xcoll(t_edpar *edi, struct t_do_edsam *buf, t_commrec *cr,
-                       int step)
-{
-    int i;
-    FILE *fp;
-    char fn[STRLEN];
-    rvec *xcoll;
-    ivec *shifts, *eshifts;
-
-
-    if (!MASTER(cr))
-        return;
-
-    xcoll   = buf->xcoll;
-    shifts  = buf->shifts_xcoll;
-    eshifts = buf->extra_shifts_xcoll;
-
-    sprintf(fn, "xcolldump_step%d.txt", step);
-    fp = fopen(fn, "w");
-
-    for (i=0; i<edi->sav.nr; i++)
-        fprintf(fp, "%d %9.5f %9.5f %9.5f   %d %d %d   %d %d %d\n",
-                edi->sav.anrs[i]+1,
-                xcoll[i][XX]  , xcoll[i][YY]  , xcoll[i][ZZ],
-                shifts[i][XX] , shifts[i][YY] , shifts[i][ZZ],
-                eshifts[i][XX], eshifts[i][YY], eshifts[i][ZZ]);
-
-    fclose(fp);
-}
-
-
-/* Debug helper */
-static void dump_edi_positions(FILE *out, struct gmx_edx *s, const char name[])
-{
-    int i;
-
-
-    fprintf(out, "#%s positions:\n%d\n", name, s->nr);
-    if (s->nr == 0)
-        return;
-
-    fprintf(out, "#index, x, y, z");
-    if (s->sqrtm)
-        fprintf(out, ", sqrt(m)");
-    for (i=0; i<s->nr; i++)
-    {
-        fprintf(out, "\n%6d  %11.6f %11.6f %11.6f",s->anrs[i], s->x[i][XX], s->x[i][YY], s->x[i][ZZ]);
-        if (s->sqrtm)
-            fprintf(out,"%9.3f",s->sqrtm[i]);
-    }
-    fprintf(out, "\n");
-}
-
-
-/* Debug helper */
-static void dump_edi_eigenvecs(FILE *out, t_eigvec *ev,
-                               const char name[], int length)
-{
-    int i,j;
-
-
-    fprintf(out, "#%s eigenvectors:\n%d\n", name, ev->neig);
-    /* Dump the data for every eigenvector: */
-    for (i=0; i<ev->neig; i++)
-    {
-        fprintf(out, "EV %4d\ncomponents %d\nstepsize %f\nxproj %f\nfproj %f\nrefproj %f\nradius %f\nComponents:\n",
-                ev->ieig[i], length, ev->stpsz[i], ev->xproj[i], ev->fproj[i], ev->refproj[i], ev->radius);
-        for (j=0; j<length; j++)
-            fprintf(out, "%11.6f %11.6f %11.6f\n", ev->vec[i][j][XX], ev->vec[i][j][YY], ev->vec[i][j][ZZ]);
-    }
-}
-
-
-/* Debug helper */
-static void dump_edi(t_edpar *edpars, t_commrec *cr, int nr_edi)
-{
-    FILE  *out;
-    char  fn[STRLEN];
-
-
-    sprintf(fn, "EDdump_node%d_edi%d", cr->nodeid, nr_edi);
-    out = ffopen(fn, "w");
-
-    fprintf(out,"#NINI\n %d\n#FITMAS\n %d\n#ANALYSIS_MAS\n %d\n",
-            edpars->nini,edpars->fitmas,edpars->pcamas);
-    fprintf(out,"#OUTFRQ\n %d\n#MAXLEN\n %d\n#SLOPECRIT\n %f\n",
-            edpars->outfrq,edpars->maxedsteps,edpars->slope);
-    fprintf(out,"#PRESTEPS\n %d\n#DELTA_F0\n %f\n#TAU\n %f\n#EFL_NULL\n %f\n#ALPHA2\n %f\n",
-            edpars->presteps,edpars->flood.deltaF0,edpars->flood.tau,
-            edpars->flood.constEfl,edpars->flood.alpha2);
-
-    /* Dump reference, average, target, origin positions */
-    dump_edi_positions(out, &edpars->sref, "REFERENCE");
-    dump_edi_positions(out, &edpars->sav , "AVERAGE"  );
-    dump_edi_positions(out, &edpars->star, "TARGET"   );
-    dump_edi_positions(out, &edpars->sori, "ORIGIN"   );
-
-    /* Dump eigenvectors */
-    dump_edi_eigenvecs(out, &edpars->vecs.mon   , "MONITORED", edpars->sav.nr);
-    dump_edi_eigenvecs(out, &edpars->vecs.linfix, "LINFIX"   , edpars->sav.nr);
-    dump_edi_eigenvecs(out, &edpars->vecs.linacc, "LINACC"   , edpars->sav.nr);
-    dump_edi_eigenvecs(out, &edpars->vecs.radfix, "RADFIX"   , edpars->sav.nr);
-    dump_edi_eigenvecs(out, &edpars->vecs.radacc, "RADACC"   , edpars->sav.nr);
-    dump_edi_eigenvecs(out, &edpars->vecs.radcon, "RADCON"   , edpars->sav.nr);
-
-    /* Dump flooding eigenvectors */
-    dump_edi_eigenvecs(out, &edpars->flood.vecs, "FLOODING"  , edpars->sav.nr);
-
-    /* Dump ed local buffer */
-    fprintf(out, "buf->do_edfit         =%p\n", (void*)edpars->buf->do_edfit  );
-    fprintf(out, "buf->do_edsam         =%p\n", (void*)edpars->buf->do_edsam  );
-    fprintf(out, "buf->do_radcon        =%p\n", (void*)edpars->buf->do_radcon );
-
-    ffclose(out);
-}
-
-
-/* Debug helper */
-static void dump_rotmat(FILE* out,matrix rotmat)
-{
-    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[XX][XX],rotmat[XX][YY],rotmat[XX][ZZ]);
-    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[YY][XX],rotmat[YY][YY],rotmat[YY][ZZ]);
-    fprintf(out,"ROTMAT: %12.8f %12.8f %12.8f\n",rotmat[ZZ][XX],rotmat[ZZ][YY],rotmat[ZZ][ZZ]);
-}
-
-
-/* Debug helper */
-static void dump_rvec(FILE *out, int dim, rvec *x)
-{
-    int i;
-
-
-    for (i=0; i<dim; i++)
-        fprintf(out,"%4d   %f %f %f\n",i,x[i][XX],x[i][YY],x[i][ZZ]);
-}
-
-
-/* Debug helper */
-static void dump_mat(FILE* out, int dim, double** mat)
-{
-    int i,j;
-
-
-    fprintf(out,"MATRIX:\n");
-    for (i=0;i<dim;i++)
-    {
-        for (j=0;j<dim;j++)
-            fprintf(out,"%f ",mat[i][j]);
-        fprintf(out,"\n");
-    }
-}
-#endif
-
-
-struct t_do_edfit {
-    double **omega;
-    double **om;
-};
-
-static void do_edfit(int natoms,rvec *xp,rvec *x,matrix R,t_edpar *edi)
-{
-    /* this is a copy of do_fit with some modifications */
-    int    c,r,n,j,i,irot;
-    double d[6],xnr,xpc;
-    matrix vh,vk,u;
-    int    index;
-    real   max_d;
-
-    struct t_do_edfit *loc;
-    gmx_bool bFirst;
-
-    if(edi->buf->do_edfit != NULL)
-        bFirst = FALSE;
-    else
-    {
-        bFirst = TRUE;
-        snew(edi->buf->do_edfit,1);
-    }
-    loc = edi->buf->do_edfit;
-
-    if (bFirst)
-    {
-        snew(loc->omega,2*DIM);
-        snew(loc->om,2*DIM);
-        for(i=0; i<2*DIM; i++)
-        {
-            snew(loc->omega[i],2*DIM);
-            snew(loc->om[i],2*DIM);
-        }
-    }
-
-    for(i=0;(i<6);i++)
-    {
-        d[i]=0;
-        for(j=0;(j<6);j++)
-        {
-            loc->omega[i][j]=0;
-            loc->om[i][j]=0;
-        }
-    }
-
-    /* calculate the matrix U */
-    clear_mat(u);
-    for(n=0;(n<natoms);n++)
-    {
-        for(c=0; (c<DIM); c++)
-        {
-            xpc=xp[n][c];
-            for(r=0; (r<DIM); r++)
-            {
-                xnr=x[n][r];
-                u[c][r]+=xnr*xpc;
-            }
-        }
-    }
-
-    /* construct loc->omega */
-    /* loc->omega is symmetric -> loc->omega==loc->omega' */
-    for(r=0;(r<6);r++)
-        for(c=0;(c<=r);c++)
-            if ((r>=3) && (c<3))
-            {
-                loc->omega[r][c]=u[r-3][c];
-                loc->omega[c][r]=u[r-3][c];
-            }
-            else
-            {
-                loc->omega[r][c]=0;
-                loc->omega[c][r]=0;
-            }
-
-    /* determine h and k */
-#ifdef DEBUG
-    {
-        int i;
-        dump_mat(stderr,2*DIM,loc->omega);
-        for (i=0; i<6; i++)
-            fprintf(stderr,"d[%d] = %f\n",i,d[i]);
-    }
-#endif
-    jacobi(loc->omega,6,d,loc->om,&irot);
-
-    if (irot==0)
-        fprintf(stderr,"IROT=0\n");
-
-    index=0; /* For the compiler only */
-
-    for(j=0;(j<3);j++)
-    {
-        max_d=-1000;
-        for(i=0;(i<6);i++)
-            if (d[i]>max_d)
-            {
-                max_d=d[i];
-                index=i;
-            }
-        d[index]=-10000;
-        for(i=0;(i<3);i++)
-        {
-            vh[j][i]=M_SQRT2*loc->om[i][index];
-            vk[j][i]=M_SQRT2*loc->om[i+DIM][index];
-        }
-    }
-
-    /* determine R */
-    for(c=0;(c<3);c++)
-        for(r=0;(r<3);r++)
-            R[c][r]=vk[0][r]*vh[0][c]+
-            vk[1][r]*vh[1][c]+
-            vk[2][r]*vh[2][c];
-    if (det(R) < 0)
-        for(c=0;(c<3);c++)
-            for(r=0;(r<3);r++)
-                R[c][r]=vk[0][r]*vh[0][c]+
-                vk[1][r]*vh[1][c]-
-                vk[2][r]*vh[2][c];
-}
-
-
-static void rmfit(int nat, rvec *xcoll, rvec transvec, matrix rotmat)
-{
-    rvec vec;
-    matrix tmat;
-
-
-    /* Remove rotation.
-     * The inverse rotation is described by the transposed rotation matrix */
-    transpose(rotmat,tmat);
-    rotate_x(xcoll, nat, tmat);
-
-    /* Remove translation */
-    vec[XX]=-transvec[XX];
-    vec[YY]=-transvec[YY];
-    vec[ZZ]=-transvec[ZZ];
-    translate_x(xcoll, nat, vec);
-}
-
-
-/**********************************************************************************
- ******************** FLOODING ****************************************************
- **********************************************************************************
-
-The flooding ability was added later to edsam. Many of the edsam functionality could be reused for that purpose.
-The flooding covariance matrix, i.e. the selected eigenvectors and their corresponding eigenvalues are
-read as 7th Component Group. The eigenvalues are coded into the stepsize parameter (as used by -linfix or -linacc).
-
-do_md clls right in the beginning the function init_edsam, which reads the edi file, saves all the necessary information in
-the edi structure and calls init_flood, to initialise some extra fields in the edi->flood structure.
-
-since the flooding acts on forces do_flood is called from the function force() (force.c), while the other
-edsam functionality is hooked into md via the update() (update.c) function acting as constraint on positions.
-
-do_flood makes a copy of the positions,
-fits them, projects them computes flooding_energy, and flooding forces. The forces are computed in the
-space of the eigenvectors and are then blown up to the full cartesian space and rotated back to remove the
-fit. Then do_flood adds these forces to the forcefield-forces
-(given as parameter) and updates the adaptive flooding parameters Efl and deltaF.
-
-To center the flooding potential at a different location one can use the -ori option in make_edi. The ori
-structure is projected to the system of eigenvectors and then this position in the subspace is used as
-center of the flooding potential.   If the option is not used, the center will be zero in the subspace,
-i.e. the average structure as given in the make_edi file.
-
-To use the flooding potential as restraint, make_edi has the option -restrain, which leads to inverted
-signs of alpha2 and Efl, such that the sign in the exponential of Vfl is not inverted but the sign of
-Vfl is inverted. Vfl = Efl * exp (- .../Efl/alpha2*x^2...) With tau>0 the negative Efl will grow slowly
-so that the restraint is switched off slowly. When Efl==0 and inverted flooding is ON is reached no
- further adaption is applied, Efl will stay constant at zero.
-
-To use restraints with harmonic potentials switch -restrain and -harmonic. Then the eigenvalues are
-used as spring constants for the harmonic potential.
-Note that eq3 in the flooding paper (J. Comp. Chem. 2006, 27, 1693-1702) defines the parameter lambda \
-as the inverse of the spring constant, whereas the implementation uses lambda as the spring constant.
-
-To use more than one flooding matrix just concatenate several .edi files (cat flood1.edi flood2.edi > flood_all.edi)
-the routine read_edi_file reads all of theses flooding files.
-The structure t_edi is now organized as a list of t_edis and the function do_flood cycles through the list
-calling the do_single_flood() routine for every single entry. Since every state variables have been kept in one
-edi there is no interdependence whatsoever. The forces are added together.
-
-  To write energies into the .edr file, call the function
-        get_flood_enx_names(char**, int *nnames) to get the Header (Vfl1 Vfl2... Vfln)
-and call
-        get_flood_energies(real Vfl[],int nnames);
-
-  TODO:
-- one could program the whole thing such that Efl, Vfl and deltaF is written to the .edr file. -- i dont know how to do that, yet.
-
-  Maybe one should give a range of atoms for which to remove motion, so that motion is removed with
-  two edsam files from two peptide chains
-*/
-
-static void write_edo_flood(t_edpar *edi, FILE *fp, gmx_large_int_t step)
-{
-    int i;
-    char buf[22];
-    gmx_bool bOutputRef=FALSE;
-
-
-    fprintf(fp,"%d.th FL: %s %12.5e %12.5e %12.5e\n",
-            edi->flood.flood_id, gmx_step_str(step,buf),
-            edi->flood.Efl, edi->flood.Vfl, edi->flood.deltaF);
-
-
-    /* Check whether any of the references changes with time (this can happen
-     * in case flooding is used as harmonic restraint). If so, output all the
-     * current reference projections. */
-    if (edi->flood.bHarmonic)
-    {
-        for (i = 0; i < edi->flood.vecs.neig; i++)
-        {
-            if (edi->flood.vecs.refprojslope[i] != 0.0)
-                bOutputRef=TRUE;
-        }
-        if (bOutputRef)
-        {
-            fprintf(fp, "Ref. projs.: ");
-            for (i = 0; i < edi->flood.vecs.neig; i++)
-            {
-                fprintf(fp, "%12.5e ", edi->flood.vecs.refproj[i]);
-            }
-            fprintf(fp, "\n");
-        }
-    }
-    fprintf(fp,"FL_FORCES: ");
-
-    for (i=0; i<edi->flood.vecs.neig; i++)
-        fprintf(fp," %12.5e",edi->flood.vecs.fproj[i]);
-
-    fprintf(fp,"\n");
-}
-
-
-/* From flood.xproj compute the Vfl(x) at this point */
-static real flood_energy(t_edpar *edi, gmx_large_int_t step)
-{
-    /* compute flooding energy Vfl
-     Vfl = Efl * exp( - \frac {kT} {2Efl alpha^2} * sum_i { \lambda_i c_i^2 } )
-     \lambda_i is the reciprocal eigenvalue 1/\sigma_i
-         it is already computed by make_edi and stored in stpsz[i]
-     bHarmonic:
-       Vfl = - Efl * 1/2(sum _i {\frac 1{\lambda_i} c_i^2})
-     */
-    real sum;
-    real Vfl;
-    int i;
-
-
-    /* Each time this routine is called (i.e. each time step), we add a small
-     * value to the reference projection. This way a harmonic restraint towards
-     * a moving reference is realized. If no value for the additive constant
-     * is provided in the edi file, the reference will not change. */
-    if (edi->flood.bHarmonic)
-    {
-        for (i=0; i<edi->flood.vecs.neig; i++)
-        {
-            edi->flood.vecs.refproj[i] = edi->flood.vecs.refproj0[i] + step * edi->flood.vecs.refprojslope[i];
-        }
-    }
-
-    sum=0.0;
-    /* Compute sum which will be the exponent of the exponential */
-    for (i=0; i<edi->flood.vecs.neig; i++)
-    {
-        /* stpsz stores the reciprocal eigenvalue 1/sigma_i */
-        sum += edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i])*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
-    }
-
-    /* Compute the Gauss function*/
-    if (edi->flood.bHarmonic)
-    {
-        Vfl = -0.5*edi->flood.Efl*sum;  /* minus sign because Efl is negative, if restrain is on. */
-    }
-    else
-    {
-        Vfl = edi->flood.Efl!=0 ? edi->flood.Efl*exp(-edi->flood.kT/2/edi->flood.Efl/edi->flood.alpha2*sum) :0;
-    }
-
-    return Vfl;
-}
-
-
-/* From the position and from Vfl compute forces in subspace -> store in edi->vec.flood.fproj */
-static void flood_forces(t_edpar *edi)
-{
-    /* compute the forces in the subspace of the flooding eigenvectors
-     * by the formula F_i= V_{fl}(c) * ( \frac {kT} {E_{fl}} \lambda_i c_i */
-
-    int i;
-    real energy=edi->flood.Vfl;
-
-
-    if (edi->flood.bHarmonic)
-        for (i=0; i<edi->flood.vecs.neig; i++)
-        {
-            edi->flood.vecs.fproj[i] = edi->flood.Efl* edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]);
-        }
-    else
-        for (i=0; i<edi->flood.vecs.neig; i++)
-        {
-            /* if Efl is zero the forces are zero if not use the formula */
-            edi->flood.vecs.fproj[i] = edi->flood.Efl!=0 ? edi->flood.kT/edi->flood.Efl/edi->flood.alpha2*energy*edi->flood.vecs.stpsz[i]*(edi->flood.vecs.xproj[i]-edi->flood.vecs.refproj[i]) : 0;
-        }
-}
-
-
-/* Raise forces from subspace into cartesian space */
-static void flood_blowup(t_edpar *edi, rvec *forces_cart)
-{
-    /* this function lifts the forces from the subspace to the cartesian space
-     all the values not contained in the subspace are assumed to be zero and then
-     a coordinate transformation from eigenvector to cartesian vectors is performed
-     The nonexistent values don't have to be set to zero explicitly, they would occur
-     as zero valued summands, hence we just stop to compute this part of the sum.
-
-     for every atom we add all the contributions to this atom from all the different eigenvectors.
-
-     NOTE: one could add directly to the forcefield forces, would mean we wouldn't have to clear the
-     field forces_cart prior the computation, but we compute the forces separately
-     to have them accessible for diagnostics
-     */
-    int  j,eig;
-    rvec dum;
-    real *forces_sub;
-
-
-    forces_sub = edi->flood.vecs.fproj;
-
-
-    /* Calculate the cartesian forces for the local atoms */
-
-    /* Clear forces first */
-    for (j=0; j<edi->sav.nr_loc; j++)
-        clear_rvec(forces_cart[j]);
-
-    /* Now compute atomwise */
-    for (j=0; j<edi->sav.nr_loc; j++)
-    {
-        /* Compute forces_cart[edi->sav.anrs[j]] */
-        for (eig=0; eig<edi->flood.vecs.neig; eig++)
-        {
-            /* Force vector is force * eigenvector (compute only atom j) */
-            svmul(forces_sub[eig],edi->flood.vecs.vec[eig][edi->sav.c_ind[j]],dum);
-            /* Add this vector to the cartesian forces */
-            rvec_inc(forces_cart[j],dum);
-        }
-    }
-}
-
-
-/* Update the values of Efl, deltaF depending on tau and Vfl */
-static void update_adaption(t_edpar *edi)
-{
-    /* this function updates the parameter Efl and deltaF according to the rules given in
-     * 'predicting unimolecular chemical reactions: chemical flooding' M Mueller et al,
-     * J. chem Phys. */
-
-    if ((edi->flood.tau < 0 ? -edi->flood.tau : edi->flood.tau ) > 0.00000001)
-    {
-        edi->flood.Efl = edi->flood.Efl+edi->flood.dt/edi->flood.tau*(edi->flood.deltaF0-edi->flood.deltaF);
-        /* check if restrain (inverted flooding) -> don't let EFL become positive */
-        if (edi->flood.alpha2<0 && edi->flood.Efl>-0.00000001)
-            edi->flood.Efl = 0;
-
-        edi->flood.deltaF = (1-edi->flood.dt/edi->flood.tau)*edi->flood.deltaF+edi->flood.dt/edi->flood.tau*edi->flood.Vfl;
-    }
-}
-
-
-static void do_single_flood(
-        FILE *edo,
-        rvec x[],
-        rvec force[],
-        t_edpar *edi,
-        gmx_large_int_t step,
-        matrix box,
-        t_commrec *cr)
-{
-    int i;
-    matrix  rotmat;         /* rotation matrix */
-    matrix  tmat;           /* inverse rotation */
-    rvec    transvec;       /* translation vector */
-    struct t_do_edsam *buf;
-
-
-    buf=edi->buf->do_edsam;
-
-    /* Broadcast the positions of the AVERAGE structure such that they are known on
-     * every processor. Each node contributes its local positions x and stores them in
-     * the collective ED array buf->xcoll */
-    communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, buf->bUpdateShifts, x,
-                    edi->sav.nr, edi->sav.nr_loc, edi->sav.anrs_loc, edi->sav.c_ind, edi->sav.x_old, box);
-
-    /* Only assembly REFERENCE positions if their indices differ from the average ones */
-    if (!edi->bRefEqAv)
-        communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, buf->bUpdateShifts, x,
-                edi->sref.nr, edi->sref.nr_loc, edi->sref.anrs_loc, edi->sref.c_ind, edi->sref.x_old, box);
-
-    /* If bUpdateShifts was TRUE, the shifts have just been updated in get_positions.
-     * We do not need to update the shifts until the next NS step */
-    buf->bUpdateShifts = FALSE;
-
-    /* Now all nodes have all of the ED/flooding positions in edi->sav->xcoll,
-     * as well as the indices in edi->sav.anrs */
-
-    /* Fit the reference indices to the reference structure */
-    if (edi->bRefEqAv)
-        fit_to_reference(buf->xcoll , transvec, rotmat, edi);
-    else
-        fit_to_reference(buf->xc_ref, transvec, rotmat, edi);
-
-    /* Now apply the translation and rotation to the ED structure */
-    translate_and_rotate(buf->xcoll, edi->sav.nr, transvec, rotmat);
-
-    /* Project fitted structure onto supbspace -> store in edi->flood.vecs.xproj */
-    project_to_eigvectors(buf->xcoll,&edi->flood.vecs,edi);
-
-    if (FALSE == edi->flood.bConstForce)
-    {
-        /* Compute Vfl(x) from flood.xproj */
-        edi->flood.Vfl = flood_energy(edi, step);
-
-        update_adaption(edi);
-
-        /* Compute the flooding forces */
-        flood_forces(edi);
-    }
-
-    /* Translate them into cartesian positions */
-    flood_blowup(edi, edi->flood.forces_cartesian);
-
-    /* Rotate forces back so that they correspond to the given structure and not to the fitted one */
-    /* Each node rotates back its local forces */
-    transpose(rotmat,tmat);
-    rotate_x(edi->flood.forces_cartesian, edi->sav.nr_loc, tmat);
-
-    /* Finally add forces to the main force variable */
-    for (i=0; i<edi->sav.nr_loc; i++)
-        rvec_inc(force[edi->sav.anrs_loc[i]],edi->flood.forces_cartesian[i]);
-
-    /* Output is written by the master process */
-    if (do_per_step(step,edi->outfrq) && MASTER(cr))
-        write_edo_flood(edi,edo,step);
-}
-
-
-/* Main flooding routine, called from do_force */
-extern void do_flood(
-        FILE            *log,    /* md.log file */
-        t_commrec       *cr,     /* Communication record */
-        rvec            x[],     /* Positions on the local processor */
-        rvec            force[], /* forcefield forces, to these the flooding forces are added */
-        gmx_edsam_t     ed,      /* ed data structure contains all ED and flooding datasets */
-        matrix          box,     /* the box */
-        gmx_large_int_t step)    /* The relative time step since ir->init_step is already subtracted */
-{
-    t_edpar *edi;
-
-
-    if (ed->eEDtype != eEDflood)
-        return;
-
-    edi = ed->edpar;
-    while (edi)
-    {
-        /* Call flooding for one matrix */
-        if (edi->flood.vecs.neig)
-            do_single_flood(ed->edo,x,force,edi,step,box,cr);
-        edi = edi->next_edi;
-    }
-}
-
-
-/* Called by init_edi, configure some flooding related variables and structures,
- * print headers to output files */
-static void init_flood(t_edpar *edi, gmx_edsam_t ed, real dt, t_commrec *cr)
-{
-    int i;
-
-
-    edi->flood.Efl = edi->flood.constEfl;
-    edi->flood.Vfl = 0;
-    edi->flood.dt  = dt;
-
-    if (edi->flood.vecs.neig)
-    {
-        /* If in any of the datasets we find a flooding vector, flooding is turned on */
-        ed->eEDtype = eEDflood;
-
-        fprintf(stderr,"ED: Flooding of matrix %d is switched on.\n", edi->flood.flood_id);
-
-        if (edi->flood.bConstForce)
-        {
-            /* We have used stpsz as a vehicle to carry the fproj values for constant
-             * force flooding. Now we copy that to flood.vecs.fproj. Note that
-             * in const force flooding, fproj is never changed. */
-            for (i=0; i<edi->flood.vecs.neig; i++)
-            {
-                edi->flood.vecs.fproj[i] = edi->flood.vecs.stpsz[i];
-
-                fprintf(stderr, "ED: applying on eigenvector %d a constant force of %g\n",
-                        edi->flood.vecs.ieig[i], edi->flood.vecs.fproj[i]);
-            }
-        }
-        fprintf(ed->edo,"FL_HEADER: Flooding of matrix %d is switched on! The flooding output will have the following format:\n",
-                edi->flood.flood_id);
-        fprintf(ed->edo,"FL_HEADER: Step     Efl          Vfl       deltaF\n");
-    }
-}
-
-
-#ifdef DEBUGHELPERS
-/*********** Energy book keeping ******/
-static void get_flood_enx_names(t_edpar *edi, char** names, int *nnames)  /* get header of energies */
-{
-    t_edpar *actual;
-    int count;
-    char buf[STRLEN];
-    actual=edi;
-    count = 1;
-    while (actual)
-    {
-        srenew(names,count);
-        sprintf(buf,"Vfl_%d",count);
-        names[count-1]=strdup(buf);
-        actual=actual->next_edi;
-        count++;
-    }
-    *nnames=count-1;
-}
-
-
-static void get_flood_energies(t_edpar *edi, real Vfl[],int nnames)
-{
-    /*fl has to be big enough to capture nnames-many entries*/
-    t_edpar *actual;
-    int count;
-
-
-    actual=edi;
-    count = 1;
-    while (actual)
-    {
-        Vfl[count-1]=actual->flood.Vfl;
-        actual=actual->next_edi;
-        count++;
-    }
-    if (nnames!=count-1)
-        gmx_fatal(FARGS,"Number of energies is not consistent with t_edi structure");
-}
-/************* END of FLOODING IMPLEMENTATION ****************************/
-#endif
-
-
-gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr)
-{
-    gmx_edsam_t ed;
-
-
-    /* Allocate space for the ED data structure */
-    snew(ed, 1);
-
-    /* We want to perform ED (this switch might later be upgraded to eEDflood) */
-    ed->eEDtype = eEDedsam;
-
-    if (MASTER(cr))
-    {
-        /* Open .edi input file: */
-        ed->edinam=ftp2fn(efEDI,nfile,fnm);
-        /* The master opens the .edo output file */
-        fprintf(stderr,"ED sampling will be performed!\n");
-        ed->edonam = ftp2fn(efEDO,nfile,fnm);
-        ed->edo    = gmx_fio_fopen(ed->edonam,(Flags & MD_APPENDFILES)? "a+" : "w+");
-        ed->bStartFromCpt = Flags & MD_STARTFROMCPT;
-    }
-    return ed;
-}
-
-
-/* Broadcasts the structure data */
-static void bc_ed_positions(t_commrec *cr, struct gmx_edx *s, int stype)
-{
-    snew_bc(cr, s->anrs, s->nr   );    /* Index numbers     */
-    snew_bc(cr, s->x   , s->nr   );    /* Positions         */
-    nblock_bc(cr, s->nr, s->anrs );
-    nblock_bc(cr, s->nr, s->x    );
-
-    /* For the average & reference structures we need an array for the collective indices,
-     * and we need to broadcast the masses as well */
-    if (stype == eedAV || stype == eedREF)
-    {
-        /* We need these additional variables in the parallel case: */
-        snew(s->c_ind    , s->nr   );   /* Collective indices */
-        /* Local atom indices get assigned in dd_make_local_group_indices.
-         * There, also memory is allocated */
-        s->nalloc_loc = 0;              /* allocation size of s->anrs_loc */
-        snew_bc(cr, s->x_old, s->nr);   /* To be able to always make the ED molecule whole, ...        */
-        nblock_bc(cr, s->nr, s->x_old); /* ... keep track of shift changes with the help of old coords */
-    }
-
-    /* broadcast masses for the reference structure (for mass-weighted fitting) */
-    if (stype == eedREF)
-    {
-        snew_bc(cr, s->m, s->nr);
-        nblock_bc(cr, s->nr, s->m);
-    }
-
-    /* For the average structure we might need the masses for mass-weighting */
-    if (stype == eedAV)
-    {
-        snew_bc(cr, s->sqrtm, s->nr);
-        nblock_bc(cr, s->nr, s->sqrtm);
-        snew_bc(cr, s->m, s->nr);
-        nblock_bc(cr, s->nr, s->m);
-    }
-}
-
-
-/* Broadcasts the eigenvector data */
-static void bc_ed_vecs(t_commrec *cr, t_eigvec *ev, int length, gmx_bool bHarmonic)
-{
-    int i;
-
-    snew_bc(cr, ev->ieig   , ev->neig);  /* index numbers of eigenvector  */
-    snew_bc(cr, ev->stpsz  , ev->neig);  /* stepsizes per eigenvector     */
-    snew_bc(cr, ev->xproj  , ev->neig);  /* instantaneous x projection    */
-    snew_bc(cr, ev->fproj  , ev->neig);  /* instantaneous f projection    */
-    snew_bc(cr, ev->refproj, ev->neig);  /* starting or target projection */
-
-    nblock_bc(cr, ev->neig, ev->ieig   );
-    nblock_bc(cr, ev->neig, ev->stpsz  );
-    nblock_bc(cr, ev->neig, ev->xproj  );
-    nblock_bc(cr, ev->neig, ev->fproj  );
-    nblock_bc(cr, ev->neig, ev->refproj);
-
-    snew_bc(cr, ev->vec, ev->neig);      /* Eigenvector components        */
-    for (i=0; i<ev->neig; i++)
-    {
-        snew_bc(cr, ev->vec[i], length);
-        nblock_bc(cr, length, ev->vec[i]);
-    }
-
-    /* For harmonic restraints the reference projections can change with time */
-    if (bHarmonic)
-    {
-        snew_bc(cr, ev->refproj0    , ev->neig);
-        snew_bc(cr, ev->refprojslope, ev->neig);
-        nblock_bc(cr, ev->neig, ev->refproj0    );
-        nblock_bc(cr, ev->neig, ev->refprojslope);
-    }
-}
-
-
-/* Broadcasts the ED / flooding data to other nodes
- * and allocates memory where needed */
-static void broadcast_ed_data(t_commrec *cr, gmx_edsam_t ed, int numedis)
-{
-    int     nr;
-    t_edpar *edi;
-
-
-    /* Master lets the other nodes know if its ED only or also flooding */
-    gmx_bcast(sizeof(ed->eEDtype), &(ed->eEDtype), cr);
-
-    snew_bc(cr, ed->edpar,1);
-    /* Now transfer the ED data set(s) */
-    edi = ed->edpar;
-    for (nr=0; nr<numedis; nr++)
-    {
-        /* Broadcast a single ED data set */
-        block_bc(cr, *edi);
-
-        /* Broadcast positions */
-        bc_ed_positions(cr, &(edi->sref), eedREF); /* reference positions (don't broadcast masses)    */
-        bc_ed_positions(cr, &(edi->sav ), eedAV ); /* average positions (do broadcast masses as well) */
-        bc_ed_positions(cr, &(edi->star), eedTAR); /* target positions                                */
-        bc_ed_positions(cr, &(edi->sori), eedORI); /* origin positions                                */
-
-        /* Broadcast eigenvectors */
-        bc_ed_vecs(cr, &edi->vecs.mon   , edi->sav.nr, FALSE);
-        bc_ed_vecs(cr, &edi->vecs.linfix, edi->sav.nr, FALSE);
-        bc_ed_vecs(cr, &edi->vecs.linacc, edi->sav.nr, FALSE);
-        bc_ed_vecs(cr, &edi->vecs.radfix, edi->sav.nr, FALSE);
-        bc_ed_vecs(cr, &edi->vecs.radacc, edi->sav.nr, FALSE);
-        bc_ed_vecs(cr, &edi->vecs.radcon, edi->sav.nr, FALSE);
-        /* Broadcast flooding eigenvectors and, if needed, values for the moving reference */
-        bc_ed_vecs(cr, &edi->flood.vecs,  edi->sav.nr, edi->flood.bHarmonic);
-
-        /* Set the pointer to the next ED dataset */
-        if (edi->next_edi)
-        {
-          snew_bc(cr, edi->next_edi, 1);
-          edi = edi->next_edi;
-        }
-    }
-}
-
-
-/* init-routine called for every *.edi-cycle, initialises t_edpar structure */
-static void init_edi(gmx_mtop_t *mtop,t_inputrec *ir,
-                     t_commrec *cr,gmx_edsam_t ed,t_edpar *edi)
-{
-    int  i;
-    real totalmass = 0.0;
-    rvec com;
-    t_atom *atom;
-
-    /* NOTE Init_edi is executed on the master process only
-     * The initialized data sets are then transmitted to the
-     * other nodes in broadcast_ed_data */
-
-    edi->bNeedDoEdsam = edi->vecs.mon.neig
-                     || edi->vecs.linfix.neig
-                     || edi->vecs.linacc.neig
-                     || edi->vecs.radfix.neig
-                     || edi->vecs.radacc.neig
-                     || edi->vecs.radcon.neig;
-
-    /* evaluate masses (reference structure) */
-    snew(edi->sref.m, edi->sref.nr);
-    for (i = 0; i < edi->sref.nr; i++)
-    {
-        if (edi->fitmas)
-        {
-            gmx_mtop_atomnr_to_atom(mtop,edi->sref.anrs[i],&atom);
-            edi->sref.m[i] = atom->m;
-        }
-        else
-        {
-            edi->sref.m[i] = 1.0;
-        }
-
-        /* Check that every m > 0. Bad things will happen otherwise. */
-        if (edi->sref.m[i] <= 0.0)
-        {
-            gmx_fatal(FARGS, "Reference structure atom %d (sam.edi index %d) has a mass of %g.\n"
-                             "For a mass-weighted fit, all reference structure atoms need to have a mass >0.\n"
-                             "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
-                             "atoms from the reference structure by creating a proper index group.\n",
-                      i, edi->sref.anrs[i]+1, edi->sref.m[i]);
-        }
-
-        totalmass += edi->sref.m[i];
-    }
-    edi->sref.mtot = totalmass;
-
-    /* Masses m and sqrt(m) for the average structure. Note that m
-     * is needed if forces have to be evaluated in do_edsam */
-    snew(edi->sav.sqrtm, edi->sav.nr );
-    snew(edi->sav.m    , edi->sav.nr );
-    for (i = 0; i < edi->sav.nr; i++)
-    {
-        gmx_mtop_atomnr_to_atom(mtop,edi->sav.anrs[i],&atom);
-        edi->sav.m[i] = atom->m;
-        if (edi->pcamas)
-        {
-            edi->sav.sqrtm[i] = sqrt(atom->m);
-        }
-        else
-        {
-            edi->sav.sqrtm[i] = 1.0;
-        }
-
-        /* Check that every m > 0. Bad things will happen otherwise. */
-        if (edi->sav.sqrtm[i] <= 0.0)
-        {
-            gmx_fatal(FARGS, "Average structure atom %d (sam.edi index %d) has a mass of %g.\n"
-                             "For ED with mass-weighting, all average structure atoms need to have a mass >0.\n"
-                             "Either make the covariance analysis non-mass-weighted, or exclude massless\n"
-                             "atoms from the average structure by creating a proper index group.\n",
-                      i, edi->sav.anrs[i]+1, atom->m);
-        }
-    }
-
-    /* put reference structure in origin */
-    get_center(edi->sref.x, edi->sref.m, edi->sref.nr, com);
-    com[XX] = -com[XX];
-    com[YY] = -com[YY];
-    com[ZZ] = -com[ZZ];
-    translate_x(edi->sref.x, edi->sref.nr, com);
-
-    /* Init ED buffer */
-    snew(edi->buf, 1);
-}
-
-
-static void check(const char *line, const char *label)
-{
-    if (!strstr(line,label))
-        gmx_fatal(FARGS,"Could not find input parameter %s at expected position in edsam input-file (.edi)\nline read instead is %s",label,line);
-}
-
-
-static int read_checked_edint(FILE *file,const char *label)
-{
-    char line[STRLEN+1];
-    int idum;
-
-
-    fgets2 (line,STRLEN,file);
-    check(line,label);
-    fgets2 (line,STRLEN,file);
-    sscanf (line,"%d",&idum);
-    return idum;
-}
-
-
-static int read_edint(FILE *file,gmx_bool *bEOF)
-{
-    char line[STRLEN+1];
-    int idum;
-    char *eof;
-
-
-    eof=fgets2 (line,STRLEN,file);
-    if (eof==NULL)
-    {
-        *bEOF = TRUE;
-        return -1;
-    }
-    eof=fgets2 (line,STRLEN,file);
-    if (eof==NULL)
-    {
-        *bEOF = TRUE;
-        return -1;
-    }
-    sscanf (line,"%d",&idum);
-    *bEOF = FALSE;
-    return idum;
-}
-
-
-static real read_checked_edreal(FILE *file,const char *label)
-{
-    char line[STRLEN+1];
-    double rdum;
-
-
-    fgets2 (line,STRLEN,file);
-    check(line,label);
-    fgets2 (line,STRLEN,file);
-    sscanf (line,"%lf",&rdum);
-    return (real) rdum; /* always read as double and convert to single */
-}
-
-
-static void read_edx(FILE *file,int number,int *anrs,rvec *x)
-{
-    int i,j;
-    char line[STRLEN+1];
-    double d[3];
-
-
-    for(i=0; i<number; i++)
-    {
-        fgets2 (line,STRLEN,file);
-        sscanf (line,"%d%lf%lf%lf",&anrs[i],&d[0],&d[1],&d[2]);
-        anrs[i]--; /* we are reading FORTRAN indices */
-        for(j=0; j<3; j++)
-            x[i][j]=d[j]; /* always read as double and convert to single */
-    }
-}
-
-
-static void scan_edvec(FILE *in,int nr,rvec *vec)
-{
-    char line[STRLEN+1];
-    int i;
-    double x,y,z;
-
-
-    for(i=0; (i < nr); i++)
-    {
-        fgets2 (line,STRLEN,in);
-        sscanf (line,"%le%le%le",&x,&y,&z);
-        vec[i][XX]=x;
-        vec[i][YY]=y;
-        vec[i][ZZ]=z;
-    }
-}
-
-
-static void read_edvec(FILE *in,int nr,t_eigvec *tvec,gmx_bool bReadRefproj, gmx_bool *bHaveReference)
-{
-    int i,idum,nscan;
-    double rdum,refproj_dum=0.0,refprojslope_dum=0.0;
-    char line[STRLEN+1];
-
-
-    tvec->neig=read_checked_edint(in,"NUMBER OF EIGENVECTORS");
-    if (tvec->neig >0)
-    {
-        snew(tvec->ieig   ,tvec->neig);
-        snew(tvec->stpsz  ,tvec->neig);
-        snew(tvec->vec    ,tvec->neig);
-        snew(tvec->xproj  ,tvec->neig);
-        snew(tvec->fproj  ,tvec->neig);
-        snew(tvec->refproj,tvec->neig);
-        if (bReadRefproj)
-        {
-            snew(tvec->refproj0    ,tvec->neig);
-            snew(tvec->refprojslope,tvec->neig);
-        }
-
-        for(i=0; (i < tvec->neig); i++)
-        {
-            fgets2 (line,STRLEN,in);
-            if (bReadRefproj) /* ONLY when using flooding as harmonic restraint */
-            {
-                nscan = sscanf(line,"%d%lf%lf%lf",&idum,&rdum,&refproj_dum,&refprojslope_dum);
-                /* Zero out values which were not scanned */
-                switch(nscan)
-                {
-                    case 4:
-                        /* Every 4 values read, including reference position */
-                        *bHaveReference = TRUE;
-                        break;
-                    case 3:
-                        /* A reference position is provided */
-                        *bHaveReference = TRUE;
-                        /* No value for slope, set to 0 */
-                        refprojslope_dum = 0.0;
-                        break;
-                    case 2:
-                        /* No values for reference projection and slope, set to 0 */
-                        refproj_dum      = 0.0;
-                        refprojslope_dum = 0.0;
-                        break;
-                    default:
-                        gmx_fatal(FARGS,"Expected 2 - 4 (not %d) values for flooding vec: <nr> <spring const> <refproj> <refproj-slope>\n", nscan);
-                        break;
-                }
-                tvec->refproj[i]=refproj_dum;
-                tvec->refproj0[i]=refproj_dum;
-                tvec->refprojslope[i]=refprojslope_dum;
-            }
-            else /* Normal flooding */
-            {
-                nscan = sscanf(line,"%d%lf",&idum,&rdum);
-                if (nscan != 2)
-                    gmx_fatal(FARGS,"Expected 2 values for flooding vec: <nr> <stpsz>\n");
-            }
-            tvec->ieig[i]=idum;
-            tvec->stpsz[i]=rdum;
-        } /* end of loop over eigenvectors */
-
-        for(i=0; (i < tvec->neig); i++)
-        {
-            snew(tvec->vec[i],nr);
-            scan_edvec(in,nr,tvec->vec[i]);
-        }
-    }
-}
-
-
-/* calls read_edvec for the vector groups, only for flooding there is an extra call */
-static void read_edvecs(FILE *in,int nr,t_edvecs *vecs)
-{
-       gmx_bool bHaveReference = FALSE;
-
-
-    read_edvec(in, nr, &vecs->mon   , FALSE, &bHaveReference);
-    read_edvec(in, nr, &vecs->linfix, FALSE, &bHaveReference);
-    read_edvec(in, nr, &vecs->linacc, FALSE, &bHaveReference);
-    read_edvec(in, nr, &vecs->radfix, FALSE, &bHaveReference);
-    read_edvec(in, nr, &vecs->radacc, FALSE, &bHaveReference);
-    read_edvec(in, nr, &vecs->radcon, FALSE, &bHaveReference);
-}
-
-
-/* Check if the same atom indices are used for reference and average positions */
-static gmx_bool check_if_same(struct gmx_edx sref, struct gmx_edx sav)
-{
-    int i;
-
-
-    /* If the number of atoms differs between the two structures,
-     * they cannot be identical */
-    if (sref.nr != sav.nr)
-        return FALSE;
-
-    /* Now that we know that both stuctures have the same number of atoms,
-     * check if also the indices are identical */
-    for (i=0; i < sav.nr; i++)
-    {
-        if (sref.anrs[i] != sav.anrs[i])
-            return FALSE;
-    }
-    fprintf(stderr, "ED: Note: Reference and average structure are composed of the same atom indices.\n");
-
-    return TRUE;
-}
-
-
-static int read_edi(FILE* in, gmx_edsam_t ed,t_edpar *edi,int nr_mdatoms, int edi_nr, t_commrec *cr)
-{
-    int readmagic;
-    const int magic=670;
-    gmx_bool bEOF;
-
-    /* Was a specific reference point for the flooding/umbrella potential provided in the edi file? */
-    gmx_bool bHaveReference = FALSE;
-
-
-    /* the edi file is not free format, so expect problems if the input is corrupt. */
-
-    /* check the magic number */
-    readmagic=read_edint(in,&bEOF);
-    /* Check whether we have reached the end of the input file */
-    if (bEOF)
-        return 0;
-
-    if (readmagic != magic)
-    {
-        if (readmagic==666 || readmagic==667 || readmagic==668)
-            gmx_fatal(FARGS,"Wrong magic number: Use newest version of make_edi to produce edi file");
-        else if (readmagic != 669)
-            gmx_fatal(FARGS,"Wrong magic number %d in %s",readmagic,ed->edinam);
-    }
-
-    /* check the number of atoms */
-    edi->nini=read_edint(in,&bEOF);
-    if (edi->nini != nr_mdatoms)
-        gmx_fatal(FARGS,"Nr of atoms in %s (%d) does not match nr of md atoms (%d)",
-                ed->edinam,edi->nini,nr_mdatoms);
-
-    /* Done checking. For the rest we blindly trust the input */
-    edi->fitmas          = read_checked_edint(in,"FITMAS");
-    edi->pcamas          = read_checked_edint(in,"ANALYSIS_MAS");
-    edi->outfrq          = read_checked_edint(in,"OUTFRQ");
-    edi->maxedsteps      = read_checked_edint(in,"MAXLEN");
-    edi->slope           = read_checked_edreal(in,"SLOPECRIT");
-
-    edi->presteps        = read_checked_edint(in,"PRESTEPS");
-    edi->flood.deltaF0   = read_checked_edreal(in,"DELTA_F0");
-    edi->flood.deltaF    = read_checked_edreal(in,"INIT_DELTA_F");
-    edi->flood.tau       = read_checked_edreal(in,"TAU");
-    edi->flood.constEfl  = read_checked_edreal(in,"EFL_NULL");
-    edi->flood.alpha2    = read_checked_edreal(in,"ALPHA2");
-    edi->flood.kT        = read_checked_edreal(in,"KT");
-    edi->flood.bHarmonic = read_checked_edint(in,"HARMONIC");
-    if (readmagic > 669)
-        edi->flood.bConstForce = read_checked_edint(in,"CONST_FORCE_FLOODING");
-    else
-        edi->flood.bConstForce = FALSE;
-    edi->flood.flood_id  = edi_nr;
-    edi->sref.nr         = read_checked_edint(in,"NREF");
-
-    /* allocate space for reference positions and read them */
-    snew(edi->sref.anrs,edi->sref.nr);
-    snew(edi->sref.x   ,edi->sref.nr);
-    if (PAR(cr))
-        snew(edi->sref.x_old,edi->sref.nr);
-    edi->sref.sqrtm    =NULL;
-    read_edx(in,edi->sref.nr,edi->sref.anrs,edi->sref.x);
-
-    /* average positions. they define which atoms will be used for ED sampling */
-    edi->sav.nr=read_checked_edint(in,"NAV");
-    snew(edi->sav.anrs,edi->sav.nr);
-    snew(edi->sav.x   ,edi->sav.nr);
-    if (PAR(cr))
-        snew(edi->sav.x_old,edi->sav.nr);
-    read_edx(in,edi->sav.nr,edi->sav.anrs,edi->sav.x);
-
-    /* Check if the same atom indices are used for reference and average positions */
-    edi->bRefEqAv = check_if_same(edi->sref, edi->sav);
-
-    /* eigenvectors */
-    read_edvecs(in,edi->sav.nr,&edi->vecs);
-    read_edvec(in,edi->sav.nr,&edi->flood.vecs,edi->flood.bHarmonic, &bHaveReference);
-
-    /* target positions */
-    edi->star.nr=read_edint(in,&bEOF);
-    if (edi->star.nr > 0)
-    {
-        snew(edi->star.anrs,edi->star.nr);
-        snew(edi->star.x   ,edi->star.nr);
-        edi->star.sqrtm    =NULL;
-        read_edx(in,edi->star.nr,edi->star.anrs,edi->star.x);
-    }
-
-    /* positions defining origin of expansion circle */
-    edi->sori.nr=read_edint(in,&bEOF);
-    if (edi->sori.nr > 0)
-    {
-       if (bHaveReference)
-       {
-               /* Both an -ori structure and a at least one manual reference point have been
-                * specified. That's ambiguous and probably not intentional. */
-               gmx_fatal(FARGS, "ED: An origin structure has been provided and a at least one (moving) reference\n"
-                                "    point was manually specified in the edi file. That is ambiguous. Aborting.\n");
-       }
-        snew(edi->sori.anrs,edi->sori.nr);
-        snew(edi->sori.x   ,edi->sori.nr);
-        edi->sori.sqrtm    =NULL;
-        read_edx(in,edi->sori.nr,edi->sori.anrs,edi->sori.x);
-    }
-
-    /* all done */
-    return 1;
-}
-
-
-
-/* Read in the edi input file. Note that it may contain several ED data sets which were
- * achieved by concatenating multiple edi files. The standard case would be a single ED
- * data set, though. */
-static void read_edi_file(gmx_edsam_t ed, t_edpar *edi, int nr_mdatoms, t_commrec *cr)
-{
-    FILE    *in;
-    t_edpar *curr_edi,*last_edi;
-    t_edpar *edi_read;
-    int     edi_nr = 0;
-
-
-    /* This routine is executed on the master only */
-
-    /* Open the .edi parameter input file */
-    in = gmx_fio_fopen(ed->edinam,"r");
-    fprintf(stderr, "ED: Reading edi file %s\n", ed->edinam);
-
-    /* Now read a sequence of ED input parameter sets from the edi file */
-    curr_edi=edi;
-    last_edi=edi;
-    while( read_edi(in, ed, curr_edi, nr_mdatoms, edi_nr, cr) )
-    {
-        edi_nr++;
-        /* Make shure that the number of atoms in each dataset is the same as in the tpr file */
-        if (edi->nini != nr_mdatoms)
-            gmx_fatal(FARGS,"edi file %s (dataset #%d) was made for %d atoms, but the simulation contains %d atoms.",
-                    ed->edinam, edi_nr, edi->nini, nr_mdatoms);
-        /* Since we arrived within this while loop we know that there is still another data set to be read in */
-        /* We need to allocate space for the data: */
-        snew(edi_read,1);
-        /* Point the 'next_edi' entry to the next edi: */
-        curr_edi->next_edi=edi_read;
-        /* Keep the curr_edi pointer for the case that the next dataset is empty: */
-        last_edi = curr_edi;
-        /* Let's prepare to read in the next edi data set: */
-        curr_edi = edi_read;
-    }
-    if (edi_nr == 0)
-        gmx_fatal(FARGS, "No complete ED data set found in edi file %s.", ed->edinam);
-
-    /* Terminate the edi dataset list with a NULL pointer: */
-    last_edi->next_edi = NULL;
-
-    fprintf(stderr, "ED: Found %d ED dataset%s.\n", edi_nr, edi_nr>1? "s" : "");
-
-    /* Close the .edi file again */
-    gmx_fio_fclose(in);
-}
-
-
-struct t_fit_to_ref {
-    rvec *xcopy;       /* Working copy of the positions in fit_to_reference */
-};
-
-/* Fit the current positions to the reference positions
- * Do not actually do the fit, just return rotation and translation.
- * Note that the COM of the reference structure was already put into
- * the origin by init_edi. */
-static void fit_to_reference(rvec      *xcoll,    /* The positions to be fitted */
-                             rvec      transvec,  /* The translation vector */
-                             matrix    rotmat,    /* The rotation matrix */
-                             t_edpar   *edi)      /* Just needed for do_edfit */
-{
-    rvec com;          /* center of mass */
-    int  i;
-    struct t_fit_to_ref *loc;
-
-
-    GMX_MPE_LOG(ev_fit_to_reference_start);
-
-    /* Allocate memory the first time this routine is called for each edi dataset */
-    if (NULL == edi->buf->fit_to_ref)
-    {
-        snew(edi->buf->fit_to_ref, 1);
-        snew(edi->buf->fit_to_ref->xcopy, edi->sref.nr);
-    }
-    loc = edi->buf->fit_to_ref;
-
-    /* We do not touch the original positions but work on a copy. */
-    for (i=0; i<edi->sref.nr; i++)
-        copy_rvec(xcoll[i], loc->xcopy[i]);
-
-    /* Calculate the center of mass */
-    get_center(loc->xcopy, edi->sref.m, edi->sref.nr, com);
-
-    transvec[XX] = -com[XX];
-    transvec[YY] = -com[YY];
-    transvec[ZZ] = -com[ZZ];
-
-    /* Subtract the center of mass from the copy */
-    translate_x(loc->xcopy, edi->sref.nr, transvec);
-
-    /* Determine the rotation matrix */
-    do_edfit(edi->sref.nr, edi->sref.x, loc->xcopy, rotmat, edi);
-
-    GMX_MPE_LOG(ev_fit_to_reference_finish);
-}
-
-
-static void translate_and_rotate(rvec *x,         /* The positions to be translated and rotated */
-                                 int nat,         /* How many positions are there? */
-                                 rvec transvec,   /* The translation vector */
-                                 matrix rotmat)   /* The rotation matrix */
-{
-    /* Translation */
-    translate_x(x, nat, transvec);
-
-    /* Rotation */
-    rotate_x(x, nat, rotmat);
-}
-
-
-/* Gets the rms deviation of the positions to the structure s */
-/* fit_to_structure has to be called before calling this routine! */
-static real rmsd_from_structure(rvec           *x,  /* The positions under consideration */
-                                struct gmx_edx *s)  /* The structure from which the rmsd shall be computed */
-{
-    real  rmsd=0.0;
-    int   i;
-
-
-    for (i=0; i < s->nr; i++)
-        rmsd += distance2(s->x[i], x[i]);
-
-    rmsd /= (real) s->nr;
-    rmsd = sqrt(rmsd);
-
-    return rmsd;
-}
-
-
-void dd_make_local_ed_indices(gmx_domdec_t *dd, struct gmx_edsam *ed)
-{
-    t_edpar *edi;
-
-
-    if (ed->eEDtype != eEDnone)
-    {
-        /* Loop over ED datasets (usually there is just one dataset, though) */
-        edi=ed->edpar;
-        while (edi)
-        {
-            /* Local atoms of the reference structure (for fitting), need only be assembled
-             * if their indices differ from the average ones */
-            if (!edi->bRefEqAv)
-                dd_make_local_group_indices(dd->ga2la, edi->sref.nr, edi->sref.anrs,
-                        &edi->sref.nr_loc, &edi->sref.anrs_loc, &edi->sref.nalloc_loc, edi->sref.c_ind);
-
-            /* Local atoms of the average structure (on these ED will be performed) */
-            dd_make_local_group_indices(dd->ga2la, edi->sav.nr, edi->sav.anrs,
-                    &edi->sav.nr_loc, &edi->sav.anrs_loc, &edi->sav.nalloc_loc, edi->sav.c_ind);
-
-            /* Indicate that the ED shift vectors for this structure need to be updated
-             * at the next call to communicate_group_positions, since obviously we are in a NS step */
-            edi->buf->do_edsam->bUpdateShifts = TRUE;
-
-            /* Set the pointer to the next ED dataset (if any) */
-            edi=edi->next_edi;
-        }
-    }
-}
-
-
-static inline void ed_unshift_single_coord(matrix box, const rvec x, const ivec is, rvec xu)
-{
-    int tx,ty,tz;
-
-
-    GMX_MPE_LOG(ev_unshift_start);
-
-    tx=is[XX];
-    ty=is[YY];
-    tz=is[ZZ];
-
-    if(TRICLINIC(box))
-    {
-        xu[XX] = x[XX]-tx*box[XX][XX]-ty*box[YY][XX]-tz*box[ZZ][XX];
-        xu[YY] = x[YY]-ty*box[YY][YY]-tz*box[ZZ][YY];
-        xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
-    } else
-    {
-        xu[XX] = x[XX]-tx*box[XX][XX];
-        xu[YY] = x[YY]-ty*box[YY][YY];
-        xu[ZZ] = x[ZZ]-tz*box[ZZ][ZZ];
-    }
-
-    GMX_MPE_LOG(ev_unshift_finish);
-}
-
-
-static void do_linfix(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
-{
-    int  i, j;
-    real proj, add;
-    rvec vec_dum;
-
-
-    /* loop over linfix vectors */
-    for (i=0; i<edi->vecs.linfix.neig; i++)
-    {
-        /* calculate the projection */
-        proj = projectx(edi, xcoll, edi->vecs.linfix.vec[i]);
-
-        /* calculate the correction */
-        add = edi->vecs.linfix.refproj[i] + step*edi->vecs.linfix.stpsz[i] - proj;
-
-        /* apply the correction */
-        add /= edi->sav.sqrtm[i];
-        for (j=0; j<edi->sav.nr; j++)
-        {
-            svmul(add, edi->vecs.linfix.vec[i][j], vec_dum);
-            rvec_inc(xcoll[j], vec_dum);
-        }
-    }
-}
-
-
-static void do_linacc(rvec *xcoll, t_edpar *edi, t_commrec *cr)
-{
-    int  i, j;
-    real proj, add;
-    rvec vec_dum;
-
-
-    /* loop over linacc vectors */
-    for (i=0; i<edi->vecs.linacc.neig; i++)
-    {
-        /* calculate the projection */
-        proj=projectx(edi, xcoll, edi->vecs.linacc.vec[i]);
-
-        /* calculate the correction */
-        add = 0.0;
-        if (edi->vecs.linacc.stpsz[i] > 0.0)
-        {
-            if ((proj-edi->vecs.linacc.refproj[i]) < 0.0)
-                add = edi->vecs.linacc.refproj[i] - proj;
-        }
-        if (edi->vecs.linacc.stpsz[i] < 0.0)
-        {
-            if ((proj-edi->vecs.linacc.refproj[i]) > 0.0)
-                add = edi->vecs.linacc.refproj[i] - proj;
-        }
-
-        /* apply the correction */
-        add /= edi->sav.sqrtm[i];
-        for (j=0; j<edi->sav.nr; j++)
-        {
-            svmul(add, edi->vecs.linacc.vec[i][j], vec_dum);
-            rvec_inc(xcoll[j], vec_dum);
-        }
-
-        /* new positions will act as reference */
-        edi->vecs.linacc.refproj[i] = proj + add;
-    }
-}
-
-
-static void do_radfix(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
-{
-    int  i,j;
-    real *proj, rad=0.0, ratio;
-    rvec vec_dum;
-
-
-    if (edi->vecs.radfix.neig == 0)
-        return;
-
-    snew(proj, edi->vecs.radfix.neig);
-
-    /* loop over radfix vectors */
-    for (i=0; i<edi->vecs.radfix.neig; i++)
-    {
-        /* calculate the projections, radius */
-        proj[i] = projectx(edi, xcoll, edi->vecs.radfix.vec[i]);
-        rad += pow(proj[i] - edi->vecs.radfix.refproj[i], 2);
-    }
-
-    rad   = sqrt(rad);
-    ratio = (edi->vecs.radfix.stpsz[0]+edi->vecs.radfix.radius)/rad - 1.0;
-    edi->vecs.radfix.radius += edi->vecs.radfix.stpsz[0];
-
-    /* loop over radfix vectors */
-    for (i=0; i<edi->vecs.radfix.neig; i++)
-    {
-        proj[i] -= edi->vecs.radfix.refproj[i];
-
-        /* apply the correction */
-        proj[i] /= edi->sav.sqrtm[i];
-        proj[i] *= ratio;
-        for (j=0; j<edi->sav.nr; j++) {
-            svmul(proj[i], edi->vecs.radfix.vec[i][j], vec_dum);
-            rvec_inc(xcoll[j], vec_dum);
-        }
-    }
-
-    sfree(proj);
-}
-
-
-static void do_radacc(rvec *xcoll, t_edpar *edi, t_commrec *cr)
-{
-    int  i,j;
-    real *proj, rad=0.0, ratio=0.0;
-    rvec vec_dum;
-
-
-    if (edi->vecs.radacc.neig == 0)
-        return;
-
-    snew(proj,edi->vecs.radacc.neig);
-
-    /* loop over radacc vectors */
-    for (i=0; i<edi->vecs.radacc.neig; i++)
-    {
-        /* calculate the projections, radius */
-        proj[i] = projectx(edi, xcoll, edi->vecs.radacc.vec[i]);
-        rad += pow(proj[i] - edi->vecs.radacc.refproj[i], 2);
-    }
-    rad = sqrt(rad);
-
-    /* only correct when radius decreased */
-    if (rad < edi->vecs.radacc.radius)
-    {
-        ratio = edi->vecs.radacc.radius/rad - 1.0;
-        rad   = edi->vecs.radacc.radius;
-    }
-    else
-        edi->vecs.radacc.radius = rad;
-
-    /* loop over radacc vectors */
-    for (i=0; i<edi->vecs.radacc.neig; i++)
-    {
-        proj[i] -= edi->vecs.radacc.refproj[i];
-
-        /* apply the correction */
-        proj[i] /= edi->sav.sqrtm[i];
-        proj[i] *= ratio;
-        for (j=0; j<edi->sav.nr; j++)
-        {
-            svmul(proj[i], edi->vecs.radacc.vec[i][j], vec_dum);
-            rvec_inc(xcoll[j], vec_dum);
-        }
-    }
-    sfree(proj);
-}
-
-
-struct t_do_radcon {
-    real *proj;
-};
-
-static void do_radcon(rvec *xcoll, t_edpar *edi, t_commrec *cr)
-{
-    int  i,j;
-    real rad=0.0, ratio=0.0;
-    struct t_do_radcon *loc;
-    gmx_bool bFirst;
-    rvec vec_dum;
-
-
-    if(edi->buf->do_radcon != NULL)
-    {
-        bFirst = FALSE;
-        loc    = edi->buf->do_radcon;
-    }
-    else
-    {
-        bFirst = TRUE;
-        snew(edi->buf->do_radcon, 1);
-    }
-    loc = edi->buf->do_radcon;
-
-    if (edi->vecs.radcon.neig == 0)
-        return;
-
-    if (bFirst)
-        snew(loc->proj, edi->vecs.radcon.neig);
-
-    /* loop over radcon vectors */
-    for (i=0; i<edi->vecs.radcon.neig; i++)
-    {
-        /* calculate the projections, radius */
-        loc->proj[i] = projectx(edi, xcoll, edi->vecs.radcon.vec[i]);
-        rad += pow(loc->proj[i] - edi->vecs.radcon.refproj[i], 2);
-    }
-    rad = sqrt(rad);
-    /* only correct when radius increased */
-    if (rad > edi->vecs.radcon.radius)
-    {
-        ratio = edi->vecs.radcon.radius/rad - 1.0;
-
-        /* loop over radcon vectors */
-        for (i=0; i<edi->vecs.radcon.neig; i++)
-        {
-            /* apply the correction */
-            loc->proj[i] -= edi->vecs.radcon.refproj[i];
-            loc->proj[i] /= edi->sav.sqrtm[i];
-            loc->proj[i] *= ratio;
-
-            for (j=0; j<edi->sav.nr; j++)
-            {
-                svmul(loc->proj[i], edi->vecs.radcon.vec[i][j], vec_dum);
-                rvec_inc(xcoll[j], vec_dum);
-            }
-        }
-    }
-    else
-        edi->vecs.radcon.radius = rad;
-
-    if (rad != edi->vecs.radcon.radius)
-    {
-        rad = 0.0;
-        for (i=0; i<edi->vecs.radcon.neig; i++)
-        {
-            /* calculate the projections, radius */
-            loc->proj[i] = projectx(edi, xcoll, edi->vecs.radcon.vec[i]);
-            rad += pow(loc->proj[i] - edi->vecs.radcon.refproj[i], 2);
-        }
-        rad = sqrt(rad);
-    }
-}
-
-
-static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, gmx_large_int_t step, t_commrec *cr)
-{
-    int i;
-
-
-    GMX_MPE_LOG(ev_ed_apply_cons_start);
-
-    /* subtract the average positions */
-    for (i=0; i<edi->sav.nr; i++)
-        rvec_dec(xcoll[i], edi->sav.x[i]);
-
-    /* apply the constraints */
-    if (step >= 0)
-        do_linfix(xcoll, edi, step, cr);
-    do_linacc(xcoll, edi, cr);
-    if (step >= 0)
-        do_radfix(xcoll, edi, step, cr);
-    do_radacc(xcoll, edi, cr);
-    do_radcon(xcoll, edi, cr);
-
-    /* add back the average positions */
-    for (i=0; i<edi->sav.nr; i++)
-        rvec_inc(xcoll[i], edi->sav.x[i]);
-
-    GMX_MPE_LOG(ev_ed_apply_cons_finish);
-}
-
-
-/* Write out the projections onto the eigenvectors */
-static void write_edo(int nr_edi, t_edpar *edi, gmx_edsam_t ed, gmx_large_int_t step,real rmsd)
-{
-    int i;
-    char buf[22];
-
-
-    if (edi->bNeedDoEdsam)
-    {
-        if (step == -1)
-            fprintf(ed->edo, "Initial projections:\n");
-        else
-        {
-            fprintf(ed->edo,"Step %s, ED #%d  ", gmx_step_str(step, buf), nr_edi);
-            fprintf(ed->edo,"  RMSD %f nm\n",rmsd);
-        }
-
-        if (edi->vecs.mon.neig)
-        {
-            fprintf(ed->edo,"  Monitor eigenvectors");
-            for (i=0; i<edi->vecs.mon.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.mon.ieig[i],edi->vecs.mon.xproj[i]);
-            fprintf(ed->edo,"\n");
-        }
-        if (edi->vecs.linfix.neig)
-        {
-            fprintf(ed->edo,"  Linfix  eigenvectors");
-            for (i=0; i<edi->vecs.linfix.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.linfix.ieig[i],edi->vecs.linfix.xproj[i]);
-            fprintf(ed->edo,"\n");
-        }
-        if (edi->vecs.linacc.neig)
-        {
-            fprintf(ed->edo,"  Linacc  eigenvectors");
-            for (i=0; i<edi->vecs.linacc.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.linacc.ieig[i],edi->vecs.linacc.xproj[i]);
-            fprintf(ed->edo,"\n");
-        }
-        if (edi->vecs.radfix.neig)
-        {
-            fprintf(ed->edo,"  Radfix  eigenvectors");
-            for (i=0; i<edi->vecs.radfix.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radfix.ieig[i],edi->vecs.radfix.xproj[i]);
-            fprintf(ed->edo,"\n");
-            fprintf(ed->edo,"  fixed increment radius = %f\n", calc_radius(&edi->vecs.radfix));
-        }
-        if (edi->vecs.radacc.neig)
-        {
-            fprintf(ed->edo,"  Radacc  eigenvectors");
-            for (i=0; i<edi->vecs.radacc.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radacc.ieig[i],edi->vecs.radacc.xproj[i]);
-            fprintf(ed->edo,"\n");
-            fprintf(ed->edo,"  acceptance radius      = %f\n", calc_radius(&edi->vecs.radacc));
-        }
-        if (edi->vecs.radcon.neig)
-        {
-            fprintf(ed->edo,"  Radcon  eigenvectors");
-            for (i=0; i<edi->vecs.radcon.neig; i++)
-                fprintf(ed->edo," %d: %12.5e ",edi->vecs.radcon.ieig[i],edi->vecs.radcon.xproj[i]);
-            fprintf(ed->edo,"\n");
-            fprintf(ed->edo,"  contracting radius     = %f\n", calc_radius(&edi->vecs.radcon));
-        }
-    }
-}
-
-/* Returns if any constraints are switched on */
-static int ed_constraints(gmx_bool edtype, t_edpar *edi)
-{
-    if (edtype == eEDedsam || edtype == eEDflood)
-    {
-        return (edi->vecs.linfix.neig || edi->vecs.linacc.neig ||
-                edi->vecs.radfix.neig || edi->vecs.radacc.neig ||
-                edi->vecs.radcon.neig);
-    }
-    return 0;
-}
-
-
-/* Copies reference projection 'refproj' to fixed 'refproj0' variable for flooding/
- * umbrella sampling simulations. */
-static void copyEvecReference(t_eigvec* floodvecs)
-{
-       int i;
-
-
-       for (i=0; i<floodvecs->neig; i++)
-       {
-               floodvecs->refproj0[i] = floodvecs->refproj[i];
-       }
-}
-
-
-void init_edsam(gmx_mtop_t  *mtop,   /* global topology                    */
-                t_inputrec  *ir,     /* input record                       */
-                t_commrec   *cr,     /* communication record               */
-                gmx_edsam_t ed,      /* contains all ED data               */
-                rvec        x[],     /* positions of the whole MD system   */
-                matrix      box)     /* the box                            */
-{
-    t_edpar *edi = NULL;    /* points to a single edi data set */
-    int     numedis=0;      /* keep track of the number of ED data sets in edi file */
-    int     i,nr_edi;
-    rvec    *x_pbc  = NULL; /* positions of the whole MD system with pbc removed  */
-    rvec    *xfit   = NULL; /* the positions which will be fitted to the reference structure  */
-    rvec    *xstart = NULL; /* the positions which are subject to ED sampling */
-    rvec    fit_transvec;   /* translation ... */
-    matrix  fit_rotmat;     /* ... and rotation from fit to reference structure */
-
-
-    if (!DOMAINDECOMP(cr) && PAR(cr) && MASTER(cr))
-        gmx_fatal(FARGS, "Please switch on domain decomposition to use essential dynamics in parallel.");
-
-    GMX_MPE_LOG(ev_edsam_start);
-
-    if (MASTER(cr))
-        fprintf(stderr, "ED: Initializing essential dynamics constraints.\n");
-
-    /* Needed for initializing radacc radius in do_edsam */
-    ed->bFirst = 1;
-
-    /* The input file is read by the master and the edi structures are
-     * initialized here. Input is stored in ed->edpar. Then the edi
-     * structures are transferred to the other nodes */
-    if (MASTER(cr))
-    {
-        snew(ed->edpar,1);
-        /* Read the whole edi file at once: */
-        read_edi_file(ed,ed->edpar,mtop->natoms,cr);
-
-        /* Initialization for every ED/flooding dataset. Flooding uses one edi dataset per
-         * flooding vector, Essential dynamics can be applied to more than one structure
-         * as well, but will be done in the order given in the edi file, so
-         * expect different results for different order of edi file concatenation! */
-        edi=ed->edpar;
-        while(edi != NULL)
-        {
-            init_edi(mtop,ir,cr,ed,edi);
-
-            /* Init flooding parameters if needed */
-            init_flood(edi,ed,ir->delta_t,cr);
-
-            edi=edi->next_edi;
-            numedis++;
-        }
-    }
-
-    /* The master does the work here. The other nodes get the positions
-     * not before dd_partition_system which is called after init_edsam */
-    if (MASTER(cr))
-    {
-        /* Remove pbc, make molecule whole.
-         * When ir->bContinuation=TRUE this has already been done, but ok.
-         */
-        snew(x_pbc,mtop->natoms);
-        m_rveccopy(mtop->natoms,x,x_pbc);
-        do_pbc_first_mtop(NULL,ir->ePBC,box,mtop,x_pbc);
-
-        /* Reset pointer to first ED data set which contains the actual ED data */
-        edi=ed->edpar;
-
-        /* Loop over all ED/flooding data sets (usually only one, though) */
-        for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
-        {
-            /* We use srenew to allocate memory since the size of the buffers
-             * is likely to change with every ED dataset */
-            srenew(xfit  , edi->sref.nr );
-            srenew(xstart, edi->sav.nr  );
-
-            /* Extract the positions of the atoms to which will be fitted */
-            for (i=0; i < edi->sref.nr; i++)
-            {
-                copy_rvec(x_pbc[edi->sref.anrs[i]], xfit[i]);
-
-                /* Save the sref positions such that in the next time step the molecule can
-                 * be made whole again (in the parallel case) */
-                if (PAR(cr))
-                    copy_rvec(xfit[i], edi->sref.x_old[i]);
-            }
-
-            /* Extract the positions of the atoms subject to ED sampling */
-            for (i=0; i < edi->sav.nr; i++)
-            {
-                copy_rvec(x_pbc[edi->sav.anrs[i]], xstart[i]);
-
-                /* Save the sav positions such that in the next time step the molecule can
-                 * be made whole again (in the parallel case) */
-                if (PAR(cr))
-                    copy_rvec(xstart[i], edi->sav.x_old[i]);
-            }
-
-            /* Make the fit to the REFERENCE structure, get translation and rotation */
-            fit_to_reference(xfit, fit_transvec, fit_rotmat, edi);
-
-            /* Output how well we fit to the reference at the start */
-            translate_and_rotate(xfit, edi->sref.nr, fit_transvec, fit_rotmat);
-            fprintf(stderr, "ED: Initial RMSD from reference after fit = %f nm (dataset #%d)\n",
-                    rmsd_from_structure(xfit, &edi->sref), nr_edi);
-
-            /* Now apply the translation and rotation to the atoms on which ED sampling will be performed */
-            translate_and_rotate(xstart, edi->sav.nr, fit_transvec, fit_rotmat);
-
-            /* calculate initial projections */
-            project(xstart, edi);
-
-            /* process target structure, if required */
-            if (edi->star.nr > 0)
-            {
-                fprintf(stderr, "ED: Fitting target structure to reference structure\n");
-                /* get translation & rotation for fit of target structure to reference structure */
-                fit_to_reference(edi->star.x, fit_transvec, fit_rotmat, edi);
-                /* do the fit */
-                translate_and_rotate(edi->star.x, edi->sav.nr, fit_transvec, fit_rotmat);
-                rad_project(edi, edi->star.x, &edi->vecs.radcon, cr);
-            } else
-                rad_project(edi, xstart, &edi->vecs.radcon, cr);
-
-            /* process structure that will serve as origin of expansion circle */
-            if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
-                fprintf(stderr, "ED: Setting center of flooding potential (0 = average structure)\n");
-            if (edi->sori.nr > 0)
-            {
-                fprintf(stderr, "ED: Fitting origin structure to reference structure\n");
-                /* fit this structure to reference structure */
-                fit_to_reference(edi->sori.x, fit_transvec, fit_rotmat, edi);
-                /* do the fit */
-                translate_and_rotate(edi->sori.x, edi->sav.nr, fit_transvec, fit_rotmat);
-                rad_project(edi, edi->sori.x, &edi->vecs.radacc, cr);
-                rad_project(edi, edi->sori.x, &edi->vecs.radfix, cr);
-                if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
-                {
-                    fprintf(stderr, "ED: The ORIGIN structure will define the flooding potential center.\n");
-                    /* Set center of flooding potential to the ORIGIN structure */
-                    rad_project(edi, edi->sori.x, &edi->flood.vecs, cr);
-                    /* We already know that no (moving) reference position was provided,
-                     * therefore we can overwrite refproj[0]*/
-                    copyEvecReference(&edi->flood.vecs);
-                }
-            }
-            else /* No origin structure given */
-            {
-                rad_project(edi, xstart, &edi->vecs.radacc, cr);
-                rad_project(edi, xstart, &edi->vecs.radfix, cr);
-                if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
-                {
-                    if (edi->flood.bHarmonic)
-                    {
-                        fprintf(stderr, "ED: A (possibly changing) ref. projection will define the flooding potential center.\n");
-                        for (i=0; i<edi->flood.vecs.neig; i++)
-                            edi->flood.vecs.refproj[i] = edi->flood.vecs.refproj0[i];
-                    }
-                    else
-                    {
-                        fprintf(stderr, "ED: The AVERAGE structure will define the flooding potential center.\n");
-                        /* Set center of flooding potential to the center of the covariance matrix,
-                         * i.e. the average structure, i.e. zero in the projected system */
-                        for (i=0; i<edi->flood.vecs.neig; i++)
-                            edi->flood.vecs.refproj[i] = 0.0;
-                    }
-                }
-            }
-            /* For convenience, output the center of the flooding potential for the eigenvectors */
-            if ( (eEDflood == ed->eEDtype) && (FALSE == edi->flood.bConstForce) )
-            {
-                for (i=0; i<edi->flood.vecs.neig; i++)
-                {
-                    fprintf(stdout, "ED: EV %d flooding potential center: %11.4e", i, edi->flood.vecs.refproj[i]);
-                    if (edi->flood.bHarmonic)
-                        fprintf(stdout, " (adding %11.4e/timestep)", edi->flood.vecs.refprojslope[i]);
-                    fprintf(stdout, "\n");
-                }
-            }
-
-            /* set starting projections for linsam */
-            rad_project(edi, xstart, &edi->vecs.linacc, cr);
-            rad_project(edi, xstart, &edi->vecs.linfix, cr);
-
-            /* Output to file, set the step to -1 so that write_edo knows it was called from init_edsam */
-            if (ed->edo && !(ed->bStartFromCpt))
-                write_edo(nr_edi, edi, ed, -1, 0);
-
-            /* Prepare for the next edi data set: */
-            edi=edi->next_edi;
-        }
-        /* Cleaning up on the master node: */
-        sfree(x_pbc);
-        sfree(xfit);
-        sfree(xstart);
-
-    } /* end of MASTER only section */
-
-    if (PAR(cr))
-    {
-        /* First let everybody know how many ED data sets to expect */
-        gmx_bcast(sizeof(numedis), &numedis, cr);
-        /* Broadcast the essential dynamics / flooding data to all nodes */
-        broadcast_ed_data(cr, ed, numedis);
-    }
-    else
-    {
-        /* In the single-CPU case, point the local atom numbers pointers to the global
-         * one, so that we can use the same notation in serial and parallel case: */
-
-        /* Loop over all ED data sets (usually only one, though) */
-        edi=ed->edpar;
-        for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
-        {
-            edi->sref.anrs_loc = edi->sref.anrs;
-            edi->sav.anrs_loc  = edi->sav.anrs;
-            edi->star.anrs_loc = edi->star.anrs;
-            edi->sori.anrs_loc = edi->sori.anrs;
-            /* For the same reason as above, make a dummy c_ind array: */
-            snew(edi->sav.c_ind, edi->sav.nr);
-            /* Initialize the array */
-            for (i=0; i<edi->sav.nr; i++)
-                edi->sav.c_ind[i] = i;
-            /* In the general case we will need a different-sized array for the reference indices: */
-            if (!edi->bRefEqAv)
-            {
-                snew(edi->sref.c_ind, edi->sref.nr);
-                for (i=0; i<edi->sref.nr; i++)
-                    edi->sref.c_ind[i] = i;
-            }
-            /* Point to the very same array in case of other structures: */
-            edi->star.c_ind = edi->sav.c_ind;
-            edi->sori.c_ind = edi->sav.c_ind;
-            /* In the serial case, the local number of atoms is the global one: */
-            edi->sref.nr_loc = edi->sref.nr;
-            edi->sav.nr_loc  = edi->sav.nr;
-            edi->star.nr_loc = edi->star.nr;
-            edi->sori.nr_loc = edi->sori.nr;
-
-            /* An on we go to the next edi dataset */
-            edi=edi->next_edi;
-        }
-    }
-
-    /* Allocate space for ED buffer variables */
-    /* Again, loop over ED data sets */
-    edi=ed->edpar;
-    for (nr_edi = 1; nr_edi <= numedis; nr_edi++)
-    {
-        /* Allocate space for ED buffer */
-        snew(edi->buf, 1);
-        snew(edi->buf->do_edsam, 1);
-
-        /* Space for collective ED buffer variables */
-
-        /* Collective positions of atoms with the average indices */
-        snew(edi->buf->do_edsam->xcoll                  , edi->sav.nr);
-        snew(edi->buf->do_edsam->shifts_xcoll           , edi->sav.nr); /* buffer for xcoll shifts */
-        snew(edi->buf->do_edsam->extra_shifts_xcoll     , edi->sav.nr);
-        /* Collective positions of atoms with the reference indices */
-        if (!edi->bRefEqAv)
-        {
-            snew(edi->buf->do_edsam->xc_ref             , edi->sref.nr);
-            snew(edi->buf->do_edsam->shifts_xc_ref      , edi->sref.nr); /* To store the shifts in */
-            snew(edi->buf->do_edsam->extra_shifts_xc_ref, edi->sref.nr);
-        }
-
-        /* Get memory for flooding forces */
-        snew(edi->flood.forces_cartesian                , edi->sav.nr);
-
-#ifdef DUMPEDI
-        /* Dump it all into one file per process */
-        dump_edi(edi, cr, nr_edi);
-#endif
-
-        /* An on we go to the next edi dataset */
-        edi=edi->next_edi;
-    }
-
-    /* Flush the edo file so that the user can check some things
-     * when the simulation has started */
-    if (ed->edo)
-        fflush(ed->edo);
-
-    GMX_MPE_LOG(ev_edsam_finish);
-}
-
-
-void do_edsam(t_inputrec  *ir,
-              gmx_large_int_t step,
-              t_mdatoms   *md,
-              t_commrec   *cr,
-              rvec        xs[],   /* The local current positions on this processor */
-              rvec        v[],    /* The velocities */
-              matrix      box,
-              gmx_edsam_t ed)
-{
-    int     i,edinr,iupdate=500;
-    matrix  rotmat;         /* rotation matrix */
-    rvec    transvec;       /* translation vector */
-    rvec    dv,dx,x_unsh;   /* tmp vectors for velocity, distance, unshifted x coordinate */
-    real    dt_1;           /* 1/dt */
-    struct t_do_edsam *buf;
-    t_edpar *edi;
-    real    rmsdev=-1;      /* RMSD from reference structure prior to applying the constraints */
-    gmx_bool bSuppress=FALSE; /* Write .edo file on master? */
-
-
-    /* Check if ED sampling has to be performed */
-    if ( ed->eEDtype==eEDnone )
-        return;
-
-    /* Suppress output on first call of do_edsam if
-     * two-step sd2 integrator is used */
-    if ( (ir->eI==eiSD2) && (v != NULL) )
-        bSuppress = TRUE;
-
-    dt_1 = 1.0/ir->delta_t;
-
-    /* Loop over all ED datasets (usually one) */
-    edi  = ed->edpar;
-    edinr = 0;
-    while (edi != NULL)
-    {
-        edinr++;
-        if (edi->bNeedDoEdsam)
-        {
-
-            buf=edi->buf->do_edsam;
-
-            if (ed->bFirst)
-                /* initialise radacc radius for slope criterion */
-                buf->oldrad=calc_radius(&edi->vecs.radacc);
-
-            /* Copy the positions into buf->xc* arrays and after ED
-             * feed back corrections to the official positions */
-
-            /* Broadcast the ED positions such that every node has all of them
-             * Every node contributes its local positions xs and stores it in
-             * the collective buf->xcoll array. Note that for edinr > 1
-             * xs could already have been modified by an earlier ED */
-
-            communicate_group_positions(cr, buf->xcoll, buf->shifts_xcoll, buf->extra_shifts_xcoll, buf->bUpdateShifts, xs,
-                    edi->sav.nr, edi->sav.nr_loc, edi->sav.anrs_loc, edi->sav.c_ind, edi->sav.x_old,  box);
-
-#ifdef DEBUG_ED
-            dump_xcoll(edi, buf, cr, step);
-#endif
-            /* Only assembly reference positions if their indices differ from the average ones */
-            if (!edi->bRefEqAv)
-                communicate_group_positions(cr, buf->xc_ref, buf->shifts_xc_ref, buf->extra_shifts_xc_ref, buf->bUpdateShifts, xs,
-                        edi->sref.nr, edi->sref.nr_loc, edi->sref.anrs_loc, edi->sref.c_ind, edi->sref.x_old, box);
-
-            /* If bUpdateShifts was TRUE then the shifts have just been updated in get_positions.
-             * We do not need to uptdate the shifts until the next NS step */
-            buf->bUpdateShifts = FALSE;
-
-            /* Now all nodes have all of the ED positions in edi->sav->xcoll,
-             * as well as the indices in edi->sav.anrs */
-
-            /* Fit the reference indices to the reference structure */
-            if (edi->bRefEqAv)
-                fit_to_reference(buf->xcoll , transvec, rotmat, edi);
-            else
-                fit_to_reference(buf->xc_ref, transvec, rotmat, edi);
-
-            /* Now apply the translation and rotation to the ED structure */
-            translate_and_rotate(buf->xcoll, edi->sav.nr, transvec, rotmat);
-
-            /* Find out how well we fit to the reference (just for output steps) */
-            if (do_per_step(step,edi->outfrq) && MASTER(cr))
-            {
-                if (edi->bRefEqAv)
-                {
-                    /* Indices of reference and average structures are identical,
-                     * thus we can calculate the rmsd to SREF using xcoll */
-                    rmsdev = rmsd_from_structure(buf->xcoll,&edi->sref);
-                }
-                else
-                {
-                    /* We have to translate & rotate the reference atoms first */
-                    translate_and_rotate(buf->xc_ref, edi->sref.nr, transvec, rotmat);
-                    rmsdev = rmsd_from_structure(buf->xc_ref,&edi->sref);
-                }
-            }
-
-            /* update radsam references, when required */
-            if (do_per_step(step,edi->maxedsteps) && step >= edi->presteps)
-            {
-                project(buf->xcoll, edi);
-                rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
-                rad_project(edi, buf->xcoll, &edi->vecs.radfix, cr);
-                buf->oldrad=-1.e5;
-            }
-
-            /* update radacc references, when required */
-            if (do_per_step(step,iupdate) && step >= edi->presteps)
-            {
-                edi->vecs.radacc.radius = calc_radius(&edi->vecs.radacc);
-                if (edi->vecs.radacc.radius - buf->oldrad < edi->slope)
-                {
-                    project(buf->xcoll, edi);
-                    rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
-                    buf->oldrad = 0.0;
-                } else
-                    buf->oldrad = edi->vecs.radacc.radius;
-            }
-
-            /* apply the constraints */
-            if (step >= edi->presteps && ed_constraints(ed->eEDtype, edi))
-            {
-                /* ED constraints should be applied already in the first MD step
-                 * (which is step 0), therefore we pass step+1 to the routine */
-                ed_apply_constraints(buf->xcoll, edi, step+1 - ir->init_step, cr);
-            }
-
-            /* write to edo, when required */
-            if (do_per_step(step,edi->outfrq))
-            {
-                project(buf->xcoll, edi);
-                if (MASTER(cr) && !bSuppress)
-                    write_edo(edinr, edi, ed, step, rmsdev);
-            }
-
-            /* Copy back the positions unless monitoring only */
-            if (ed_constraints(ed->eEDtype, edi))
-            {
-                /* remove fitting */
-                rmfit(edi->sav.nr, buf->xcoll, transvec, rotmat);
-
-                /* Copy the ED corrected positions into the coordinate array */
-                /* Each node copies its local part. In the serial case, nat_loc is the
-                 * total number of ED atoms */
-                for (i=0; i<edi->sav.nr_loc; i++)
-                {
-                    /* Unshift local ED coordinate and store in x_unsh */
-                    ed_unshift_single_coord(box, buf->xcoll[edi->sav.c_ind[i]],
-                                            buf->shifts_xcoll[edi->sav.c_ind[i]], x_unsh);
-
-                    /* dx is the ED correction to the positions: */
-                    rvec_sub(x_unsh, xs[edi->sav.anrs_loc[i]], dx);
-
-                    if (v != NULL)
-                    {
-                        /* dv is the ED correction to the velocity: */
-                        svmul(dt_1, dx, dv);
-                        /* apply the velocity correction: */
-                        rvec_inc(v[edi->sav.anrs_loc[i]], dv);
-                    }
-                    /* Finally apply the position correction due to ED: */
-                    copy_rvec(x_unsh, xs[edi->sav.anrs_loc[i]]);
-                }
-            }
-        } /* END of if (edi->bNeedDoEdsam) */
-
-        /* Prepare for the next ED dataset */
-        edi = edi->next_edi;
-
-    } /* END of loop over ED datasets */
-
-    ed->bFirst = FALSE;
-
-    GMX_MPE_LOG(ev_edsam_finish);
-}
diff --git a/src/mdlib/force.c b/src/mdlib/force.c
deleted file mode 100644 (file)
index 6d09179..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <math.h>
-#include <string.h>
-#include "sysstuff.h"
-#include "typedefs.h"
-#include "macros.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "physics.h"
-#include "force.h"
-#include "nonbonded.h"
-#include "names.h"
-#include "network.h"
-#include "pbc.h"
-#include "ns.h"
-#include "nrnb.h"
-#include "bondf.h"
-#include "mshift.h"
-#include "txtdump.h"
-#include "coulomb.h"
-#include "pppm.h"
-#include "pme.h"
-#include "mdrun.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "qmmm.h"
-#include "mpelogging.h"
-
-
-void ns(FILE *fp,
-        t_forcerec *fr,
-        rvec       x[],
-        matrix     box,
-        gmx_groups_t *groups,
-        t_grpopts  *opts,
-        gmx_localtop_t *top,
-        t_mdatoms  *md,
-        t_commrec  *cr,
-        t_nrnb     *nrnb,
-        real       lambda,
-        real       *dvdlambda,
-        gmx_grppairener_t *grppener,
-        gmx_bool       bFillGrid,
-        gmx_bool       bDoLongRange,
-        gmx_bool       bDoForces,
-        rvec       *f)
-{
-  char   *ptr;
-  int    nsearch;
-
-  GMX_MPE_LOG(ev_ns_start);
-  if (!fr->ns.nblist_initialized)
-  {
-      init_neighbor_list(fp, fr, md->homenr);
-  }
-    
-  if (fr->bTwinRange) 
-    fr->nlr=0;
-
-    nsearch = search_neighbours(fp,fr,x,box,top,groups,cr,nrnb,md,
-                                lambda,dvdlambda,grppener,
-                                bFillGrid,bDoLongRange,
-                                bDoForces,f);
-  if (debug)
-    fprintf(debug,"nsearch = %d\n",nsearch);
-    
-  /* Check whether we have to do dynamic load balancing */
-  /*if ((nsb->nstDlb > 0) && (mod(step,nsb->nstDlb) == 0))
-    count_nb(cr,nsb,&(top->blocks[ebCGS]),nns,fr->nlr,
-    &(top->idef),opts->ngener);
-  */
-  if (fr->ns.dump_nl > 0)
-    dump_nblist(fp,cr,fr,fr->ns.dump_nl);
-
-  GMX_MPE_LOG(ev_ns_finish);
-}
-
-void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
-                       t_forcerec *fr,      t_inputrec *ir,
-                       t_idef     *idef,    t_commrec  *cr,
-                       t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
-                       t_mdatoms  *md,
-                       t_grpopts  *opts,
-                       rvec       x[],      history_t  *hist,
-                       rvec       f[],
-                       gmx_enerdata_t *enerd,
-                       t_fcdata   *fcd,
-                       gmx_mtop_t     *mtop,
-                       gmx_localtop_t *top,
-                       gmx_genborn_t *born,
-                       t_atomtypes *atype,
-                       gmx_bool       bBornRadii,
-                       matrix     box,
-                       real       lambda,  
-                       t_graph    *graph,
-                       t_blocka   *excl,    
-                       rvec       mu_tot[],
-                       int        flags,
-                       float      *cycles_pme)
-{
-    int     i,status;
-    int     donb_flags;
-    gmx_bool    bDoEpot,bSepDVDL,bSB;
-    int     pme_flags;
-    matrix  boxs;
-    rvec    box_size;
-    real    dvdlambda,Vsr,Vlr,Vcorr=0,vdip,vcharge;
-    t_pbc   pbc;
-    real    dvdgb;
-    char    buf[22];
-    gmx_enerdata_t ed_lam;
-    double  lam_i;
-    real    dvdl_dum;
-
-#ifdef GMX_MPI
-    double  t0=0.0,t1,t2,t3; /* time measurement for coarse load balancing */
-#endif
-    
-#define PRINT_SEPDVDL(s,v,dvdl) if (bSepDVDL) fprintf(fplog,sepdvdlformat,s,v,dvdl);
-    
-    GMX_MPE_LOG(ev_force_start);
-    set_pbc(&pbc,fr->ePBC,box);
-    
-    /* Reset box */
-    for(i=0; (i<DIM); i++)
-    {
-        box_size[i]=box[i][i];
-    }
-    
-    bSepDVDL=(fr->bSepDVDL && do_per_step(step,ir->nstlog));
-    debug_gmx();
-    
-    /* do QMMM first if requested */
-    if(fr->bQMMM)
-    {
-        enerd->term[F_EQM] = calculate_QMMM(cr,x,f,fr,md);
-    }
-    
-    if (bSepDVDL)
-    {
-        fprintf(fplog,"Step %s: non-bonded V and dVdl for node %d:\n",
-                gmx_step_str(step,buf),cr->nodeid);
-    }
-    
-    /* Call the short range functions all in one go. */
-    GMX_MPE_LOG(ev_do_fnbf_start);
-    
-    dvdlambda = 0;
-    
-#ifdef GMX_MPI
-    /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
-#define TAKETIME FALSE
-    if (TAKETIME)
-    {
-        MPI_Barrier(cr->mpi_comm_mygroup);
-        t0=MPI_Wtime();
-    }
-#endif
-    
-    if (ir->nwall)
-    {
-        dvdlambda = do_walls(ir,fr,box,md,x,f,lambda,
-                             enerd->grpp.ener[egLJSR],nrnb);
-        PRINT_SEPDVDL("Walls",0.0,dvdlambda);
-        enerd->dvdl_lin += dvdlambda;
-    }
-               
-       /* If doing GB, reset dvda and calculate the Born radii */
-       if (ir->implicit_solvent)
-       {
-               /* wallcycle_start(wcycle,ewcGB); */
-               
-               for(i=0;i<born->nr;i++)
-               {
-                       fr->dvda[i]=0;
-               }
-               
-               if(bBornRadii)
-               {
-                       calc_gb_rad(cr,fr,ir,top,atype,x,&(fr->gblist),born,md,nrnb);
-               }
-               
-               /* wallcycle_stop(wcycle, ewcGB); */
-       }
-       
-    where();
-    donb_flags = 0;
-    if (flags & GMX_FORCE_FORCES)
-    {
-        donb_flags |= GMX_DONB_FORCES;
-    }
-    do_nonbonded(cr,fr,x,f,md,excl,
-                 fr->bBHAM ?
-                 enerd->grpp.ener[egBHAMSR] :
-                 enerd->grpp.ener[egLJSR],
-                 enerd->grpp.ener[egCOULSR],
-                                enerd->grpp.ener[egGB],box_size,nrnb,
-                 lambda,&dvdlambda,-1,-1,donb_flags);
-    /* If we do foreign lambda and we have soft-core interactions
-     * we have to recalculate the (non-linear) energies contributions.
-     */
-    if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) && ir->sc_alpha != 0)
-    {
-        init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
-        
-        for(i=0; i<enerd->n_lambda; i++)
-        {
-            lam_i = (i==0 ? lambda : ir->flambda[i-1]);
-            dvdl_dum = 0;
-            reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
-            do_nonbonded(cr,fr,x,f,md,excl,
-                         fr->bBHAM ?
-                         ed_lam.grpp.ener[egBHAMSR] :
-                         ed_lam.grpp.ener[egLJSR],
-                         ed_lam.grpp.ener[egCOULSR],
-                         enerd->grpp.ener[egGB], box_size,nrnb,
-                         lam_i,&dvdl_dum,-1,-1,
-                         GMX_DONB_FOREIGNLAMBDA);
-            sum_epot(&ir->opts,&ed_lam);
-            enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
-        }
-        destroy_enerdata(&ed_lam);
-    }
-    where();
-       
-       /* If we are doing GB, calculate bonded forces and apply corrections 
-        * to the solvation forces */
-       if (ir->implicit_solvent)  {
-               calc_gb_forces(cr,md,born,top,atype,x,f,fr,idef,
-                       ir->gb_algorithm,ir->sa_algorithm,nrnb,bBornRadii,&pbc,graph,enerd);
-    }
-
-#ifdef GMX_MPI
-    if (TAKETIME)
-    {
-        t1=MPI_Wtime();
-        fr->t_fnbf += t1-t0;
-    }
-#endif
-    
-    if (ir->sc_alpha != 0)
-    {
-        enerd->dvdl_nonlin += dvdlambda;
-    }
-    else
-    {
-        enerd->dvdl_lin    += dvdlambda;
-    }
-    Vsr = 0;
-    if (bSepDVDL)
-    {
-        for(i=0; i<enerd->grpp.nener; i++)
-        {
-            Vsr +=
-                (fr->bBHAM ?
-                 enerd->grpp.ener[egBHAMSR][i] :
-                 enerd->grpp.ener[egLJSR][i])
-                + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
-        }
-    }
-    PRINT_SEPDVDL("VdW and Coulomb SR particle-p.",Vsr,dvdlambda);
-    debug_gmx();
-    
-    GMX_MPE_LOG(ev_do_fnbf_finish);
-    
-    if (debug)
-    {
-        pr_rvecs(debug,0,"fshift after SR",fr->fshift,SHIFTS);
-    }
-    
-    /* Shift the coordinates. Must be done before bonded forces and PPPM, 
-     * but is also necessary for SHAKE and update, therefore it can NOT 
-     * go when no bonded forces have to be evaluated.
-     */
-    
-    /* Here sometimes we would not need to shift with NBFonly,
-     * but we do so anyhow for consistency of the returned coordinates.
-     */
-    if (graph)
-    {
-        shift_self(graph,box,x);
-        if (TRICLINIC(box))
-        {
-            inc_nrnb(nrnb,eNR_SHIFTX,2*graph->nnodes);
-        }
-        else
-        {
-            inc_nrnb(nrnb,eNR_SHIFTX,graph->nnodes);
-        }
-    }
-    /* Check whether we need to do bondeds or correct for exclusions */
-    if (fr->bMolPBC &&
-        ((flags & GMX_FORCE_BONDED)
-         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
-    {
-        /* Since all atoms are in the rectangular or triclinic unit-cell,
-         * only single box vector shifts (2 in x) are required.
-         */
-        set_pbc_dd(&pbc,fr->ePBC,cr->dd,TRUE,box);
-    }
-    debug_gmx();
-    
-    if (flags & GMX_FORCE_BONDED)
-    {
-        GMX_MPE_LOG(ev_calc_bonds_start);
-        calc_bonds(fplog,cr->ms,
-                   idef,x,hist,f,fr,&pbc,graph,enerd,nrnb,lambda,md,fcd,
-                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
-                   fr->bSepDVDL && do_per_step(step,ir->nstlog),step);
-        
-        /* Check if we have to determine energy differences
-         * at foreign lambda's.
-         */
-        if (ir->n_flambda > 0 && (flags & GMX_FORCE_DHDL) &&
-            idef->ilsort != ilsortNO_FE)
-        {
-            if (idef->ilsort != ilsortFE_SORTED)
-            {
-                gmx_incons("The bonded interactions are not sorted for free energy");
-            }
-            init_enerdata(mtop->groups.grps[egcENER].nr,ir->n_flambda,&ed_lam);
-            
-            for(i=0; i<enerd->n_lambda; i++)
-            {
-                lam_i = (i==0 ? lambda : ir->flambda[i-1]);
-                dvdl_dum = 0;
-                reset_enerdata(&ir->opts,fr,TRUE,&ed_lam,FALSE);
-                calc_bonds_lambda(fplog,
-                                  idef,x,fr,&pbc,graph,&ed_lam,nrnb,lam_i,md,
-                                  fcd,
-                                  DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
-                sum_epot(&ir->opts,&ed_lam);
-                enerd->enerpart_lambda[i] += ed_lam.term[F_EPOT];
-            }
-            destroy_enerdata(&ed_lam);
-        }
-        debug_gmx();
-        GMX_MPE_LOG(ev_calc_bonds_finish);
-    }
-
-    where();
-
-    *cycles_pme = 0;
-    if (EEL_FULL(fr->eeltype))
-    {
-        bSB = (ir->nwall == 2);
-        if (bSB)
-        {
-            copy_mat(box,boxs);
-            svmul(ir->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
-            box_size[ZZ] *= ir->wall_ewald_zfac;
-        }
-        
-        clear_mat(fr->vir_el_recip);   
-        
-        if (fr->bEwald)
-        {
-            if (fr->n_tpi == 0)
-            {
-                dvdlambda = 0;
-                Vcorr = ewald_LRcorrection(fplog,md->start,md->start+md->homenr,
-                                           cr,fr,
-                                           md->chargeA,
-                                           md->nChargePerturbed ? md->chargeB : NULL,
-                                           excl,x,bSB ? boxs : box,mu_tot,
-                                           ir->ewald_geometry,
-                                           ir->epsilon_surface,
-                                           lambda,&dvdlambda,&vdip,&vcharge);
-                PRINT_SEPDVDL("Ewald excl./charge/dip. corr.",Vcorr,dvdlambda);
-                enerd->dvdl_lin += dvdlambda;
-            }
-            else
-            {
-                if (ir->ewald_geometry != eewg3D || ir->epsilon_surface != 0)
-                {
-                    gmx_fatal(FARGS,"TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions");
-                }
-                /* The TPI molecule does not have exclusions with the rest
-                 * of the system and no intra-molecular PME grid contributions
-                 * will be calculated in gmx_pme_calc_energy.
-                 */
-                Vcorr = 0;
-            }
-        }
-        else
-        {
-            Vcorr = shift_LRcorrection(fplog,md->start,md->homenr,cr,fr,
-                                       md->chargeA,excl,x,TRUE,box,
-                                       fr->vir_el_recip);
-        }
-        
-        dvdlambda = 0;
-        status = 0;
-        switch (fr->eeltype)
-        {
-        case eelPPPM:
-            status = gmx_pppm_do(fplog,fr->pmedata,FALSE,x,fr->f_novirsum,
-                                 md->chargeA,
-                                 box_size,fr->phi,cr,md->start,md->homenr,
-                                 nrnb,ir->pme_order,&Vlr);
-            break;
-        case eelPME:
-        case eelPMESWITCH:
-        case eelPMEUSER:
-        case eelPMEUSERSWITCH:
-            if (cr->duty & DUTY_PME)
-            {
-                if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
-                {
-                    pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE;
-                    if (flags & GMX_FORCE_FORCES)
-                    {
-                        pme_flags |= GMX_PME_CALC_F;
-                    }
-                    if (flags & GMX_FORCE_VIRIAL)
-                    {
-                        pme_flags |= GMX_PME_CALC_ENER_VIR;
-                    }
-                    if (fr->n_tpi > 0)
-                    {
-                        /* We don't calculate f, but we do want the potential */
-                        pme_flags |= GMX_PME_CALC_POT;
-                    }
-                    wallcycle_start(wcycle,ewcPMEMESH);
-                    status = gmx_pme_do(fr->pmedata,
-                                        md->start,md->homenr - fr->n_tpi,
-                                        x,fr->f_novirsum,
-                                        md->chargeA,md->chargeB,
-                                        bSB ? boxs : box,cr,
-                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
-                                        DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
-                                        nrnb,wcycle,
-                                        fr->vir_el_recip,fr->ewaldcoeff,
-                                        &Vlr,lambda,&dvdlambda,
-                                        pme_flags);
-                    *cycles_pme = wallcycle_stop(wcycle,ewcPMEMESH);
-
-                    /* We should try to do as little computation after
-                     * this as possible, because parallel PME synchronizes
-                     * the nodes, so we want all load imbalance of the rest
-                     * of the force calculation to be before the PME call.
-                     * DD load balancing is done on the whole time of
-                     * the force call (without PME).
-                     */
-                }
-                if (fr->n_tpi > 0)
-                {
-                    /* Determine the PME grid energy of the test molecule
-                     * with the PME grid potential of the other charges.
-                     */
-                    gmx_pme_calc_energy(fr->pmedata,fr->n_tpi,
-                                        x + md->homenr - fr->n_tpi,
-                                        md->chargeA + md->homenr - fr->n_tpi,
-                                        &Vlr);
-                }
-                PRINT_SEPDVDL("PME mesh",Vlr,dvdlambda);
-            } 
-            else
-            {
-                /* Energies and virial are obtained later from the PME nodes */
-                /* but values have to be zeroed out here */
-                Vlr=0.0;
-            }
-            break;
-        case eelEWALD:
-            Vlr = do_ewald(fplog,FALSE,ir,x,fr->f_novirsum,
-                           md->chargeA,md->chargeB,
-                           box_size,cr,md->homenr,
-                           fr->vir_el_recip,fr->ewaldcoeff,
-                           lambda,&dvdlambda,fr->ewald_table);
-            PRINT_SEPDVDL("Ewald long-range",Vlr,dvdlambda);
-            break;
-        default:
-            Vlr = 0;
-            gmx_fatal(FARGS,"No such electrostatics method implemented %s",
-                      eel_names[fr->eeltype]);
-        }
-        if (status != 0)
-        {
-            gmx_fatal(FARGS,"Error %d in long range electrostatics routine %s",
-                      status,EELTYPE(fr->eeltype));
-               }
-        enerd->dvdl_lin += dvdlambda;
-        enerd->term[F_COUL_RECIP] = Vlr + Vcorr;
-        if (debug)
-        {
-            fprintf(debug,"Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
-                    Vlr,Vcorr,enerd->term[F_COUL_RECIP]);
-            pr_rvecs(debug,0,"vir_el_recip after corr",fr->vir_el_recip,DIM);
-            pr_rvecs(debug,0,"fshift after LR Corrections",fr->fshift,SHIFTS);
-        }
-    }
-    else
-    {
-        if (EEL_RF(fr->eeltype))
-        {
-            dvdlambda = 0;
-            
-            if (fr->eeltype != eelRF_NEC)
-            {
-                enerd->term[F_RF_EXCL] =
-                    RF_excl_correction(fplog,fr,graph,md,excl,x,f,
-                                       fr->fshift,&pbc,lambda,&dvdlambda);
-            }
-            
-            enerd->dvdl_lin += dvdlambda;
-            PRINT_SEPDVDL("RF exclusion correction",
-                          enerd->term[F_RF_EXCL],dvdlambda);
-        }
-    }
-    where();
-    debug_gmx();
-       
-    if (debug)
-    {
-        print_nrnb(debug,nrnb); 
-    }
-    debug_gmx();
-    
-#ifdef GMX_MPI
-    if (TAKETIME)
-    {
-        t2=MPI_Wtime();
-        MPI_Barrier(cr->mpi_comm_mygroup);
-        t3=MPI_Wtime();
-        fr->t_wait += t3-t2;
-        if (fr->timesteps == 11)
-        {
-            fprintf(stderr,"* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n", 
-                    cr->nodeid, gmx_step_str(fr->timesteps,buf), 
-                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf), 
-                    (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
-        }        
-        fr->timesteps++;
-    }
-#endif
-    
-    if (debug)
-    {
-        pr_rvecs(debug,0,"fshift after bondeds",fr->fshift,SHIFTS);
-    }
-    
-    GMX_MPE_LOG(ev_force_finish);
-
-}
-
-void init_enerdata(int ngener,int n_flambda,gmx_enerdata_t *enerd)
-{
-    int i,n2;
-    
-    for(i=0; i<F_NRE; i++)
-    {
-        enerd->term[i] = 0;
-    }
-    
-    n2=ngener*ngener;
-    if (debug)
-    {
-        fprintf(debug,"Creating %d sized group matrix for energies\n",n2);
-    }
-    enerd->grpp.nener = n2;
-    for(i=0; (i<egNR); i++)
-    {
-        snew(enerd->grpp.ener[i],n2);
-    }
-
-    if (n_flambda)
-    {
-        enerd->n_lambda = 1 + n_flambda;
-        snew(enerd->enerpart_lambda,enerd->n_lambda);
-    }
-    else
-    {
-        enerd->n_lambda = 0;
-    }
-}
-
-void destroy_enerdata(gmx_enerdata_t *enerd)
-{
-    int i;
-
-    for(i=0; (i<egNR); i++)
-    {
-        sfree(enerd->grpp.ener[i]);
-    }
-
-    if (enerd->n_lambda)
-    {
-        sfree(enerd->enerpart_lambda);
-    }
-}
-
-static real sum_v(int n,real v[])
-{
-  real t;
-  int  i;
-  
-  t = 0.0;
-  for(i=0; (i<n); i++)
-    t = t + v[i];
-    
-  return t;
-}
-
-void sum_epot(t_grpopts *opts,gmx_enerdata_t *enerd)
-{
-  gmx_grppairener_t *grpp;
-  real *epot;
-  int i;
-  
-  grpp = &enerd->grpp;
-  epot = enerd->term;
-
-  /* Accumulate energies */
-  epot[F_COUL_SR]  = sum_v(grpp->nener,grpp->ener[egCOULSR]);
-  epot[F_LJ]       = sum_v(grpp->nener,grpp->ener[egLJSR]);
-  epot[F_LJ14]     = sum_v(grpp->nener,grpp->ener[egLJ14]);
-  epot[F_COUL14]   = sum_v(grpp->nener,grpp->ener[egCOUL14]);
-  epot[F_COUL_LR]  = sum_v(grpp->nener,grpp->ener[egCOULLR]);
-  epot[F_LJ_LR]    = sum_v(grpp->nener,grpp->ener[egLJLR]);
-  /* We have already added 1-2,1-3, and 1-4 terms to F_GBPOL */
-  epot[F_GBPOL]   += sum_v(grpp->nener,grpp->ener[egGB]);
-    
-/* lattice part of LR doesnt belong to any group
- * and has been added earlier
- */
-  epot[F_BHAM]     = sum_v(grpp->nener,grpp->ener[egBHAMSR]);
-  epot[F_BHAM_LR]  = sum_v(grpp->nener,grpp->ener[egBHAMLR]);
-
-  epot[F_EPOT] = 0;
-  for(i=0; (i<F_EPOT); i++)
-    if (i != F_DISRESVIOL && i != F_ORIRESDEV && i != F_DIHRESVIOL)
-      epot[F_EPOT] += epot[i];
-}
-
-void sum_dhdl(gmx_enerdata_t *enerd,double lambda,t_inputrec *ir)
-{
-    int i;
-    double dlam,dhdl_lin;
-
-    enerd->term[F_DVDL] = enerd->dvdl_lin + enerd->dvdl_nonlin;
-
-    if (debug)
-    {
-        fprintf(debug,"dvdl: %f, non-linear %f + linear %f\n",
-                enerd->term[F_DVDL],enerd->dvdl_nonlin,enerd->dvdl_lin);
-    }
-
-    /* Notes on the foreign lambda free energy difference evaluation:
-     * Adding the potential and ekin terms that depend linearly on lambda
-     * as delta lam * dvdl to the energy differences is exact.
-     * For the constraint dvdl this is not exact, but we have no other option.
-     * For the non-bonded LR term we assume that the soft-core (if present)
-     * no longer affects the energy beyond the short-range cut-off,
-     * which is a very good approximation (except for exotic settings).
-     */
-    for(i=1; i<enerd->n_lambda; i++)
-    {
-        dlam = (ir->flambda[i-1] - lambda);
-        dhdl_lin =
-            enerd->dvdl_lin + enerd->term[F_DKDL] + enerd->term[F_DHDL_CON];
-        if (debug)
-        {
-            fprintf(debug,"enerdiff lam %g: non-linear %f linear %f*%f\n",
-                    ir->flambda[i-1],
-                    enerd->enerpart_lambda[i] - enerd->enerpart_lambda[0],
-                    dlam,dhdl_lin);
-        }
-        enerd->enerpart_lambda[i] += dlam*dhdl_lin;
-
-    }
-}
-
-void reset_enerdata(t_grpopts *opts,
-                    t_forcerec *fr,gmx_bool bNS,
-                    gmx_enerdata_t *enerd,
-                    gmx_bool bMaster)
-{
-  gmx_bool bKeepLR;
-  int  i,j;
-  
-  /* First reset all energy components, except for the long range terms
-   * on the master at non neighbor search steps, since the long range
-   * terms have already been summed at the last neighbor search step.
-   */
-  bKeepLR = (fr->bTwinRange && !bNS);
-  for(i=0; (i<egNR); i++) {
-    if (!(bKeepLR && bMaster && (i == egCOULLR || i == egLJLR))) {
-      for(j=0; (j<enerd->grpp.nener); j++)
-       enerd->grpp.ener[i][j] = 0.0;
-    }
-  }
-  enerd->dvdl_lin    = 0.0;
-  enerd->dvdl_nonlin = 0.0;
-
-  /* Normal potential energy components */
-  for(i=0; (i<=F_EPOT); i++) {
-    enerd->term[i] = 0.0;
-  }
-  /* Initialize the dVdlambda term with the long range contribution */
-  enerd->term[F_DVDL]     = 0.0;
-  enerd->term[F_DKDL]     = 0.0;
-  enerd->term[F_DHDL_CON] = 0.0;
-  if (enerd->n_lambda > 0)
-  {
-      for(i=0; i<enerd->n_lambda; i++)
-      {
-          enerd->enerpart_lambda[i] = 0.0;
-      }
-  }
-}
diff --git a/src/mdlib/gmx_wallcycle.c b/src/mdlib/gmx_wallcycle.c
deleted file mode 100644 (file)
index 8224baf..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include "gmx_wallcycle.h"
-#include "gmx_cyclecounter.h"
-#include "smalloc.h"
-#include "gmx_fatal.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-typedef struct
-{
-    int          n;
-    gmx_cycles_t c;
-    gmx_cycles_t start;
-    gmx_cycles_t last;
-} wallcc_t;
-
-typedef struct gmx_wallcycle
-{
-    wallcc_t     *wcc;
-    /* variables for testing/debugging */
-    gmx_bool         wc_barrier;
-    wallcc_t     *wcc_all;
-    int          wc_depth;
-    int          ewc_prev;
-    gmx_cycles_t cycle_prev;
-    gmx_large_int_t   reset_counters;
-#ifdef GMX_MPI
-    MPI_Comm     mpi_comm_mygroup;
-#endif
-} gmx_wallcycle_t_t;
-
-/* Each name should not exceed 19 characters */
-static const char *wcn[ewcNR] =
-{ "Run", "Step", "PP during PME", "Domain decomp.", "DD comm. load", "DD comm. bounds", "Vsite constr.", "Send X to PME", "Comm. coord.", "Neighbor search", "Born radii", "Force", "Wait + Comm. F", "PME mesh", "PME redist. X/F", "PME spread/gather", "PME 3D-FFT", "PME solve", "Wait + Comm. X/F", "Wait + Recv. PME F", "Vsite spread", "Write traj.", "Update", "Constraints", "Comm. energies", "Test" };
-
-gmx_bool wallcycle_have_counter(void)
-{
-  return gmx_cycles_have_counter();
-}
-
-gmx_wallcycle_t wallcycle_init(FILE *fplog,int resetstep,t_commrec *cr)
-{
-    gmx_wallcycle_t wc;
-    
-    
-    if (!wallcycle_have_counter())
-    {
-        return NULL;
-    }
-
-    snew(wc,1);
-
-    wc->wc_barrier = FALSE;
-    wc->wcc_all    = NULL;
-    wc->wc_depth   = 0;
-    wc->ewc_prev   = -1;
-    wc->reset_counters = resetstep;
-
-#ifdef GMX_MPI
-    if (PAR(cr) && getenv("GMX_CYCLE_BARRIER") != NULL)
-    {
-        if (fplog) 
-        {
-            fprintf(fplog,"\nWill call MPI_Barrier before each cycle start/stop call\n\n");
-        }
-        wc->wc_barrier = TRUE;
-        wc->mpi_comm_mygroup = cr->mpi_comm_mygroup;
-    }
-#endif
-
-    snew(wc->wcc,ewcNR);
-    if (getenv("GMX_CYCLE_ALL") != NULL)
-    {
-/*#ifndef GMX_THREADS*/
-        if (fplog) 
-        {
-            fprintf(fplog,"\nWill time all the code during the run\n\n");
-        }
-        snew(wc->wcc_all,ewcNR*ewcNR);
-/*#else*/
-        gmx_fatal(FARGS, "GMX_CYCLE_ALL is incompatible with threaded code");
-/*#endif*/
-    }
-    
-    return wc;
-}
-
-void wallcycle_destroy(gmx_wallcycle_t wc)
-{
-    if (wc == NULL)
-    {
-        return;
-    }
-    
-    if (wc->wcc != NULL)
-    {
-        sfree(wc->wcc);
-    }
-    if (wc->wcc_all != NULL)
-    {
-        sfree(wc->wcc_all);
-    }
-    sfree(wc);
-}
-
-static void wallcycle_all_start(gmx_wallcycle_t wc,int ewc,gmx_cycles_t cycle)
-{
-    wc->ewc_prev = ewc;
-    wc->cycle_prev = cycle;
-}
-
-static void wallcycle_all_stop(gmx_wallcycle_t wc,int ewc,gmx_cycles_t cycle)
-{
-    wc->wcc_all[wc->ewc_prev*ewcNR+ewc].n += 1;
-    wc->wcc_all[wc->ewc_prev*ewcNR+ewc].c += cycle - wc->cycle_prev;
-}
-
-void wallcycle_start(gmx_wallcycle_t wc, int ewc)
-{
-    gmx_cycles_t cycle;
-
-    if (wc == NULL)
-    {
-        return;
-    }
-
-#ifdef GMX_MPI
-    if (wc->wc_barrier)
-    {
-        MPI_Barrier(wc->mpi_comm_mygroup);
-    }
-#endif
-
-    cycle = gmx_cycles_read();
-    wc->wcc[ewc].start = cycle;
-    if (wc->wcc_all != NULL)
-    {
-        wc->wc_depth++;
-        if (ewc == ewcRUN)
-        {
-            wallcycle_all_start(wc,ewc,cycle);
-        }
-        else if (wc->wc_depth == 3)
-        {
-            wallcycle_all_stop(wc,ewc,cycle);
-        }
-    }
-}
-
-double wallcycle_stop(gmx_wallcycle_t wc, int ewc)
-{
-    gmx_cycles_t cycle,last;
-    
-    if (wc == NULL)
-    {
-        return 0;
-    }
-    
-#ifdef GMX_MPI
-    if (wc->wc_barrier)
-    {
-        MPI_Barrier(wc->mpi_comm_mygroup);
-    }
-#endif
-    
-    cycle = gmx_cycles_read();
-    last = cycle - wc->wcc[ewc].start;
-    wc->wcc[ewc].c += last;
-    wc->wcc[ewc].n++;
-    if (wc->wcc_all)
-    {
-        wc->wc_depth--;
-        if (ewc == ewcRUN)
-        {
-            wallcycle_all_stop(wc,ewc,cycle);
-        }
-        else if (wc->wc_depth == 2)
-        {
-            wallcycle_all_start(wc,ewc,cycle);
-        }
-    }
-
-    return last;
-}
-
-void wallcycle_reset_all(gmx_wallcycle_t wc)
-{
-    int i;
-
-    if (wc == NULL)
-    {
-        return;
-    }
-
-    for(i=0; i<ewcNR; i++)
-    {
-        wc->wcc[i].n = 0;
-        wc->wcc[i].c = 0;
-        wc->wcc[i].start = 0;
-        wc->wcc[i].last = 0;
-    }
-}
-
-void wallcycle_sum(t_commrec *cr, gmx_wallcycle_t wc,double cycles[])
-{
-    wallcc_t *wcc;
-    double cycles_n[ewcNR],buf[ewcNR],*cyc_all,*buf_all;
-    int    i;
-
-    if (wc == NULL)
-    {
-        return;
-    }
-
-    wcc = wc->wcc;
-
-    if (wcc[ewcDDCOMMLOAD].n > 0)
-    {
-        wcc[ewcDOMDEC].c -= wcc[ewcDDCOMMLOAD].c;
-    }
-    if (wcc[ewcDDCOMMBOUND].n > 0)
-    {
-        wcc[ewcDOMDEC].c -= wcc[ewcDDCOMMBOUND].c;
-    }
-    if (cr->npmenodes == 0)
-    {
-        /* All nodes do PME (or no PME at all) */
-        if (wcc[ewcPMEMESH].n > 0)
-        {
-            wcc[ewcFORCE].c -= wcc[ewcPMEMESH].c;
-        }
-    }
-    else
-    {
-        /* The are PME-only nodes */
-        if (wcc[ewcPMEMESH].n > 0)
-        {
-            /* This must be a PME only node, calculate the Wait + Comm. time */
-            wcc[ewcPMEWAITCOMM].c = wcc[ewcRUN].c - wcc[ewcPMEMESH].c;
-        }
-    }
-    
-    /* Store the cycles in a double buffer for summing */
-    for(i=0; i<ewcNR; i++)
-    {
-        cycles_n[i] = (double)wcc[i].n;
-        cycles[i]   = (double)wcc[i].c;
-    }
-    
-#ifdef GMX_MPI
-    if (cr->nnodes > 1)
-    {
-        MPI_Allreduce(cycles_n,buf,ewcNR,MPI_DOUBLE,MPI_MAX,
-                      cr->mpi_comm_mysim);
-        for(i=0; i<ewcNR; i++)
-        {
-            wcc[i].n = (int)(buf[i] + 0.5);
-        }
-        MPI_Allreduce(cycles,buf,ewcNR,MPI_DOUBLE,MPI_SUM,
-                      cr->mpi_comm_mysim);
-        for(i=0; i<ewcNR; i++)
-        {
-            cycles[i] = buf[i];
-        }
-
-        if (wc->wcc_all != NULL)
-        {
-            snew(cyc_all,ewcNR*ewcNR);
-            snew(buf_all,ewcNR*ewcNR);
-            for(i=0; i<ewcNR*ewcNR; i++)
-            {
-                cyc_all[i] = wc->wcc_all[i].c;
-            }
-            MPI_Allreduce(cyc_all,buf_all,ewcNR*ewcNR,MPI_DOUBLE,MPI_SUM,
-                          cr->mpi_comm_mysim);
-            for(i=0; i<ewcNR*ewcNR; i++)
-            {
-                wc->wcc_all[i].c = buf_all[i];
-            }
-            sfree(buf_all);
-            sfree(cyc_all);
-        }
-    }
-#endif
-}
-
-static void print_cycles(FILE *fplog, double c2t, const char *name, int nnodes,
-                         int n, double c, double tot)
-{
-    char num[11];
-  
-    if (c > 0)
-    {
-        if (n > 0)
-        {
-            sprintf(num,"%10d",n);
-        }
-        else
-        {
-            sprintf(num,"          ");
-        }
-        fprintf(fplog," %-19s %4d %10s %12.3f %10.1f   %5.1f\n",
-                name,nnodes,num,c*1e-9,c*c2t,100*c/tot);
-    }
-}
-
-static gmx_bool subdivision(int ewc)
-{
-    return (ewc >= ewcPME_REDISTXF && ewc <= ewcPME_SOLVE);
-}
-
-void wallcycle_print(FILE *fplog, int nnodes, int npme, double realtime,
-                     gmx_wallcycle_t wc, double cycles[])
-{
-    double c2t,tot,sum;
-    int    i,j,npp;
-    char   buf[STRLEN];
-    const char *myline = "-----------------------------------------------------------------------";
-    
-    if (wc == NULL)
-    {
-        return;
-    }
-
-    if (npme > 0)
-    {
-        npp = nnodes - npme;
-    }
-    else
-    {
-        npp  = nnodes;
-        npme = nnodes;
-    }
-    tot = cycles[ewcRUN];
-    /* Conversion factor from cycles to seconds */
-    if (tot > 0)
-    {
-      c2t = nnodes*realtime/tot;
-    }
-    else
-    {
-      c2t = 0;
-    }
-
-    fprintf(fplog,"\n     R E A L   C Y C L E   A N D   T I M E   A C C O U N T I N G\n\n");
-
-    fprintf(fplog," Computing:         Nodes     Number     G-Cycles    Seconds     %c\n",'%');
-    fprintf(fplog,"%s\n",myline);
-    sum = 0;
-    for(i=ewcPPDURINGPME+1; i<ewcNR; i++)
-    {
-        if (!subdivision(i))
-        {
-            print_cycles(fplog,c2t,wcn[i],
-                         (i==ewcPMEMESH || i==ewcPMEWAITCOMM) ? npme : npp,
-                         wc->wcc[i].n,cycles[i],tot);
-            sum += cycles[i];
-        }
-    }
-    if (wc->wcc_all != NULL)
-    {
-        for(i=0; i<ewcNR; i++)
-        {
-            for(j=0; j<ewcNR; j++)
-            {
-                sprintf(buf,"%-9s",wcn[i]);
-                buf[9] = ' ';
-                sprintf(buf+10,"%-9s",wcn[j]);
-                buf[19] = '\0';
-                print_cycles(fplog,c2t,buf,
-                             (i==ewcPMEMESH || i==ewcPMEWAITCOMM) ? npme : npp,
-                             wc->wcc_all[i*ewcNR+j].n,
-                             wc->wcc_all[i*ewcNR+j].c,
-                             tot);
-            }
-        }
-    }
-    print_cycles(fplog,c2t,"Rest",npp,0,tot-sum,tot);
-    fprintf(fplog,"%s\n",myline);
-    print_cycles(fplog,c2t,"Total",nnodes,0,tot,tot);
-    fprintf(fplog,"%s\n",myline);
-    
-    if (wc->wcc[ewcPMEMESH].n > 0)
-    {
-        fprintf(fplog,"%s\n",myline);
-        for(i=ewcPPDURINGPME+1; i<ewcNR; i++)
-        {
-            if (subdivision(i))
-            {
-                print_cycles(fplog,c2t,wcn[i],
-                             (i>=ewcPMEMESH || i<=ewcPME_SOLVE) ? npme : npp,
-                             wc->wcc[i].n,cycles[i],tot);
-            }
-        }
-        fprintf(fplog,"%s\n",myline);
-    }
-
-    if (cycles[ewcMoveE] > tot*0.05)
-    {
-        sprintf(buf,
-                "NOTE: %d %% of the run time was spent communicating energies,\n"
-                "      you might want to use the -gcom option of mdrun\n",
-                (int)(100*cycles[ewcMoveE]/tot+0.5));
-        if (fplog)
-        {
-            fprintf(fplog,"\n%s\n",buf);
-        }
-        /* Only the sim master calls this function, so always print to stderr */
-        fprintf(stderr,"\n%s\n",buf);
-    }
-}
-
-extern gmx_large_int_t wcycle_get_reset_counters(gmx_wallcycle_t wc)
-{
-    if (wc == NULL)
-    {
-        return -1;
-    }
-    
-    return wc->reset_counters;
-}
-
-extern void wcycle_set_reset_counters(gmx_wallcycle_t wc, gmx_large_int_t reset_counters)
-{
-    if (wc == NULL)
-        return;
-
-    wc->reset_counters = reset_counters;
-}
diff --git a/src/mdlib/groupcoord.c b/src/mdlib/groupcoord.c
deleted file mode 100644 (file)
index 6ec672b..0000000
+++ /dev/null
@@ -1,394 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 4.5
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Groningen Machine for Chemical Simulation
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include "groupcoord.h"
-#include "mpelogging.h"
-#include "network.h"
-#include "pbc.h"
-#include "vec.h"
-#include "smalloc.h"
-#include "gmx_ga2la.h"
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-
-
-
-/* Select the indices of the group's atoms which are local and store them in 
- * anrs_loc[0..nr_loc]. The indices are saved in coll_ind[] for later reduction
- * in communicate_group_positions()
- */
-extern void dd_make_local_group_indices(
-        gmx_ga2la_t   ga2la,
-        const int     nr,          /* IN:  Total number of atoms in the group */
-        int           anrs[],      /* IN:  Global atom numbers of the groups atoms */
-        int           *nr_loc,     /* OUT: Number of group atoms found locally */
-        int           *anrs_loc[], /* OUT: Local atom numbers of the group  */
-        int           *nalloc_loc, /* IN+OUT: Allocation size of anrs_loc */
-        int           coll_ind[])  /* OUT (opt): Where is this position found in the collective array? */
-{
-    int  i,ii;
-    int  localnr;       
-
-    
-    /* Loop over all the atom indices of the group to check
-     * which ones are on the local node */
-    localnr = 0;
-    for(i=0; i<nr; i++)
-    {
-        if (ga2la_get_home(ga2la,anrs[i],&ii))
-        {
-            /* The atom with this index is a home atom */
-            if (localnr >= *nalloc_loc) /* Check whether memory suffices */
-            {
-                *nalloc_loc = over_alloc_dd(localnr+1);
-                /* We never need more memory than the number of atoms in the group */
-                *nalloc_loc = MIN(*nalloc_loc, nr);
-                srenew(*anrs_loc,*nalloc_loc);
-            }
-            /* Save the atoms index in the local atom numbers array */
-            (*anrs_loc)[localnr] = ii;
-
-            if (coll_ind != NULL)
-            {
-                /* Keep track of where this local atom belongs in the collective index array.
-                 * This is needed when reducing the local arrays to a collective/global array
-                 * in communicate_group_positions */
-                coll_ind[localnr] = i;
-            }
-
-            /* add one to the local atom count */
-            localnr++;
-        }
-    }
-    /* Return the number of local atoms that were found */
-    *nr_loc = localnr;
-}
-
-
-static void get_shifts_group(
-        int    npbcdim, 
-        matrix box,
-        rvec   *xcoll,     /* IN:  Collective set of positions [0..nr] */
-        int    nr,         /* IN:  Total number of atoms in the group */
-        rvec   *xcoll_old, /* IN:  Positions from the last time step [0...nr] */
-        ivec   *shifts)    /* OUT: Shifts for xcoll */
-{
-    int  i,m,d;
-    rvec dx;
-
-
-    /* Get the shifts such that each atom is within closest
-     * distance to its position at the last NS time step after shifting.
-     * If we start with a whole group, and always keep track of 
-     * shift changes, the group will stay whole this way */
-    for (i=0; i < nr; i++)
-        clear_ivec(shifts[i]);
-
-    for (i=0; i<nr; i++)
-    {
-        /* The distance this atom moved since the last time step */
-        /* If this is more than just a bit, it has changed its home pbc box */
-        rvec_sub(xcoll[i],xcoll_old[i],dx);
-
-        for(m=npbcdim-1; m>=0; m--)
-        {
-            while (dx[m] < -0.5*box[m][m])
-            {
-                for(d=0; d<DIM; d++)
-                    dx[d] += box[m][d];
-                shifts[i][m]++;
-            }
-            while (dx[m] >= 0.5*box[m][m])
-            {
-                for(d=0; d<DIM; d++)
-                    dx[d] -= box[m][d];
-                shifts[i][m]--;
-            }
-        }
-    }
-}
-
-
-static void shift_positions_group(
-        matrix box, 
-        rvec   x[],      /* The positions [0..nr] */ 
-        ivec   *is,      /* The shifts [0..nr] */ 
-        int    nr)       /* The number of positions and shifts */
-{
-    int      i,tx,ty,tz;
-
-
-    GMX_MPE_LOG(ev_shift_start);
-
-    /* Loop over the group's atoms */
-    if(TRICLINIC(box)) 
-    {
-        for (i=0; i < nr; i++)
-        {
-            tx=is[i][XX];
-            ty=is[i][YY];
-            tz=is[i][ZZ];
-
-            x[i][XX]=x[i][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
-            x[i][YY]=x[i][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
-            x[i][ZZ]=x[i][ZZ]+tz*box[ZZ][ZZ];
-        }
-    } else
-    {
-        for (i=0; i < nr; i++)
-        {
-            tx=is[i][XX];
-            ty=is[i][YY];
-            tz=is[i][ZZ];
-
-            x[i][XX]=x[i][XX]+tx*box[XX][XX];
-            x[i][YY]=x[i][YY]+ty*box[YY][YY];
-            x[i][ZZ]=x[i][ZZ]+tz*box[ZZ][ZZ];
-        }
-    }    
-    GMX_MPE_LOG(ev_shift_finish);
-}
-
-
-/* Assemble the positions of the group such that every node has all of them. 
- * The atom indices are retrieved from anrs_loc[0..nr_loc] 
- * Note that coll_ind[i] = i is needed in the serial case */
-extern void communicate_group_positions(
-        t_commrec  *cr, 
-        rvec       *xcoll,        /* OUT: Collective array of positions */
-        ivec       *shifts,       /* IN+OUT: Collective array of shifts for xcoll */
-        ivec       *extra_shifts, /* BUF: Extra shifts since last time step */
-        const gmx_bool bNS,           /* IN:  NS step, the shifts have changed */
-        rvec       *x_loc,        /* IN:  Local positions on this node */ 
-        const int  nr,            /* IN:  Total number of atoms in the group */
-        const int  nr_loc,        /* IN:  Local number of atoms in the group */
-        int        *anrs_loc,     /* IN:  Local atom numbers */
-        int        *coll_ind,     /* IN:  Collective index */
-        rvec       *xcoll_old,    /* IN+OUT: Positions from the last time step, used to make group whole */
-        matrix     box)
-{
-    int i;
-
-
-    GMX_MPE_LOG(ev_get_group_x_start);
-
-    /* Zero out the groups' global position array */
-    clear_rvecs(nr, xcoll);
-
-    /* Put the local positions that this node has into the right place of 
-     * the collective array. Note that in the serial case, coll_ind[i] = i */
-    for (i=0; i<nr_loc; i++)
-        copy_rvec(x_loc[anrs_loc[i]], xcoll[coll_ind[i]]);
-
-    if (PAR(cr))
-    {
-        /* Add the arrays from all nodes together */
-        gmx_sum(nr*3, xcoll[0], cr);
-
-        /* To make the group whole, start with a whole group and each
-         * step move the assembled positions at closest distance to the positions 
-         * from the last step. First shift the positions with the saved shift 
-         * vectors (these are 0 when this routine is called for the first time!) */
-        shift_positions_group(box, xcoll, shifts, nr);
-        
-        /* Now check if some shifts changed since the last step.
-         * This only needs to be done when the shifts are expected to have changed,
-         * i.e. after neighboursearching */
-        if (bNS) 
-        {
-            get_shifts_group(3, box, xcoll, nr, xcoll_old, extra_shifts);
-            
-            /* Shift with the additional shifts such that we get a whole group now */
-            shift_positions_group(box, xcoll, extra_shifts, nr);
-            
-            /* Add the shift vectors together for the next time step */
-            for (i=0; i<nr; i++)
-            {
-                shifts[i][XX] += extra_shifts[i][XX];
-                shifts[i][YY] += extra_shifts[i][YY];
-                shifts[i][ZZ] += extra_shifts[i][ZZ];
-            }
-            
-            /* Store current correctly-shifted positions for comparison in the next NS time step */
-            for (i=0; i<nr; i++)
-                copy_rvec(xcoll[i],xcoll_old[i]);   
-        }
-    }
-    
-    GMX_MPE_LOG(ev_get_group_x_finish);
-}
-
-
-/* Determine the (weighted) sum vector from positions x */
-extern double get_sum_of_positions(rvec x[], real weight[], const int nat, dvec dsumvec)
-{
-    int i;
-    rvec x_weighted;
-    double weight_sum = 0.0;
-
-
-    /* Zero out the center */
-    clear_dvec(dsumvec);
-
-    /* Loop over all atoms and add their weighted position vectors */
-    if (weight != NULL)
-    {
-        for (i=0; i<nat; i++)
-        {
-            weight_sum += weight[i];
-            svmul(weight[i], x[i], x_weighted);
-            dsumvec[XX] += x_weighted[XX];
-            dsumvec[YY] += x_weighted[YY];
-            dsumvec[ZZ] += x_weighted[ZZ];
-        }
-    }
-    else
-    {
-        for (i=0; i<nat; i++)
-        {
-            dsumvec[XX] += x[i][XX];
-            dsumvec[YY] += x[i][YY];
-            dsumvec[ZZ] += x[i][ZZ];
-        }
-    }
-    return weight_sum;
-}
-
-
-/* Determine center of structure from collective positions x */
-extern void get_center(rvec x[], real weight[], const int nr, rvec rcenter)
-{
-    dvec   dcenter;
-    double weight_sum, denom;
-
-    
-    weight_sum = get_sum_of_positions(x, weight, nr, dcenter);
-    
-    if (weight != NULL)
-        denom = weight_sum; /* Divide by the sum of weight */
-    else
-        denom = nr;        /* Divide by the number of atoms */
-        
-    dsvmul(1.0/denom, dcenter, dcenter);
-    
-    rcenter[XX] = dcenter[XX];
-    rcenter[YY] = dcenter[YY];
-    rcenter[ZZ] = dcenter[ZZ];
-}
-
-
-/* Get the center from local positions that already have the correct
- * PBC representation */
-extern void get_center_comm(
-        t_commrec *cr,
-        rvec x_loc[],       /* Local positions */
-        real weight_loc[],  /* Local masses or other weights */
-        int nr_loc,         /* Local number of atoms */
-        int nr_group,       /* Total number of atoms of the group */ 
-        rvec center)        /* Weighted center */
-{
-    double weight_sum, denom;
-    dvec   dsumvec;
-    double buf[4];    
-    
-    
-    weight_sum = get_sum_of_positions(x_loc, weight_loc, nr_loc, dsumvec);
-    
-    /* Add the local contributions from all nodes. Put the sum vector and the 
-     * weight in a buffer array so that we get along with a single communication
-     * call. */
-    if (PAR(cr))
-    {
-        buf[0] = dsumvec[XX];
-        buf[1] = dsumvec[YY];
-        buf[2] = dsumvec[ZZ];
-        buf[3] = weight_sum;
-        
-        /* Communicate buffer */
-        gmx_sumd(4, buf, cr);
-        
-        dsumvec[XX] = buf[0];
-        dsumvec[YY] = buf[1];
-        dsumvec[ZZ] = buf[2];
-        weight_sum  = buf[3];
-    }
-    
-    if (weight_loc != NULL)
-        denom = 1.0/weight_sum; /* Divide by the sum of weight to get center of mass e.g. */
-    else
-        denom = 1.0/nr_group;   /* Divide by the number of atoms to get the geometrical center */
-        
-    center[XX] = dsumvec[XX]*denom;
-    center[YY] = dsumvec[YY]*denom;
-    center[ZZ] = dsumvec[ZZ]*denom;
-}
-
-
-/* Translate x with transvec */
-extern void translate_x(rvec x[], const int nr, const rvec transvec)
-{
-    int i;
-    
-    
-    for (i=0; i<nr; i++)
-        rvec_inc(x[i], transvec);
-}
-
-
-extern void rotate_x(rvec x[], const int nr, matrix rmat)
-{
-    int i,j,k;
-    rvec x_old;
-
-    
-    /* Apply the rotation matrix */
-    for (i=0; i<nr; i++)
-    {
-        for (j=0; j<3; j++)
-            x_old[j] = x[i][j];
-        for (j=0; j<3; j++)
-        {
-            x[i][j] = 0;
-            for (k=0; k<3; k++)
-                x[i][j] += rmat[k][j]*x_old[k];
-        }
-    }
-}
-
diff --git a/src/mdlib/libmd.pc.cmakein b/src/mdlib/libmd.pc.cmakein
deleted file mode 100644 (file)
index 0006b96..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-libdir=@LIB_INSTALL_DIR@
-includedir=@INCL_INSTALL_DIR@
-
-Name: libmd
-Description: Gromacs md lib
-URL: http://www.gromacs.org
-Version: @PROJECT_VERSION@
-Requires: libgmx@GMX_LIBS_SUFFIX@ @PKG_FFT@ @PKG_XML@
-Libs.private: -lm @CMAKE_THREAD_LIBS_INIT@
-Libs: -L${libdir} -lmd@GMX_LIBS_SUFFIX@ @PKG_FFT_LIBS@
-Cflags: -I${includedir} @PKG_CFLAGS@
-
diff --git a/src/mdlib/md_support.c b/src/mdlib/md_support.c
deleted file mode 100644 (file)
index 7551a76..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-/* _isnan() */
-#include <float.h>
-#endif
-
-#include "typedefs.h"
-#include "string2.h"
-#include "smalloc.h"
-#include "mdrun.h"
-#include "domdec.h"
-#include "mtop_util.h"
-#include "gmx_wallcycle.h"
-#include "vcm.h"
-#include "nrnb.h"
-
-/* Is the signal in one simulation independent of other simulations? */
-gmx_bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
-
-/* check which of the multisim simulations has the shortest number of
-   steps and return that number of nsteps */
-gmx_large_int_t get_multisim_nsteps(const t_commrec *cr,
-                                    gmx_large_int_t nsteps)
-{
-    gmx_large_int_t steps_out;
-
-    if MASTER(cr)
-    {
-        gmx_large_int_t *buf;
-        int s;
-
-        snew(buf,cr->ms->nsim);
-
-        buf[cr->ms->sim] = nsteps;
-        gmx_sumli_sim(cr->ms->nsim, buf, cr->ms);
-
-        steps_out=-1;
-        for(s=0; s<cr->ms->nsim; s++)
-        {
-            /* find the smallest positive number */
-            if (buf[s]>= 0 && ((steps_out < 0) || (buf[s]<steps_out)) )
-            {
-                steps_out=buf[s];
-            }
-        }
-        sfree(buf);
-
-        /* if we're the limiting simulation, don't do anything */
-        if (steps_out>=0 && steps_out<nsteps) 
-        {
-            char strbuf[255];
-            snprintf(strbuf, 255, "Will stop simulation %%d after %s steps (another simulation will end then).\n", gmx_large_int_pfmt);
-            fprintf(stderr, strbuf, cr->ms->sim, steps_out);
-        }
-    }
-    /* broadcast to non-masters */
-    gmx_bcast(sizeof(gmx_large_int_t), &steps_out, cr);
-    return steps_out;
-}
-
-int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
-{
-    int  *buf;
-    gmx_bool bPos,bEqual;
-    int  s,d;
-
-    snew(buf,ms->nsim);
-    buf[ms->sim] = n;
-    gmx_sumi_sim(ms->nsim,buf,ms);
-    bPos   = TRUE;
-    bEqual = TRUE;
-    for(s=0; s<ms->nsim; s++)
-    {
-        bPos   = bPos   && (buf[s] > 0);
-        bEqual = bEqual && (buf[s] == buf[0]);
-    }
-    if (bPos)
-    {
-        if (bEqual)
-        {
-            nmin = min(nmin,buf[0]);
-        }
-        else
-        {
-            /* Find the least common multiple */
-            for(d=2; d<nmin; d++)
-            {
-                s = 0;
-                while (s < ms->nsim && d % buf[s] == 0)
-                {
-                    s++;
-                }
-                if (s == ms->nsim)
-                {
-                    /* We found the LCM and it is less than nmin */
-                    nmin = d;
-                    break;
-                }
-            }
-        }
-    }
-    sfree(buf);
-
-    return nmin;
-}
-
-int multisim_nstsimsync(const t_commrec *cr,
-                        const t_inputrec *ir,int repl_ex_nst)
-{
-    int nmin;
-
-    if (MASTER(cr))
-    {
-        nmin = INT_MAX;
-        nmin = multisim_min(cr->ms,nmin,ir->nstlist);
-        nmin = multisim_min(cr->ms,nmin,ir->nstcalcenergy);
-        nmin = multisim_min(cr->ms,nmin,repl_ex_nst);
-        if (nmin == INT_MAX)
-        {
-            gmx_fatal(FARGS,"Can not find an appropriate interval for inter-simulation communication, since nstlist, nstcalcenergy and -replex are all <= 0");
-        }
-        /* Avoid inter-simulation communication at every (second) step */
-        if (nmin <= 2)
-        {
-            nmin = 10;
-        }
-    }
-
-    gmx_bcast(sizeof(int),&nmin,cr);
-
-    return nmin;
-}
-
-void init_global_signals(globsig_t *gs,const t_commrec *cr,
-                         const t_inputrec *ir,int repl_ex_nst)
-{
-    int i;
-
-    if (MULTISIM(cr))
-    {
-        gs->nstms = multisim_nstsimsync(cr,ir,repl_ex_nst);
-        if (debug)
-        {
-            fprintf(debug,"Syncing simulations for checkpointing and termination every %d steps\n",gs->nstms);
-        }
-    }
-    else
-    {
-        gs->nstms = 1;
-    }
-
-    for(i=0; i<eglsNR; i++)
-    {
-        gs->sig[i] = 0;
-        gs->set[i] = 0;
-    }
-}
-
-void copy_coupling_state(t_state *statea,t_state *stateb, 
-                         gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts) 
-{
-    
-    /* MRS note -- might be able to get rid of some of the arguments.  Look over it when it's all debugged */
-    
-    int i,j,nc;
-
-    /* Make sure we have enough space for x and v */
-    if (statea->nalloc > stateb->nalloc)
-    {
-        stateb->nalloc = statea->nalloc;
-        srenew(stateb->x,stateb->nalloc);
-        srenew(stateb->v,stateb->nalloc);
-    }
-
-    stateb->natoms     = statea->natoms;
-    stateb->ngtc       = statea->ngtc;
-    stateb->nnhpres    = statea->nnhpres;
-    stateb->veta       = statea->veta;
-    if (ekinda) 
-    {
-        copy_mat(ekinda->ekin,ekindb->ekin);
-        for (i=0; i<stateb->ngtc; i++) 
-        {
-            ekindb->tcstat[i].T = ekinda->tcstat[i].T;
-            ekindb->tcstat[i].Th = ekinda->tcstat[i].Th;
-            copy_mat(ekinda->tcstat[i].ekinh,ekindb->tcstat[i].ekinh);
-            copy_mat(ekinda->tcstat[i].ekinf,ekindb->tcstat[i].ekinf);
-            ekindb->tcstat[i].ekinscalef_nhc =  ekinda->tcstat[i].ekinscalef_nhc;
-            ekindb->tcstat[i].ekinscaleh_nhc =  ekinda->tcstat[i].ekinscaleh_nhc;
-            ekindb->tcstat[i].vscale_nhc =  ekinda->tcstat[i].vscale_nhc;
-        }
-    }
-    copy_rvecn(statea->x,stateb->x,0,stateb->natoms);
-    copy_rvecn(statea->v,stateb->v,0,stateb->natoms);
-    copy_mat(statea->box,stateb->box);
-    copy_mat(statea->box_rel,stateb->box_rel);
-    copy_mat(statea->boxv,stateb->boxv);
-
-    for (i = 0; i<stateb->ngtc; i++) 
-    { 
-        nc = i*opts->nhchainlength;
-        for (j=0; j<opts->nhchainlength; j++) 
-        {
-            stateb->nosehoover_xi[nc+j]  = statea->nosehoover_xi[nc+j];
-            stateb->nosehoover_vxi[nc+j] = statea->nosehoover_vxi[nc+j];
-        }
-    }
-    if (stateb->nhpres_xi != NULL)
-    {
-        for (i = 0; i<stateb->nnhpres; i++) 
-        {
-            nc = i*opts->nhchainlength;
-            for (j=0; j<opts->nhchainlength; j++) 
-            {
-                stateb->nhpres_xi[nc+j]  = statea->nhpres_xi[nc+j];
-                stateb->nhpres_vxi[nc+j] = statea->nhpres_vxi[nc+j];
-            }
-        }
-    }
-}
-
-real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state, t_extmass *MassQ)
-{
-    real quantity = 0;
-    switch (ir->etc) 
-    {
-    case etcNO:
-        break;
-    case etcBERENDSEN:
-        break;
-    case etcNOSEHOOVER:
-        quantity = NPT_energy(ir,state,MassQ);                
-        break;
-    case etcVRESCALE:
-        quantity = vrescale_energy(&(ir->opts),state->therm_integral);
-        break;
-    default:
-        break;
-    }
-    return quantity;
-}
-
-void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir, 
-                     t_forcerec *fr, gmx_ekindata_t *ekind, 
-                     t_state *state, t_state *state_global, t_mdatoms *mdatoms, 
-                     t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
-                     gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir, 
-                     tensor pres, rvec mu_tot, gmx_constr_t constr, 
-                     globsig_t *gs,gmx_bool bInterSimGS,
-                     matrix box, gmx_mtop_t *top_global, real *pcurr, 
-                     int natoms, gmx_bool *bSumEkinhOld, int flags)
-{
-    int  i,gsi;
-    real gs_buf[eglsNR];
-    tensor corr_vir,corr_pres,shakeall_vir;
-    gmx_bool bEner,bPres,bTemp, bVV;
-    gmx_bool bRerunMD, bStopCM, bGStat, bIterate, 
-        bFirstIterate,bReadEkin,bEkinAveVel,bScaleEkin, bConstrain;
-    real ekin,temp,prescorr,enercorr,dvdlcorr;
-    
-    /* translate CGLO flags to gmx_booleans */
-    bRerunMD = flags & CGLO_RERUNMD;
-    bStopCM = flags & CGLO_STOPCM;
-    bGStat = flags & CGLO_GSTAT;
-
-    bReadEkin = (flags & CGLO_READEKIN);
-    bScaleEkin = (flags & CGLO_SCALEEKIN);
-    bEner = flags & CGLO_ENERGY;
-    bTemp = flags & CGLO_TEMPERATURE;
-    bPres  = (flags & CGLO_PRESSURE);
-    bConstrain = (flags & CGLO_CONSTRAINT);
-    bIterate = (flags & CGLO_ITERATE);
-    bFirstIterate = (flags & CGLO_FIRSTITERATE);
-
-    /* we calculate a full state kinetic energy either with full-step velocity verlet
-       or half step where we need the pressure */
-    
-    bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && bPres) || bReadEkin);
-    
-    /* in initalization, it sums the shake virial in vv, and to 
-       sums ekinh_old in leapfrog (or if we are calculating ekinh_old) for other reasons */
-
-    /* ########## Kinetic energy  ############## */
-    
-    if (bTemp) 
-    {
-        /* Non-equilibrium MD: this is parallellized, but only does communication
-         * when there really is NEMD.
-         */
-        
-        if (PAR(cr) && (ekind->bNEMD)) 
-        {
-            accumulate_u(cr,&(ir->opts),ekind);
-        }
-        debug_gmx();
-        if (bReadEkin)
-        {
-            restore_ekinstate_from_state(cr,ekind,&state_global->ekinstate);
-        }
-        else 
-        {
-
-            calc_ke_part(state,&(ir->opts),mdatoms,ekind,nrnb,bEkinAveVel,bIterate);
-        }
-        
-        debug_gmx();
-        
-        /* Calculate center of mass velocity if necessary, also parallellized */
-        if (bStopCM && !bRerunMD && bEner) 
-        {
-            calc_vcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms,
-                         state->x,state->v,vcm);
-        }
-    }
-
-    if (bTemp || bPres || bEner || bConstrain) 
-    {
-        if (!bGStat)
-        {
-            /* We will not sum ekinh_old,                                                            
-             * so signal that we still have to do it.                                                
-             */
-            *bSumEkinhOld = TRUE;
-
-        }
-        else
-        {
-            if (gs != NULL)
-            {
-                for(i=0; i<eglsNR; i++)
-                {
-                    gs_buf[i] = gs->sig[i];
-                }
-            }
-            if (PAR(cr)) 
-            {
-                wallcycle_start(wcycle,ewcMoveE);
-                GMX_MPE_LOG(ev_global_stat_start);
-                global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
-                            ir,ekind,constr,vcm,
-                            gs != NULL ? eglsNR : 0,gs_buf,
-                            top_global,state,
-                            *bSumEkinhOld,flags);
-                GMX_MPE_LOG(ev_global_stat_finish);
-                wallcycle_stop(wcycle,ewcMoveE);
-            }
-            if (gs != NULL)
-            {
-                if (MULTISIM(cr) && bInterSimGS)
-                {
-                    if (MASTER(cr))
-                    {
-                        /* Communicate the signals between the simulations */
-                        gmx_sum_sim(eglsNR,gs_buf,cr->ms);
-                    }
-                    /* Communicate the signals form the master to the others */
-                    gmx_bcast(eglsNR*sizeof(gs_buf[0]),gs_buf,cr);
-                }
-                for(i=0; i<eglsNR; i++)
-                {
-                    if (bInterSimGS || gs_simlocal[i])
-                    {
-                        /* Set the communicated signal only when it is non-zero,
-                         * since signals might not be processed at each MD step.
-                         */
-                        gsi = (gs_buf[i] >= 0 ?
-                               (int)(gs_buf[i] + 0.5) :
-                               (int)(gs_buf[i] - 0.5));
-                        if (gsi != 0)
-                        {
-                            gs->set[i] = gsi;
-                        }
-                        /* Turn off the local signal */
-                        gs->sig[i] = 0;
-                    }
-                }
-            }
-            *bSumEkinhOld = FALSE;
-        }
-    }
-    
-    if (!ekind->bNEMD && debug && bTemp && (vcm->nr > 0))
-    {
-        correct_ekin(debug,
-                     mdatoms->start,mdatoms->start+mdatoms->homenr,
-                     state->v,vcm->group_p[0],
-                     mdatoms->massT,mdatoms->tmass,ekind->ekin);
-    }
-    
-    if (bEner) {
-        /* Do center of mass motion removal */
-        if (bStopCM && !bRerunMD) /* is this correct?  Does it get called too often with this logic? */
-        {
-            check_cm_grp(fplog,vcm,ir,1);
-            do_stopcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms->cVCM,
-                          state->x,state->v,vcm);
-            inc_nrnb(nrnb,eNR_STOPCM,mdatoms->homenr);
-        }
-
-        /* Calculate the amplitude of the cosine velocity profile */
-        ekind->cosacc.vcos = ekind->cosacc.mvcos/mdatoms->tmass;
-    }
-
-    if (bTemp) 
-    {
-        /* Sum the kinetic energies of the groups & calc temp */
-        /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
-        /* three maincase:  VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).  
-           Leap with AveVel is not supported; it's not clear that it will actually work.  
-           bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy. 
-           If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
-           bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.  
-           If FALSE, we go ahead and erase over it.
-        */ 
-        enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,&(enerd->term[F_DKDL]),
-                                       bEkinAveVel,bIterate,bScaleEkin);
-        enerd->term[F_EKIN] = trace(ekind->ekin);
-    }
-    
-    /* ##########  Long range energy information ###### */
-    
-    if (bEner || bPres || bConstrain) 
-    {
-        calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda,
-                      corr_pres,corr_vir,&prescorr,&enercorr,&dvdlcorr);
-    }
-    
-    if (bEner && bFirstIterate) 
-    {
-        enerd->term[F_DISPCORR] = enercorr;
-        enerd->term[F_EPOT] += enercorr;
-        enerd->term[F_DVDL] += dvdlcorr;
-        if (fr->efep != efepNO) {
-            enerd->dvdl_lin += dvdlcorr;
-        }
-    }
-    
-    /* ########## Now pressure ############## */
-    if (bPres || bConstrain) 
-    {
-        
-        m_add(force_vir,shake_vir,total_vir);
-        
-        /* Calculate pressure and apply LR correction if PPPM is used.
-         * Use the box from last timestep since we already called update().
-         */
-        
-        enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres,
-                                        (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
-        
-        /* Calculate long range corrections to pressure and energy */
-        /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT], 
-           and computes enerd->term[F_DISPCORR].  Also modifies the 
-           total_vir and pres tesors */
-        
-        m_add(total_vir,corr_vir,total_vir);
-        m_add(pres,corr_pres,pres);
-        enerd->term[F_PDISPCORR] = prescorr;
-        enerd->term[F_PRES] += prescorr;
-        *pcurr = enerd->term[F_PRES];
-        /* calculate temperature using virial */
-        enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
-        
-    }    
-}
-
-void check_nst_param(FILE *fplog,t_commrec *cr,
-                     const char *desc_nst,int nst,
-                     const char *desc_p,int *p)
-{
-    char buf[STRLEN];
-
-    if (*p > 0 && *p % nst != 0)
-    {
-        /* Round up to the next multiple of nst */
-        *p = ((*p)/nst + 1)*nst;
-        sprintf(buf,"NOTE: %s changes %s to %d\n",desc_nst,desc_p,*p);
-        md_print_warning(cr,fplog,buf);
-    }
-}
-
-void reset_all_counters(FILE *fplog,t_commrec *cr,
-                        gmx_large_int_t step,
-                        gmx_large_int_t *step_rel,t_inputrec *ir,
-                        gmx_wallcycle_t wcycle,t_nrnb *nrnb,
-                        gmx_runtime_t *runtime)
-{
-    char buf[STRLEN],sbuf[STEPSTRSIZE];
-
-    /* Reset all the counters related to performance over the run */
-    sprintf(buf,"Step %s: resetting all time and cycle counters\n",
-            gmx_step_str(step,sbuf));
-    md_print_warning(cr,fplog,buf);
-
-    wallcycle_stop(wcycle,ewcRUN);
-    wallcycle_reset_all(wcycle);
-    if (DOMAINDECOMP(cr))
-    {
-        reset_dd_statistics_counters(cr->dd);
-    }
-    init_nrnb(nrnb);
-    ir->init_step += *step_rel;
-    ir->nsteps    -= *step_rel;
-    *step_rel = 0;
-    wallcycle_start(wcycle,ewcRUN);
-    runtime_start(runtime);
-    print_date_and_time(fplog,cr->nodeid,"Restarted time",runtime);
-}
-
-void min_zero(int *n,int i)
-{
-    if (i > 0 && (*n == 0 || i < *n))
-    {
-        *n = i;
-    }
-}
-
-int lcd4(int i1,int i2,int i3,int i4)
-{
-    int nst;
-
-    nst = 0;
-    min_zero(&nst,i1);
-    min_zero(&nst,i2);
-    min_zero(&nst,i3);
-    min_zero(&nst,i4);
-    if (nst == 0)
-    {
-        gmx_incons("All 4 inputs for determininig nstglobalcomm are <= 0");
-    }
-    
-    while (nst > 1 && ((i1 > 0 && i1 % nst != 0)  ||
-                       (i2 > 0 && i2 % nst != 0)  ||
-                       (i3 > 0 && i3 % nst != 0)  ||
-                       (i4 > 0 && i4 % nst != 0)))
-    {
-        nst--;
-    }
-
-    return nst;
-}
-
-int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
-                        int nstglobalcomm,t_inputrec *ir)
-{
-    char buf[STRLEN];
-
-    if (!EI_DYNAMICS(ir->eI))
-    {
-        nstglobalcomm = 1;
-    }
-
-    if (nstglobalcomm == -1)
-    {
-        if (!(ir->nstcalcenergy > 0 ||
-              ir->nstlist > 0 ||
-              ir->etc != etcNO ||
-              ir->epc != epcNO))
-        {
-            nstglobalcomm = 10;
-            if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm)
-            {
-                nstglobalcomm = ir->nstenergy;
-            }
-        }
-        else
-        {
-            /* Ensure that we do timely global communication for
-             * (possibly) each of the four following options.
-             */
-            nstglobalcomm = lcd4(ir->nstcalcenergy,
-                                 ir->nstlist,
-                                 ir->etc != etcNO ? ir->nsttcouple : 0,
-                                 ir->epc != epcNO ? ir->nstpcouple : 0);
-        }
-    }
-    else
-    {
-        if (ir->nstlist > 0 &&
-            nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0)
-        {
-            nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist;
-            sprintf(buf,"WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n",nstglobalcomm);
-            md_print_warning(cr,fplog,buf);
-        }
-        if (ir->nstcalcenergy > 0)
-        {
-            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
-                            "nstcalcenergy",&ir->nstcalcenergy);
-        }
-        if (ir->etc != etcNO && ir->nsttcouple > 0)
-        {
-            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
-                            "nsttcouple",&ir->nsttcouple);
-        }
-        if (ir->epc != epcNO && ir->nstpcouple > 0)
-        {
-            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
-                            "nstpcouple",&ir->nstpcouple);
-        }
-
-        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
-                        "nstenergy",&ir->nstenergy);
-
-        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
-                        "nstlog",&ir->nstlog);
-    }
-
-    if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm)
-    {
-        sprintf(buf,"WARNING: Changing nstcomm from %d to %d\n",
-                ir->nstcomm,nstglobalcomm);
-        md_print_warning(cr,fplog,buf);
-        ir->nstcomm = nstglobalcomm;
-    }
-
-    return nstglobalcomm;
-}
-
-void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
-                               t_inputrec *ir,gmx_mtop_t *mtop)
-{
-    /* Check required for old tpx files */
-    if (IR_TWINRANGE(*ir) && ir->nstlist > 1 &&
-        ir->nstcalcenergy % ir->nstlist != 0)
-    {
-        md_print_warning(cr,fplog,"Old tpr file with twin-range settings: modifying energy calculation and/or T/P-coupling frequencies");
-
-        if (gmx_mtop_ftype_count(mtop,F_CONSTR) +
-            gmx_mtop_ftype_count(mtop,F_CONSTRNC) > 0 &&
-            ir->eConstrAlg == econtSHAKE)
-        {
-            md_print_warning(cr,fplog,"With twin-range cut-off's and SHAKE the virial and pressure are incorrect");
-            if (ir->epc != epcNO)
-            {
-                gmx_fatal(FARGS,"Can not do pressure coupling with twin-range cut-off's and SHAKE");
-            }
-        }
-        check_nst_param(fplog,cr,"nstlist",ir->nstlist,
-                        "nstcalcenergy",&ir->nstcalcenergy);
-        if (ir->epc != epcNO)
-        {
-            check_nst_param(fplog,cr,"nstlist",ir->nstlist,
-                            "nstpcouple",&ir->nstpcouple);
-        }
-        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                        "nstenergy",&ir->nstenergy);
-        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                        "nstlog",&ir->nstlog);
-        if (ir->efep != efepNO)
-        {
-            check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                            "nstdhdl",&ir->nstdhdl);
-        }
-    }
-}
-
-void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
-                         gmx_bool *bNotLastFrame)
-{
-    gmx_bool bAlloc;
-    rvec *xp,*vp;
-
-    bAlloc = (fr->natoms == 0);
-
-    if (MASTER(cr) && !*bNotLastFrame)
-    {
-        fr->natoms = -1;
-    }
-    xp = fr->x;
-    vp = fr->v;
-    gmx_bcast(sizeof(*fr),fr,cr);
-    fr->x = xp;
-    fr->v = vp;
-
-    *bNotLastFrame = (fr->natoms >= 0);
-
-    if (*bNotLastFrame && PARTDECOMP(cr))
-    {
-        /* x and v are the only variable size quantities stored in trr
-         * that are required for rerun (f is not needed).
-         */
-        if (bAlloc)
-        {
-            snew(fr->x,fr->natoms);
-            snew(fr->v,fr->natoms);
-        }
-        if (fr->bX)
-        {
-            gmx_bcast(fr->natoms*sizeof(fr->x[0]),fr->x[0],cr);
-        }
-        if (fr->bV)
-        {
-            gmx_bcast(fr->natoms*sizeof(fr->v[0]),fr->v[0],cr);
-        }
-    }
-}
-
-void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf)
-{
-    if (MASTER(cr))
-    {
-        fprintf(stderr,"\n%s\n",buf);
-    }
-    if (fplog)
-    {
-        fprintf(fplog,"\n%s\n",buf);
-    }
-}
diff --git a/src/mdlib/mdebin.c b/src/mdlib/mdebin.c
deleted file mode 100644 (file)
index 7e102e1..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <float.h>
-#include "typedefs.h"
-#include "string2.h"
-#include "mdebin.h"
-#include "smalloc.h"
-#include "physics.h"
-#include "enxio.h"
-#include "vec.h"
-#include "disre.h"
-#include "main.h"
-#include "network.h"
-#include "names.h"
-#include "orires.h"
-#include "constr.h"
-#include "mtop_util.h"
-#include "xvgr.h"
-#include "gmxfio.h"
-
-#include "mdebin_bar.h"
-
-
-static const char *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
-
-static const char *boxs_nm[] = { "Box-X", "Box-Y", "Box-Z" };
-
-static const char *tricl_boxs_nm[] = { 
-    "Box-XX", "Box-YY", "Box-ZZ",
-    "Box-YX", "Box-ZX", "Box-ZY" 
-};
-
-static const char *vol_nm[] = { "Volume" };
-
-static const char *dens_nm[] = {"Density" };
-
-static const char *pv_nm[] = {"pV" };
-
-static const char *enthalpy_nm[] = {"Enthalpy" };
-
-static const char *boxvel_nm[] = {
-    "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
-    "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY"
-};
-
-#define NBOXS asize(boxs_nm)
-#define NTRICLBOXS asize(tricl_boxs_nm)
-
-
-t_mdebin *init_mdebin(ener_file_t fp_ene,
-                      const gmx_mtop_t *mtop,
-                      const t_inputrec *ir,
-                      FILE *fp_dhdl)
-{
-    const char *ener_nm[F_NRE];
-    static const char *vir_nm[] = {
-        "Vir-XX", "Vir-XY", "Vir-XZ",
-        "Vir-YX", "Vir-YY", "Vir-YZ",
-        "Vir-ZX", "Vir-ZY", "Vir-ZZ"
-    };
-    static const char *sv_nm[] = {
-        "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
-        "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
-        "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
-    };
-    static const char *fv_nm[] = {
-        "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
-        "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
-        "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
-    };
-    static const char *pres_nm[] = {
-        "Pres-XX","Pres-XY","Pres-XZ",
-        "Pres-YX","Pres-YY","Pres-YZ",
-        "Pres-ZX","Pres-ZY","Pres-ZZ"
-    };
-    static const char *surft_nm[] = {
-        "#Surf*SurfTen"
-    };
-    static const char *mu_nm[] = {
-        "Mu-X", "Mu-Y", "Mu-Z"
-    };
-    static const char *vcos_nm[] = {
-        "2CosZ*Vel-X"
-    };
-    static const char *visc_nm[] = {
-        "1/Viscosity"
-    };
-    static const char *baro_nm[] = {
-        "Barostat"
-    };
-
-    char     **grpnms;
-    const gmx_groups_t *groups;
-    char     **gnm;
-    char     buf[256];
-    const char     *bufi;
-    t_mdebin *md;
-    int      i,j,ni,nj,n,nh,k,kk,ncon,nset;
-    gmx_bool     bBHAM,bNoseHoover,b14;
-
-    snew(md,1);
-
-    if (EI_DYNAMICS(ir->eI))
-    {
-        md->delta_t = ir->delta_t;
-    }
-    else
-    {
-        md->delta_t = 0;
-    }
-
-    groups = &mtop->groups;
-
-    bBHAM = (mtop->ffparams.functype[0] == F_BHAM);
-    b14   = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 ||
-             gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0);
-
-    ncon = gmx_mtop_ftype_count(mtop,F_CONSTR);
-    nset = gmx_mtop_ftype_count(mtop,F_SETTLE);
-    md->bConstr    = (ncon > 0 || nset > 0);
-    md->bConstrVir = FALSE;
-    if (md->bConstr) {
-        if (ncon > 0 && ir->eConstrAlg == econtLINCS) {
-            if (ir->eI == eiSD2)
-                md->nCrmsd = 2;
-            else
-                md->nCrmsd = 1;
-        }
-        md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL);
-    } else {
-        md->nCrmsd = 0;
-    }
-
-    /* Energy monitoring */
-    for(i=0;i<egNR;i++)
-    {
-        md->bEInd[i]=FALSE;
-    }
-
-#ifndef GMX_OPENMM
-    for(i=0; i<F_NRE; i++)
-    {
-        md->bEner[i] = FALSE;
-        if (i == F_LJ)
-            md->bEner[i] = !bBHAM;
-        else if (i == F_BHAM)
-            md->bEner[i] = bBHAM;
-        else if (i == F_EQM)
-            md->bEner[i] = ir->bQMMM;
-        else if (i == F_COUL_LR)
-            md->bEner[i] = (ir->rcoulomb > ir->rlist);
-        else if (i == F_LJ_LR)
-            md->bEner[i] = (!bBHAM && ir->rvdw > ir->rlist);
-        else if (i == F_BHAM_LR)
-            md->bEner[i] = (bBHAM && ir->rvdw > ir->rlist);
-        else if (i == F_RF_EXCL)
-            md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC);
-        else if (i == F_COUL_RECIP)
-            md->bEner[i] = EEL_FULL(ir->coulombtype);
-        else if (i == F_LJ14)
-            md->bEner[i] = b14;
-        else if (i == F_COUL14)
-            md->bEner[i] = b14;
-        else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
-            md->bEner[i] = FALSE;
-        else if ((i == F_DVDL) || (i == F_DKDL))
-            md->bEner[i] = (ir->efep != efepNO);
-        else if (i == F_DHDL_CON)
-            md->bEner[i] = (ir->efep != efepNO && md->bConstr);
-        else if ((interaction_function[i].flags & IF_VSITE) ||
-                 (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE))
-            md->bEner[i] = FALSE;
-        else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES)  || (i==F_EQM))
-            md->bEner[i] = TRUE;
-        else if ((i == F_GBPOL) && ir->implicit_solvent==eisGBSA)
-            md->bEner[i] = TRUE;
-        else if ((i == F_NPSOLVATION) && ir->implicit_solvent==eisGBSA && (ir->sa_algorithm != esaNO))
-            md->bEner[i] = TRUE;
-        else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14))
-            md->bEner[i] = FALSE;
-        else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
-            md->bEner[i] = EI_DYNAMICS(ir->eI);
-        else if (i==F_VTEMP) 
-            md->bEner[i] =  (EI_DYNAMICS(ir->eI) && getenv("GMX_VIRIAL_TEMPERATURE"));
-        else if (i == F_DISPCORR || i == F_PDISPCORR)
-            md->bEner[i] = (ir->eDispCorr != edispcNO);
-        else if (i == F_DISRESVIOL)
-            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0);
-        else if (i == F_ORIRESDEV)
-            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0);
-        else if (i == F_CONNBONDS)
-            md->bEner[i] = FALSE;
-        else if (i == F_COM_PULL)
-            md->bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F);
-        else if (i == F_ECONSERVED)
-            md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) &&
-                            (ir->epc == epcNO || ir->epc==epcMTTK));
-        else
-            md->bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0);
-    }
-#else
-    /* OpenMM always produces only the following 4 energy terms */
-    md->bEner[F_EPOT] = TRUE;
-    md->bEner[F_EKIN] = TRUE;
-    md->bEner[F_ETOT] = TRUE;
-    md->bEner[F_TEMP] = TRUE;
-#endif
-
-    md->f_nre=0;
-    for(i=0; i<F_NRE; i++)
-    {
-        if (md->bEner[i])
-        {
-            /* FIXME: The constness should not be cast away */
-            /*ener_nm[f_nre]=(char *)interaction_function[i].longname;*/
-            ener_nm[md->f_nre]=interaction_function[i].longname;
-            md->f_nre++;
-        }
-    }
-
-    md->epc = ir->epc;
-    md->bDiagPres = !TRICLINIC(ir->ref_p);
-    md->ref_p = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM;
-    md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
-    md->bDynBox = DYNAMIC_BOX(*ir);
-    md->etc = ir->etc;
-    md->bNHC_trotter = IR_NVT_TROTTER(ir);
-    md->bMTTK = IR_NPT_TROTTER(ir);
-
-    md->ebin  = mk_ebin();
-    /* Pass NULL for unit to let get_ebin_space determine the units
-     * for interaction_function[i].longname
-     */
-    md->ie    = get_ebin_space(md->ebin,md->f_nre,ener_nm,NULL);
-    if (md->nCrmsd)
-    {
-        /* This should be called directly after the call for md->ie,
-         * such that md->iconrmsd follows directly in the list.
-         */
-        md->iconrmsd = get_ebin_space(md->ebin,md->nCrmsd,conrmsd_nm,"");
-    }
-    if (md->bDynBox)
-    {
-        md->ib    = get_ebin_space(md->ebin, 
-                                   md->bTricl ? NTRICLBOXS : NBOXS, 
-                                   md->bTricl ? tricl_boxs_nm : boxs_nm,
-                                   unit_length);
-        md->ivol  = get_ebin_space(md->ebin, 1, vol_nm,  unit_volume);
-        md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI);
-        if (md->bDiagPres)
-        {
-            md->ipv   = get_ebin_space(md->ebin, 1, pv_nm,   unit_energy);
-            md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm,   unit_energy);
-        }
-    }
-    if (md->bConstrVir)
-    {
-        md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm,unit_energy);
-        md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm,unit_energy);
-    }
-    md->ivir   = get_ebin_space(md->ebin,asize(vir_nm),vir_nm,unit_energy);
-    md->ipres  = get_ebin_space(md->ebin,asize(pres_nm),pres_nm,unit_pres_bar);
-    md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm,
-                                unit_surft_bar);
-    if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
-    {
-        md->ipc = get_ebin_space(md->ebin,md->bTricl ? 6 : 3,
-                                 boxvel_nm,unit_vel);
-    }
-    md->imu    = get_ebin_space(md->ebin,asize(mu_nm),mu_nm,unit_dipole_D);
-    if (ir->cos_accel != 0)
-    {
-        md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm,unit_vel);
-        md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm,
-                                   unit_invvisc_SI);
-    }
-
-    /* Energy monitoring */
-    for(i=0;i<egNR;i++)
-    {
-        md->bEInd[i] = FALSE;
-    }
-    md->bEInd[egCOULSR] = TRUE;
-    md->bEInd[egLJSR  ] = TRUE;
-
-    if (ir->rcoulomb > ir->rlist)
-    {
-        md->bEInd[egCOULLR] = TRUE;
-    }
-    if (!bBHAM)
-    {
-        if (ir->rvdw > ir->rlist)
-        {
-            md->bEInd[egLJLR]   = TRUE;
-        }
-    }
-    else
-    {
-        md->bEInd[egLJSR]   = FALSE;
-        md->bEInd[egBHAMSR] = TRUE;
-        if (ir->rvdw > ir->rlist)
-        {
-            md->bEInd[egBHAMLR]   = TRUE;
-        }
-    }
-    if (b14)
-    {
-        md->bEInd[egLJ14] = TRUE;
-        md->bEInd[egCOUL14] = TRUE;
-    }
-    md->nEc=0;
-    for(i=0; (i<egNR); i++)
-    {
-        if (md->bEInd[i])
-        {
-            md->nEc++;
-        }
-    }
-
-    n=groups->grps[egcENER].nr;
-    md->nEg=n;
-    md->nE=(n*(n+1))/2;
-    snew(md->igrp,md->nE);
-    if (md->nE > 1)
-    {
-        n=0;
-        snew(gnm,md->nEc);
-        for(k=0; (k<md->nEc); k++)
-        {
-            snew(gnm[k],STRLEN);
-        }
-        for(i=0; (i<groups->grps[egcENER].nr); i++)
-        {
-            ni=groups->grps[egcENER].nm_ind[i];
-            for(j=i; (j<groups->grps[egcENER].nr); j++)
-            {
-                nj=groups->grps[egcENER].nm_ind[j];
-                for(k=kk=0; (k<egNR); k++)
-                {
-                    if (md->bEInd[k])
-                    {
-                        sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k],
-                                *(groups->grpname[ni]),*(groups->grpname[nj]));
-                        kk++;
-                    }
-                }
-                md->igrp[n]=get_ebin_space(md->ebin,md->nEc,
-                                           (const char **)gnm,unit_energy);
-                n++;
-            }
-        }
-        for(k=0; (k<md->nEc); k++)
-        {
-            sfree(gnm[k]);
-        }
-        sfree(gnm);
-
-        if (n != md->nE)
-        {
-            gmx_incons("Number of energy terms wrong");
-        }
-    }
-
-    md->nTC=groups->grps[egcTC].nr;
-    md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */ 
-    if (md->bMTTK)
-    {
-        md->nTCP = 1;  /* assume only one possible coupling system for barostat 
-                          for now */
-    } 
-    else 
-    {
-        md->nTCP = 0;
-    }
-
-    if (md->etc == etcNOSEHOOVER) {
-        if (md->bNHC_trotter) { 
-            md->mde_n = 2*md->nNHC*md->nTC;
-        }
-        else 
-        {
-            md->mde_n = 2*md->nTC;
-        }
-        if (md->epc == epcMTTK)
-        {
-            md->mdeb_n = 2*md->nNHC*md->nTCP;
-        }
-    } else { 
-        md->mde_n = md->nTC;
-        md->mdeb_n = 0;
-    }
-
-    snew(md->tmp_r,md->mde_n);
-    snew(md->tmp_v,md->mde_n);
-    snew(md->grpnms,md->mde_n);
-    grpnms = md->grpnms;
-
-    for(i=0; (i<md->nTC); i++)
-    {
-        ni=groups->grps[egcTC].nm_ind[i];
-        sprintf(buf,"T-%s",*(groups->grpname[ni]));
-        grpnms[i]=strdup(buf);
-    }
-    md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms,
-                             unit_temp_K);
-
-    bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); /* whether to print Nose-Hoover chains */
-
-    if (md->etc == etcNOSEHOOVER)
-    {
-        if (bNoseHoover) 
-        {
-            if (md->bNHC_trotter) 
-            {
-                for(i=0; (i<md->nTC); i++) 
-                {
-                    ni=groups->grps[egcTC].nm_ind[i];
-                    bufi = *(groups->grpname[ni]);
-                    for(j=0; (j<md->nNHC); j++) 
-                    {
-                        sprintf(buf,"Xi-%d-%s",j,bufi);
-                        grpnms[2*(i*md->nNHC+j)]=strdup(buf);
-                        sprintf(buf,"vXi-%d-%s",j,bufi);
-                        grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
-                    }
-                }
-                md->itc=get_ebin_space(md->ebin,md->mde_n,
-                                       (const char **)grpnms,unit_invtime);
-                if (md->bMTTK) 
-                {
-                    for(i=0; (i<md->nTCP); i++) 
-                    {
-                        bufi = baro_nm[0];  /* All barostat DOF's together for now. */
-                        for(j=0; (j<md->nNHC); j++) 
-                        {
-                            sprintf(buf,"Xi-%d-%s",j,bufi);
-                            grpnms[2*(i*md->nNHC+j)]=strdup(buf);
-                            sprintf(buf,"vXi-%d-%s",j,bufi);
-                            grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
-                        }
-                    }
-                    md->itcb=get_ebin_space(md->ebin,md->mdeb_n,
-                                            (const char **)grpnms,unit_invtime);
-                }
-            } 
-            else
-            {
-                for(i=0; (i<md->nTC); i++) 
-                {
-                    ni=groups->grps[egcTC].nm_ind[i];
-                    bufi = *(groups->grpname[ni]);
-                    sprintf(buf,"Xi-%s",bufi);
-                    grpnms[2*i]=strdup(buf);
-                    sprintf(buf,"vXi-%s",bufi);
-                    grpnms[2*i+1]=strdup(buf);
-                }
-                md->itc=get_ebin_space(md->ebin,md->mde_n,
-                                       (const char **)grpnms,unit_invtime);
-            }
-        }
-    }
-    else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
-             md->etc == etcVRESCALE)
-    {
-        for(i=0; (i<md->nTC); i++)
-        {
-            ni=groups->grps[egcTC].nm_ind[i];
-            sprintf(buf,"Lamb-%s",*(groups->grpname[ni]));
-            grpnms[i]=strdup(buf);
-        }
-        md->itc=get_ebin_space(md->ebin,md->mde_n,(const char **)grpnms,"");
-    }
-
-    sfree(grpnms);
-
-
-    md->nU=groups->grps[egcACC].nr;
-    if (md->nU > 1)
-    {
-        snew(grpnms,3*md->nU);
-        for(i=0; (i<md->nU); i++)
-        {
-            ni=groups->grps[egcACC].nm_ind[i];
-            sprintf(buf,"Ux-%s",*(groups->grpname[ni]));
-            grpnms[3*i+XX]=strdup(buf);
-            sprintf(buf,"Uy-%s",*(groups->grpname[ni]));
-            grpnms[3*i+YY]=strdup(buf);
-            sprintf(buf,"Uz-%s",*(groups->grpname[ni]));
-            grpnms[3*i+ZZ]=strdup(buf);
-        }
-        md->iu=get_ebin_space(md->ebin,3*md->nU,(const char **)grpnms,unit_vel);
-        sfree(grpnms);
-    }
-
-    if ( fp_ene )
-    {
-        do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm);
-    }
-
-    md->print_grpnms=NULL;
-
-    /* check whether we're going to write dh histograms */
-    md->dhc=NULL; 
-    if (ir->separate_dhdl_file == sepdhdlfileNO )
-    {
-        int i;
-        snew(md->dhc, 1);
-
-        mde_delta_h_coll_init(md->dhc, ir);
-        md->fp_dhdl = NULL;
-    }
-    else
-    {
-        md->fp_dhdl = fp_dhdl;
-    }
-    md->dhdl_derivatives = (ir->dhdl_derivatives==dhdlderivativesYES);
-    return md;
-}
-
-FILE *open_dhdl(const char *filename,const t_inputrec *ir,
-                const output_env_t oenv)
-{
-    FILE *fp;
-    const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
-    char title[STRLEN],label_x[STRLEN],label_y[STRLEN];
-    char **setname;
-    char buf[STRLEN];
-
-    sprintf(label_x,"%s (%s)","Time",unit_time);
-    if (ir->n_flambda == 0)
-    {
-        sprintf(title,"%s",dhdl);
-        sprintf(label_y,"%s (%s %s)",
-                dhdl,unit_energy,"[\\lambda]\\S-1\\N");
-    }
-    else
-    {
-        sprintf(title,"%s, %s",dhdl,deltag);
-        sprintf(label_y,"(%s)",unit_energy);
-    }
-    fp = gmx_fio_fopen(filename,"w+");
-    xvgr_header(fp,title,label_x,label_y,exvggtXNY,oenv);
-
-    if (ir->delta_lambda == 0)
-    {
-        sprintf(buf,"T = %g (K), %s = %g",
-                ir->opts.ref_t[0],lambda,ir->init_lambda);
-    }
-    else
-    {
-        sprintf(buf,"T = %g (K)",
-                ir->opts.ref_t[0]);
-    }
-    xvgr_subtitle(fp,buf,oenv);
-
-    if (ir->n_flambda > 0)
-    {
-        int nsets,s,nsi=0;
-        /* g_bar has to determine the lambda values used in this simulation
-         * from this xvg legend.  */
-        nsets = ( (ir->dhdl_derivatives==dhdlderivativesYES) ? 1 : 0) + 
-                  ir->n_flambda;
-        snew(setname,nsets);
-        if (ir->dhdl_derivatives == dhdlderivativesYES)
-        {
-            sprintf(buf,"%s %s %g",dhdl,lambda,ir->init_lambda);
-            setname[nsi++] = gmx_strdup(buf);
-        }
-        for(s=0; s<ir->n_flambda; s++)
-        {
-            sprintf(buf,"%s %s %g",deltag,lambda,ir->flambda[s]);
-            setname[nsi++] = gmx_strdup(buf);
-        }
-        xvgr_legend(fp,nsets,(const char**)setname,oenv);
-
-        for(s=0; s<nsets; s++)
-        {
-            sfree(setname[s]);
-        }
-        sfree(setname);
-    }
-
-    return fp;
-}
-
-static void copy_energy(t_mdebin *md, real e[],real ecpy[])
-{
-    int i,j;
-
-    for(i=j=0; (i<F_NRE); i++)
-        if (md->bEner[i])
-            ecpy[j++] = e[i];
-    if (j != md->f_nre) 
-        gmx_incons("Number of energy terms wrong");
-}
-
-void upd_mdebin(t_mdebin *md, gmx_bool write_dhdl,
-                gmx_bool bSum,
-                double time,
-                real tmass,
-                gmx_enerdata_t *enerd,
-                t_state *state,
-                matrix  box,
-                tensor svir,
-                tensor fvir,
-                tensor vir,
-                tensor pres,
-                gmx_ekindata_t *ekind,
-                rvec mu_tot,
-                gmx_constr_t constr)
-{
-    int    i,j,k,kk,m,n,gid;
-    real   crmsd[2],tmp6[6];
-    real   bs[NTRICLBOXS],vol,dens,pv,enthalpy;
-    real   eee[egNR];
-    real   ecopy[F_NRE];
-    real   tmp;
-    gmx_bool   bNoseHoover;
-
-    /* Do NOT use the box in the state variable, but the separate box provided
-     * as an argument. This is because we sometimes need to write the box from
-     * the last timestep to match the trajectory frames.
-     */
-    copy_energy(md, enerd->term,ecopy);
-    add_ebin(md->ebin,md->ie,md->f_nre,ecopy,bSum);
-    if (md->nCrmsd)
-    {
-        crmsd[0] = constr_rmsd(constr,FALSE);
-        if (md->nCrmsd > 1)
-        {
-            crmsd[1] = constr_rmsd(constr,TRUE);
-        }
-        add_ebin(md->ebin,md->iconrmsd,md->nCrmsd,crmsd,FALSE);
-    }
-    if (md->bDynBox)
-    {
-        int nboxs;
-        if(md->bTricl)
-        {
-            bs[0] = box[XX][XX];
-            bs[1] = box[YY][YY];
-            bs[2] = box[ZZ][ZZ];
-            bs[3] = box[YY][XX];
-            bs[4] = box[ZZ][XX];
-            bs[5] = box[ZZ][YY];
-            nboxs=NTRICLBOXS;
-        }
-        else
-        {
-            bs[0] = box[XX][XX];
-            bs[1] = box[YY][YY];
-            bs[2] = box[ZZ][ZZ];
-            nboxs=NBOXS;
-        }
-        vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
-        dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
-
-        add_ebin(md->ebin,md->ib   ,nboxs,bs   ,bSum);
-        add_ebin(md->ebin,md->ivol ,1    ,&vol ,bSum);
-        add_ebin(md->ebin,md->idens,1    ,&dens,bSum);
-
-        if (md->bDiagPres)
-        {
-            /* This is pV (in kJ/mol).  The pressure is the reference pressure,
-               not the instantaneous pressure */  
-            pv = vol*md->ref_p/PRESFAC;
-
-            add_ebin(md->ebin,md->ipv  ,1    ,&pv  ,bSum);
-            enthalpy = pv + enerd->term[F_ETOT];
-            add_ebin(md->ebin,md->ienthalpy  ,1    ,&enthalpy  ,bSum);
-        }
-    }
-    if (md->bConstrVir)
-    {
-        add_ebin(md->ebin,md->isvir,9,svir[0],bSum);
-        add_ebin(md->ebin,md->ifvir,9,fvir[0],bSum);
-    }
-    add_ebin(md->ebin,md->ivir,9,vir[0],bSum);
-    add_ebin(md->ebin,md->ipres,9,pres[0],bSum);
-    tmp = (pres[ZZ][ZZ]-(pres[XX][XX]+pres[YY][YY])*0.5)*box[ZZ][ZZ];
-    add_ebin(md->ebin,md->isurft,1,&tmp,bSum);
-    if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
-    {
-        tmp6[0] = state->boxv[XX][XX];
-        tmp6[1] = state->boxv[YY][YY];
-        tmp6[2] = state->boxv[ZZ][ZZ];
-        tmp6[3] = state->boxv[YY][XX];
-        tmp6[4] = state->boxv[ZZ][XX];
-        tmp6[5] = state->boxv[ZZ][YY];
-        add_ebin(md->ebin,md->ipc,md->bTricl ? 6 : 3,tmp6,bSum);
-    }
-    add_ebin(md->ebin,md->imu,3,mu_tot,bSum);
-    if (ekind && ekind->cosacc.cos_accel != 0)
-    {
-        vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
-        dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
-        add_ebin(md->ebin,md->ivcos,1,&(ekind->cosacc.vcos),bSum);
-        /* 1/viscosity, unit 1/(kg m^-1 s^-1) */
-        tmp = 1/(ekind->cosacc.cos_accel/(ekind->cosacc.vcos*PICO)
-                 *dens*vol*sqr(box[ZZ][ZZ]*NANO/(2*M_PI)));
-        add_ebin(md->ebin,md->ivisc,1,&tmp,bSum);    
-    }
-    if (md->nE > 1)
-    {
-        n=0;
-        for(i=0; (i<md->nEg); i++)
-        {
-            for(j=i; (j<md->nEg); j++)
-            {
-                gid=GID(i,j,md->nEg);
-                for(k=kk=0; (k<egNR); k++)
-                {
-                    if (md->bEInd[k])
-                    {
-                        eee[kk++] = enerd->grpp.ener[k][gid];
-                    }
-                }
-                add_ebin(md->ebin,md->igrp[n],md->nEc,eee,bSum);
-                n++;
-            }
-        }
-    }
-
-    if (ekind)
-    {
-        for(i=0; (i<md->nTC); i++)
-        {
-            md->tmp_r[i] = ekind->tcstat[i].T;
-        }
-        add_ebin(md->ebin,md->itemp,md->nTC,md->tmp_r,bSum);
-
-        /* whether to print Nose-Hoover chains: */
-        bNoseHoover = (getenv("GMX_NOSEHOOVER_CHAINS") != NULL); 
-
-        if (md->etc == etcNOSEHOOVER)
-        {
-            if (bNoseHoover) 
-            {
-                if (md->bNHC_trotter)
-                {
-                    for(i=0; (i<md->nTC); i++) 
-                    {
-                        for (j=0;j<md->nNHC;j++) 
-                        {
-                            k = i*md->nNHC+j;
-                            md->tmp_r[2*k] = state->nosehoover_xi[k];
-                            md->tmp_r[2*k+1] = state->nosehoover_vxi[k];
-                        }
-                    }
-                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);      
-
-                    if (md->bMTTK) {
-                        for(i=0; (i<md->nTCP); i++) 
-                        {
-                            for (j=0;j<md->nNHC;j++) 
-                            {
-                                k = i*md->nNHC+j;
-                                md->tmp_r[2*k] = state->nhpres_xi[k];
-                                md->tmp_r[2*k+1] = state->nhpres_vxi[k];
-                            }
-                        }
-                        add_ebin(md->ebin,md->itcb,md->mdeb_n,md->tmp_r,bSum);      
-                    }
-
-                } 
-                else 
-                {
-                    for(i=0; (i<md->nTC); i++)
-                    {
-                        md->tmp_r[2*i] = state->nosehoover_xi[i];
-                        md->tmp_r[2*i+1] = state->nosehoover_vxi[i];
-                    }
-                    add_ebin(md->ebin,md->itc,md->mde_n,md->tmp_r,bSum);
-                }
-            }
-        }
-        else if (md->etc == etcBERENDSEN || md->etc == etcYES || 
-                 md->etc == etcVRESCALE)
-        {
-            for(i=0; (i<md->nTC); i++)
-            {
-                md->tmp_r[i] = ekind->tcstat[i].lambda;
-            }
-            add_ebin(md->ebin,md->itc,md->nTC,md->tmp_r,bSum);
-        }
-    }
-
-    if (ekind && md->nU > 1)
-    {
-        for(i=0; (i<md->nU); i++)
-        {
-            copy_rvec(ekind->grpstat[i].u,md->tmp_v[i]);
-        }
-        add_ebin(md->ebin,md->iu,3*md->nU,md->tmp_v[0],bSum);
-    }
-
-    ebin_increase_count(md->ebin,bSum);
-
-    /* BAR + thermodynamic integration values */
-    if (write_dhdl)
-    {
-        if (md->fp_dhdl)
-        {
-            fprintf(md->fp_dhdl,"%.4f", time);
-
-            if (md->dhdl_derivatives)
-            {
-                fprintf(md->fp_dhdl," %g", enerd->term[F_DVDL]+ 
-                                           enerd->term[F_DKDL]+
-                                           enerd->term[F_DHDL_CON]);
-            }
-            for(i=1; i<enerd->n_lambda; i++)
-            {
-                fprintf(md->fp_dhdl," %g",
-                        enerd->enerpart_lambda[i]-enerd->enerpart_lambda[0]);
-            }
-            fprintf(md->fp_dhdl,"\n");
-        }
-        /* and the binary BAR output */
-        if (md->dhc)
-        {
-            mde_delta_h_coll_add_dh(md->dhc, 
-                                    enerd->term[F_DVDL]+ enerd->term[F_DKDL]+
-                                    enerd->term[F_DHDL_CON],
-                                    enerd->enerpart_lambda, time, 
-                                    state->lambda);
-        }
-    }
-}
-
-void upd_mdebin_step(t_mdebin *md)
-{
-    ebin_increase_count(md->ebin,FALSE); 
-}
-
-static void npr(FILE *log,int n,char c)
-{
-    for(; (n>0); n--) fprintf(log,"%c",c);
-}
-
-static void pprint(FILE *log,const char *s,t_mdebin *md)
-{
-    char CHAR='#';
-    int  slen;
-    char buf1[22],buf2[22];
-
-    slen = strlen(s);
-    fprintf(log,"\t<======  ");
-    npr(log,slen,CHAR);
-    fprintf(log,"  ==>\n");
-    fprintf(log,"\t<====  %s  ====>\n",s);
-    fprintf(log,"\t<==  ");
-    npr(log,slen,CHAR);
-    fprintf(log,"  ======>\n\n");
-
-    fprintf(log,"\tStatistics over %s steps using %s frames\n",
-            gmx_step_str(md->ebin->nsteps_sim,buf1),
-            gmx_step_str(md->ebin->nsum_sim,buf2));
-    fprintf(log,"\n");
-}
-
-void print_ebin_header(FILE *log,gmx_large_int_t steps,double time,real lamb)
-{
-    char buf[22];
-
-    fprintf(log,"   %12s   %12s   %12s\n"
-            "   %12s   %12.5f   %12.5f\n\n",
-            "Step","Time","Lambda",gmx_step_str(steps,buf),time,lamb);
-}
-
-void print_ebin(ener_file_t fp_ene,gmx_bool bEne,gmx_bool bDR,gmx_bool bOR,
-                FILE *log,
-                gmx_large_int_t step,double time,
-                int mode,gmx_bool bCompact,
-                t_mdebin *md,t_fcdata *fcd,
-                gmx_groups_t *groups,t_grpopts *opts)
-{
-    /*static char **grpnms=NULL;*/
-    char        buf[246];
-    int         i,j,n,ni,nj,ndr,nor,b;
-    int         ndisre=0;
-    real        *disre_rm3tav, *disre_rt;
-
-    /* these are for the old-style blocks (1 subblock, only reals), because
-       there can be only one per ID for these */
-    int         nr[enxNR];
-    int         id[enxNR];
-    real        *block[enxNR];
-
-    /* temporary arrays for the lambda values to write out */
-    double      enxlambda_data[2]; 
-
-    t_enxframe  fr;
-
-    switch (mode)
-    {
-        case eprNORMAL:
-            init_enxframe(&fr);
-            fr.t            = time;
-            fr.step         = step;
-            fr.nsteps       = md->ebin->nsteps;
-            fr.dt           = md->delta_t;
-            fr.nsum         = md->ebin->nsum;
-            fr.nre          = (bEne) ? md->ebin->nener : 0;
-            fr.ener         = md->ebin->e;
-            ndisre          = bDR ? fcd->disres.npair : 0;
-            disre_rm3tav    = fcd->disres.rm3tav;
-            disre_rt        = fcd->disres.rt;
-            /* Optional additional old-style (real-only) blocks. */
-            for(i=0; i<enxNR; i++)
-            {
-                nr[i] = 0;
-            }
-            if (fcd->orires.nr > 0 && bOR)
-            {
-                diagonalize_orires_tensors(&(fcd->orires));
-                nr[enxOR]     = fcd->orires.nr;
-                block[enxOR]  = fcd->orires.otav;
-                id[enxOR]     = enxOR;
-                nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ? 
-                          fcd->orires.nr : 0;
-                block[enxORI] = fcd->orires.oinsl;
-                id[enxORI]    = enxORI;
-                nr[enxORT]    = fcd->orires.nex*12;
-                block[enxORT] = fcd->orires.eig;
-                id[enxORT]    = enxORT;
-            }        
-
-            /* whether we are going to wrte anything out: */
-            if (fr.nre || ndisre || nr[enxOR] || nr[enxORI])
-            {
-
-                /* the old-style blocks go first */
-                fr.nblock = 0;
-                for(i=0; i<enxNR; i++)
-                {
-                    if (nr[i] > 0)
-                    {
-                        fr.nblock = i + 1;
-                    }
-                }
-                add_blocks_enxframe(&fr, fr.nblock);
-                for(b=0;b<fr.nblock;b++)
-                {
-                    add_subblocks_enxblock(&(fr.block[b]), 1);
-                    fr.block[b].id=id[b]; 
-                    fr.block[b].sub[0].nr = nr[b];
-#ifndef GMX_DOUBLE
-                    fr.block[b].sub[0].type = xdr_datatype_float;
-                    fr.block[b].sub[0].fval = block[b];
-#else
-                    fr.block[b].sub[0].type = xdr_datatype_double;
-                    fr.block[b].sub[0].dval = block[b];
-#endif
-                }
-
-                /* check for disre block & fill it. */
-                if (ndisre>0)
-                {
-                    int db = fr.nblock;
-                    fr.nblock+=1;
-                    add_blocks_enxframe(&fr, fr.nblock);
-
-                    add_subblocks_enxblock(&(fr.block[db]), 2);
-                    fr.block[db].id=enxDISRE;
-                    fr.block[db].sub[0].nr=ndisre;
-                    fr.block[db].sub[1].nr=ndisre;
-#ifndef GMX_DOUBLE
-                    fr.block[db].sub[0].type=xdr_datatype_float;
-                    fr.block[db].sub[1].type=xdr_datatype_float;
-                    fr.block[db].sub[0].fval=disre_rt;
-                    fr.block[db].sub[1].fval=disre_rm3tav;
-#else
-                    fr.block[db].sub[0].type=xdr_datatype_double;
-                    fr.block[db].sub[1].type=xdr_datatype_double;
-                    fr.block[db].sub[0].dval=disre_rt;
-                    fr.block[db].sub[1].dval=disre_rm3tav;
-#endif
-                }
-                /* here we can put new-style blocks */
-
-                /* Free energy perturbation blocks */
-                if (md->dhc)
-                {
-                    mde_delta_h_coll_handle_block(md->dhc, &fr, fr.nblock);
-                }
-
-                /* do the actual I/O */
-                do_enx(fp_ene,&fr);
-                gmx_fio_check_file_position(enx_file_pointer(fp_ene));
-                if (fr.nre)
-                {
-                    /* We have stored the sums, so reset the sum history */
-                    reset_ebin_sums(md->ebin);
-                }
-
-                /* we can now free & reset the data in the blocks */
-                if (md->dhc)
-                    mde_delta_h_coll_reset(md->dhc);
-            }
-            free_enxframe(&fr);
-            break;
-        case eprAVER:
-            if (log)
-            {
-                pprint(log,"A V E R A G E S",md);
-            }
-            break;
-        case eprRMS:
-            if (log)
-            {
-                pprint(log,"R M S - F L U C T U A T I O N S",md);
-            }
-            break;
-        default:
-            gmx_fatal(FARGS,"Invalid print mode (%d)",mode);
-    }
-
-    if (log)
-    {
-        for(i=0;i<opts->ngtc;i++)
-        {
-            if(opts->annealing[i]!=eannNO)
-            {
-                fprintf(log,"Current ref_t for group %s: %8.1f\n",
-                        *(groups->grpname[groups->grps[egcTC].nm_ind[i]]),
-                        opts->ref_t[i]);
-            }
-        }
-        if (mode==eprNORMAL && fcd->orires.nr>0)
-        {
-            print_orires_log(log,&(fcd->orires));
-        }
-        fprintf(log,"   Energies (%s)\n",unit_energy);
-        pr_ebin(log,md->ebin,md->ie,md->f_nre+md->nCrmsd,5,mode,TRUE);  
-        fprintf(log,"\n");
-
-        if (!bCompact)
-        {
-            if (md->bDynBox)
-            {
-                pr_ebin(log,md->ebin,md->ib, md->bTricl ? NTRICLBOXS : NBOXS,5,
-                        mode,TRUE);      
-                fprintf(log,"\n");
-            }
-            if (md->bConstrVir)
-            {
-                fprintf(log,"   Constraint Virial (%s)\n",unit_energy);
-                pr_ebin(log,md->ebin,md->isvir,9,3,mode,FALSE);  
-                fprintf(log,"\n");
-                fprintf(log,"   Force Virial (%s)\n",unit_energy);
-                pr_ebin(log,md->ebin,md->ifvir,9,3,mode,FALSE);  
-                fprintf(log,"\n");
-            }
-            fprintf(log,"   Total Virial (%s)\n",unit_energy);
-            pr_ebin(log,md->ebin,md->ivir,9,3,mode,FALSE);   
-            fprintf(log,"\n");
-            fprintf(log,"   Pressure (%s)\n",unit_pres_bar);
-            pr_ebin(log,md->ebin,md->ipres,9,3,mode,FALSE);  
-            fprintf(log,"\n");
-            fprintf(log,"   Total Dipole (%s)\n",unit_dipole_D);
-            pr_ebin(log,md->ebin,md->imu,3,3,mode,FALSE);    
-            fprintf(log,"\n");
-
-            if (md->nE > 1)
-            {
-                if (md->print_grpnms==NULL)
-                {
-                    snew(md->print_grpnms,md->nE);
-                    n=0;
-                    for(i=0; (i<md->nEg); i++)
-                    {
-                        ni=groups->grps[egcENER].nm_ind[i];
-                        for(j=i; (j<md->nEg); j++)
-                        {
-                            nj=groups->grps[egcENER].nm_ind[j];
-                            sprintf(buf,"%s-%s",*(groups->grpname[ni]),
-                                    *(groups->grpname[nj]));
-                            md->print_grpnms[n++]=strdup(buf);
-                        }
-                    }
-                }
-                sprintf(buf,"Epot (%s)",unit_energy);
-                fprintf(log,"%15s   ",buf);
-                for(i=0; (i<egNR); i++)
-                {
-                    if (md->bEInd[i])
-                    {
-                        fprintf(log,"%12s   ",egrp_nm[i]);
-                    }
-                }
-                fprintf(log,"\n");
-                for(i=0; (i<md->nE); i++)
-                {
-                    fprintf(log,"%15s",md->print_grpnms[i]);
-                    pr_ebin(log,md->ebin,md->igrp[i],md->nEc,md->nEc,mode,
-                            FALSE);
-                }
-                fprintf(log,"\n");
-            }
-            if (md->nTC > 1)
-            {
-                pr_ebin(log,md->ebin,md->itemp,md->nTC,4,mode,TRUE);
-                fprintf(log,"\n");
-            }
-            if (md->nU > 1)
-            {
-                fprintf(log,"%15s   %12s   %12s   %12s\n",
-                        "Group","Ux","Uy","Uz");
-                for(i=0; (i<md->nU); i++)
-                {
-                    ni=groups->grps[egcACC].nm_ind[i];
-                    fprintf(log,"%15s",*groups->grpname[ni]);
-                    pr_ebin(log,md->ebin,md->iu+3*i,3,3,mode,FALSE);
-                }
-                fprintf(log,"\n");
-            }
-        }
-    }
-
-}
-
-void update_energyhistory(energyhistory_t * enerhist,t_mdebin * mdebin)
-{
-    int i;
-
-    enerhist->nsteps     = mdebin->ebin->nsteps;
-    enerhist->nsum       = mdebin->ebin->nsum;
-    enerhist->nsteps_sim = mdebin->ebin->nsteps_sim;
-    enerhist->nsum_sim   = mdebin->ebin->nsum_sim;
-    enerhist->nener      = mdebin->ebin->nener;
-
-    if (mdebin->ebin->nsum > 0)
-    {
-        /* Check if we need to allocate first */
-        if(enerhist->ener_ave == NULL)
-        {
-            snew(enerhist->ener_ave,enerhist->nener);
-            snew(enerhist->ener_sum,enerhist->nener);
-        }
-
-        for(i=0;i<enerhist->nener;i++)
-        {
-            enerhist->ener_ave[i] = mdebin->ebin->e[i].eav;
-            enerhist->ener_sum[i] = mdebin->ebin->e[i].esum;
-        }
-    }
-
-    if (mdebin->ebin->nsum_sim > 0)
-    {
-        /* Check if we need to allocate first */
-        if(enerhist->ener_sum_sim == NULL)
-        {
-            snew(enerhist->ener_sum_sim,enerhist->nener);
-        }
-
-        for(i=0;i<enerhist->nener;i++)
-        {
-            enerhist->ener_sum_sim[i] = mdebin->ebin->e_sim[i].esum;
-        }
-    }
-    if (mdebin->dhc)
-    {
-        mde_delta_h_coll_update_energyhistory(mdebin->dhc, enerhist);
-    }
-}
-
-void restore_energyhistory_from_state(t_mdebin * mdebin,
-                                      energyhistory_t * enerhist)
-{
-    int i;
-
-    if ((enerhist->nsum > 0 || enerhist->nsum_sim > 0) &&
-        mdebin->ebin->nener != enerhist->nener)
-    {
-        gmx_fatal(FARGS,"Mismatch between number of energies in run input (%d) and checkpoint file (%d).",
-                  mdebin->ebin->nener,enerhist->nener);
-    }
-
-    mdebin->ebin->nsteps     = enerhist->nsteps;
-    mdebin->ebin->nsum       = enerhist->nsum;
-    mdebin->ebin->nsteps_sim = enerhist->nsteps_sim;
-    mdebin->ebin->nsum_sim   = enerhist->nsum_sim;
-
-    for(i=0; i<mdebin->ebin->nener; i++)
-    {
-        mdebin->ebin->e[i].eav  =
-                  (enerhist->nsum > 0 ? enerhist->ener_ave[i] : 0);
-        mdebin->ebin->e[i].esum =
-                  (enerhist->nsum > 0 ? enerhist->ener_sum[i] : 0);
-        mdebin->ebin->e_sim[i].esum =
-                  (enerhist->nsum_sim > 0 ? enerhist->ener_sum_sim[i] : 0);
-    }
-    if (mdebin->dhc)
-    {         
-        mde_delta_h_coll_restore_energyhistory(mdebin->dhc, enerhist);
-    }
-}
diff --git a/src/mdlib/minimize.c b/src/mdlib/minimize.c
deleted file mode 100644 (file)
index 588544c..0000000
+++ /dev/null
@@ -1,2511 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <time.h>
-#include <math.h>
-#include "sysstuff.h"
-#include "string2.h"
-#include "network.h"
-#include "confio.h"
-#include "copyrite.h"
-#include "smalloc.h"
-#include "nrnb.h"
-#include "main.h"
-#include "force.h"
-#include "macros.h"
-#include "random.h"
-#include "names.h"
-#include "gmx_fatal.h"
-#include "txtdump.h"
-#include "typedefs.h"
-#include "update.h"
-#include "constr.h"
-#include "vec.h"
-#include "statutil.h"
-#include "tgroup.h"
-#include "mdebin.h"
-#include "vsite.h"
-#include "force.h"
-#include "mdrun.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "trnio.h"
-#include "sparsematrix.h"
-#include "mtxio.h"
-#include "mdatoms.h"
-#include "ns.h"
-#include "gmx_wallcycle.h"
-#include "mtop_util.h"
-#include "gmxfio.h"
-#include "pme.h"
-
-typedef struct {
-  t_state s;
-  rvec    *f;
-  real    epot;
-  real    fnorm;
-  real    fmax;
-  int     a_fmax;
-} em_state_t;
-
-static em_state_t *init_em_state()
-{
-  em_state_t *ems;
-  
-  snew(ems,1);
-
-  return ems;
-}
-
-static void print_em_start(FILE *fplog,t_commrec *cr,gmx_runtime_t *runtime,
-                           gmx_wallcycle_t wcycle,
-                           const char *name)
-{
-    char buf[STRLEN];
-
-    runtime_start(runtime);
-
-    sprintf(buf,"Started %s",name);
-    print_date_and_time(fplog,cr->nodeid,buf,NULL);
-
-    wallcycle_start(wcycle,ewcRUN);
-}
-static void em_time_end(FILE *fplog,t_commrec *cr,gmx_runtime_t *runtime,
-                        gmx_wallcycle_t wcycle)
-{
-    wallcycle_stop(wcycle,ewcRUN);
-
-    runtime_end(runtime);
-}
-
-static void sp_header(FILE *out,const char *minimizer,real ftol,int nsteps)
-{
-    fprintf(out,"\n");
-    fprintf(out,"%s:\n",minimizer);
-    fprintf(out,"   Tolerance (Fmax)   = %12.5e\n",ftol);
-    fprintf(out,"   Number of steps    = %12d\n",nsteps);
-}
-
-static void warn_step(FILE *fp,real ftol,gmx_bool bLastStep,gmx_bool bConstrain)
-{
-    if (bLastStep)
-    {
-        fprintf(fp,"\nReached the maximum number of steps before reaching Fmax < %g\n",ftol);
-    }
-    else
-    {
-        fprintf(fp,"\nStepsize too small, or no change in energy.\n"
-                "Converged to machine precision,\n"
-                "but not to the requested precision Fmax < %g\n",
-                ftol);
-        if (sizeof(real)<sizeof(double))
-        {
-            fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
-        }
-        if (bConstrain)
-        {
-            fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
-                    "off constraints alltogether (set constraints = none in mdp file)\n");
-        }
-    }
-}
-
-
-
-static void print_converged(FILE *fp,const char *alg,real ftol,
-                           gmx_large_int_t count,gmx_bool bDone,gmx_large_int_t nsteps,
-                           real epot,real fmax, int nfmax, real fnorm)
-{
-  char buf[STEPSTRSIZE];
-
-  if (bDone)
-    fprintf(fp,"\n%s converged to Fmax < %g in %s steps\n",
-           alg,ftol,gmx_step_str(count,buf)); 
-  else if(count<nsteps)
-    fprintf(fp,"\n%s converged to machine precision in %s steps,\n"
-               "but did not reach the requested Fmax < %g.\n",
-           alg,gmx_step_str(count,buf),ftol);
-  else 
-    fprintf(fp,"\n%s did not converge to Fmax < %g in %s steps.\n",
-           alg,ftol,gmx_step_str(count,buf));
-
-#ifdef GMX_DOUBLE
-  fprintf(fp,"Potential Energy  = %21.14e\n",epot); 
-  fprintf(fp,"Maximum force     = %21.14e on atom %d\n",fmax,nfmax+1); 
-  fprintf(fp,"Norm of force     = %21.14e\n",fnorm); 
-#else
-  fprintf(fp,"Potential Energy  = %14.7e\n",epot); 
-  fprintf(fp,"Maximum force     = %14.7e on atom %d\n",fmax,nfmax+1); 
-  fprintf(fp,"Norm of force     = %14.7e\n",fnorm); 
-#endif
-}
-
-static void get_f_norm_max(t_commrec *cr,
-                          t_grpopts *opts,t_mdatoms *mdatoms,rvec *f,
-                          real *fnorm,real *fmax,int *a_fmax)
-{
-  double fnorm2,*sum;
-  real fmax2,fmax2_0,fam;
-  int  la_max,a_max,start,end,i,m,gf;
-
-  /* This routine finds the largest force and returns it.
-   * On parallel machines the global max is taken.
-   */
-  fnorm2 = 0;
-  fmax2 = 0;
-  la_max = -1;
-  gf = 0;
-  start = mdatoms->start;
-  end   = mdatoms->homenr + start;
-  if (mdatoms->cFREEZE) {
-    for(i=start; i<end; i++) {
-      gf = mdatoms->cFREEZE[i];
-      fam = 0;
-      for(m=0; m<DIM; m++)
-       if (!opts->nFreeze[gf][m])
-         fam += sqr(f[i][m]);
-      fnorm2 += fam;
-      if (fam > fmax2) {
-       fmax2  = fam;
-       la_max = i;
-      }
-    }
-  } else {
-    for(i=start; i<end; i++) {
-      fam = norm2(f[i]);
-      fnorm2 += fam;
-      if (fam > fmax2) {
-       fmax2  = fam;
-       la_max = i;
-      }
-    }
-  }
-
-  if (la_max >= 0 && DOMAINDECOMP(cr)) {
-    a_max = cr->dd->gatindex[la_max];
-  } else {
-    a_max = la_max;
-  }
-  if (PAR(cr)) {
-    snew(sum,2*cr->nnodes+1);
-    sum[2*cr->nodeid]   = fmax2;
-    sum[2*cr->nodeid+1] = a_max;
-    sum[2*cr->nnodes]   = fnorm2;
-    gmx_sumd(2*cr->nnodes+1,sum,cr);
-    fnorm2 = sum[2*cr->nnodes];
-    /* Determine the global maximum */
-    for(i=0; i<cr->nnodes; i++) {
-      if (sum[2*i] > fmax2) {
-       fmax2 = sum[2*i];
-       a_max = (int)(sum[2*i+1] + 0.5);
-      }
-    }
-    sfree(sum);
-  }
-
-  if (fnorm)
-    *fnorm = sqrt(fnorm2);
-  if (fmax)
-    *fmax  = sqrt(fmax2);
-  if (a_fmax)
-    *a_fmax = a_max;
-}
-
-static void get_state_f_norm_max(t_commrec *cr,
-                          t_grpopts *opts,t_mdatoms *mdatoms,
-                          em_state_t *ems)
-{
-  get_f_norm_max(cr,opts,mdatoms,ems->f,&ems->fnorm,&ems->fmax,&ems->a_fmax);
-}
-
-void init_em(FILE *fplog,const char *title,
-             t_commrec *cr,t_inputrec *ir,
-             t_state *state_global,gmx_mtop_t *top_global,
-             em_state_t *ems,gmx_localtop_t **top,
-             rvec **f,rvec **f_global,
-             t_nrnb *nrnb,rvec mu_tot,
-             t_forcerec *fr,gmx_enerdata_t **enerd,
-             t_graph **graph,t_mdatoms *mdatoms,gmx_global_stat_t *gstat,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int nfile,const t_filenm fnm[],
-             gmx_mdoutf_t **outf,t_mdebin **mdebin)
-{
-    int  start,homenr,i;
-    real dvdlambda;
-    
-    if (fplog)
-    {
-        fprintf(fplog,"Initiating %s\n",title);
-    }
-    
-    state_global->ngtc = 0;
-    
-    /* Initiate some variables */
-    if (ir->efep != efepNO)
-    {
-        state_global->lambda = ir->init_lambda;
-    }
-    else 
-    {
-        state_global->lambda = 0.0;
-    }
-    
-    init_nrnb(nrnb);
-    
-    if (DOMAINDECOMP(cr))
-    {
-        *top = dd_init_local_top(top_global);
-        
-        dd_init_local_state(cr->dd,state_global,&ems->s);
-
-        *f = NULL;
-        
-        /* Distribute the charge groups over the nodes from the master node */
-        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
-                            state_global,top_global,ir,
-                            &ems->s,&ems->f,mdatoms,*top,
-                            fr,vsite,NULL,constr,
-                            nrnb,NULL,FALSE);
-        dd_store_state(cr->dd,&ems->s);
-        
-        if (ir->nstfout)
-        {
-            snew(*f_global,top_global->natoms);
-        }
-        else
-        {
-            *f_global = NULL;
-        }
-        *graph = NULL;
-    }
-    else
-    {
-        snew(*f,top_global->natoms);
-
-        /* Just copy the state */
-        ems->s = *state_global;
-        snew(ems->s.x,ems->s.nalloc);
-        snew(ems->f,ems->s.nalloc);
-        for(i=0; i<state_global->natoms; i++)
-        {
-            copy_rvec(state_global->x[i],ems->s.x[i]);
-        }
-        copy_mat(state_global->box,ems->s.box);
-        
-        if (PAR(cr) && ir->eI != eiNM)
-        {
-            /* Initialize the particle decomposition and split the topology */
-            *top = split_system(fplog,top_global,ir,cr);
-            
-            pd_cg_range(cr,&fr->cg0,&fr->hcg);
-        }
-        else
-        {
-            *top = gmx_mtop_generate_local_top(top_global,ir);
-        }
-        *f_global = *f;
-        
-        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
-        {
-            *graph = mk_graph(fplog,&((*top)->idef),0,top_global->natoms,FALSE,FALSE);
-        }
-        else
-        {
-            *graph = NULL;
-        }
-
-        if (PARTDECOMP(cr))
-        {
-            pd_at_range(cr,&start,&homenr);
-            homenr -= start;
-        }
-        else
-        {
-            start  = 0;
-            homenr = top_global->natoms;
-        }
-        atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
-        update_mdatoms(mdatoms,state_global->lambda);
-    
-        if (vsite)
-        {
-            set_vsite_top(vsite,*top,mdatoms,cr);
-        }
-    }
-    
-    if (constr)
-    {
-        if (ir->eConstrAlg == econtSHAKE &&
-            gmx_mtop_ftype_count(top_global,F_CONSTR) > 0)
-        {
-            gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
-                      econstr_names[econtSHAKE],econstr_names[econtLINCS]);
-        }
-        
-        if (!DOMAINDECOMP(cr))
-        {
-            set_constraints(constr,*top,ir,mdatoms,cr);
-        }
-
-        if (!ir->bContinuation)
-        {
-            /* Constrain the starting coordinates */
-            dvdlambda=0;
-            constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
-                      ir,NULL,cr,-1,0,mdatoms,
-                      ems->s.x,ems->s.x,NULL,ems->s.box,
-                      ems->s.lambda,&dvdlambda,
-                      NULL,NULL,nrnb,econqCoord,FALSE,0,0);
-        }
-    }
-    
-    if (PAR(cr))
-    {
-        *gstat = global_stat_init(ir);
-    }
-    
-    *outf = init_mdoutf(nfile,fnm,0,cr,ir,NULL);
-
-    snew(*enerd,1);
-    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
-
-    if (mdebin != NULL)
-    {
-        /* Init bin for energy stuff */
-        *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir,NULL); 
-    }
-
-    clear_rvec(mu_tot);
-    calc_shifts(ems->s.box,fr->shift_vec);
-}
-
-static void finish_em(FILE *fplog,t_commrec *cr,gmx_mdoutf_t *outf,
-                      gmx_runtime_t *runtime,gmx_wallcycle_t wcycle)
-{
-  if (!(cr->duty & DUTY_PME)) {
-    /* Tell the PME only node to finish */
-    gmx_pme_finish(cr);
-  }
-
-  done_mdoutf(outf);
-
-  em_time_end(fplog,cr,runtime,wcycle);
-}
-
-static void swap_em_state(em_state_t *ems1,em_state_t *ems2)
-{
-  em_state_t tmp;
-
-  tmp   = *ems1;
-  *ems1 = *ems2;
-  *ems2 = tmp;
-}
-
-static void copy_em_coords_back(em_state_t *ems,t_state *state,rvec *f)
-{
-  int i;
-
-  for(i=0; (i<state->natoms); i++)
-    copy_rvec(ems->s.x[i],state->x[i]);
-  if (f != NULL)
-    copy_rvec(ems->f[i],f[i]);
-}
-
-static void write_em_traj(FILE *fplog,t_commrec *cr,
-                          gmx_mdoutf_t *outf,
-                          gmx_bool bX,gmx_bool bF,const char *confout,
-                          gmx_mtop_t *top_global,
-                          t_inputrec *ir,gmx_large_int_t step,
-                          em_state_t *state,
-                          t_state *state_global,rvec *f_global)
-{
-    int mdof_flags;
-
-    if ((bX || bF || confout != NULL) && !DOMAINDECOMP(cr))
-    {
-        f_global = state->f;
-        copy_em_coords_back(state,state_global,bF ? f_global : NULL);
-    }
-    
-    mdof_flags = 0;
-    if (bX) { mdof_flags |= MDOF_X; }
-    if (bF) { mdof_flags |= MDOF_F; }
-    write_traj(fplog,cr,outf,mdof_flags,
-               top_global,step,(double)step,
-               &state->s,state_global,state->f,f_global,NULL,NULL);
-    
-    if (confout != NULL && MASTER(cr))
-    {
-        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols && DOMAINDECOMP(cr))
-        {
-            /* Make molecules whole only for confout writing */
-            do_pbc_mtop(fplog,ir->ePBC,state_global->box,top_global,
-                        state_global->x);
-        }
-
-        write_sto_conf_mtop(confout,
-                            *top_global->name,top_global,
-                            state_global->x,NULL,ir->ePBC,state_global->box);
-    }
-}
-
-static void do_em_step(t_commrec *cr,t_inputrec *ir,t_mdatoms *md,
-                      em_state_t *ems1,real a,rvec *f,em_state_t *ems2,
-                      gmx_constr_t constr,gmx_localtop_t *top,
-                      t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                      gmx_large_int_t count)
-
-{
-  t_state *s1,*s2;
-  int  start,end,gf,i,m;
-  rvec *x1,*x2;
-  real dvdlambda;
-
-  s1 = &ems1->s;
-  s2 = &ems2->s;
-
-  if (DOMAINDECOMP(cr) && s1->ddp_count != cr->dd->ddp_count)
-    gmx_incons("state mismatch in do_em_step");
-
-  s2->flags = s1->flags;
-
-  if (s2->nalloc != s1->nalloc) {
-    s2->nalloc = s1->nalloc;
-    srenew(s2->x,s1->nalloc);
-    srenew(ems2->f,  s1->nalloc);
-    if (s2->flags & (1<<estCGP))
-      srenew(s2->cg_p,  s1->nalloc);
-  }
-  
-  s2->natoms = s1->natoms;
-  s2->lambda = s1->lambda;
-  copy_mat(s1->box,s2->box);
-
-  start = md->start;
-  end   = md->start + md->homenr;
-
-  x1 = s1->x;
-  x2 = s2->x;
-  gf = 0;
-  for(i=start; i<end; i++) {
-    if (md->cFREEZE)
-      gf = md->cFREEZE[i];
-    for(m=0; m<DIM; m++) {
-      if (ir->opts.nFreeze[gf][m])
-       x2[i][m] = x1[i][m];
-      else
-       x2[i][m] = x1[i][m] + a*f[i][m];
-    }
-  }
-
-  if (s2->flags & (1<<estCGP)) {
-    /* Copy the CG p vector */
-    x1 = s1->cg_p;
-    x2 = s2->cg_p;
-    for(i=start; i<end; i++)
-      copy_rvec(x1[i],x2[i]);
-  }
-
-  if (DOMAINDECOMP(cr)) {
-    s2->ddp_count = s1->ddp_count;
-    if (s2->cg_gl_nalloc < s1->cg_gl_nalloc) {
-      s2->cg_gl_nalloc = s1->cg_gl_nalloc;
-      srenew(s2->cg_gl,s2->cg_gl_nalloc);
-    }
-    s2->ncg_gl = s1->ncg_gl;
-    for(i=0; i<s2->ncg_gl; i++)
-      s2->cg_gl[i] = s1->cg_gl[i];
-    s2->ddp_count_cg_gl = s1->ddp_count_cg_gl;
-  }
-
-  if (constr) {
-    wallcycle_start(wcycle,ewcCONSTR);
-    dvdlambda = 0;
-    constrain(NULL,TRUE,TRUE,constr,&top->idef,        
-              ir,NULL,cr,count,0,md,
-              s1->x,s2->x,NULL,s2->box,s2->lambda,
-              &dvdlambda,NULL,NULL,nrnb,econqCoord,FALSE,0,0);
-    wallcycle_stop(wcycle,ewcCONSTR);
-  }
-}
-
-static void do_x_step(t_commrec *cr,int n,rvec *x1,real a,rvec *f,rvec *x2)
-
-{
-  int  start,end,i,m;
-
-  if (DOMAINDECOMP(cr)) {
-    start = 0;
-    end   = cr->dd->nat_home;
-  } else if (PARTDECOMP(cr)) {
-    pd_at_range(cr,&start,&end);
-  } else {
-    start = 0;
-    end   = n;
-  }
-
-  for(i=start; i<end; i++) {
-    for(m=0; m<DIM; m++) {
-      x2[i][m] = x1[i][m] + a*f[i][m];
-    }
-  }
-}
-
-static void do_x_sub(t_commrec *cr,int n,rvec *x1,rvec *x2,real a,rvec *f)
-
-{
-  int  start,end,i,m;
-
-  if (DOMAINDECOMP(cr)) {
-    start = 0;
-    end   = cr->dd->nat_home;
-  } else if (PARTDECOMP(cr)) {
-    pd_at_range(cr,&start,&end);
-  } else {
-    start = 0;
-    end   = n;
-  }
-
-  for(i=start; i<end; i++) {
-    for(m=0; m<DIM; m++) {
-      f[i][m] = (x1[i][m] - x2[i][m])*a;
-    }
-  }
-}
-
-static void em_dd_partition_system(FILE *fplog,int step,t_commrec *cr,
-                                   gmx_mtop_t *top_global,t_inputrec *ir,
-                                   em_state_t *ems,gmx_localtop_t *top,
-                                   t_mdatoms *mdatoms,t_forcerec *fr,
-                                   gmx_vsite_t *vsite,gmx_constr_t constr,
-                                   t_nrnb *nrnb,gmx_wallcycle_t wcycle)
-{
-    /* Repartition the domain decomposition */
-    wallcycle_start(wcycle,ewcDOMDEC);
-    dd_partition_system(fplog,step,cr,FALSE,1,
-                        NULL,top_global,ir,
-                        &ems->s,&ems->f,
-                        mdatoms,top,fr,vsite,NULL,constr,
-                        nrnb,wcycle,FALSE);
-    dd_store_state(cr->dd,&ems->s);
-    wallcycle_stop(wcycle,ewcDOMDEC);
-}
-    
-static void evaluate_energy(FILE *fplog,gmx_bool bVerbose,t_commrec *cr,
-                            t_state *state_global,gmx_mtop_t *top_global,
-                            em_state_t *ems,gmx_localtop_t *top,
-                            t_inputrec *inputrec,
-                            t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                            gmx_global_stat_t gstat,
-                            gmx_vsite_t *vsite,gmx_constr_t constr,
-                            t_fcdata *fcd,
-                            t_graph *graph,t_mdatoms *mdatoms,
-                            t_forcerec *fr,rvec mu_tot,
-                            gmx_enerdata_t *enerd,tensor vir,tensor pres,
-                            gmx_large_int_t count,gmx_bool bFirst)
-{
-  real t;
-  gmx_bool bNS;
-  int  nabnsb;
-  tensor force_vir,shake_vir,ekin;
-  real dvdl,prescorr,enercorr,dvdlcorr;
-  real terminate=0;
-  
-  /* Set the time to the initial time, the time does not change during EM */
-  t = inputrec->init_t;
-
-  if (bFirst ||
-      (DOMAINDECOMP(cr) && ems->s.ddp_count < cr->dd->ddp_count)) {
-    /* This the first state or an old state used before the last ns */
-    bNS = TRUE;
-  } else {
-    bNS = FALSE;
-    if (inputrec->nstlist > 0) {
-      bNS = TRUE;
-    } else if (inputrec->nstlist == -1) {
-      nabnsb = natoms_beyond_ns_buffer(inputrec,fr,&top->cgs,NULL,ems->s.x);
-      if (PAR(cr))
-       gmx_sumi(1,&nabnsb,cr);
-      bNS = (nabnsb > 0);
-    }
-  }
-
-  if (vsite)
-    construct_vsites(fplog,vsite,ems->s.x,nrnb,1,NULL,
-                    top->idef.iparams,top->idef.il,
-                    fr->ePBC,fr->bMolPBC,graph,cr,ems->s.box);
-
-  if (DOMAINDECOMP(cr)) {
-    if (bNS) {
-      /* Repartition the domain decomposition */
-      em_dd_partition_system(fplog,count,cr,top_global,inputrec,
-                            ems,top,mdatoms,fr,vsite,constr,
-                            nrnb,wcycle);
-    }
-  }
-      
-    /* Calc force & energy on new trial position  */
-    /* do_force always puts the charge groups in the box and shifts again
-     * We do not unshift, so molecules are always whole in congrad.c
-     */
-    do_force(fplog,cr,inputrec,
-             count,nrnb,wcycle,top,top_global,&top_global->groups,
-             ems->s.box,ems->s.x,&ems->s.hist,
-             ems->f,force_vir,mdatoms,enerd,fcd,
-             ems->s.lambda,graph,fr,vsite,mu_tot,t,NULL,NULL,TRUE,
-             GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES | GMX_FORCE_VIRIAL |
-             (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0));
-       
-  /* Clear the unused shake virial and pressure */
-  clear_mat(shake_vir);
-  clear_mat(pres);
-
-  /* Calculate long range corrections to pressure and energy */
-  calc_dispcorr(fplog,inputrec,fr,count,top_global->natoms,ems->s.box,ems->s.lambda,
-                pres,force_vir,&prescorr,&enercorr,&dvdlcorr);
-  /* don't think these next 4 lines  can be moved in for now, because we 
-     don't always want to write it -- figure out how to clean this up MRS 8/4/2009 */
-  enerd->term[F_DISPCORR] = enercorr;
-  enerd->term[F_EPOT] += enercorr;
-  enerd->term[F_PRES] += prescorr;
-  enerd->term[F_DVDL] += dvdlcorr;
-
-    /* Communicate stuff when parallel */
-    if (PAR(cr) && inputrec->eI != eiNM)
-    {
-        wallcycle_start(wcycle,ewcMoveE);
-
-        global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
-                    inputrec,NULL,NULL,NULL,1,&terminate,
-                    top_global,&ems->s,FALSE,
-                    CGLO_ENERGY | 
-                    CGLO_PRESSURE | 
-                    CGLO_CONSTRAINT | 
-                    CGLO_FIRSTITERATE);
-
-        wallcycle_stop(wcycle,ewcMoveE);
-    }
-
-  ems->epot = enerd->term[F_EPOT];
-  
-  if (constr) {
-    /* Project out the constraint components of the force */
-    wallcycle_start(wcycle,ewcCONSTR);
-    dvdl = 0;
-    constrain(NULL,FALSE,FALSE,constr,&top->idef,
-              inputrec,NULL,cr,count,0,mdatoms,
-              ems->s.x,ems->f,ems->f,ems->s.box,ems->s.lambda,&dvdl,
-              NULL,&shake_vir,nrnb,econqForceDispl,FALSE,0,0);
-    if (fr->bSepDVDL && fplog)
-      fprintf(fplog,sepdvdlformat,"Constraints",t,dvdl);
-    enerd->term[F_DHDL_CON] += dvdl;
-    m_add(force_vir,shake_vir,vir);
-    wallcycle_stop(wcycle,ewcCONSTR);
-  } else {
-    copy_mat(force_vir,vir);
-  }
-
-  clear_mat(ekin);
-  enerd->term[F_PRES] =
-    calc_pres(fr->ePBC,inputrec->nwall,ems->s.box,ekin,vir,pres,
-             (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
-
-  sum_dhdl(enerd,ems->s.lambda,inputrec);
-
-    if (EI_ENERGY_MINIMIZATION(inputrec->eI))
-    {
-        get_state_f_norm_max(cr,&(inputrec->opts),mdatoms,ems);
-    }
-}
-
-static double reorder_partsum(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
-                             gmx_mtop_t *mtop,
-                             em_state_t *s_min,em_state_t *s_b)
-{
-  rvec *fm,*fb,*fmg;
-  t_block *cgs_gl;
-  int ncg,*cg_gl,*index,c,cg,i,a0,a1,a,gf,m;
-  double partsum;
-  unsigned char *grpnrFREEZE;
-
-  if (debug)
-    fprintf(debug,"Doing reorder_partsum\n");
-
-  fm = s_min->f;
-  fb = s_b->f;
-
-  cgs_gl = dd_charge_groups_global(cr->dd);
-  index = cgs_gl->index;
-
-  /* Collect fm in a global vector fmg.
-   * This conflicts with the spirit of domain decomposition,
-   * but to fully optimize this a much more complicated algorithm is required.
-   */
-  snew(fmg,mtop->natoms);
-  
-  ncg   = s_min->s.ncg_gl;
-  cg_gl = s_min->s.cg_gl;
-  i = 0;
-  for(c=0; c<ncg; c++) {
-    cg = cg_gl[c];
-    a0 = index[cg];
-    a1 = index[cg+1];
-    for(a=a0; a<a1; a++) {
-      copy_rvec(fm[i],fmg[a]);
-      i++;
-    }
-  }
-  gmx_sum(mtop->natoms*3,fmg[0],cr);
-
-  /* Now we will determine the part of the sum for the cgs in state s_b */
-  ncg   = s_b->s.ncg_gl;
-  cg_gl = s_b->s.cg_gl;
-  partsum = 0;
-  i = 0;
-  gf = 0;
-  grpnrFREEZE = mtop->groups.grpnr[egcFREEZE];
-  for(c=0; c<ncg; c++) {
-    cg = cg_gl[c];
-    a0 = index[cg];
-    a1 = index[cg+1];
-    for(a=a0; a<a1; a++) {
-      if (mdatoms->cFREEZE && grpnrFREEZE) {
-       gf = grpnrFREEZE[i];
-      }
-      for(m=0; m<DIM; m++) {
-       if (!opts->nFreeze[gf][m]) {
-         partsum += (fb[i][m] - fmg[a][m])*fb[i][m];
-       }
-      }
-      i++;
-    }
-  }
-  
-  sfree(fmg);
-
-  return partsum;
-}
-
-static real pr_beta(t_commrec *cr,t_grpopts *opts,t_mdatoms *mdatoms,
-                   gmx_mtop_t *mtop,
-                   em_state_t *s_min,em_state_t *s_b)
-{
-  rvec *fm,*fb;
-  double sum;
-  int  gf,i,m;
-
-  /* This is just the classical Polak-Ribiere calculation of beta;
-   * it looks a bit complicated since we take freeze groups into account,
-   * and might have to sum it in parallel runs.
-   */
-  
-  if (!DOMAINDECOMP(cr) ||
-      (s_min->s.ddp_count == cr->dd->ddp_count &&
-       s_b->s.ddp_count   == cr->dd->ddp_count)) {
-    fm = s_min->f;
-    fb = s_b->f;
-    sum = 0;
-    gf = 0;
-    /* This part of code can be incorrect with DD,
-     * since the atom ordering in s_b and s_min might differ.
-     */
-    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      if (mdatoms->cFREEZE)
-       gf = mdatoms->cFREEZE[i];
-      for(m=0; m<DIM; m++)
-       if (!opts->nFreeze[gf][m]) {
-         sum += (fb[i][m] - fm[i][m])*fb[i][m];
-       } 
-    }
-  } else {
-    /* We need to reorder cgs while summing */
-    sum = reorder_partsum(cr,opts,mdatoms,mtop,s_min,s_b);
-  }
-  if (PAR(cr))
-    gmx_sumd(1,&sum,cr);
-
-  return sum/sqr(s_min->fnorm);
-}
-
-double do_cg(FILE *fplog,t_commrec *cr,
-             int nfile,const t_filenm fnm[],
-             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-             int nstglobalcomm,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int stepout,
-             t_inputrec *inputrec,
-             gmx_mtop_t *top_global,t_fcdata *fcd,
-             t_state *state_global,
-             t_mdatoms *mdatoms,
-             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-             gmx_edsam_t ed,
-             t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
-             real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags,
-             gmx_runtime_t *runtime)
-{
-  const char *CG="Polak-Ribiere Conjugate Gradients";
-
-  em_state_t *s_min,*s_a,*s_b,*s_c;
-  gmx_localtop_t *top;
-  gmx_enerdata_t *enerd;
-  rvec   *f;
-  gmx_global_stat_t gstat;
-  t_graph    *graph;
-  rvec   *f_global,*p,*sf,*sfm;
-  double gpa,gpb,gpc,tmp,sum[2],minstep;
-  real   fnormn;
-  real   stepsize;     
-  real   a,b,c,beta=0.0;
-  real   epot_repl=0;
-  real   pnorm;
-  t_mdebin   *mdebin;
-  gmx_bool   converged,foundlower;
-  rvec   mu_tot;
-  gmx_bool   do_log=FALSE,do_ene=FALSE,do_x,do_f;
-  tensor vir,pres;
-  int    number_steps,neval=0,nstcg=inputrec->nstcgsteep;
-  gmx_mdoutf_t *outf;
-  int    i,m,gf,step,nminstep;
-  real   terminate=0;  
-
-  step=0;
-
-  s_min = init_em_state();
-  s_a   = init_em_state();
-  s_b   = init_em_state();
-  s_c   = init_em_state();
-
-  /* Init em and store the local state in s_min */
-  init_em(fplog,CG,cr,inputrec,
-          state_global,top_global,s_min,&top,&f,&f_global,
-          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
-          nfile,fnm,&outf,&mdebin);
-  
-  /* Print to log file */
-  print_em_start(fplog,cr,runtime,wcycle,CG);
-  
-  /* Max number of steps */
-  number_steps=inputrec->nsteps;
-
-  if (MASTER(cr))
-    sp_header(stderr,CG,inputrec->em_tol,number_steps);
-  if (fplog)
-    sp_header(fplog,CG,inputrec->em_tol,number_steps);
-
-  /* Call the force routine and some auxiliary (neighboursearching etc.) */
-  /* do_force always puts the charge groups in the box and shifts again
-   * We do not unshift, so molecules are always whole in congrad.c
-   */
-  evaluate_energy(fplog,bVerbose,cr,
-                 state_global,top_global,s_min,top,
-                 inputrec,nrnb,wcycle,gstat,
-                 vsite,constr,fcd,graph,mdatoms,fr,
-                 mu_tot,enerd,vir,pres,-1,TRUE);
-  where();
-
-  if (MASTER(cr)) {
-    /* Copy stuff to the energy bin for easy printing etc. */
-    upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-              mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
-              NULL,NULL,vir,pres,NULL,mu_tot,constr);
-    
-    print_ebin_header(fplog,step,step,s_min->s.lambda);
-    print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
-               TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-  }
-  where();
-
-  /* Estimate/guess the initial stepsize */
-  stepsize = inputrec->em_stepsize/s_min->fnorm;
-  if (MASTER(cr)) {
-    fprintf(stderr,"   F-max             = %12.5e on atom %d\n",
-           s_min->fmax,s_min->a_fmax+1);
-    fprintf(stderr,"   F-Norm            = %12.5e\n",
-           s_min->fnorm/sqrt(state_global->natoms));
-    fprintf(stderr,"\n");
-    /* and copy to the log file too... */
-    fprintf(fplog,"   F-max             = %12.5e on atom %d\n",
-           s_min->fmax,s_min->a_fmax+1);
-    fprintf(fplog,"   F-Norm            = %12.5e\n",
-           s_min->fnorm/sqrt(state_global->natoms));
-    fprintf(fplog,"\n");
-  }  
-  /* Start the loop over CG steps.             
-   * Each successful step is counted, and we continue until
-   * we either converge or reach the max number of steps.
-   */
-  converged = FALSE;
-  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged;step++) {
-    
-    /* start taking steps in a new direction 
-     * First time we enter the routine, beta=0, and the direction is 
-     * simply the negative gradient.
-     */
-
-    /* Calculate the new direction in p, and the gradient in this direction, gpa */
-    p  = s_min->s.cg_p;
-    sf = s_min->f;
-    gpa = 0;
-    gf = 0;
-    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      if (mdatoms->cFREEZE) 
-       gf = mdatoms->cFREEZE[i];
-      for(m=0; m<DIM; m++) {
-       if (!inputrec->opts.nFreeze[gf][m]) {
-         p[i][m] = sf[i][m] + beta*p[i][m];
-         gpa -= p[i][m]*sf[i][m];
-         /* f is negative gradient, thus the sign */
-       } else {
-          p[i][m] = 0;
-       }
-      }
-    }
-    
-    /* Sum the gradient along the line across CPUs */
-    if (PAR(cr))
-      gmx_sumd(1,&gpa,cr);
-
-    /* Calculate the norm of the search vector */
-    get_f_norm_max(cr,&(inputrec->opts),mdatoms,p,&pnorm,NULL,NULL);
-    
-    /* Just in case stepsize reaches zero due to numerical precision... */
-    if(stepsize<=0)      
-      stepsize = inputrec->em_stepsize/pnorm;
-    
-    /* 
-     * Double check the value of the derivative in the search direction.
-     * If it is positive it must be due to the old information in the
-     * CG formula, so just remove that and start over with beta=0.
-     * This corresponds to a steepest descent step.
-     */
-    if(gpa>0) {
-      beta = 0;
-      step--; /* Don't count this step since we are restarting */
-      continue; /* Go back to the beginning of the big for-loop */
-    }
-
-    /* Calculate minimum allowed stepsize, before the average (norm)
-     * relative change in coordinate is smaller than precision
-     */
-    minstep=0;
-    for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      for(m=0; m<DIM; m++) {
-       tmp = fabs(s_min->s.x[i][m]);
-       if(tmp < 1.0)
-         tmp = 1.0;
-       tmp = p[i][m]/tmp;
-       minstep += tmp*tmp;
-      }
-    }
-    /* Add up from all CPUs */
-    if(PAR(cr))
-      gmx_sumd(1,&minstep,cr);
-
-    minstep = GMX_REAL_EPS/sqrt(minstep/(3*state_global->natoms));
-
-    if(stepsize<minstep) {
-      converged=TRUE;
-      break;
-    }
-    
-    /* Write coordinates if necessary */
-    do_x = do_per_step(step,inputrec->nstxout);
-    do_f = do_per_step(step,inputrec->nstfout);
-    
-    write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
-                  top_global,inputrec,step,
-                  s_min,state_global,f_global);
-    
-    /* Take a step downhill.
-     * In theory, we should minimize the function along this direction.
-     * That is quite possible, but it turns out to take 5-10 function evaluations
-     * for each line. However, we dont really need to find the exact minimum -
-     * it is much better to start a new CG step in a modified direction as soon
-     * as we are close to it. This will save a lot of energy evaluations.
-     *
-     * In practice, we just try to take a single step.
-     * If it worked (i.e. lowered the energy), we increase the stepsize but
-     * the continue straight to the next CG step without trying to find any minimum.
-     * If it didn't work (higher energy), there must be a minimum somewhere between
-     * the old position and the new one.
-     * 
-     * Due to the finite numerical accuracy, it turns out that it is a good idea
-     * to even accept a SMALL increase in energy, if the derivative is still downhill.
-     * This leads to lower final energies in the tests I've done. / Erik 
-     */
-    s_a->epot = s_min->epot;
-    a = 0.0;
-    c = a + stepsize; /* reference position along line is zero */
-    
-    if (DOMAINDECOMP(cr) && s_min->s.ddp_count < cr->dd->ddp_count) {
-      em_dd_partition_system(fplog,step,cr,top_global,inputrec,
-                            s_min,top,mdatoms,fr,vsite,constr,
-                            nrnb,wcycle);
-    }
-
-    /* Take a trial step (new coords in s_c) */
-    do_em_step(cr,inputrec,mdatoms,s_min,c,s_min->s.cg_p,s_c,
-              constr,top,nrnb,wcycle,-1);
-    
-    neval++;
-    /* Calculate energy for the trial step */
-    evaluate_energy(fplog,bVerbose,cr,
-                   state_global,top_global,s_c,top,
-                   inputrec,nrnb,wcycle,gstat,
-                   vsite,constr,fcd,graph,mdatoms,fr,
-                   mu_tot,enerd,vir,pres,-1,FALSE);
-    
-    /* Calc derivative along line */
-    p  = s_c->s.cg_p;
-    sf = s_c->f;
-    gpc=0;
-    for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-      for(m=0; m<DIM; m++) 
-         gpc -= p[i][m]*sf[i][m];  /* f is negative gradient, thus the sign */
-    }
-    /* Sum the gradient along the line across CPUs */
-    if (PAR(cr))
-      gmx_sumd(1,&gpc,cr);
-
-    /* This is the max amount of increase in energy we tolerate */
-    tmp=sqrt(GMX_REAL_EPS)*fabs(s_a->epot);
-
-    /* Accept the step if the energy is lower, or if it is not significantly higher
-     * and the line derivative is still negative.
-     */
-    if (s_c->epot < s_a->epot || (gpc < 0 && s_c->epot < (s_a->epot + tmp))) {
-      foundlower = TRUE;
-      /* Great, we found a better energy. Increase step for next iteration
-       * if we are still going down, decrease it otherwise
-       */
-      if(gpc<0)
-       stepsize *= 1.618034;  /* The golden section */
-      else
-       stepsize *= 0.618034;  /* 1/golden section */
-    } else {
-      /* New energy is the same or higher. We will have to do some work
-       * to find a smaller value in the interval. Take smaller step next time!
-       */
-      foundlower = FALSE;
-      stepsize *= 0.618034;
-    }    
-
-
-
-    
-    /* OK, if we didn't find a lower value we will have to locate one now - there must
-     * be one in the interval [a=0,c].
-     * The same thing is valid here, though: Don't spend dozens of iterations to find
-     * the line minimum. We try to interpolate based on the derivative at the endpoints,
-     * and only continue until we find a lower value. In most cases this means 1-2 iterations.
-     *
-     * I also have a safeguard for potentially really patological functions so we never
-     * take more than 20 steps before we give up ...
-     *
-     * If we already found a lower value we just skip this step and continue to the update.
-     */
-    if (!foundlower) {
-      nminstep=0;
-
-      do {
-       /* Select a new trial point.
-        * If the derivatives at points a & c have different sign we interpolate to zero,
-        * otherwise just do a bisection.
-        */
-       if(gpa<0 && gpc>0)
-         b = a + gpa*(a-c)/(gpc-gpa);
-       else
-         b = 0.5*(a+c);                
-       
-       /* safeguard if interpolation close to machine accuracy causes errors:
-        * never go outside the interval
-        */
-       if(b<=a || b>=c)
-         b = 0.5*(a+c);
-       
-       if (DOMAINDECOMP(cr) && s_min->s.ddp_count != cr->dd->ddp_count) {
-         /* Reload the old state */
-         em_dd_partition_system(fplog,-1,cr,top_global,inputrec,
-                                s_min,top,mdatoms,fr,vsite,constr,
-                                nrnb,wcycle);
-       }
-
-       /* Take a trial step to this new point - new coords in s_b */
-       do_em_step(cr,inputrec,mdatoms,s_min,b,s_min->s.cg_p,s_b,
-                  constr,top,nrnb,wcycle,-1);
-       
-       neval++;
-       /* Calculate energy for the trial step */
-       evaluate_energy(fplog,bVerbose,cr,
-                       state_global,top_global,s_b,top,
-                       inputrec,nrnb,wcycle,gstat,
-                       vsite,constr,fcd,graph,mdatoms,fr,
-                       mu_tot,enerd,vir,pres,-1,FALSE);
-       
-       /* p does not change within a step, but since the domain decomposition
-        * might change, we have to use cg_p of s_b here.
-        */
-       p  = s_b->s.cg_p;
-       sf = s_b->f;
-       gpb=0;
-       for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++) {
-         for(m=0; m<DIM; m++)
-             gpb -= p[i][m]*sf[i][m];   /* f is negative gradient, thus the sign */
-       }
-       /* Sum the gradient along the line across CPUs */
-       if (PAR(cr))
-         gmx_sumd(1,&gpb,cr);
-       
-       if (debug)
-         fprintf(debug,"CGE: EpotA %f EpotB %f EpotC %f gpb %f\n",
-                 s_a->epot,s_b->epot,s_c->epot,gpb);
-
-       epot_repl = s_b->epot;
-       
-       /* Keep one of the intervals based on the value of the derivative at the new point */
-       if (gpb > 0) {
-         /* Replace c endpoint with b */
-         swap_em_state(s_b,s_c);
-         c = b;
-         gpc = gpb;
-       } else {
-         /* Replace a endpoint with b */
-         swap_em_state(s_b,s_a);
-         a = b;
-         gpa = gpb;
-       }
-       
-       /* 
-        * Stop search as soon as we find a value smaller than the endpoints.
-        * Never run more than 20 steps, no matter what.
-        */
-       nminstep++;
-      } while ((epot_repl > s_a->epot || epot_repl > s_c->epot) &&
-              (nminstep < 20));     
-      
-      if (fabs(epot_repl - s_min->epot) < fabs(s_min->epot)*GMX_REAL_EPS ||
-         nminstep >= 20) {
-       /* OK. We couldn't find a significantly lower energy.
-        * If beta==0 this was steepest descent, and then we give up.
-        * If not, set beta=0 and restart with steepest descent before quitting.
-         */
-       if (beta == 0.0) {
-         /* Converged */
-         converged = TRUE;
-         break;
-       } else {
-         /* Reset memory before giving up */
-         beta = 0.0;
-         continue;
-       }
-      }
-      
-      /* Select min energy state of A & C, put the best in B.
-       */
-      if (s_c->epot < s_a->epot) {
-       if (debug)
-         fprintf(debug,"CGE: C (%f) is lower than A (%f), moving C to B\n",
-                 s_c->epot,s_a->epot);
-       swap_em_state(s_b,s_c);
-       gpb = gpc;
-       b = c;
-      } else {
-       if (debug)
-         fprintf(debug,"CGE: A (%f) is lower than C (%f), moving A to B\n",
-                 s_a->epot,s_c->epot);
-       swap_em_state(s_b,s_a);
-       gpb = gpa;
-       b = a;
-      }
-      
-    } else {
-      if (debug)
-       fprintf(debug,"CGE: Found a lower energy %f, moving C to B\n",
-               s_c->epot);
-      swap_em_state(s_b,s_c);
-      gpb = gpc;
-      b = c;
-    }
-    
-    /* new search direction */
-    /* beta = 0 means forget all memory and restart with steepest descents. */
-    if (nstcg && ((step % nstcg)==0)) 
-      beta = 0.0;
-    else {
-      /* s_min->fnorm cannot be zero, because then we would have converged
-       * and broken out.
-       */
-
-      /* Polak-Ribiere update.
-       * Change to fnorm2/fnorm2_old for Fletcher-Reeves
-       */
-      beta = pr_beta(cr,&inputrec->opts,mdatoms,top_global,s_min,s_b);
-    }
-    /* Limit beta to prevent oscillations */
-    if (fabs(beta) > 5.0)
-      beta = 0.0;
-    
-    
-    /* update positions */
-    swap_em_state(s_min,s_b);
-    gpa = gpb;
-    
-    /* Print it if necessary */
-    if (MASTER(cr)) {
-      if(bVerbose)
-       fprintf(stderr,"\rStep %d, Epot=%12.6e, Fnorm=%9.3e, Fmax=%9.3e (atom %d)\n",
-               step,s_min->epot,s_min->fnorm/sqrt(state_global->natoms),
-               s_min->fmax,s_min->a_fmax+1);
-      /* Store the new (lower) energies */
-      upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-                mdatoms->tmass,enerd,&s_min->s,s_min->s.box,
-                NULL,NULL,vir,pres,NULL,mu_tot,constr);
-      do_log = do_per_step(step,inputrec->nstlog);
-      do_ene = do_per_step(step,inputrec->nstenergy);
-      if(do_log)
-       print_ebin_header(fplog,step,step,s_min->s.lambda);
-      print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
-                do_log ? fplog : NULL,step,step,eprNORMAL,
-                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-    }
-    
-    /* Stop when the maximum force lies below tolerance.
-     * If we have reached machine precision, converged is already set to true.
-     */        
-    converged = converged || (s_min->fmax < inputrec->em_tol);
-    
-  } /* End of the loop */
-  
-  if (converged)       
-    step--; /* we never took that last step in this case */
-  
-    if (s_min->fmax > inputrec->em_tol)
-    {
-        if (MASTER(cr))
-        {
-            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
-            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
-        }
-        converged = FALSE; 
-    }
-  
-  if (MASTER(cr)) {
-    /* If we printed energy and/or logfile last step (which was the last step)
-     * we don't have to do it again, but otherwise print the final values.
-     */
-    if(!do_log) {
-      /* Write final value to log since we didn't do anything the last step */
-      print_ebin_header(fplog,step,step,s_min->s.lambda);
-    }
-    if (!do_ene || !do_log) {
-      /* Write final energy file entries */
-      print_ebin(outf->fp_ene,!do_ene,FALSE,FALSE,
-                !do_log ? fplog : NULL,step,step,eprNORMAL,
-                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-    }
-  }
-
-  /* Print some stuff... */
-  if (MASTER(cr))
-    fprintf(stderr,"\nwriting lowest energy coordinates.\n");
-  
-  /* IMPORTANT!
-   * For accurate normal mode calculation it is imperative that we
-   * store the last conformation into the full precision binary trajectory.
-   *
-   * However, we should only do it if we did NOT already write this step
-   * above (which we did if do_x or do_f was true).
-   */  
-  do_x = !do_per_step(step,inputrec->nstxout);
-  do_f = (inputrec->nstfout > 0 && !do_per_step(step,inputrec->nstfout));
-  
-  write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
-                top_global,inputrec,step,
-                s_min,state_global,f_global);
-  
-  fnormn = s_min->fnorm/sqrt(state_global->natoms);
-  
-  if (MASTER(cr)) {
-    print_converged(stderr,CG,inputrec->em_tol,step,converged,number_steps,
-                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
-    print_converged(fplog,CG,inputrec->em_tol,step,converged,number_steps,
-                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
-    
-    fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
-  }
-  
-  finish_em(fplog,cr,outf,runtime,wcycle);
-  
-  /* To print the actual number of steps we needed somewhere */
-  runtime->nsteps_done = step;
-
-  return 0;
-} /* That's all folks */
-
-
-double do_lbfgs(FILE *fplog,t_commrec *cr,
-                int nfile,const t_filenm fnm[],
-                const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-                int nstglobalcomm,
-                gmx_vsite_t *vsite,gmx_constr_t constr,
-                int stepout,
-                t_inputrec *inputrec,
-                gmx_mtop_t *top_global,t_fcdata *fcd,
-                t_state *state,
-                t_mdatoms *mdatoms,
-                t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                gmx_edsam_t ed,
-                t_forcerec *fr,
-                int repl_ex_nst,int repl_ex_seed,
-                real cpt_period,real max_hours,
-                const char *deviceOptions,
-                unsigned long Flags,
-                gmx_runtime_t *runtime)
-{
-  static const char *LBFGS="Low-Memory BFGS Minimizer";
-  em_state_t ems;
-  gmx_localtop_t *top;
-  gmx_enerdata_t *enerd;
-  rvec   *f;
-  gmx_global_stat_t gstat;
-  t_graph    *graph;
-  rvec   *f_global;
-  int    ncorr,nmaxcorr,point,cp,neval,nminstep;
-  double stepsize,gpa,gpb,gpc,tmp,minstep;
-  real   *rho,*alpha,*ff,*xx,*p,*s,*lastx,*lastf,**dx,**dg;    
-  real   *xa,*xb,*xc,*fa,*fb,*fc,*xtmp,*ftmp;
-  real   a,b,c,maxdelta,delta;
-  real   diag,Epot0,Epot,EpotA,EpotB,EpotC;
-  real   dgdx,dgdg,sq,yr,beta;
-  t_mdebin   *mdebin;
-  gmx_bool   converged,first;
-  rvec   mu_tot;
-  real   fnorm,fmax;
-  gmx_bool   do_log,do_ene,do_x,do_f,foundlower,*frozen;
-  tensor vir,pres;
-  int    start,end,number_steps;
-  gmx_mdoutf_t *outf;
-  int    i,k,m,n,nfmax,gf,step;
-  /* not used */
-  real   terminate;
-
-  if (PAR(cr))
-    gmx_fatal(FARGS,"Cannot do parallel L-BFGS Minimization - yet.\n");
-  
-  n = 3*state->natoms;
-  nmaxcorr = inputrec->nbfgscorr;
-  
-  /* Allocate memory */
-  /* Use pointers to real so we dont have to loop over both atoms and
-   * dimensions all the time...
-   * x/f are allocated as rvec *, so make new x0/f0 pointers-to-real
-   * that point to the same memory.
-   */
-  snew(xa,n);
-  snew(xb,n);
-  snew(xc,n);
-  snew(fa,n);
-  snew(fb,n);
-  snew(fc,n);
-  snew(frozen,n);
-
-  snew(p,n); 
-  snew(lastx,n); 
-  snew(lastf,n); 
-  snew(rho,nmaxcorr);
-  snew(alpha,nmaxcorr);
-  
-  snew(dx,nmaxcorr);
-  for(i=0;i<nmaxcorr;i++)
-    snew(dx[i],n);
-  
-  snew(dg,nmaxcorr);
-  for(i=0;i<nmaxcorr;i++)
-    snew(dg[i],n);
-
-  step = 0;
-  neval = 0; 
-
-  /* Init em */
-  init_em(fplog,LBFGS,cr,inputrec,
-          state,top_global,&ems,&top,&f,&f_global,
-          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
-          nfile,fnm,&outf,&mdebin);
-  /* Do_lbfgs is not completely updated like do_steep and do_cg,
-   * so we free some memory again.
-   */
-  sfree(ems.s.x);
-  sfree(ems.f);
-
-  xx = (real *)state->x;
-  ff = (real *)f;
-
-  start = mdatoms->start;
-  end   = mdatoms->homenr + start;
-    
-  /* Print to log file */
-  print_em_start(fplog,cr,runtime,wcycle,LBFGS);
-  
-  do_log = do_ene = do_x = do_f = TRUE;
-  
-  /* Max number of steps */
-  number_steps=inputrec->nsteps;
-
-  /* Create a 3*natoms index to tell whether each degree of freedom is frozen */
-  gf = 0;
-  for(i=start; i<end; i++) {
-    if (mdatoms->cFREEZE)
-      gf = mdatoms->cFREEZE[i];
-     for(m=0; m<DIM; m++) 
-       frozen[3*i+m]=inputrec->opts.nFreeze[gf][m];  
-  }
-  if (MASTER(cr))
-    sp_header(stderr,LBFGS,inputrec->em_tol,number_steps);
-  if (fplog)
-    sp_header(fplog,LBFGS,inputrec->em_tol,number_steps);
-  
-  if (vsite)
-    construct_vsites(fplog,vsite,state->x,nrnb,1,NULL,
-                    top->idef.iparams,top->idef.il,
-                    fr->ePBC,fr->bMolPBC,graph,cr,state->box);
-  
-  /* Call the force routine and some auxiliary (neighboursearching etc.) */
-  /* do_force always puts the charge groups in the box and shifts again
-   * We do not unshift, so molecules are always whole
-   */
-  neval++;
-  ems.s.x = state->x;
-  ems.f = f;
-  evaluate_energy(fplog,bVerbose,cr,
-                 state,top_global,&ems,top,
-                 inputrec,nrnb,wcycle,gstat,
-                 vsite,constr,fcd,graph,mdatoms,fr,
-                 mu_tot,enerd,vir,pres,-1,TRUE);
-  where();
-       
-  if (MASTER(cr)) {
-    /* Copy stuff to the energy bin for easy printing etc. */
-    upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-              mdatoms->tmass,enerd,state,state->box,
-              NULL,NULL,vir,pres,NULL,mu_tot,constr);
-    
-    print_ebin_header(fplog,step,step,state->lambda);
-    print_ebin(outf->fp_ene,TRUE,FALSE,FALSE,fplog,step,step,eprNORMAL,
-               TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-  }
-  where();
-  
-  /* This is the starting energy */
-  Epot = enerd->term[F_EPOT];
-  
-  fnorm = ems.fnorm;
-  fmax  = ems.fmax;
-  nfmax = ems.a_fmax;
-  
-  /* Set the initial step.
-   * since it will be multiplied by the non-normalized search direction 
-   * vector (force vector the first time), we scale it by the
-   * norm of the force.
-   */
-  
-  if (MASTER(cr)) {
-    fprintf(stderr,"Using %d BFGS correction steps.\n\n",nmaxcorr);
-    fprintf(stderr,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
-    fprintf(stderr,"   F-Norm            = %12.5e\n",fnorm/sqrt(state->natoms));
-    fprintf(stderr,"\n");
-    /* and copy to the log file too... */
-    fprintf(fplog,"Using %d BFGS correction steps.\n\n",nmaxcorr);
-    fprintf(fplog,"   F-max             = %12.5e on atom %d\n",fmax,nfmax+1);
-    fprintf(fplog,"   F-Norm            = %12.5e\n",fnorm/sqrt(state->natoms));
-    fprintf(fplog,"\n");
-  }   
-  
-  point=0;
-  for(i=0;i<n;i++)
-    if(!frozen[i])
-      dx[point][i] = ff[i];  /* Initial search direction */
-    else
-      dx[point][i] = 0;
-
-  stepsize = 1.0/fnorm;
-  converged = FALSE;
-  
-  /* Start the loop over BFGS steps.           
-   * Each successful step is counted, and we continue until
-   * we either converge or reach the max number of steps.
-   */
-  
-  ncorr=0;
-
-  /* Set the gradient from the force */
-  converged = FALSE;
-  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged; step++) {
-    
-    /* Write coordinates if necessary */
-    do_x = do_per_step(step,inputrec->nstxout);
-    do_f = do_per_step(step,inputrec->nstfout);
-    
-    write_traj(fplog,cr,outf,MDOF_X | MDOF_F,
-               top_global,step,(real)step,state,state,f,f,NULL,NULL);
-
-    /* Do the linesearching in the direction dx[point][0..(n-1)] */
-    
-    /* pointer to current direction - point=0 first time here */
-    s=dx[point];
-    
-    /* calculate line gradient */
-    for(gpa=0,i=0;i<n;i++) 
-       gpa-=s[i]*ff[i];
-
-    /* Calculate minimum allowed stepsize, before the average (norm) 
-     * relative change in coordinate is smaller than precision 
-     */
-    for(minstep=0,i=0;i<n;i++) {
-      tmp=fabs(xx[i]);
-      if(tmp<1.0)
-       tmp=1.0;
-      tmp = s[i]/tmp;
-      minstep += tmp*tmp;
-    }
-    minstep = GMX_REAL_EPS/sqrt(minstep/n);
-    
-    if(stepsize<minstep) {
-      converged=TRUE;
-      break;
-    }
-    
-    /* Store old forces and coordinates */
-    for(i=0;i<n;i++) {
-      lastx[i]=xx[i];
-      lastf[i]=ff[i];
-    }
-    Epot0=Epot;
-    
-    first=TRUE;
-    
-    for(i=0;i<n;i++)
-      xa[i]=xx[i];
-    
-    /* Take a step downhill.
-     * In theory, we should minimize the function along this direction.
-     * That is quite possible, but it turns out to take 5-10 function evaluations
-     * for each line. However, we dont really need to find the exact minimum -
-     * it is much better to start a new BFGS step in a modified direction as soon
-     * as we are close to it. This will save a lot of energy evaluations.
-     *
-     * In practice, we just try to take a single step.
-     * If it worked (i.e. lowered the energy), we increase the stepsize but
-     * the continue straight to the next BFGS step without trying to find any minimum.
-     * If it didn't work (higher energy), there must be a minimum somewhere between
-     * the old position and the new one.
-     * 
-     * Due to the finite numerical accuracy, it turns out that it is a good idea
-     * to even accept a SMALL increase in energy, if the derivative is still downhill.
-     * This leads to lower final energies in the tests I've done. / Erik 
-     */
-    foundlower=FALSE;
-    EpotA = Epot0;
-    a = 0.0;
-    c = a + stepsize; /* reference position along line is zero */
-
-    /* Check stepsize first. We do not allow displacements 
-     * larger than emstep.
-     */
-    do {
-      c = a + stepsize;
-      maxdelta=0;
-      for(i=0;i<n;i++) {
-       delta=c*s[i];
-       if(delta>maxdelta)
-         maxdelta=delta;
-      }
-      if(maxdelta>inputrec->em_stepsize)
-       stepsize*=0.1;
-    } while(maxdelta>inputrec->em_stepsize);
-
-    /* Take a trial step */
-    for (i=0; i<n; i++)
-      xc[i] = lastx[i] + c*s[i];
-    
-    neval++;
-    /* Calculate energy for the trial step */
-    ems.s.x = (rvec *)xc;
-    ems.f   = (rvec *)fc;
-    evaluate_energy(fplog,bVerbose,cr,
-                   state,top_global,&ems,top,
-                   inputrec,nrnb,wcycle,gstat,
-                   vsite,constr,fcd,graph,mdatoms,fr,
-                   mu_tot,enerd,vir,pres,step,FALSE);
-    EpotC = ems.epot;
-    
-    /* Calc derivative along line */
-    for(gpc=0,i=0; i<n; i++) {
-       gpc -= s[i]*fc[i];   /* f is negative gradient, thus the sign */
-    }
-    /* Sum the gradient along the line across CPUs */
-    if (PAR(cr))
-      gmx_sumd(1,&gpc,cr);
-    
-     /* This is the max amount of increase in energy we tolerate */
-   tmp=sqrt(GMX_REAL_EPS)*fabs(EpotA);
-    
-    /* Accept the step if the energy is lower, or if it is not significantly higher
-     * and the line derivative is still negative.
-     */
-    if(EpotC<EpotA || (gpc<0 && EpotC<(EpotA+tmp))) {
-      foundlower = TRUE;
-      /* Great, we found a better energy. Increase step for next iteration
-       * if we are still going down, decrease it otherwise
-       */
-      if(gpc<0)
-       stepsize *= 1.618034;  /* The golden section */
-      else
-       stepsize *= 0.618034;  /* 1/golden section */
-    } else {
-      /* New energy is the same or higher. We will have to do some work
-       * to find a smaller value in the interval. Take smaller step next time!
-       */
-      foundlower = FALSE;
-      stepsize *= 0.618034;
-    }    
-    
-    /* OK, if we didn't find a lower value we will have to locate one now - there must
-     * be one in the interval [a=0,c].
-     * The same thing is valid here, though: Don't spend dozens of iterations to find
-     * the line minimum. We try to interpolate based on the derivative at the endpoints,
-     * and only continue until we find a lower value. In most cases this means 1-2 iterations.
-     *
-     * I also have a safeguard for potentially really patological functions so we never
-     * take more than 20 steps before we give up ...
-     *
-     * If we already found a lower value we just skip this step and continue to the update.
-     */
-
-    if(!foundlower) {
-     
-      nminstep=0;
-      do {
-       /* Select a new trial point.
-        * If the derivatives at points a & c have different sign we interpolate to zero,
-        * otherwise just do a bisection.
-        */
-       
-       if(gpa<0 && gpc>0)
-         b = a + gpa*(a-c)/(gpc-gpa);
-       else
-         b = 0.5*(a+c);                
-       
-       /* safeguard if interpolation close to machine accuracy causes errors:
-        * never go outside the interval
-        */
-       if(b<=a || b>=c)
-         b = 0.5*(a+c);
-       
-       /* Take a trial step */
-       for (i=0; i<n; i++) 
-         xb[i] = lastx[i] + b*s[i];
-       
-       neval++;
-       /* Calculate energy for the trial step */
-       ems.s.x = (rvec *)xb;
-       ems.f   = (rvec *)fb;
-       evaluate_energy(fplog,bVerbose,cr,
-                       state,top_global,&ems,top,
-                       inputrec,nrnb,wcycle,gstat,
-                       vsite,constr,fcd,graph,mdatoms,fr,
-                       mu_tot,enerd,vir,pres,step,FALSE);
-       EpotB = ems.epot;
-       
-       fnorm = ems.fnorm;
-       
-       for(gpb=0,i=0; i<n; i++) 
-         gpb -= s[i]*fb[i];   /* f is negative gradient, thus the sign */
-       
-       /* Sum the gradient along the line across CPUs */
-       if (PAR(cr))
-         gmx_sumd(1,&gpb,cr);
-       
-       /* Keep one of the intervals based on the value of the derivative at the new point */
-       if(gpb>0) {
-         /* Replace c endpoint with b */
-         EpotC = EpotB;
-         c = b;
-         gpc = gpb;
-         /* swap coord pointers b/c */
-         xtmp = xb; 
-         ftmp = fb;
-         xb = xc; 
-         fb = fc;
-         xc = xtmp;
-         fc = ftmp;
-       } else {
-         /* Replace a endpoint with b */
-         EpotA = EpotB;
-         a = b;
-         gpa = gpb;
-         /* swap coord pointers a/b */
-         xtmp = xb; 
-         ftmp = fb;
-         xb = xa; 
-         fb = fa;
-         xa = xtmp; 
-         fa = ftmp;
-       }
-       
-       /* 
-        * Stop search as soon as we find a value smaller than the endpoints,
-        * or if the tolerance is below machine precision.
-        * Never run more than 20 steps, no matter what.
-        */
-       nminstep++; 
-      } while((EpotB>EpotA || EpotB>EpotC) && (nminstep<20));
-
-      if(fabs(EpotB-Epot0)<GMX_REAL_EPS || nminstep>=20) {
-       /* OK. We couldn't find a significantly lower energy.
-        * If ncorr==0 this was steepest descent, and then we give up.
-        * If not, reset memory to restart as steepest descent before quitting.
-         */
-       if(ncorr==0) {
-       /* Converged */
-         converged=TRUE;
-         break;
-       } else {
-         /* Reset memory */
-         ncorr=0;
-         /* Search in gradient direction */
-         for(i=0;i<n;i++)
-           dx[point][i]=ff[i];
-         /* Reset stepsize */
-         stepsize = 1.0/fnorm;
-         continue;
-       }
-      }
-      
-      /* Select min energy state of A & C, put the best in xx/ff/Epot
-       */
-      if(EpotC<EpotA) {
-       Epot = EpotC;
-       /* Use state C */
-       for(i=0;i<n;i++) {
-         xx[i]=xc[i];
-         ff[i]=fc[i];
-       }
-       stepsize=c;
-      } else {
-       Epot = EpotA;
-       /* Use state A */
-       for(i=0;i<n;i++) {
-         xx[i]=xa[i];
-         ff[i]=fa[i];
-       }
-       stepsize=a;
-      }
-      
-    } else {
-      /* found lower */
-      Epot = EpotC;
-      /* Use state C */
-      for(i=0;i<n;i++) {
-       xx[i]=xc[i];
-       ff[i]=fc[i];
-      }
-      stepsize=c;
-    }
-
-    /* Update the memory information, and calculate a new 
-     * approximation of the inverse hessian 
-     */
-    
-    /* Have new data in Epot, xx, ff */        
-    if(ncorr<nmaxcorr)
-      ncorr++;
-
-    for(i=0;i<n;i++) {
-      dg[point][i]=lastf[i]-ff[i];
-      dx[point][i]*=stepsize;
-    }
-    
-    dgdg=0;
-    dgdx=0;    
-    for(i=0;i<n;i++) {
-      dgdg+=dg[point][i]*dg[point][i];
-      dgdx+=dg[point][i]*dx[point][i];
-    }
-    
-    diag=dgdx/dgdg;
-    
-    rho[point]=1.0/dgdx;
-    point++;
-    
-    if(point>=nmaxcorr)
-      point=0;
-    
-    /* Update */
-    for(i=0;i<n;i++)
-      p[i]=ff[i];
-    
-    cp=point;
-    
-    /* Recursive update. First go back over the memory points */
-    for(k=0;k<ncorr;k++) {
-      cp--;
-      if(cp<0) 
-       cp=ncorr-1;
-      
-      sq=0;
-      for(i=0;i<n;i++)
-       sq+=dx[cp][i]*p[i];
-      
-      alpha[cp]=rho[cp]*sq;
-      
-      for(i=0;i<n;i++)
-       p[i] -= alpha[cp]*dg[cp][i];            
-    }
-    
-    for(i=0;i<n;i++)
-      p[i] *= diag;
-    
-    /* And then go forward again */
-    for(k=0;k<ncorr;k++) {
-      yr = 0;
-      for(i=0;i<n;i++)
-       yr += p[i]*dg[cp][i];
-      
-      beta = rho[cp]*yr;           
-      beta = alpha[cp]-beta;
-      
-      for(i=0;i<n;i++)
-       p[i] += beta*dx[cp][i];
-      
-      cp++;    
-      if(cp>=ncorr)
-       cp=0;
-    }
-    
-    for(i=0;i<n;i++)
-      if(!frozen[i])
-       dx[point][i] = p[i];
-      else
-       dx[point][i] = 0;
-
-    stepsize=1.0;
-    
-    /* Test whether the convergence criterion is met */
-    get_f_norm_max(cr,&(inputrec->opts),mdatoms,f,&fnorm,&fmax,&nfmax);
-    
-    /* Print it if necessary */
-    if (MASTER(cr)) {
-      if(bVerbose)
-       fprintf(stderr,"\rStep %d, Epot=%12.6e, Fnorm=%9.3e, Fmax=%9.3e (atom %d)\n",
-               step,Epot,fnorm/sqrt(state->natoms),fmax,nfmax+1);
-      /* Store the new (lower) energies */
-      upd_mdebin(mdebin,FALSE,FALSE,(double)step,
-                mdatoms->tmass,enerd,state,state->box,
-                NULL,NULL,vir,pres,NULL,mu_tot,constr);
-      do_log = do_per_step(step,inputrec->nstlog);
-      do_ene = do_per_step(step,inputrec->nstenergy);
-      if(do_log)
-       print_ebin_header(fplog,step,step,state->lambda);
-      print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,
-                do_log ? fplog : NULL,step,step,eprNORMAL,
-                TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-    }
-    
-    /* Stop when the maximum force lies below tolerance.
-     * If we have reached machine precision, converged is already set to true.
-     */
-    
-    converged = converged || (fmax < inputrec->em_tol);
-    
-  } /* End of the loop */
-  
-  if(converged)        
-    step--; /* we never took that last step in this case */
-  
-    if(fmax>inputrec->em_tol)
-    {
-        if (MASTER(cr))
-        {
-            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
-            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
-        }
-        converged = FALSE; 
-    }
-  
-  /* If we printed energy and/or logfile last step (which was the last step)
-   * we don't have to do it again, but otherwise print the final values.
-   */
-  if(!do_log) /* Write final value to log since we didn't do anythin last step */
-    print_ebin_header(fplog,step,step,state->lambda);
-  if(!do_ene || !do_log) /* Write final energy file entries */
-    print_ebin(outf->fp_ene,!do_ene,FALSE,FALSE,
-              !do_log ? fplog : NULL,step,step,eprNORMAL,
-              TRUE,mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-  
-  /* Print some stuff... */
-  if (MASTER(cr))
-    fprintf(stderr,"\nwriting lowest energy coordinates.\n");
-  
-  /* IMPORTANT!
-   * For accurate normal mode calculation it is imperative that we
-   * store the last conformation into the full precision binary trajectory.
-   *
-   * However, we should only do it if we did NOT already write this step
-   * above (which we did if do_x or do_f was true).
-   */  
-  do_x = !do_per_step(step,inputrec->nstxout);
-  do_f = !do_per_step(step,inputrec->nstfout);
-  write_em_traj(fplog,cr,outf,do_x,do_f,ftp2fn(efSTO,nfile,fnm),
-                top_global,inputrec,step,
-                &ems,state,f);
-  
-  if (MASTER(cr)) {
-    print_converged(stderr,LBFGS,inputrec->em_tol,step,converged,
-                   number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
-    print_converged(fplog,LBFGS,inputrec->em_tol,step,converged,
-                   number_steps,Epot,fmax,nfmax,fnorm/sqrt(state->natoms));
-    
-    fprintf(fplog,"\nPerformed %d energy evaluations in total.\n",neval);
-  }
-  
-  finish_em(fplog,cr,outf,runtime,wcycle);
-
-  /* To print the actual number of steps we needed somewhere */
-  runtime->nsteps_done = step;
-
-  return 0;
-} /* That's all folks */
-
-
-double do_steep(FILE *fplog,t_commrec *cr,
-                int nfile, const t_filenm fnm[],
-                const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-                int nstglobalcomm,
-                gmx_vsite_t *vsite,gmx_constr_t constr,
-                int stepout,
-                t_inputrec *inputrec,
-                gmx_mtop_t *top_global,t_fcdata *fcd,
-                t_state *state_global,
-                t_mdatoms *mdatoms,
-                t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-                gmx_edsam_t ed,
-                t_forcerec *fr,
-                int repl_ex_nst,int repl_ex_seed,
-                real cpt_period,real max_hours,
-                const char *deviceOptions,
-                unsigned long Flags,
-                gmx_runtime_t *runtime)
-{ 
-  const char *SD="Steepest Descents";
-  em_state_t *s_min,*s_try;
-  rvec       *f_global;
-  gmx_localtop_t *top;
-  gmx_enerdata_t *enerd;
-  rvec   *f;
-  gmx_global_stat_t gstat;
-  t_graph    *graph;
-  real   stepsize,constepsize;
-  real   ustep,dvdlambda,fnormn;
-  gmx_mdoutf_t *outf;
-  t_mdebin   *mdebin; 
-  gmx_bool   bDone,bAbort,do_x,do_f; 
-  tensor vir,pres; 
-  rvec   mu_tot;
-  int    nsteps;
-  int    count=0; 
-  int    steps_accepted=0; 
-  /* not used */
-  real   terminate=0;
-
-  s_min = init_em_state();
-  s_try = init_em_state();
-
-  /* Init em and store the local state in s_try */
-  init_em(fplog,SD,cr,inputrec,
-          state_global,top_global,s_try,&top,&f,&f_global,
-          nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
-          nfile,fnm,&outf,&mdebin);
-       
-  /* Print to log file  */
-  print_em_start(fplog,cr,runtime,wcycle,SD);
-    
-  /* Set variables for stepsize (in nm). This is the largest  
-   * step that we are going to make in any direction. 
-   */
-  ustep = inputrec->em_stepsize; 
-  stepsize = 0;
-  
-  /* Max number of steps  */
-  nsteps = inputrec->nsteps; 
-  
-  if (MASTER(cr)) 
-    /* Print to the screen  */
-    sp_header(stderr,SD,inputrec->em_tol,nsteps);
-  if (fplog)
-    sp_header(fplog,SD,inputrec->em_tol,nsteps);
-    
-  /**** HERE STARTS THE LOOP ****
-   * count is the counter for the number of steps 
-   * bDone will be TRUE when the minimization has converged
-   * bAbort will be TRUE when nsteps steps have been performed or when
-   * the stepsize becomes smaller than is reasonable for machine precision
-   */
-  count  = 0;
-  bDone  = FALSE;
-  bAbort = FALSE;
-  while( !bDone && !bAbort ) {
-    bAbort = (nsteps >= 0) && (count == nsteps);
-    
-    /* set new coordinates, except for first step */
-    if (count > 0) {
-      do_em_step(cr,inputrec,mdatoms,s_min,stepsize,s_min->f,s_try,
-                constr,top,nrnb,wcycle,count);
-    }
-    
-    evaluate_energy(fplog,bVerbose,cr,
-                   state_global,top_global,s_try,top,
-                   inputrec,nrnb,wcycle,gstat,
-                   vsite,constr,fcd,graph,mdatoms,fr,
-                   mu_tot,enerd,vir,pres,count,count==0);
-        
-    if (MASTER(cr))
-      print_ebin_header(fplog,count,count,s_try->s.lambda);
-
-    if (count == 0)
-      s_min->epot = s_try->epot + 1;
-    
-    /* Print it if necessary  */
-    if (MASTER(cr)) {
-      if (bVerbose) {
-       fprintf(stderr,"Step=%5d, Dmax= %6.1e nm, Epot= %12.5e Fmax= %11.5e, atom= %d%c",
-               count,ustep,s_try->epot,s_try->fmax,s_try->a_fmax+1,
-               (s_try->epot < s_min->epot) ? '\n' : '\r');
-      }
-      
-      if (s_try->epot < s_min->epot) {
-       /* Store the new (lower) energies  */
-       upd_mdebin(mdebin,FALSE,FALSE,(double)count,
-                  mdatoms->tmass,enerd,&s_try->s,s_try->s.box,
-                  NULL,NULL,vir,pres,NULL,mu_tot,constr);
-       print_ebin(outf->fp_ene,TRUE,
-                  do_per_step(steps_accepted,inputrec->nstdisreout),
-                  do_per_step(steps_accepted,inputrec->nstorireout),
-                  fplog,count,count,eprNORMAL,TRUE,
-                  mdebin,fcd,&(top_global->groups),&(inputrec->opts));
-       fflush(fplog);
-      }
-    } 
-    
-    /* Now if the new energy is smaller than the previous...  
-     * or if this is the first step!
-     * or if we did random steps! 
-     */
-    
-    if ( (count==0) || (s_try->epot < s_min->epot) ) {
-      steps_accepted++; 
-
-      /* Test whether the convergence criterion is met...  */
-      bDone = (s_try->fmax < inputrec->em_tol);
-      
-      /* Copy the arrays for force, positions and energy  */
-      /* The 'Min' array always holds the coords and forces of the minimal 
-        sampled energy  */
-      swap_em_state(s_min,s_try);
-      if (count > 0)
-       ustep *= 1.2;
-
-      /* Write to trn, if necessary */
-      do_x = do_per_step(steps_accepted,inputrec->nstxout);
-      do_f = do_per_step(steps_accepted,inputrec->nstfout);
-      write_em_traj(fplog,cr,outf,do_x,do_f,NULL,
-                    top_global,inputrec,count,
-                    s_min,state_global,f_global);
-    } 
-    else {
-      /* If energy is not smaller make the step smaller...  */
-      ustep *= 0.5;
-
-      if (DOMAINDECOMP(cr) && s_min->s.ddp_count != cr->dd->ddp_count) {
-       /* Reload the old state */
-       em_dd_partition_system(fplog,count,cr,top_global,inputrec,
-                              s_min,top,mdatoms,fr,vsite,constr,
-                              nrnb,wcycle);
-      }
-    }
-    
-    /* Determine new step  */
-    stepsize = ustep/s_min->fmax;
-    
-    /* Check if stepsize is too small, with 1 nm as a characteristic length */
-#ifdef GMX_DOUBLE
-        if (count == nsteps || ustep < 1e-12)
-#else
-        if (count == nsteps || ustep < 1e-6)
-#endif
-        {
-            if (MASTER(cr))
-            {
-                warn_step(stderr,inputrec->em_tol,count==nsteps,constr!=NULL);
-                warn_step(fplog ,inputrec->em_tol,count==nsteps,constr!=NULL);
-            }
-            bAbort=TRUE;
-        }
-    
-    count++;
-  } /* End of the loop  */
-  
-    /* Print some shit...  */
-  if (MASTER(cr)) 
-    fprintf(stderr,"\nwriting lowest energy coordinates.\n"); 
-  write_em_traj(fplog,cr,outf,TRUE,inputrec->nstfout,ftp2fn(efSTO,nfile,fnm),
-               top_global,inputrec,count,
-               s_min,state_global,f_global);
-
-  fnormn = s_min->fnorm/sqrt(state_global->natoms);
-
-  if (MASTER(cr)) {
-    print_converged(stderr,SD,inputrec->em_tol,count,bDone,nsteps,
-                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
-    print_converged(fplog,SD,inputrec->em_tol,count,bDone,nsteps,
-                   s_min->epot,s_min->fmax,s_min->a_fmax,fnormn);
-  }
-
-  finish_em(fplog,cr,outf,runtime,wcycle);
-  
-  /* To print the actual number of steps we needed somewhere */
-  inputrec->nsteps=count;
-
-  runtime->nsteps_done = count;
-  
-  return 0;
-} /* That's all folks */
-
-
-double do_nm(FILE *fplog,t_commrec *cr,
-             int nfile,const t_filenm fnm[],
-             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-             int nstglobalcomm,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int stepout,
-             t_inputrec *inputrec,
-             gmx_mtop_t *top_global,t_fcdata *fcd,
-             t_state *state_global,
-             t_mdatoms *mdatoms,
-             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-             gmx_edsam_t ed,
-             t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
-             real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags,
-             gmx_runtime_t *runtime)
-{
-    const char *NM = "Normal Mode Analysis";
-    gmx_mdoutf_t *outf;
-    int        natoms,atom,d;
-    int        nnodes,node;
-    rvec       *f_global;
-    gmx_localtop_t *top;
-    gmx_enerdata_t *enerd;
-    rvec       *f;
-    gmx_global_stat_t gstat;
-    t_graph    *graph;
-    real       t,lambda;
-    gmx_bool       bNS;
-    tensor     vir,pres;
-    rvec       mu_tot;
-    rvec       *fneg,*dfdx;
-    gmx_bool       bSparse; /* use sparse matrix storage format */
-    size_t     sz;
-    gmx_sparsematrix_t * sparse_matrix = NULL;
-    real *     full_matrix             = NULL;
-    em_state_t *   state_work;
-       
-    /* added with respect to mdrun */
-    int        i,j,k,row,col;
-    real       der_range=10.0*sqrt(GMX_REAL_EPS);
-    real       x_min;
-    real       fnorm,fmax;
-    
-    if (constr != NULL)
-    {
-        gmx_fatal(FARGS,"Constraints present with Normal Mode Analysis, this combination is not supported");
-    }
-
-    state_work = init_em_state();
-    
-    /* Init em and store the local state in state_minimum */
-    init_em(fplog,NM,cr,inputrec,
-            state_global,top_global,state_work,&top,
-            &f,&f_global,
-            nrnb,mu_tot,fr,&enerd,&graph,mdatoms,&gstat,vsite,constr,
-            nfile,fnm,&outf,NULL);
-    
-    natoms = top_global->natoms;
-    snew(fneg,natoms);
-    snew(dfdx,natoms);
-    
-#ifndef GMX_DOUBLE
-    if (MASTER(cr))
-    {
-        fprintf(stderr,
-                "NOTE: This version of Gromacs has been compiled in single precision,\n"
-                "      which MIGHT not be accurate enough for normal mode analysis.\n"
-                "      Gromacs now uses sparse matrix storage, so the memory requirements\n"
-                "      are fairly modest even if you recompile in double precision.\n\n");
-    }
-#endif
-    
-    /* Check if we can/should use sparse storage format.
-     *
-     * Sparse format is only useful when the Hessian itself is sparse, which it
-      * will be when we use a cutoff.    
-      * For small systems (n<1000) it is easier to always use full matrix format, though.
-      */
-    if(EEL_FULL(fr->eeltype) || fr->rlist==0.0)
-    {
-        fprintf(stderr,"Non-cutoff electrostatics used, forcing full Hessian format.\n");
-        bSparse = FALSE;
-    }
-    else if(top_global->natoms < 1000)
-    {
-        fprintf(stderr,"Small system size (N=%d), using full Hessian format.\n",top_global->natoms);
-        bSparse = FALSE;
-    }
-    else
-    {
-        fprintf(stderr,"Using compressed symmetric sparse Hessian format.\n");
-        bSparse = TRUE;
-    }
-    
-    sz = DIM*top_global->natoms;
-    
-    fprintf(stderr,"Allocating Hessian memory...\n\n");
-
-    if(bSparse)
-    {
-        sparse_matrix=gmx_sparsematrix_init(sz);
-        sparse_matrix->compressed_symmetric = TRUE;
-    }
-    else
-    {
-        snew(full_matrix,sz*sz);
-    }
-    
-    /* Initial values */
-    t      = inputrec->init_t;
-    lambda = inputrec->init_lambda;
-    
-    init_nrnb(nrnb);
-    
-    where();
-    
-    /* Write start time and temperature */
-    print_em_start(fplog,cr,runtime,wcycle,NM);
-
-    /* fudge nr of steps to nr of atoms */
-    inputrec->nsteps = natoms*2;
-
-    if (MASTER(cr)) 
-    {
-        fprintf(stderr,"starting normal mode calculation '%s'\n%d steps.\n\n",
-                *(top_global->name),(int)inputrec->nsteps);
-    }
-
-    nnodes = cr->nnodes;
-   
-    /* Make evaluate_energy do a single node force calculation */
-    cr->nnodes = 1;
-    evaluate_energy(fplog,bVerbose,cr,
-                    state_global,top_global,state_work,top,
-                    inputrec,nrnb,wcycle,gstat,
-                    vsite,constr,fcd,graph,mdatoms,fr,
-                    mu_tot,enerd,vir,pres,-1,TRUE);
-    cr->nnodes = nnodes;
-
-    /* if forces are not small, warn user */
-    get_state_f_norm_max(cr,&(inputrec->opts),mdatoms,state_work);
-
-    if (MASTER(cr))
-    {
-        fprintf(stderr,"Maximum force:%12.5e\n",state_work->fmax);
-        if (state_work->fmax > 1.0e-3) 
-        {
-            fprintf(stderr,"Maximum force probably not small enough to");
-            fprintf(stderr," ensure that you are in an \nenergy well. ");
-            fprintf(stderr,"Be aware that negative eigenvalues may occur");
-            fprintf(stderr," when the\nresulting matrix is diagonalized.\n");
-        }
-    }
-    
-    /***********************************************************
-     *
-     *      Loop over all pairs in matrix 
-     * 
-     *      do_force called twice. Once with positive and 
-     *      once with negative displacement 
-     *
-     ************************************************************/
-
-    /* Steps are divided one by one over the nodes */
-    for(atom=cr->nodeid; atom<natoms; atom+=nnodes) 
-    {
-        
-        for (d=0; d<DIM; d++) 
-        {
-            x_min = state_work->s.x[atom][d];
-
-            state_work->s.x[atom][d] = x_min - der_range;
-          
-            /* Make evaluate_energy do a single node force calculation */
-            cr->nnodes = 1;
-            evaluate_energy(fplog,bVerbose,cr,
-                            state_global,top_global,state_work,top,
-                            inputrec,nrnb,wcycle,gstat,
-                            vsite,constr,fcd,graph,mdatoms,fr,
-                            mu_tot,enerd,vir,pres,atom*2,FALSE);
-                       
-            for(i=0; i<natoms; i++)
-            {
-                copy_rvec(state_work->f[i], fneg[i]);
-            }
-            
-            state_work->s.x[atom][d] = x_min + der_range;
-            
-            evaluate_energy(fplog,bVerbose,cr,
-                            state_global,top_global,state_work,top,
-                            inputrec,nrnb,wcycle,gstat,
-                            vsite,constr,fcd,graph,mdatoms,fr,
-                            mu_tot,enerd,vir,pres,atom*2+1,FALSE);
-            cr->nnodes = nnodes;
-
-            /* x is restored to original */
-            state_work->s.x[atom][d] = x_min;
-
-            for(j=0; j<natoms; j++) 
-            {
-                for (k=0; (k<DIM); k++) 
-                {
-                    dfdx[j][k] =
-                        -(state_work->f[j][k] - fneg[j][k])/(2*der_range);
-                }
-            }
-
-            if (!MASTER(cr))
-            {
-#ifdef GMX_MPI
-#ifdef GMX_DOUBLE
-#define mpi_type MPI_DOUBLE
-#else
-#define mpi_type MPI_FLOAT
-#endif
-                MPI_Send(dfdx[0],natoms*DIM,mpi_type,MASTERNODE(cr),cr->nodeid,
-                         cr->mpi_comm_mygroup);
-#endif
-            }
-            else
-            {
-                for(node=0; (node<nnodes && atom+node<natoms); node++)
-                {
-                    if (node > 0)
-                    {
-#ifdef GMX_MPI
-                        MPI_Status stat;
-                        MPI_Recv(dfdx[0],natoms*DIM,mpi_type,node,node,
-                                 cr->mpi_comm_mygroup,&stat);
-#undef mpi_type
-#endif
-                    }
-
-                    row = (atom + node)*DIM + d;
-
-                    for(j=0; j<natoms; j++) 
-                    {
-                        for(k=0; k<DIM; k++) 
-                        {
-                            col = j*DIM + k;
-                            
-                            if (bSparse)
-                            {
-                                if (col >= row && dfdx[j][k] != 0.0)
-                                {
-                                    gmx_sparsematrix_increment_value(sparse_matrix,
-                                                                     row,col,dfdx[j][k]);
-                                }
-                            }
-                            else
-                            {
-                                full_matrix[row*sz+col] = dfdx[j][k];
-                            }
-                        }
-                    }
-                }
-            }
-            
-            if (bVerbose && fplog)
-            {
-                fflush(fplog);            
-            }
-        }
-        /* write progress */
-        if (MASTER(cr) && bVerbose) 
-        {
-            fprintf(stderr,"\rFinished step %d out of %d",
-                    min(atom+nnodes,natoms),natoms); 
-            fflush(stderr);
-        }
-    }
-    
-    if (MASTER(cr)) 
-    {
-        fprintf(stderr,"\n\nWriting Hessian...\n");
-        gmx_mtxio_write(ftp2fn(efMTX,nfile,fnm),sz,sz,full_matrix,sparse_matrix);
-    }
-
-    finish_em(fplog,cr,outf,runtime,wcycle);
-
-    runtime->nsteps_done = natoms*2;
-    
-    return 0;
-}
diff --git a/src/mdlib/ns.c b/src/mdlib/ns.c
deleted file mode 100644 (file)
index ded8457..0000000
+++ /dev/null
@@ -1,2794 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef GMX_THREAD_SHM_FDECOMP
-#include <pthread.h> 
-#endif
-
-#include <math.h>
-#include <string.h>
-#include "sysstuff.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "maths.h"
-#include "vec.h"
-#include "network.h"
-#include "nsgrid.h"
-#include "force.h"
-#include "nonbonded.h"
-#include "ns.h"
-#include "pbc.h"
-#include "names.h"
-#include "gmx_fatal.h"
-#include "nrnb.h"
-#include "txtdump.h"
-#include "mtop_util.h"
-
-#include "domdec.h"
-
-
-/* 
- *    E X C L U S I O N   H A N D L I N G
- */
-
-#ifdef DEBUG
-static void SETEXCL_(t_excl e[],atom_id i,atom_id j)
-{   e[j] = e[j] | (1<<i); }
-static void RMEXCL_(t_excl e[],atom_id i,atom_id j) 
-{ e[j]=e[j] & ~(1<<i); }
-static gmx_bool ISEXCL_(t_excl e[],atom_id i,atom_id j) 
-{ return (gmx_bool)(e[j] & (1<<i)); }
-static gmx_bool NOTEXCL_(t_excl e[],atom_id i,atom_id j)
-{  return !(ISEXCL(e,i,j)); }
-#else
-#define SETEXCL(e,i,j) (e)[((atom_id) (j))] |= (1<<((atom_id) (i)))
-#define RMEXCL(e,i,j)  (e)[((atom_id) (j))] &= (~(1<<((atom_id) (i))))
-#define ISEXCL(e,i,j)  (gmx_bool) ((e)[((atom_id) (j))] & (1<<((atom_id) (i))))
-#define NOTEXCL(e,i,j) !(ISEXCL(e,i,j))
-#endif
-
-/************************************************
- *
- *  U T I L I T I E S    F O R    N S
- *
- ************************************************/
-
-static void reallocate_nblist(t_nblist *nl)
-{
-    if (gmx_debug_at)
-    {
-        fprintf(debug,"reallocating neigborlist il_code=%d, maxnri=%d\n",
-                nl->il_code,nl->maxnri); 
-    }
-    srenew(nl->iinr,   nl->maxnri);
-    if (nl->enlist == enlistCG_CG)
-    {
-        srenew(nl->iinr_end,nl->maxnri);
-    }
-    srenew(nl->gid,    nl->maxnri);
-    srenew(nl->shift,  nl->maxnri);
-    srenew(nl->jindex, nl->maxnri+1);
-}
-
-/* ivdw/icoul are used to determine the type of interaction, so we
- * can set an innerloop index here. The obvious choice for this would have
- * been the vdwtype/coultype values in the forcerecord, but unfortunately 
- * those types are braindead - for instance both Buckingham and normal 
- * Lennard-Jones use the same value (evdwCUT), and a separate gmx_boolean variable
- * to determine which interaction is used. There is further no special value
- * for 'no interaction'. For backward compatibility with old TPR files we won't
- * change this in the 3.x series, so when calling this routine you should use:
- *
- * icoul=0 no coulomb interaction
- * icoul=1 cutoff standard coulomb
- * icoul=2 reaction-field coulomb
- * icoul=3 tabulated coulomb
- *
- * ivdw=0 no vdw interaction
- * ivdw=1 standard L-J interaction
- * ivdw=2 Buckingham
- * ivdw=3 tabulated vdw.
- *
- * Kind of ugly, but it works.
- */
-static void init_nblist(t_nblist *nl_sr,t_nblist *nl_lr,
-                        int maxsr,int maxlr,
-                        int ivdw, int icoul, 
-                        gmx_bool bfree, int enlist)
-{
-    t_nblist *nl;
-    int      homenr;
-    int      i,nn;
-    
-    int inloop[20] =
-    { 
-        eNR_NBKERNEL_NONE,
-        eNR_NBKERNEL010,
-        eNR_NBKERNEL020,
-        eNR_NBKERNEL030,
-        eNR_NBKERNEL100,
-        eNR_NBKERNEL110,
-        eNR_NBKERNEL120,
-        eNR_NBKERNEL130,
-        eNR_NBKERNEL200,
-        eNR_NBKERNEL210,
-        eNR_NBKERNEL220,
-        eNR_NBKERNEL230,
-        eNR_NBKERNEL300,
-        eNR_NBKERNEL310,
-        eNR_NBKERNEL320,
-        eNR_NBKERNEL330,
-        eNR_NBKERNEL400,
-        eNR_NBKERNEL410,
-        eNR_NBKERNEL_NONE,
-        eNR_NBKERNEL430
-    };
-  
-    for(i=0; (i<2); i++)
-    {
-        nl     = (i == 0) ? nl_sr : nl_lr;
-        homenr = (i == 0) ? maxsr : maxlr;
-
-        if (nl == NULL)
-        {
-            continue;
-        }
-        
-        /* Set coul/vdw in neighborlist, and for the normal loops we determine
-         * an index of which one to call.
-         */
-        nl->ivdw  = ivdw;
-        nl->icoul = icoul;
-        nl->free_energy = bfree;
-    
-        if (bfree)
-        {
-            nl->enlist  = enlistATOM_ATOM;
-            nl->il_code = eNR_NBKERNEL_FREE_ENERGY;
-        }
-        else
-        {
-            nl->enlist = enlist;
-
-            nn = inloop[4*icoul + ivdw];
-            
-            /* solvent loops follow directly after the corresponding
-            * ordinary loops, in the order:
-            *
-            * SPC, SPC-SPC, TIP4p, TIP4p-TIP4p
-            *   
-            */
-            switch (enlist) {
-            case enlistATOM_ATOM:
-            case enlistCG_CG:
-                break;
-            case enlistSPC_ATOM:     nn += 1; break;
-            case enlistSPC_SPC:      nn += 2; break;
-            case enlistTIP4P_ATOM:   nn += 3; break;
-            case enlistTIP4P_TIP4P:  nn += 4; break;
-            }
-            
-            nl->il_code = nn;
-        }
-
-        if (debug)
-            fprintf(debug,"Initiating neighbourlist type %d for %s interactions,\nwith %d SR, %d LR atoms.\n",
-                    nl->il_code,ENLISTTYPE(enlist),maxsr,maxlr);
-        
-        /* maxnri is influenced by the number of shifts (maximum is 8)
-         * and the number of energy groups.
-         * If it is not enough, nl memory will be reallocated during the run.
-         * 4 seems to be a reasonable factor, which only causes reallocation
-         * during runs with tiny and many energygroups.
-         */
-        nl->maxnri      = homenr*4;
-        nl->maxnrj      = 0;
-        nl->maxlen      = 0;
-        nl->nri         = -1;
-        nl->nrj         = 0;
-        nl->iinr        = NULL;
-        nl->gid         = NULL;
-        nl->shift       = NULL;
-        nl->jindex      = NULL;
-        reallocate_nblist(nl);
-        nl->jindex[0] = 0;
-#ifdef GMX_THREAD_SHM_FDECOMP
-        nl->counter = 0;
-        snew(nl->mtx,1);
-        pthread_mutex_init(nl->mtx,NULL);
-#endif
-    }
-}
-
-void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
-{
-   /* Make maxlr tunable! (does not seem to be a big difference though) 
-    * This parameter determines the number of i particles in a long range 
-    * neighbourlist. Too few means many function calls, too many means
-    * cache trashing.
-    */
-   int maxsr,maxsr_wat,maxlr,maxlr_wat;
-   int icoul,icoulf,ivdw;
-   int solvent;
-   int enlist_def,enlist_w,enlist_ww;
-   int i;
-   t_nblists *nbl;
-
-   /* maxsr     = homenr-fr->nWatMol*3; */
-   maxsr     = homenr;
-
-   if (maxsr < 0)
-   {
-     gmx_fatal(FARGS,"%s, %d: Negative number of short range atoms.\n"
-                "Call your Gromacs dealer for assistance.",__FILE__,__LINE__);
-   }
-   /* This is just for initial allocation, so we do not reallocate
-    * all the nlist arrays many times in a row.
-    * The numbers seem very accurate, but they are uncritical.
-    */
-   maxsr_wat = min(fr->nWatMol,(homenr+2)/3); 
-   if (fr->bTwinRange) 
-   {
-       maxlr     = 50;
-       maxlr_wat = min(maxsr_wat,maxlr);
-   }
-   else
-   {
-     maxlr = maxlr_wat = 0;
-   }  
-
-   /* Determine the values for icoul/ivdw. */
-   /* Start with GB */
-   if(fr->bGB)
-   {
-       icoul=4;
-   }
-   else if (fr->bcoultab)
-   {
-       icoul = 3;
-   }
-   else if (EEL_RF(fr->eeltype))
-   {
-       icoul = 2;
-   }
-   else 
-   {
-       icoul = 1;
-   }
-   
-   if (fr->bvdwtab)
-   {
-       ivdw = 3;
-   }
-   else if (fr->bBHAM)
-   {
-       ivdw = 2;
-   }
-   else 
-   {
-       ivdw = 1;
-   }
-
-   fr->ns.bCGlist = (getenv("GMX_NBLISTCG") != 0);
-   if (!fr->ns.bCGlist)
-   {
-       enlist_def = enlistATOM_ATOM;
-   }
-   else
-   {
-       enlist_def = enlistCG_CG;
-       if (log != NULL)
-       {
-           fprintf(log,"\nUsing charge-group - charge-group neighbor lists and kernels\n\n");
-       }
-   }
-   
-   if (fr->solvent_opt == esolTIP4P) {
-       enlist_w  = enlistTIP4P_ATOM;
-       enlist_ww = enlistTIP4P_TIP4P;
-   } else {
-       enlist_w  = enlistSPC_ATOM;
-       enlist_ww = enlistSPC_SPC;
-   }
-
-   for(i=0; i<fr->nnblists; i++) 
-   {
-       nbl = &(fr->nblists[i]);
-       init_nblist(&nbl->nlist_sr[eNL_VDWQQ],&nbl->nlist_lr[eNL_VDWQQ],
-                   maxsr,maxlr,ivdw,icoul,FALSE,enlist_def);
-       init_nblist(&nbl->nlist_sr[eNL_VDW],&nbl->nlist_lr[eNL_VDW],
-                   maxsr,maxlr,ivdw,0,FALSE,enlist_def);
-       init_nblist(&nbl->nlist_sr[eNL_QQ],&nbl->nlist_lr[eNL_QQ],
-                   maxsr,maxlr,0,icoul,FALSE,enlist_def);
-       init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATER],&nbl->nlist_lr[eNL_VDWQQ_WATER],
-                   maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_w);
-       init_nblist(&nbl->nlist_sr[eNL_QQ_WATER],&nbl->nlist_lr[eNL_QQ_WATER],
-                   maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_w);
-       init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATERWATER],&nbl->nlist_lr[eNL_VDWQQ_WATERWATER],
-                   maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_ww);
-       init_nblist(&nbl->nlist_sr[eNL_QQ_WATERWATER],&nbl->nlist_lr[eNL_QQ_WATERWATER],
-                   maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_ww);
-       
-       if (fr->efep != efepNO) 
-       {
-           if (fr->bEwald)
-           {
-               icoulf = 5;
-           }
-           else
-           {
-               icoulf = icoul;
-           }
-
-           init_nblist(&nbl->nlist_sr[eNL_VDWQQ_FREE],&nbl->nlist_lr[eNL_VDWQQ_FREE],
-                       maxsr,maxlr,ivdw,icoulf,TRUE,enlistATOM_ATOM);
-           init_nblist(&nbl->nlist_sr[eNL_VDW_FREE],&nbl->nlist_lr[eNL_VDW_FREE],
-                       maxsr,maxlr,ivdw,0,TRUE,enlistATOM_ATOM);
-           init_nblist(&nbl->nlist_sr[eNL_QQ_FREE],&nbl->nlist_lr[eNL_QQ_FREE],
-                       maxsr,maxlr,0,icoulf,TRUE,enlistATOM_ATOM);
-       }  
-   }
-   /* QMMM MM list */
-   if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
-   {
-       init_nblist(&fr->QMMMlist,NULL,
-                   maxsr,maxlr,0,icoul,FALSE,enlistATOM_ATOM);
-   }
-
-   fr->ns.nblist_initialized=TRUE;
-}
-
-static void reset_nblist(t_nblist *nl)
-{
-     nl->nri       = -1;
-     nl->nrj       = 0;
-     nl->maxlen    = 0;
-     if (nl->jindex)
-     {
-         nl->jindex[0] = 0;
-     }
-}
-
-static void reset_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL)
-{
-    int n,i;
-  
-    if (bLR) 
-    {
-        reset_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
-    }
-    else 
-    {
-        for(n=0; n<fr->nnblists; n++)
-        {
-            for(i=0; i<eNL_NR; i++)
-            {
-                reset_nblist(&(fr->nblists[n].nlist_sr[i]));
-            }
-        }
-        if (fr->bQMMM)
-        { 
-            /* only reset the short-range nblist */
-            reset_nblist(&(fr->QMMMlist));
-        }
-    }
-}
-
-
-
-
-static inline void new_i_nblist(t_nblist *nlist,
-                                gmx_bool bLR,atom_id i_atom,int shift,int gid)
-{
-    int    i,k,nri,nshift;
-    
-    nri = nlist->nri;
-    
-    /* Check whether we have to increase the i counter */
-    if ((nri == -1) ||
-        (nlist->iinr[nri]  != i_atom) || 
-        (nlist->shift[nri] != shift) || 
-        (nlist->gid[nri]   != gid))
-    {
-        /* This is something else. Now see if any entries have 
-         * been added in the list of the previous atom.
-         */
-        if ((nri == -1) ||
-            ((nlist->jindex[nri+1] > nlist->jindex[nri]) && 
-             (nlist->gid[nri] != -1)))
-        {
-            /* If so increase the counter */
-            nlist->nri++;
-            nri++;
-            if (nlist->nri >= nlist->maxnri)
-            {
-                nlist->maxnri += over_alloc_large(nlist->nri);
-                reallocate_nblist(nlist);
-            }
-        }
-        /* Set the number of neighbours and the atom number */
-        nlist->jindex[nri+1] = nlist->jindex[nri];
-        nlist->iinr[nri]     = i_atom;
-        nlist->gid[nri]      = gid;
-        nlist->shift[nri]    = shift;
-    }
-}
-
-static inline void close_i_nblist(t_nblist *nlist) 
-{
-    int nri = nlist->nri;
-    int len;
-    
-    if (nri >= 0)
-    {
-        nlist->jindex[nri+1] = nlist->nrj;
-        
-        len=nlist->nrj -  nlist->jindex[nri];
-        
-        /* nlist length for water i molecules is treated statically 
-         * in the innerloops 
-         */
-        if (len > nlist->maxlen)
-        {
-            nlist->maxlen = len;
-        }
-    }
-}
-
-static inline void close_nblist(t_nblist *nlist)
-{
-    /* Only close this nblist when it has been initialized.
-     * Avoid the creation of i-lists with no j-particles.
-     */
-    if (nlist->nrj == 0)
-    {
-        /* Some assembly kernels do not support empty lists,
-         * make sure here that we don't generate any empty lists.
-         * With the current ns code this branch is taken in two cases:
-         * No i-particles at all: nri=-1 here
-         * There are i-particles, but no j-particles; nri=0 here
-         */
-        nlist->nri = 0;
-    }
-    else
-    {
-        /* Close list number nri by incrementing the count */
-        nlist->nri++;
-    }
-}
-
-static inline void close_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL, 
-                                       gmx_bool bMakeQMMMnblist)
-{
-    int n,i;
-    
-    if (bMakeQMMMnblist) {
-        if (!bLR)
-        {
-            close_nblist(&(fr->QMMMlist));
-        }
-    }
-    else 
-    {
-        if (bLR)
-        {
-            close_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
-        }
-        else
-        { 
-            for(n=0; n<fr->nnblists; n++)
-            {
-                for(i=0; (i<eNL_NR); i++)
-                {
-                    close_nblist(&(fr->nblists[n].nlist_sr[i]));
-                }
-            }
-        }
-    }
-}
-
-static inline void add_j_to_nblist(t_nblist *nlist,atom_id j_atom,gmx_bool bLR)
-{
-    int nrj=nlist->nrj;
-    
-    if (nlist->nrj >= nlist->maxnrj)
-    {
-        nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
-        if (gmx_debug_at)
-            fprintf(debug,"Increasing %s nblist %s j size to %d\n",
-                    bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
-        
-        srenew(nlist->jjnr,nlist->maxnrj);
-    }
-
-    nlist->jjnr[nrj] = j_atom;
-    nlist->nrj ++;
-}
-
-static inline void add_j_to_nblist_cg(t_nblist *nlist,
-                                      atom_id j_start,int j_end,
-                                      t_excl *bexcl,gmx_bool i_is_j,
-                                      gmx_bool bLR)
-{
-    int nrj=nlist->nrj;
-    int j;
-
-    if (nlist->nrj >= nlist->maxnrj)
-    {
-        nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
-        if (gmx_debug_at)
-            fprintf(debug,"Increasing %s nblist %s j size to %d\n",
-                    bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
-        
-        srenew(nlist->jjnr    ,nlist->maxnrj);
-        srenew(nlist->jjnr_end,nlist->maxnrj);
-        srenew(nlist->excl    ,nlist->maxnrj*MAX_CGCGSIZE);
-    }
-
-    nlist->jjnr[nrj]     = j_start;
-    nlist->jjnr_end[nrj] = j_end;
-
-    if (j_end - j_start > MAX_CGCGSIZE)
-    {
-        gmx_fatal(FARGS,"The charge-group - charge-group neighborlist do not support charge groups larger than %d, found a charge group of size %d",MAX_CGCGSIZE,j_end-j_start);
-    }
-
-    /* Set the exclusions */
-    for(j=j_start; j<j_end; j++)
-    {
-        nlist->excl[nrj*MAX_CGCGSIZE + j - j_start] = bexcl[j];
-    }
-    if (i_is_j)
-    {
-        /* Avoid double counting of intra-cg interactions */
-        for(j=1; j<j_end-j_start; j++)
-        {
-            nlist->excl[nrj*MAX_CGCGSIZE + j] |= (1<<j) - 1;
-        }
-    }
-
-    nlist->nrj ++;
-}
-
-typedef void
-put_in_list_t(gmx_bool              bHaveVdW[],
-              int               ngid,
-              t_mdatoms *       md,
-              int               icg,
-              int               jgid,
-              int               nj,
-              atom_id           jjcg[],
-              atom_id           index[],
-              t_excl            bExcl[],
-              int               shift,
-              t_forcerec *      fr,
-              gmx_bool              bLR,
-              gmx_bool              bDoVdW,
-              gmx_bool              bDoCoul);
-
-static void 
-put_in_list_at(gmx_bool              bHaveVdW[],
-               int               ngid,
-               t_mdatoms *       md,
-               int               icg,
-               int               jgid,
-               int               nj,
-               atom_id           jjcg[],
-               atom_id           index[],
-               t_excl            bExcl[],
-               int               shift,
-               t_forcerec *      fr,
-               gmx_bool              bLR,
-               gmx_bool              bDoVdW,
-               gmx_bool              bDoCoul)
-{
-    /* The a[] index has been removed,
-     * to put it back in i_atom should be a[i0] and jj should be a[jj].
-     */
-    t_nblist *   vdwc;
-    t_nblist *   vdw;
-    t_nblist *   coul;
-    t_nblist *   vdwc_free  = NULL;
-    t_nblist *   vdw_free   = NULL;
-    t_nblist *   coul_free  = NULL;
-    t_nblist *   vdwc_ww    = NULL;
-    t_nblist *   coul_ww    = NULL;
-    
-    int            i,j,jcg,igid,gid,nbl_ind,ind_ij;
-    atom_id   jj,jj0,jj1,i_atom;
-    int       i0,nicg,len;
-    
-    int       *cginfo;
-    int       *type,*typeB;
-    real      *charge,*chargeB;
-    real      qi,qiB,qq,rlj;
-    gmx_bool      bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
-    gmx_bool      bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
-    int       iwater,jwater;
-    t_nblist  *nlist;
-    
-    /* Copy some pointers */
-    cginfo  = fr->cginfo;
-    charge  = md->chargeA;
-    chargeB = md->chargeB;
-    type    = md->typeA;
-    typeB   = md->typeB;
-    bPert   = md->bPerturbed;
-    
-    /* Get atom range */
-    i0     = index[icg];
-    nicg   = index[icg+1]-i0;
-    
-    /* Get the i charge group info */
-    igid   = GET_CGINFO_GID(cginfo[icg]);
-    iwater = GET_CGINFO_SOLOPT(cginfo[icg]);
-    
-    bFreeEnergy = FALSE;
-    if (md->nPerturbed) 
-    {
-        /* Check if any of the particles involved are perturbed. 
-         * If not we can do the cheaper normal put_in_list
-         * and use more solvent optimization.
-         */
-        for(i=0; i<nicg; i++)
-        {
-            bFreeEnergy |= bPert[i0+i];
-        }
-        /* Loop over the j charge groups */
-        for(j=0; (j<nj && !bFreeEnergy); j++) 
-        {
-            jcg = jjcg[j];
-            jj0 = index[jcg];
-            jj1 = index[jcg+1];
-            /* Finally loop over the atoms in the j-charge group */    
-            for(jj=jj0; jj<jj1; jj++)
-            {
-                bFreeEnergy |= bPert[jj];
-            }
-        }
-    }
-    
-    /* Unpack pointers to neighbourlist structs */
-    if (fr->nnblists == 1)
-    {
-        nbl_ind = 0;
-    }
-    else
-    {
-        nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
-    }
-    if (bLR)
-    {
-        nlist = fr->nblists[nbl_ind].nlist_lr;
-    }
-    else
-    {
-        nlist = fr->nblists[nbl_ind].nlist_sr;
-    }
-    
-    if (iwater != esolNO)
-    {
-        vdwc = &nlist[eNL_VDWQQ_WATER];
-        vdw  = &nlist[eNL_VDW];
-        coul = &nlist[eNL_QQ_WATER];
-#ifndef DISABLE_WATERWATER_NLIST
-        vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
-        coul_ww = &nlist[eNL_QQ_WATERWATER];
-#endif
-    } 
-    else 
-    {
-        vdwc = &nlist[eNL_VDWQQ];
-        vdw  = &nlist[eNL_VDW];
-        coul = &nlist[eNL_QQ];
-    }
-    
-    if (!bFreeEnergy) 
-    {
-        if (iwater != esolNO) 
-        {
-            /* Loop over the atoms in the i charge group */    
-            i_atom  = i0;
-            gid     = GID(igid,jgid,ngid);
-            /* Create new i_atom for each energy group */
-            if (bDoCoul && bDoVdW)
-            {
-                new_i_nblist(vdwc,bLR,i_atom,shift,gid);
-#ifndef DISABLE_WATERWATER_NLIST
-                new_i_nblist(vdwc_ww,bLR,i_atom,shift,gid);
-#endif
-            }
-            if (bDoVdW)
-            {
-                new_i_nblist(vdw,bLR,i_atom,shift,gid);
-            }
-            if (bDoCoul) 
-            {
-                new_i_nblist(coul,bLR,i_atom,shift,gid);
-#ifndef DISABLE_WATERWATER_NLIST
-                new_i_nblist(coul_ww,bLR,i_atom,shift,gid);
-#endif
-            }      
-         /* Loop over the j charge groups */
-            for(j=0; (j<nj); j++) 
-            {
-                jcg=jjcg[j];
-                
-                if (jcg == icg)
-                {
-                    continue;
-                }
-                
-                jj0 = index[jcg];
-                jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
-                
-                if (iwater == esolSPC && jwater == esolSPC)
-                {
-                    /* Interaction between two SPC molecules */
-                    if (!bDoCoul)
-                    {
-                        /* VdW only - only first atoms in each water interact */
-                        add_j_to_nblist(vdw,jj0,bLR);
-                    }
-                    else 
-                    {
-#ifdef DISABLE_WATERWATER_NLIST        
-                        /* Add entries for the three atoms - only do VdW if we need to */
-                        if (!bDoVdW)
-                        {
-                            add_j_to_nblist(coul,jj0,bLR);
-                        }
-                        else
-                        {
-                            add_j_to_nblist(vdwc,jj0,bLR);
-                        }
-                        add_j_to_nblist(coul,jj0+1,bLR);
-                        add_j_to_nblist(coul,jj0+2,bLR);           
-#else
-                        /* One entry for the entire water-water interaction */
-                        if (!bDoVdW)
-                        {
-                            add_j_to_nblist(coul_ww,jj0,bLR);
-                        }
-                        else
-                        {
-                            add_j_to_nblist(vdwc_ww,jj0,bLR);
-                        }
-#endif
-                    }  
-                } 
-                else if (iwater == esolTIP4P && jwater == esolTIP4P) 
-                {
-                    /* Interaction between two TIP4p molecules */
-                    if (!bDoCoul)
-                    {
-                        /* VdW only - only first atoms in each water interact */
-                        add_j_to_nblist(vdw,jj0,bLR);
-                    }
-                    else 
-                    {
-#ifdef DISABLE_WATERWATER_NLIST        
-                        /* Add entries for the four atoms - only do VdW if we need to */
-                        if (bDoVdW)
-                        {
-                            add_j_to_nblist(vdw,jj0,bLR);
-                        }
-                        add_j_to_nblist(coul,jj0+1,bLR);
-                        add_j_to_nblist(coul,jj0+2,bLR);           
-                        add_j_to_nblist(coul,jj0+3,bLR);           
-#else
-                        /* One entry for the entire water-water interaction */
-                        if (!bDoVdW)
-                        {
-                            add_j_to_nblist(coul_ww,jj0,bLR);
-                        }
-                        else
-                        {
-                            add_j_to_nblist(vdwc_ww,jj0,bLR);
-                        }
-#endif
-                    }                                          
-                }
-                else 
-                {
-                    /* j charge group is not water, but i is.
-                     * Add entries to the water-other_atom lists; the geometry of the water
-                     * molecule doesn't matter - that is taken care of in the nonbonded kernel,
-                     * so we don't care if it is SPC or TIP4P...
-                     */
-                    
-                    jj1 = index[jcg+1];
-                    
-                    if (!bDoVdW) 
-                    {
-                        for(jj=jj0; (jj<jj1); jj++) 
-                        {
-                            if (charge[jj] != 0)
-                            {
-                                add_j_to_nblist(coul,jj,bLR);
-                            }
-                        }
-                    }
-                    else if (!bDoCoul)
-                    {
-                        for(jj=jj0; (jj<jj1); jj++)
-                        {
-                            if (bHaveVdW[type[jj]])
-                            {
-                                add_j_to_nblist(vdw,jj,bLR);
-                            }
-                        }
-                    }
-                    else 
-                    {
-                        /* _charge_ _groups_ interact with both coulomb and LJ */
-                        /* Check which atoms we should add to the lists!       */
-                        for(jj=jj0; (jj<jj1); jj++) 
-                        {
-                            if (bHaveVdW[type[jj]]) 
-                            {
-                                if (charge[jj] != 0)
-                                {
-                                    add_j_to_nblist(vdwc,jj,bLR);
-                                }
-                                else
-                                {
-                                    add_j_to_nblist(vdw,jj,bLR);
-                                }
-                            }
-                            else if (charge[jj] != 0)
-                            {
-                                add_j_to_nblist(coul,jj,bLR);
-                            }
-                        }
-                    }
-                }
-            }
-            close_i_nblist(vdw); 
-            close_i_nblist(coul); 
-            close_i_nblist(vdwc);  
-#ifndef DISABLE_WATERWATER_NLIST
-            close_i_nblist(coul_ww);
-            close_i_nblist(vdwc_ww); 
-#endif
-        } 
-        else
-        { 
-            /* no solvent as i charge group */
-            /* Loop over the atoms in the i charge group */    
-            for(i=0; i<nicg; i++) 
-            {
-                i_atom  = i0+i;
-                gid     = GID(igid,jgid,ngid);
-                qi      = charge[i_atom];
-                
-                /* Create new i_atom for each energy group */
-                if (bDoVdW && bDoCoul)
-                {
-                    new_i_nblist(vdwc,bLR,i_atom,shift,gid);
-                }
-                if (bDoVdW)
-                {
-                    new_i_nblist(vdw,bLR,i_atom,shift,gid);
-                }
-                if (bDoCoul)
-                {
-                    new_i_nblist(coul,bLR,i_atom,shift,gid);
-                }
-                bDoVdW_i  = (bDoVdW  && bHaveVdW[type[i_atom]]);
-                bDoCoul_i = (bDoCoul && qi!=0);
-                
-                if (bDoVdW_i || bDoCoul_i) 
-                {
-                    /* Loop over the j charge groups */
-                    for(j=0; (j<nj); j++) 
-                    {
-                        jcg=jjcg[j];
-                        
-                        /* Check for large charge groups */
-                        if (jcg == icg)
-                        {
-                            jj0 = i0 + i + 1;
-                        }
-                        else
-                        {
-                            jj0 = index[jcg];
-                        }
-                        
-                        jj1=index[jcg+1];
-                        /* Finally loop over the atoms in the j-charge group */        
-                        for(jj=jj0; jj<jj1; jj++) 
-                        {
-                            bNotEx = NOTEXCL(bExcl,i,jj);
-                            
-                            if (bNotEx) 
-                            {
-                                if (!bDoVdW_i) 
-                                { 
-                                    if (charge[jj] != 0)
-                                    {
-                                        add_j_to_nblist(coul,jj,bLR);
-                                    }
-                                }
-                                else if (!bDoCoul_i) 
-                                {
-                                    if (bHaveVdW[type[jj]])
-                                    {
-                                        add_j_to_nblist(vdw,jj,bLR);
-                                    }
-                                }
-                                else 
-                                {
-                                    if (bHaveVdW[type[jj]]) 
-                                    {
-                                        if (charge[jj] != 0)
-                                        {
-                                            add_j_to_nblist(vdwc,jj,bLR);
-                                        }
-                                        else
-                                        {
-                                            add_j_to_nblist(vdw,jj,bLR);
-                                        }
-                                    } 
-                                    else if (charge[jj] != 0)
-                                    {
-                                        add_j_to_nblist(coul,jj,bLR);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                close_i_nblist(vdw);
-                close_i_nblist(coul);
-                close_i_nblist(vdwc);
-            }
-        }
-    }
-    else
-    {
-        /* we are doing free energy */
-        vdwc_free = &nlist[eNL_VDWQQ_FREE];
-        vdw_free  = &nlist[eNL_VDW_FREE];
-        coul_free = &nlist[eNL_QQ_FREE];
-        /* Loop over the atoms in the i charge group */    
-        for(i=0; i<nicg; i++) 
-        {
-            i_atom  = i0+i;
-            gid     = GID(igid,jgid,ngid);
-            qi      = charge[i_atom];
-            qiB     = chargeB[i_atom];
-            
-            /* Create new i_atom for each energy group */
-            if (bDoVdW && bDoCoul) 
-                new_i_nblist(vdwc,bLR,i_atom,shift,gid);
-            if (bDoVdW)   
-                new_i_nblist(vdw,bLR,i_atom,shift,gid);
-            if (bDoCoul) 
-                new_i_nblist(coul,bLR,i_atom,shift,gid);
-            
-            new_i_nblist(vdw_free,bLR,i_atom,shift,gid);
-            new_i_nblist(coul_free,bLR,i_atom,shift,gid);
-            new_i_nblist(vdwc_free,bLR,i_atom,shift,gid);
-            
-            bDoVdW_i  = (bDoVdW  &&
-                         (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
-            bDoCoul_i = (bDoCoul && (qi!=0 || qiB!=0));
-            /* For TIP4P the first atom does not have a charge,
-             * but the last three do. So we should still put an atom
-             * without LJ but with charge in the water-atom neighborlist
-             * for a TIP4p i charge group.
-             * For SPC type water the first atom has LJ and charge,
-             * so there is no such problem.
-             */
-            if (iwater == esolNO)
-            {
-                bDoCoul_i_sol = bDoCoul_i;
-            }
-            else
-            {
-                bDoCoul_i_sol = bDoCoul;
-            }
-            
-            if (bDoVdW_i || bDoCoul_i_sol) 
-            {
-                /* Loop over the j charge groups */
-                for(j=0; (j<nj); j++)
-                {
-                    jcg=jjcg[j];
-                    
-                    /* Check for large charge groups */
-                    if (jcg == icg)
-                    {
-                        jj0 = i0 + i + 1;
-                    }
-                    else
-                    {
-                        jj0 = index[jcg];
-                    }
-                    
-                    jj1=index[jcg+1];
-                    /* Finally loop over the atoms in the j-charge group */    
-                    bFree = bPert[i_atom];
-                    for(jj=jj0; (jj<jj1); jj++) 
-                    {
-                        bFreeJ = bFree || bPert[jj];
-                        /* Complicated if, because the water H's should also
-                         * see perturbed j-particles
-                         */
-                        if (iwater==esolNO || i==0 || bFreeJ) 
-                        {
-                            bNotEx = NOTEXCL(bExcl,i,jj);
-                            
-                            if (bNotEx) 
-                            {
-                                if (bFreeJ)
-                                {
-                                    if (!bDoVdW_i) 
-                                    {
-                                        if (charge[jj]!=0 || chargeB[jj]!=0)
-                                        {
-                                            add_j_to_nblist(coul_free,jj,bLR);
-                                        }
-                                    }
-                                    else if (!bDoCoul_i) 
-                                    {
-                                        if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
-                                        {
-                                            add_j_to_nblist(vdw_free,jj,bLR);
-                                        }
-                                    }
-                                    else 
-                                    {
-                                        if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]]) 
-                                        {
-                                            if (charge[jj]!=0 || chargeB[jj]!=0)
-                                            {
-                                                add_j_to_nblist(vdwc_free,jj,bLR);
-                                            }
-                                            else
-                                            {
-                                                add_j_to_nblist(vdw_free,jj,bLR);
-                                            }
-                                        }
-                                        else if (charge[jj]!=0 || chargeB[jj]!=0)
-                                            add_j_to_nblist(coul_free,jj,bLR);
-                                    }
-                                }
-                                else if (!bDoVdW_i) 
-                                { 
-                                    /* This is done whether or not bWater is set */
-                                    if (charge[jj] != 0)
-                                    {
-                                        add_j_to_nblist(coul,jj,bLR);
-                                    }
-                                }
-                                else if (!bDoCoul_i_sol) 
-                                { 
-                                    if (bHaveVdW[type[jj]])
-                                    {
-                                        add_j_to_nblist(vdw,jj,bLR);
-                                    }
-                                }
-                                else 
-                                {
-                                    if (bHaveVdW[type[jj]]) 
-                                    {
-                                        if (charge[jj] != 0)
-                                        {
-                                            add_j_to_nblist(vdwc,jj,bLR);
-                                        }
-                                        else
-                                        {
-                                            add_j_to_nblist(vdw,jj,bLR);
-                                        }
-                                    } 
-                                    else if (charge[jj] != 0)
-                                    {
-                                        add_j_to_nblist(coul,jj,bLR);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            close_i_nblist(vdw);
-            close_i_nblist(coul);
-            close_i_nblist(vdwc);
-            close_i_nblist(vdw_free);
-            close_i_nblist(coul_free);
-            close_i_nblist(vdwc_free);
-        }
-    }
-}
-
-static void 
-put_in_list_qmmm(gmx_bool              bHaveVdW[],
-                 int               ngid,
-                 t_mdatoms *       md,
-                 int               icg,
-                 int               jgid,
-                 int               nj,
-                 atom_id           jjcg[],
-                 atom_id           index[],
-                 t_excl            bExcl[],
-                 int               shift,
-                 t_forcerec *      fr,
-                 gmx_bool              bLR,
-                 gmx_bool              bDoVdW,
-                 gmx_bool              bDoCoul)
-{
-    t_nblist *   coul;
-    int          i,j,jcg,igid,gid;
-    atom_id   jj,jj0,jj1,i_atom;
-    int       i0,nicg;
-    gmx_bool      bNotEx;
-    
-    /* Get atom range */
-    i0     = index[icg];
-    nicg   = index[icg+1]-i0;
-    
-    /* Get the i charge group info */
-    igid   = GET_CGINFO_GID(fr->cginfo[icg]);
-    
-    coul = &fr->QMMMlist;
-    
-    /* Loop over atoms in the ith charge group */
-    for (i=0;i<nicg;i++)
-    {
-        i_atom = i0+i;
-        gid    = GID(igid,jgid,ngid);
-        /* Create new i_atom for each energy group */
-        new_i_nblist(coul,bLR,i_atom,shift,gid);
-        
-        /* Loop over the j charge groups */
-        for (j=0;j<nj;j++)
-        {
-            jcg=jjcg[j];
-            
-            /* Charge groups cannot have QM and MM atoms simultaneously */
-            if (jcg!=icg)
-            {
-                jj0 = index[jcg];
-                jj1 = index[jcg+1];
-                /* Finally loop over the atoms in the j-charge group */
-                for(jj=jj0; jj<jj1; jj++)
-                {
-                    bNotEx = NOTEXCL(bExcl,i,jj);
-                    if(bNotEx)
-                        add_j_to_nblist(coul,jj,bLR);
-                }
-            }
-        }
-        close_i_nblist(coul);
-    }
-}
-
-static void 
-put_in_list_cg(gmx_bool              bHaveVdW[],
-               int               ngid,
-               t_mdatoms *       md,
-               int               icg,
-               int               jgid,
-               int               nj,
-               atom_id           jjcg[],
-               atom_id           index[],
-               t_excl            bExcl[],
-               int               shift,
-               t_forcerec *      fr,
-               gmx_bool              bLR,
-               gmx_bool              bDoVdW,
-               gmx_bool              bDoCoul)
-{
-    int          cginfo;
-    int          igid,gid,nbl_ind;
-    t_nblist *   vdwc;
-    int          j,jcg;
-
-    cginfo = fr->cginfo[icg];
-
-    igid = GET_CGINFO_GID(cginfo);
-    gid  = GID(igid,jgid,ngid);
-
-    /* Unpack pointers to neighbourlist structs */
-    if (fr->nnblists == 1)
-    {
-        nbl_ind = 0;
-    }
-    else
-    {
-        nbl_ind = fr->gid2nblists[gid];
-    }
-    if (bLR)
-    {
-        vdwc = &fr->nblists[nbl_ind].nlist_lr[eNL_VDWQQ];
-    }
-    else
-    {
-        vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
-    }
-
-    /* Make a new neighbor list for charge group icg.
-     * Currently simply one neighbor list is made with LJ and Coulomb.
-     * If required, zero interactions could be removed here
-     * or in the force loop.
-     */
-    new_i_nblist(vdwc,bLR,index[icg],shift,gid);
-    vdwc->iinr_end[vdwc->nri] = index[icg+1];
-
-    for(j=0; (j<nj); j++) 
-    {
-        jcg = jjcg[j];
-        /* Skip the icg-icg pairs if all self interactions are excluded */
-        if (!(jcg == icg && GET_CGINFO_EXCL_INTRA(cginfo)))
-        {
-            /* Here we add the j charge group jcg to the list,
-             * exclusions are also added to the list.
-             */
-            add_j_to_nblist_cg(vdwc,index[jcg],index[jcg+1],bExcl,icg==jcg,bLR);
-        }
-    }
-
-    close_i_nblist(vdwc);  
-}
-
-static void setexcl(atom_id start,atom_id end,t_blocka *excl,gmx_bool b,
-                    t_excl bexcl[])
-{
-    atom_id i,k;
-    
-    if (b)
-    {
-        for(i=start; i<end; i++)
-        {
-            for(k=excl->index[i]; k<excl->index[i+1]; k++)
-            {
-                SETEXCL(bexcl,i-start,excl->a[k]);
-            }
-        }
-    }
-    else
-    {
-        for(i=start; i<end; i++)
-        {
-            for(k=excl->index[i]; k<excl->index[i+1]; k++)
-            {
-                RMEXCL(bexcl,i-start,excl->a[k]);
-            }
-        }
-    }
-}
-
-int calc_naaj(int icg,int cgtot)
-{
-    int naaj;
-    
-    if ((cgtot % 2) == 1)
-    {
-        /* Odd number of charge groups, easy */
-        naaj = 1 + (cgtot/2);
-    }
-    else if ((cgtot % 4) == 0)
-    {
-    /* Multiple of four is hard */
-        if (icg < cgtot/2)
-        {
-            if ((icg % 2) == 0)
-            {
-                naaj=1+(cgtot/2);
-            }
-            else
-            {
-                naaj=cgtot/2;
-            }
-        }
-        else
-        {
-            if ((icg % 2) == 1)
-            {
-                naaj=1+(cgtot/2);
-            }
-            else
-            {
-                naaj=cgtot/2;
-            }
-        }
-    }
-    else
-    {
-        /* cgtot/2 = odd */
-        if ((icg % 2) == 0)
-        {
-            naaj=1+(cgtot/2);
-        }
-        else
-        {
-            naaj=cgtot/2;
-        }
-    }
-#ifdef DEBUG
-    fprintf(log,"naaj=%d\n",naaj);
-#endif
-
-    return naaj;
-}
-
-/************************************************
- *
- *  S I M P L E      C O R E     S T U F F
- *
- ************************************************/
-
-static real calc_image_tric(rvec xi,rvec xj,matrix box,
-                            rvec b_inv,int *shift)
-{
-    /* This code assumes that the cut-off is smaller than
-     * a half times the smallest diagonal element of the box.
-     */
-    const real h25=2.5;
-    real dx,dy,dz;
-    real r2;
-    int  tx,ty,tz;
-    
-    /* Compute diff vector */
-    dz = xj[ZZ] - xi[ZZ];
-    dy = xj[YY] - xi[YY];
-    dx = xj[XX] - xi[XX];
-    
-  /* Perform NINT operation, using trunc operation, therefore
-   * we first add 2.5 then subtract 2 again
-   */
-    tz = dz*b_inv[ZZ] + h25;
-    tz -= 2;
-    dz -= tz*box[ZZ][ZZ];
-    dy -= tz*box[ZZ][YY];
-    dx -= tz*box[ZZ][XX];
-
-    ty = dy*b_inv[YY] + h25;
-    ty -= 2;
-    dy -= ty*box[YY][YY];
-    dx -= ty*box[YY][XX];
-    
-    tx = dx*b_inv[XX]+h25;
-    tx -= 2;
-    dx -= tx*box[XX][XX];
-  
-    /* Distance squared */
-    r2 = (dx*dx) + (dy*dy) + (dz*dz);
-
-    *shift = XYZ2IS(tx,ty,tz);
-
-    return r2;
-}
-
-static real calc_image_rect(rvec xi,rvec xj,rvec box_size,
-                            rvec b_inv,int *shift)
-{
-    const real h15=1.5;
-    real ddx,ddy,ddz;
-    real dx,dy,dz;
-    real r2;
-    int  tx,ty,tz;
-    
-    /* Compute diff vector */
-    dx = xj[XX] - xi[XX];
-    dy = xj[YY] - xi[YY];
-    dz = xj[ZZ] - xi[ZZ];
-  
-    /* Perform NINT operation, using trunc operation, therefore
-     * we first add 1.5 then subtract 1 again
-     */
-    tx = dx*b_inv[XX] + h15;
-    ty = dy*b_inv[YY] + h15;
-    tz = dz*b_inv[ZZ] + h15;
-    tx--;
-    ty--;
-    tz--;
-    
-    /* Correct diff vector for translation */
-    ddx = tx*box_size[XX] - dx;
-    ddy = ty*box_size[YY] - dy;
-    ddz = tz*box_size[ZZ] - dz;
-    
-    /* Distance squared */
-    r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
-    
-    *shift = XYZ2IS(tx,ty,tz);
-    
-    return r2;
-}
-
-static void add_simple(t_ns_buf *nsbuf,int nrj,atom_id cg_j,
-                       gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
-                       int icg,int jgid,t_block *cgs,t_excl bexcl[],
-                       int shift,t_forcerec *fr,put_in_list_t *put_in_list)
-{
-    if (nsbuf->nj + nrj > MAX_CG)
-    {
-        put_in_list(bHaveVdW,ngid,md,icg,jgid,nsbuf->ncg,nsbuf->jcg,
-                    cgs->index,bexcl,shift,fr,FALSE,TRUE,TRUE);
-        /* Reset buffer contents */
-        nsbuf->ncg = nsbuf->nj = 0;
-    }
-    nsbuf->jcg[nsbuf->ncg++] = cg_j;
-    nsbuf->nj += nrj;
-}
-
-static void ns_inner_tric(rvec x[],int icg,int *i_egp_flags,
-                          int njcg,atom_id jcg[],
-                          matrix box,rvec b_inv,real rcut2,
-                          t_block *cgs,t_ns_buf **ns_buf,
-                          gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
-                          t_excl bexcl[],t_forcerec *fr,
-                          put_in_list_t *put_in_list)
-{
-    int      shift;
-    int      j,nrj,jgid;
-    int      *cginfo=fr->cginfo;
-    atom_id  cg_j,*cgindex;
-    t_ns_buf *nsbuf;
-    
-    cgindex = cgs->index;
-    shift   = CENTRAL;
-    for(j=0; (j<njcg); j++)
-    {
-        cg_j   = jcg[j];
-        nrj    = cgindex[cg_j+1]-cgindex[cg_j];
-        if (calc_image_tric(x[icg],x[cg_j],box,b_inv,&shift) < rcut2)
-        {
-            jgid  = GET_CGINFO_GID(cginfo[cg_j]);
-            if (!(i_egp_flags[jgid] & EGP_EXCL))
-            {
-                add_simple(&ns_buf[jgid][shift],nrj,cg_j,
-                           bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
-                           put_in_list);
-            }
-        }
-    }
-}
-
-static void ns_inner_rect(rvec x[],int icg,int *i_egp_flags,
-                          int njcg,atom_id jcg[],
-                          gmx_bool bBox,rvec box_size,rvec b_inv,real rcut2,
-                          t_block *cgs,t_ns_buf **ns_buf,
-                          gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
-                          t_excl bexcl[],t_forcerec *fr,
-                          put_in_list_t *put_in_list)
-{
-    int      shift;
-    int      j,nrj,jgid;
-    int      *cginfo=fr->cginfo;
-    atom_id  cg_j,*cgindex;
-    t_ns_buf *nsbuf;
-
-    cgindex = cgs->index;
-    if (bBox)
-    {
-        shift = CENTRAL;
-        for(j=0; (j<njcg); j++)
-        {
-            cg_j   = jcg[j];
-            nrj    = cgindex[cg_j+1]-cgindex[cg_j];
-            if (calc_image_rect(x[icg],x[cg_j],box_size,b_inv,&shift) < rcut2)
-            {
-                jgid  = GET_CGINFO_GID(cginfo[cg_j]);
-                if (!(i_egp_flags[jgid] & EGP_EXCL))
-                {
-                    add_simple(&ns_buf[jgid][shift],nrj,cg_j,
-                               bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
-                               put_in_list);
-                }
-            }
-        }
-    } 
-    else
-    {
-        for(j=0; (j<njcg); j++)
-        {
-            cg_j   = jcg[j];
-            nrj    = cgindex[cg_j+1]-cgindex[cg_j];
-            if ((rcut2 == 0) || (distance2(x[icg],x[cg_j]) < rcut2)) {
-                jgid  = GET_CGINFO_GID(cginfo[cg_j]);
-                if (!(i_egp_flags[jgid] & EGP_EXCL))
-                {
-                    add_simple(&ns_buf[jgid][CENTRAL],nrj,cg_j,
-                               bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,CENTRAL,fr,
-                               put_in_list);
-                }
-            }
-        }
-    }
-}
-
-/* ns_simple_core needs to be adapted for QMMM still 2005 */
-
-static int ns_simple_core(t_forcerec *fr,
-                          gmx_localtop_t *top,
-                          t_mdatoms *md,
-                          matrix box,rvec box_size,
-                          t_excl bexcl[],atom_id *aaj,
-                          int ngid,t_ns_buf **ns_buf,
-                          put_in_list_t *put_in_list,gmx_bool bHaveVdW[])
-{
-    int      naaj,k;
-    real     rlist2;
-    int      nsearch,icg,jcg,igid,i0,nri,nn;
-    int      *cginfo;
-    t_ns_buf *nsbuf;
-    /* atom_id  *i_atoms; */
-    t_block  *cgs=&(top->cgs);
-    t_blocka *excl=&(top->excls);
-    rvec     b_inv;
-    int      m;
-    gmx_bool     bBox,bTriclinic;
-    int      *i_egp_flags;
-    
-    rlist2 = sqr(fr->rlist);
-    
-    bBox = (fr->ePBC != epbcNONE);
-    if (bBox)
-    {
-        for(m=0; (m<DIM); m++)
-        {
-            b_inv[m] = divide(1.0,box_size[m]);
-        }
-        bTriclinic = TRICLINIC(box);
-    }
-    else
-    {
-        bTriclinic = FALSE;
-    }
-    
-    cginfo = fr->cginfo;
-    
-    nsearch=0;
-    for (icg=fr->cg0; (icg<fr->hcg); icg++)
-    {
-        /*
-          i0        = cgs->index[icg];
-          nri       = cgs->index[icg+1]-i0;
-          i_atoms   = &(cgs->a[i0]);
-          i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
-          setexcl(nri,i_atoms,excl,TRUE,bexcl);
-        */
-        igid = GET_CGINFO_GID(cginfo[icg]);
-        i_egp_flags = fr->egp_flags + ngid*igid;
-        setexcl(cgs->index[icg],cgs->index[icg+1],excl,TRUE,bexcl);
-        
-        naaj=calc_naaj(icg,cgs->nr);
-        if (bTriclinic)
-        {
-            ns_inner_tric(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
-                          box,b_inv,rlist2,cgs,ns_buf,
-                          bHaveVdW,ngid,md,bexcl,fr,put_in_list);
-        }
-        else
-        {
-            ns_inner_rect(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
-                          bBox,box_size,b_inv,rlist2,cgs,ns_buf,
-                          bHaveVdW,ngid,md,bexcl,fr,put_in_list);
-        }
-        nsearch += naaj;
-        
-        for(nn=0; (nn<ngid); nn++)
-        {
-            for(k=0; (k<SHIFTS); k++)
-            {
-                nsbuf = &(ns_buf[nn][k]);
-                if (nsbuf->ncg > 0)
-                {
-                    put_in_list(bHaveVdW,ngid,md,icg,nn,nsbuf->ncg,nsbuf->jcg,
-                                cgs->index,bexcl,k,fr,FALSE,TRUE,TRUE);
-                    nsbuf->ncg=nsbuf->nj=0;
-                }
-            }
-        }
-        /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
-        setexcl(cgs->index[icg],cgs->index[icg+1],excl,FALSE,bexcl);
-    }
-    close_neighbor_list(fr,FALSE,-1,-1,FALSE);
-    
-    return nsearch;
-}
-
-/************************************************
- *
- *    N S 5     G R I D     S T U F F
- *
- ************************************************/
-
-static inline void get_dx(int Nx,real gridx,real rc2,int xgi,real x,
-                          int *dx0,int *dx1,real *dcx2)
-{
-    real dcx,tmp;
-    int  xgi0,xgi1,i;
-    
-    if (xgi < 0)
-    {
-        *dx0 = 0;
-        xgi0 = -1;
-        *dx1 = -1;
-        xgi1 = 0;
-    }
-    else if (xgi >= Nx)
-    {
-        *dx0 = Nx;
-        xgi0 = Nx-1;
-        *dx1 = Nx-1;
-        xgi1 = Nx;
-    }
-    else
-    {
-        dcx2[xgi] = 0;
-        *dx0 = xgi;
-        xgi0 = xgi-1;
-        *dx1 = xgi;
-        xgi1 = xgi+1;
-    }
-    
-    for(i=xgi0; i>=0; i--)
-    {
-        dcx = (i+1)*gridx-x;
-        tmp = dcx*dcx;
-        if (tmp >= rc2)
-            break;
-        *dx0 = i;
-        dcx2[i] = tmp;
-    }
-    for(i=xgi1; i<Nx; i++)
-    {
-        dcx = i*gridx-x;
-        tmp = dcx*dcx;
-        if (tmp >= rc2)
-        {
-            break;
-        }
-        *dx1 = i;
-        dcx2[i] = tmp;
-    }
-}
-
-static inline void get_dx_dd(int Nx,real gridx,real rc2,int xgi,real x,
-                             int ncpddc,int shift_min,int shift_max,
-                             int *g0,int *g1,real *dcx2)
-{
-    real dcx,tmp;
-    int  g_min,g_max,shift_home;
-    
-    if (xgi < 0)
-    {
-        g_min = 0;
-        g_max = Nx - 1;
-        *g0   = 0;
-        *g1   = -1;
-    }
-    else if (xgi >= Nx)
-    {
-        g_min = 0;
-        g_max = Nx - 1;
-        *g0   = Nx;
-        *g1   = Nx - 1;
-    }
-    else
-    {
-        if (ncpddc == 0)
-        {
-            g_min = 0;
-            g_max = Nx - 1;
-        }
-        else
-        {
-            if (xgi < ncpddc)
-            {
-                shift_home = 0;
-            }
-            else
-            {
-                shift_home = -1;
-            }
-            g_min = (shift_min == shift_home ? 0          : ncpddc);
-            g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
-        }
-        if (shift_min > 0)
-        {
-            *g0 = g_min;
-            *g1 = g_min - 1;
-        }
-        else if (shift_max < 0)
-        {
-            *g0 = g_max + 1;
-            *g1 = g_max;
-        }
-        else
-        {
-            *g0 = xgi;
-            *g1 = xgi;
-            dcx2[xgi] = 0;
-        }
-    }
-    
-    while (*g0 > g_min)
-    {
-        /* Check one grid cell down */
-        dcx = ((*g0 - 1) + 1)*gridx - x;
-        tmp = dcx*dcx;
-        if (tmp >= rc2)
-        {
-            break;
-        }
-        (*g0)--;
-        dcx2[*g0] = tmp;
-    }
-    
-    while (*g1 < g_max)
-    {
-        /* Check one grid cell up */
-        dcx = (*g1 + 1)*gridx - x;
-        tmp = dcx*dcx;
-        if (tmp >= rc2)
-        {
-            break;
-        }
-        (*g1)++;
-        dcx2[*g1] = tmp;
-    }
-}
-
-
-#define sqr(x) ((x)*(x))
-#define calc_dx2(XI,YI,ZI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]) + sqr(ZI-y[ZZ]))
-#define calc_cyl_dx2(XI,YI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]))
-/****************************************************
- *
- *    F A S T   N E I G H B O R  S E A R C H I N G
- *
- *    Optimized neighboursearching routine using grid 
- *    at least 1x1x1, see GROMACS manual
- *
- ****************************************************/
-
-static void do_longrange(t_commrec *cr,gmx_localtop_t *top,t_forcerec *fr,
-                         int ngid,t_mdatoms *md,int icg,
-                         int jgid,int nlr,
-                         atom_id lr[],t_excl bexcl[],int shift,
-                         rvec x[],rvec box_size,t_nrnb *nrnb,
-                         real lambda,real *dvdlambda,
-                         gmx_grppairener_t *grppener,
-                         gmx_bool bDoVdW,gmx_bool bDoCoul,
-                         gmx_bool bEvaluateNow,put_in_list_t *put_in_list,
-                         gmx_bool bHaveVdW[],
-                         gmx_bool bDoForces,rvec *f)
-{
-    int n,i;
-    t_nblist *nl;
-    
-    for(n=0; n<fr->nnblists; n++)
-    {
-        for(i=0; (i<eNL_NR); i++)
-        {
-            nl = &fr->nblists[n].nlist_lr[i];
-            if ((nl->nri > nl->maxnri-32) || bEvaluateNow)
-            {
-                close_neighbor_list(fr,TRUE,n,i,FALSE);
-                /* Evaluate the energies and forces */
-                do_nonbonded(cr,fr,x,f,md,NULL,
-                             grppener->ener[fr->bBHAM ? egBHAMLR : egLJLR],
-                             grppener->ener[egCOULLR],
-                                                        grppener->ener[egGB],box_size,
-                             nrnb,lambda,dvdlambda,n,i,
-                             GMX_DONB_LR | GMX_DONB_FORCES);
-                
-                reset_neighbor_list(fr,TRUE,n,i);
-            }
-        }
-    }
-    
-    if (!bEvaluateNow)
-    {  
-        /* Put the long range particles in a list */
-        /* do_longrange is never called for QMMM  */
-        put_in_list(bHaveVdW,ngid,md,icg,jgid,nlr,lr,top->cgs.index,
-                    bexcl,shift,fr,TRUE,bDoVdW,bDoCoul);
-    }
-}
-
-static void get_cutoff2(t_forcerec *fr,gmx_bool bDoLongRange,
-                        real *rvdw2,real *rcoul2,
-                        real *rs2,real *rm2,real *rl2)
-{
-    *rs2 = sqr(fr->rlist);
-    if (bDoLongRange && fr->bTwinRange)
-    {
-        /* The VdW and elec. LR cut-off's could be different,
-         * so we can not simply set them to rlistlong.
-         */
-        if (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(fr->vdwtype) &&
-            fr->rvdw > fr->rlist)
-        {
-            *rvdw2  = sqr(fr->rlistlong);
-        }
-        else
-        {
-            *rvdw2  = sqr(fr->rvdw);
-        }
-        if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(fr->eeltype) &&
-            fr->rcoulomb > fr->rlist)
-        {
-            *rcoul2 = sqr(fr->rlistlong);
-        }
-        else
-        {
-            *rcoul2 = sqr(fr->rcoulomb);
-        }
-    }
-    else
-    {
-        /* Workaround for a gcc -O3 or -ffast-math problem */
-        *rvdw2  = *rs2;
-        *rcoul2 = *rs2;
-    }
-    *rm2 = min(*rvdw2,*rcoul2);
-    *rl2 = max(*rvdw2,*rcoul2);
-}
-
-static void init_nsgrid_lists(t_forcerec *fr,int ngid,gmx_ns_t *ns)
-{
-    real rvdw2,rcoul2,rs2,rm2,rl2;
-    int j;
-
-    get_cutoff2(fr,TRUE,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
-
-    /* Short range buffers */
-    snew(ns->nl_sr,ngid);
-    /* Counters */
-    snew(ns->nsr,ngid);
-    snew(ns->nlr_ljc,ngid);
-    snew(ns->nlr_one,ngid);
-    
-    if (rm2 > rs2)
-    {
-            /* Long range VdW and Coul buffers */
-        snew(ns->nl_lr_ljc,ngid);
-    }
-    if (rl2 > rm2)
-    {
-        /* Long range VdW or Coul only buffers */
-        snew(ns->nl_lr_one,ngid);
-    }
-    for(j=0; (j<ngid); j++) {
-        snew(ns->nl_sr[j],MAX_CG);
-        if (rm2 > rs2)
-        {
-            snew(ns->nl_lr_ljc[j],MAX_CG);
-        }
-        if (rl2 > rm2)
-        {
-            snew(ns->nl_lr_one[j],MAX_CG);
-        }
-    }
-    if (debug)
-    {
-        fprintf(debug,
-                "ns5_core: rs2 = %g, rm2 = %g, rl2 = %g (nm^2)\n",
-                rs2,rm2,rl2);
-    }
-}
-
-static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
-                       matrix box,rvec box_size,int ngid,
-                       gmx_localtop_t *top,
-                       t_grid *grid,rvec x[],
-                       t_excl bexcl[],gmx_bool *bExcludeAlleg,
-                       t_nrnb *nrnb,t_mdatoms *md,
-                       real lambda,real *dvdlambda,
-                       gmx_grppairener_t *grppener,
-                       put_in_list_t *put_in_list,
-                       gmx_bool bHaveVdW[],
-                       gmx_bool bDoLongRange,gmx_bool bDoForces,rvec *f,
-                       gmx_bool bMakeQMMMnblist)
-{
-    gmx_ns_t *ns;
-    atom_id **nl_lr_ljc,**nl_lr_one,**nl_sr;
-    int     *nlr_ljc,*nlr_one,*nsr;
-    gmx_domdec_t *dd=NULL;
-    t_block *cgs=&(top->cgs);
-    int     *cginfo=fr->cginfo;
-    /* atom_id *i_atoms,*cgsindex=cgs->index; */
-    ivec    sh0,sh1,shp;
-    int     cell_x,cell_y,cell_z;
-    int     d,tx,ty,tz,dx,dy,dz,cj;
-#ifdef ALLOW_OFFDIAG_LT_HALFDIAG
-    int     zsh_ty,zsh_tx,ysh_tx;
-#endif
-    int     dx0,dx1,dy0,dy1,dz0,dz1;
-    int     Nx,Ny,Nz,shift=-1,j,nrj,nns,nn=-1;
-    real    gridx,gridy,gridz,grid_x,grid_y,grid_z;
-    real    *dcx2,*dcy2,*dcz2;
-    int     zgi,ygi,xgi;
-    int     cg0,cg1,icg=-1,cgsnr,i0,igid,nri,naaj,max_jcg;
-    int     jcg0,jcg1,jjcg,cgj0,jgid;
-    int     *grida,*gridnra,*gridind;
-    gmx_bool    rvdw_lt_rcoul,rcoul_lt_rvdw;
-    rvec    xi,*cgcm,grid_offset;
-    real    r2,rs2,rvdw2,rcoul2,rm2,rl2,XI,YI,ZI,dcx,dcy,dcz,tmp1,tmp2;
-    int     *i_egp_flags;
-    gmx_bool    bDomDec,bTriclinicX,bTriclinicY;
-    ivec    ncpddc;
-    
-    ns = &fr->ns;
-    
-    bDomDec = DOMAINDECOMP(cr);
-    if (bDomDec)
-    {
-        dd = cr->dd;
-    }
-    
-    bTriclinicX = ((YY < grid->npbcdim &&
-                    (!bDomDec || dd->nc[YY]==1) && box[YY][XX] != 0) ||
-                   (ZZ < grid->npbcdim &&
-                    (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][XX] != 0));
-    bTriclinicY =  (ZZ < grid->npbcdim &&
-                    (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][YY] != 0);
-    
-    cgsnr    = cgs->nr;
-
-    get_cutoff2(fr,bDoLongRange,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
-
-    rvdw_lt_rcoul = (rvdw2 >= rcoul2);
-    rcoul_lt_rvdw = (rcoul2 >= rvdw2);
-    
-    if (bMakeQMMMnblist)
-    {
-        rm2 = rl2;
-        rs2 = rl2;
-    }
-
-    nl_sr     = ns->nl_sr;
-    nsr       = ns->nsr;
-    nl_lr_ljc = ns->nl_lr_ljc;
-    nl_lr_one = ns->nl_lr_one;
-    nlr_ljc   = ns->nlr_ljc;
-    nlr_one   = ns->nlr_one;
-    
-    /* Unpack arrays */
-    cgcm    = fr->cg_cm;
-    Nx      = grid->n[XX];
-    Ny      = grid->n[YY];
-    Nz      = grid->n[ZZ];
-    grida   = grid->a;
-    gridind = grid->index;
-    gridnra = grid->nra;
-    nns     = 0;
-    
-    gridx      = grid->cell_size[XX];
-    gridy      = grid->cell_size[YY];
-    gridz      = grid->cell_size[ZZ];
-    grid_x     = 1/gridx;
-    grid_y     = 1/gridy;
-    grid_z     = 1/gridz;
-    copy_rvec(grid->cell_offset,grid_offset);
-    copy_ivec(grid->ncpddc,ncpddc);
-    dcx2       = grid->dcx2;
-    dcy2       = grid->dcy2;
-    dcz2       = grid->dcz2;
-    
-#ifdef ALLOW_OFFDIAG_LT_HALFDIAG
-    zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
-    zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
-    ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
-    if (zsh_tx!=0 && ysh_tx!=0)
-    {
-        /* This could happen due to rounding, when both ratios are 0.5 */
-        ysh_tx = 0;
-    }
-#endif
-    
-    debug_gmx();
-
-    if (fr->n_tpi)
-    {
-        /* We only want a list for the test particle */
-        cg0 = cgsnr - 1;
-    }
-    else
-    {
-        cg0 = grid->icg0;
-    }
-    cg1 = grid->icg1;
-
-    /* Set the shift range */
-    for(d=0; d<DIM; d++)
-    {
-        sh0[d] = -1;
-        sh1[d] = 1;
-        /* Check if we need periodicity shifts.
-         * Without PBC or with domain decomposition we don't need them.
-         */
-        if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
-        {
-            shp[d] = 0;
-        }
-        else
-        {
-            if (d == XX &&
-                box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
-            {
-                shp[d] = 2;
-            }
-            else
-            {
-                shp[d] = 1;
-            }
-        }
-    }
-    
-    /* Loop over charge groups */
-    for(icg=cg0; (icg < cg1); icg++)
-    {
-        igid = GET_CGINFO_GID(cginfo[icg]);
-        /* Skip this charge group if all energy groups are excluded! */
-        if (bExcludeAlleg[igid])
-        {
-            continue;
-        }
-        
-        i0   = cgs->index[icg];
-        
-        if (bMakeQMMMnblist)
-        { 
-            /* Skip this charge group if it is not a QM atom while making a
-             * QM/MM neighbourlist
-             */
-            if (md->bQM[i0]==FALSE)
-            {
-                continue; /* MM particle, go to next particle */ 
-            }
-            
-            /* Compute the number of charge groups that fall within the control
-             * of this one (icg)
-             */
-            naaj    = calc_naaj(icg,cgsnr);
-            jcg0    = icg;
-            jcg1    = icg + naaj;
-            max_jcg = cgsnr;       
-        } 
-        else
-        { 
-            /* make a normal neighbourlist */
-            
-            if (bDomDec)
-            {
-                /* Get the j charge-group and dd cell shift ranges */
-                dd_get_ns_ranges(cr->dd,icg,&jcg0,&jcg1,sh0,sh1);
-                max_jcg = 0;
-            }
-            else
-            {
-                /* Compute the number of charge groups that fall within the control
-                 * of this one (icg)
-                 */
-                naaj = calc_naaj(icg,cgsnr);
-                jcg0 = icg;
-                jcg1 = icg + naaj;
-                
-                if (fr->n_tpi)
-                {
-                    /* The i-particle is awlways the test particle,
-                     * so we want all j-particles
-                     */
-                    max_jcg = cgsnr - 1;
-                }
-                else
-                {
-                    max_jcg  = jcg1 - cgsnr;
-                }
-            }
-        }
-        
-        i_egp_flags = fr->egp_flags + igid*ngid;
-        
-        /* Set the exclusions for the atoms in charge group icg using a bitmask */
-        setexcl(i0,cgs->index[icg+1],&top->excls,TRUE,bexcl);
-        
-        ci2xyz(grid,icg,&cell_x,&cell_y,&cell_z);
-        
-        /* Changed iicg to icg, DvdS 990115 
-         * (but see consistency check above, DvdS 990330) 
-         */
-#ifdef NS5DB
-        fprintf(log,"icg=%5d, naaj=%5d, cell %d %d %d\n",
-                icg,naaj,cell_x,cell_y,cell_z);
-#endif
-        /* Loop over shift vectors in three dimensions */
-        for (tz=-shp[ZZ]; tz<=shp[ZZ]; tz++)
-        {
-            ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
-            /* Calculate range of cells in Z direction that have the shift tz */
-            zgi = cell_z + tz*Nz;
-#define FAST_DD_NS
-#ifndef FAST_DD_NS
-            get_dx(Nz,gridz,rl2,zgi,ZI,&dz0,&dz1,dcz2);
-#else
-            get_dx_dd(Nz,gridz,rl2,zgi,ZI-grid_offset[ZZ],
-                      ncpddc[ZZ],sh0[ZZ],sh1[ZZ],&dz0,&dz1,dcz2);
-#endif
-            if (dz0 > dz1)
-            {
-                continue;
-            }
-            for (ty=-shp[YY]; ty<=shp[YY]; ty++)
-            {
-                YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
-                /* Calculate range of cells in Y direction that have the shift ty */
-                if (bTriclinicY)
-                {
-                    ygi = (int)(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
-                }
-                else
-                {
-                    ygi = cell_y + ty*Ny;
-                }
-#ifndef FAST_DD_NS
-                get_dx(Ny,gridy,rl2,ygi,YI,&dy0,&dy1,dcy2);
-#else
-                get_dx_dd(Ny,gridy,rl2,ygi,YI-grid_offset[YY],
-                          ncpddc[YY],sh0[YY],sh1[YY],&dy0,&dy1,dcy2);
-#endif
-                if (dy0 > dy1)
-                {
-                    continue;
-                }
-                for (tx=-shp[XX]; tx<=shp[XX]; tx++)
-                {
-                    XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
-                    /* Calculate range of cells in X direction that have the shift tx */
-                    if (bTriclinicX)
-                    {
-                        xgi = (int)(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
-                    }
-                    else
-                    {
-                        xgi = cell_x + tx*Nx;
-                    }
-#ifndef FAST_DD_NS
-                    get_dx(Nx,gridx,rl2,xgi*Nx,XI,&dx0,&dx1,dcx2);
-#else
-                    get_dx_dd(Nx,gridx,rl2,xgi,XI-grid_offset[XX],
-                              ncpddc[XX],sh0[XX],sh1[XX],&dx0,&dx1,dcx2);
-#endif
-                    if (dx0 > dx1)
-                    {
-                        continue;
-                    }
-                    /* Get shift vector */       
-                    shift=XYZ2IS(tx,ty,tz);
-#ifdef NS5DB
-                    range_check(shift,0,SHIFTS);
-#endif
-                    for(nn=0; (nn<ngid); nn++)
-                    {
-                        nsr[nn]      = 0;
-                        nlr_ljc[nn]  = 0;
-                        nlr_one[nn] = 0;
-                    }
-#ifdef NS5DB
-                    fprintf(log,"shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
-                            shift,dx0,dx1,dy0,dy1,dz0,dz1);
-                    fprintf(log,"cgcm: %8.3f  %8.3f  %8.3f\n",cgcm[icg][XX],
-                            cgcm[icg][YY],cgcm[icg][ZZ]);
-                    fprintf(log,"xi:   %8.3f  %8.3f  %8.3f\n",XI,YI,ZI);
-#endif
-                    for (dx=dx0; (dx<=dx1); dx++)
-                    {
-                        tmp1 = rl2 - dcx2[dx];
-                        for (dy=dy0; (dy<=dy1); dy++)
-                        {
-                            tmp2 = tmp1 - dcy2[dy];
-                            if (tmp2 > 0)
-                            {
-                                for (dz=dz0; (dz<=dz1); dz++) {
-                                    if (tmp2 > dcz2[dz]) {
-                                        /* Find grid-cell cj in which possible neighbours are */
-                                        cj   = xyz2ci(Ny,Nz,dx,dy,dz);
-                                        
-                                        /* Check out how many cgs (nrj) there in this cell */
-                                        nrj  = gridnra[cj];
-                                        
-                                        /* Find the offset in the cg list */
-                                        cgj0 = gridind[cj];
-                                        
-                                        /* Check if all j's are out of range so we
-                                         * can skip the whole cell.
-                                         * Should save some time, especially with DD.
-                                         */
-                                        if (nrj == 0 ||
-                                            (grida[cgj0] >= max_jcg &&
-                                             (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
-                                        {
-                                            continue;
-                                        }
-                                        
-                                        /* Loop over cgs */
-                                        for (j=0; (j<nrj); j++)
-                                        {
-                                            jjcg = grida[cgj0+j];
-                                            
-                                            /* check whether this guy is in range! */
-                                            if ((jjcg >= jcg0 && jjcg < jcg1) ||
-                                                (jjcg < max_jcg))
-                                            {
-                                                r2=calc_dx2(XI,YI,ZI,cgcm[jjcg]);
-                                                if (r2 < rl2) {
-                                                    /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
-                                                    jgid = GET_CGINFO_GID(cginfo[jjcg]);
-                                                    /* check energy group exclusions */
-                                                    if (!(i_egp_flags[jgid] & EGP_EXCL))
-                                                    {
-                                                        if (r2 < rs2)
-                                                        {
-                                                            if (nsr[jgid] >= MAX_CG)
-                                                            {
-                                                                put_in_list(bHaveVdW,ngid,md,icg,jgid,
-                                                                            nsr[jgid],nl_sr[jgid],
-                                                                            cgs->index,/* cgsatoms, */ bexcl,
-                                                                            shift,fr,FALSE,TRUE,TRUE);
-                                                                nsr[jgid]=0;
-                                                            }
-                                                            nl_sr[jgid][nsr[jgid]++]=jjcg;
-                                                        } 
-                                                        else if (r2 < rm2)
-                                                        {
-                                                            if (nlr_ljc[jgid] >= MAX_CG)
-                                                            {
-                                                                do_longrange(cr,top,fr,ngid,md,icg,jgid,
-                                                                             nlr_ljc[jgid],
-                                                                             nl_lr_ljc[jgid],bexcl,shift,x,
-                                                                             box_size,nrnb,
-                                                                             lambda,dvdlambda,
-                                                                             grppener,
-                                                                             TRUE,TRUE,FALSE,
-                                                                             put_in_list,
-                                                                             bHaveVdW,
-                                                                             bDoForces,f);
-                                                                nlr_ljc[jgid]=0;
-                                                            }
-                                                            nl_lr_ljc[jgid][nlr_ljc[jgid]++]=jjcg;
-                                                        }
-                                                        else
-                                                        {
-                                                            if (nlr_one[jgid] >= MAX_CG) {
-                                                                do_longrange(cr,top,fr,ngid,md,icg,jgid,
-                                                                             nlr_one[jgid],
-                                                                             nl_lr_one[jgid],bexcl,shift,x,
-                                                                             box_size,nrnb,
-                                                                             lambda,dvdlambda,
-                                                                             grppener,
-                                                                             rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
-                                                                             put_in_list,
-                                                                             bHaveVdW,
-                                                                             bDoForces,f);
-                                                                nlr_one[jgid]=0;
-                                                            }
-                                                            nl_lr_one[jgid][nlr_one[jgid]++]=jjcg;
-                                                        }
-                                                    }
-                                                }
-                                                nns++;
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    /* CHECK whether there is anything left in the buffers */
-                    for(nn=0; (nn<ngid); nn++)
-                    {
-                        if (nsr[nn] > 0)
-                        {
-                            put_in_list(bHaveVdW,ngid,md,icg,nn,nsr[nn],nl_sr[nn],
-                                        cgs->index, /* cgsatoms, */ bexcl,
-                                        shift,fr,FALSE,TRUE,TRUE);
-                        }
-                        
-                        if (nlr_ljc[nn] > 0)
-                        {
-                            do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_ljc[nn],
-                                         nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
-                                         lambda,dvdlambda,grppener,TRUE,TRUE,FALSE,
-                                         put_in_list,bHaveVdW,bDoForces,f);
-                        }
-                        
-                        if (nlr_one[nn] > 0)
-                        {
-                            do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_one[nn],
-                                         nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
-                                         lambda,dvdlambda,grppener,
-                                         rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
-                                         put_in_list,bHaveVdW,bDoForces,f);
-                        }
-                    }
-                }
-            }
-        }
-        /* setexcl(nri,i_atoms,&top->atoms.excl,FALSE,bexcl); */
-        setexcl(cgs->index[icg],cgs->index[icg+1],&top->excls,FALSE,bexcl);
-    }
-    /* Perform any left over force calculations */
-    for (nn=0; (nn<ngid); nn++)
-    {
-        if (rm2 > rs2)
-        {
-            do_longrange(cr,top,fr,0,md,icg,nn,nlr_ljc[nn],
-                         nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
-                         lambda,dvdlambda,grppener,
-                         TRUE,TRUE,TRUE,put_in_list,bHaveVdW,bDoForces,f);
-        }
-        if (rl2 > rm2) {
-            do_longrange(cr,top,fr,0,md,icg,nn,nlr_one[nn],
-                         nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
-                         lambda,dvdlambda,grppener,
-                         rvdw_lt_rcoul,rcoul_lt_rvdw,
-                         TRUE,put_in_list,bHaveVdW,bDoForces,f);
-        }
-    }
-    debug_gmx();
-    
-    /* Close off short range neighbourlists */
-    close_neighbor_list(fr,FALSE,-1,-1,bMakeQMMMnblist);
-    
-    return nns;
-}
-
-void ns_realloc_natoms(gmx_ns_t *ns,int natoms)
-{
-    int i;
-    
-    if (natoms > ns->nra_alloc)
-    {
-        ns->nra_alloc = over_alloc_dd(natoms);
-        srenew(ns->bexcl,ns->nra_alloc);
-        for(i=0; i<ns->nra_alloc; i++)
-        {
-            ns->bexcl[i] = 0;
-        }
-    }
-}
-
-void init_ns(FILE *fplog,const t_commrec *cr,
-             gmx_ns_t *ns,t_forcerec *fr,
-             const gmx_mtop_t *mtop,
-             matrix box)
-{
-    int  mt,icg,nr_in_cg,maxcg,i,j,jcg,ngid,ncg;
-    t_block *cgs;
-    char *ptr;
-    
-    /* Compute largest charge groups size (# atoms) */
-    nr_in_cg=1;
-    for(mt=0; mt<mtop->nmoltype; mt++) {
-        cgs = &mtop->moltype[mt].cgs;
-        for (icg=0; (icg < cgs->nr); icg++)
-        {
-            nr_in_cg=max(nr_in_cg,(int)(cgs->index[icg+1]-cgs->index[icg]));
-        }
-    }
-
-    /* Verify whether largest charge group is <= max cg.
-     * This is determined by the type of the local exclusion type 
-     * Exclusions are stored in bits. (If the type is not large
-     * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
-     */
-    maxcg = sizeof(t_excl)*8;
-    if (nr_in_cg > maxcg)
-    {
-        gmx_fatal(FARGS,"Max #atoms in a charge group: %d > %d\n",
-                  nr_in_cg,maxcg);
-    }
-    
-    ngid = mtop->groups.grps[egcENER].nr;
-    snew(ns->bExcludeAlleg,ngid);
-    for(i=0; i<ngid; i++) {
-        ns->bExcludeAlleg[i] = TRUE;
-        for(j=0; j<ngid; j++)
-        {
-            if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
-            {
-                ns->bExcludeAlleg[i] = FALSE;
-            }
-        }
-    }
-    
-    if (fr->bGrid) {
-        /* Grid search */
-        ns->grid = init_grid(fplog,fr);
-        init_nsgrid_lists(fr,ngid,ns);
-    }
-    else
-    {
-        /* Simple search */
-        snew(ns->ns_buf,ngid);
-        for(i=0; (i<ngid); i++)
-        {
-            snew(ns->ns_buf[i],SHIFTS);
-        }
-        ncg = ncg_mtop(mtop);
-        snew(ns->simple_aaj,2*ncg);
-        for(jcg=0; (jcg<ncg); jcg++)
-        {
-            ns->simple_aaj[jcg]     = jcg;
-            ns->simple_aaj[jcg+ncg] = jcg;
-        }
-    }
-    
-    /* Create array that determines whether or not atoms have VdW */
-    snew(ns->bHaveVdW,fr->ntype);
-    for(i=0; (i<fr->ntype); i++)
-    {
-        for(j=0; (j<fr->ntype); j++)
-        {
-            ns->bHaveVdW[i] = (ns->bHaveVdW[i] || 
-                               (fr->bBHAM ? 
-                                ((BHAMA(fr->nbfp,fr->ntype,i,j) != 0) ||
-                                 (BHAMB(fr->nbfp,fr->ntype,i,j) != 0) ||
-                                 (BHAMC(fr->nbfp,fr->ntype,i,j) != 0)) :
-                                ((C6(fr->nbfp,fr->ntype,i,j) != 0) ||
-                                 (C12(fr->nbfp,fr->ntype,i,j) != 0))));
-        }
-    }
-    if (debug) 
-        pr_bvec(debug,0,"bHaveVdW",ns->bHaveVdW,fr->ntype,TRUE);
-    
-    ns->nra_alloc = 0;
-    ns->bexcl = NULL;
-    if (!DOMAINDECOMP(cr))
-    {
-        /* This could be reduced with particle decomposition */
-        ns_realloc_natoms(ns,mtop->natoms);
-    }
-
-    ns->nblist_initialized=FALSE;
-
-    /* nbr list debug dump */
-    {
-        char *ptr=getenv("GMX_DUMP_NL");
-        if (ptr)
-        {
-            ns->dump_nl=strtol(ptr,NULL,10);
-            if (fplog)
-            {
-                fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
-            }
-        }
-        else
-        {
-            ns->dump_nl=0;
-        }
-    }
-}
-
-                        
-int search_neighbours(FILE *log,t_forcerec *fr,
-                      rvec x[],matrix box,
-                      gmx_localtop_t *top,
-                      gmx_groups_t *groups,
-                      t_commrec *cr,
-                      t_nrnb *nrnb,t_mdatoms *md,
-                      real lambda,real *dvdlambda,
-                      gmx_grppairener_t *grppener,
-                      gmx_bool bFillGrid,
-                      gmx_bool bDoLongRange,
-                      gmx_bool bDoForces,rvec *f)
-{
-    t_block  *cgs=&(top->cgs);
-    rvec     box_size,grid_x0,grid_x1;
-    int      i,j,m,ngid;
-    real     min_size,grid_dens;
-    int      nsearch;
-    gmx_bool     bGrid;
-    char     *ptr;
-    gmx_bool     *i_egp_flags;
-    int      cg_start,cg_end,start,end;
-    gmx_ns_t *ns;
-    t_grid   *grid;
-    gmx_domdec_zones_t *dd_zones;
-    put_in_list_t *put_in_list;
-       
-    ns = &fr->ns;
-
-    /* Set some local variables */
-    bGrid = fr->bGrid;
-    ngid = groups->grps[egcENER].nr;
-    
-    for(m=0; (m<DIM); m++)
-    {
-        box_size[m] = box[m][m];
-    }
-  
-    if (fr->ePBC != epbcNONE)
-    {
-        if (sqr(fr->rlistlong) >= max_cutoff2(fr->ePBC,box))
-        {
-            gmx_fatal(FARGS,"One of the box vectors has become shorter than twice the cut-off length or box_yy-|box_zy| or box_zz has become smaller than the cut-off.");
-        }
-        if (!bGrid)
-        {
-            min_size = min(box_size[XX],min(box_size[YY],box_size[ZZ]));
-            if (2*fr->rlistlong >= min_size)
-                gmx_fatal(FARGS,"One of the box diagonal elements has become smaller than twice the cut-off length.");
-        }
-    }
-    
-    if (DOMAINDECOMP(cr))
-    {
-        ns_realloc_natoms(ns,cgs->index[cgs->nr]);
-    }
-    debug_gmx();
-    
-    /* Reset the neighbourlists */
-    reset_neighbor_list(fr,FALSE,-1,-1);
-    
-    if (bGrid && bFillGrid)
-    {
-               
-        grid = ns->grid;
-        if (DOMAINDECOMP(cr))
-        {
-            dd_zones = domdec_zones(cr->dd);
-        }
-        else
-        {
-            dd_zones = NULL;
-
-            get_nsgrid_boundaries(grid,NULL,box,NULL,NULL,NULL,
-                                  cgs->nr,fr->cg_cm,grid_x0,grid_x1,&grid_dens);
-
-            grid_first(log,grid,NULL,NULL,fr->ePBC,box,grid_x0,grid_x1,
-                       fr->rlistlong,grid_dens);
-        }
-        debug_gmx();
-        
-        /* Don't know why this all is... (DvdS 3/99) */
-#ifndef SEGV
-        start = 0;
-        end   = cgs->nr;
-#else
-        start = fr->cg0;
-        end   = (cgs->nr+1)/2;
-#endif
-        
-        if (DOMAINDECOMP(cr))
-        {
-            end = cgs->nr;
-            fill_grid(log,dd_zones,grid,end,-1,end,fr->cg_cm);
-            grid->icg0 = 0;
-            grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
-        }
-        else
-        {
-            fill_grid(log,NULL,grid,cgs->nr,fr->cg0,fr->hcg,fr->cg_cm);
-            grid->icg0 = fr->cg0;
-            grid->icg1 = fr->hcg;
-            debug_gmx();
-            
-            if (PARTDECOMP(cr))
-                mv_grid(cr,grid);
-            debug_gmx();
-        }
-        
-        calc_elemnr(log,grid,start,end,cgs->nr);
-        calc_ptrs(grid);
-        grid_last(log,grid,start,end,cgs->nr);
-        
-        if (gmx_debug_at)
-        {
-            check_grid(debug,grid);
-            print_grid(debug,grid);
-        }
-    }
-    else if (fr->n_tpi)
-    {
-        /* Set the grid cell index for the test particle only.
-         * The cell to cg index is not corrected, but that does not matter.
-         */
-        fill_grid(log,NULL,ns->grid,fr->hcg,fr->hcg-1,fr->hcg,fr->cg_cm);
-    }
-    debug_gmx();
-    
-    if (!fr->ns.bCGlist)
-    {
-        put_in_list = put_in_list_at;
-    }
-    else
-    {
-        put_in_list = put_in_list_cg;
-    }
-
-    /* Do the core! */
-    if (bGrid)
-    {
-        grid = ns->grid;
-        nsearch = nsgrid_core(log,cr,fr,box,box_size,ngid,top,
-                              grid,x,ns->bexcl,ns->bExcludeAlleg,
-                              nrnb,md,lambda,dvdlambda,grppener,
-                              put_in_list,ns->bHaveVdW,
-                              bDoLongRange,bDoForces,f,
-                              FALSE);
-        
-        /* neighbour searching withouth QMMM! QM atoms have zero charge in
-         * the classical calculation. The charge-charge interaction
-         * between QM and MM atoms is handled in the QMMM core calculation
-         * (see QMMM.c). The VDW however, we'd like to compute classically
-         * and the QM MM atom pairs have just been put in the
-         * corresponding neighbourlists. in case of QMMM we still need to
-         * fill a special QMMM neighbourlist that contains all neighbours
-         * of the QM atoms. If bQMMM is true, this list will now be made: 
-         */
-        if (fr->bQMMM && fr->qr->QMMMscheme!=eQMMMschemeoniom)
-        {
-            nsearch += nsgrid_core(log,cr,fr,box,box_size,ngid,top,
-                                   grid,x,ns->bexcl,ns->bExcludeAlleg,
-                                   nrnb,md,lambda,dvdlambda,grppener,
-                                   put_in_list_qmmm,ns->bHaveVdW,
-                                   bDoLongRange,bDoForces,f,
-                                   TRUE);
-        }
-    }
-    else 
-    {
-        nsearch = ns_simple_core(fr,top,md,box,box_size,
-                                 ns->bexcl,ns->simple_aaj,
-                                 ngid,ns->ns_buf,put_in_list,ns->bHaveVdW);
-    }
-    debug_gmx();
-    
-#ifdef DEBUG
-    pr_nsblock(log);
-#endif
-    
-    inc_nrnb(nrnb,eNR_NS,nsearch);
-    /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
-    
-    return nsearch;
-}
-
-int natoms_beyond_ns_buffer(t_inputrec *ir,t_forcerec *fr,t_block *cgs,
-                            matrix scale_tot,rvec *x)
-{
-    int  cg0,cg1,cg,a0,a1,a,i,j;
-    real rint,hbuf2,scale;
-    rvec *cg_cm,cgsc;
-    gmx_bool bIsotropic;
-    int  nBeyond;
-    
-    nBeyond = 0;
-    
-    rint = max(ir->rcoulomb,ir->rvdw);
-    if (ir->rlist < rint)
-    {
-        gmx_fatal(FARGS,"The neighbor search buffer has negative size: %f nm",
-                  ir->rlist - rint);
-    }
-    cg_cm = fr->cg_cm;
-    
-    cg0 = fr->cg0;
-    cg1 = fr->hcg;
-    
-    if (!EI_DYNAMICS(ir->eI) || !DYNAMIC_BOX(*ir))
-    {
-        hbuf2 = sqr(0.5*(ir->rlist - rint));
-        for(cg=cg0; cg<cg1; cg++)
-        {
-            a0 = cgs->index[cg];
-            a1 = cgs->index[cg+1];
-            for(a=a0; a<a1; a++)
-            {
-                if (distance2(cg_cm[cg],x[a]) > hbuf2)
-                {
-                    nBeyond++;
-                }
-            }
-        }
-    }
-    else
-    {
-        bIsotropic = TRUE;
-        scale = scale_tot[0][0];
-        for(i=1; i<DIM; i++)
-        {
-            /* With anisotropic scaling, the original spherical ns volumes become
-             * ellipsoids. To avoid costly transformations we use the minimum
-             * eigenvalue of the scaling matrix for determining the buffer size.
-             * Since the lower half is 0, the eigenvalues are the diagonal elements.
-             */
-            scale = min(scale,scale_tot[i][i]);
-            if (scale_tot[i][i] != scale_tot[i-1][i-1])
-            {
-                bIsotropic = FALSE;
-            }
-            for(j=0; j<i; j++)
-            {
-                if (scale_tot[i][j] != 0)
-                {
-                    bIsotropic = FALSE;
-                }
-            }
-        }
-        hbuf2 = sqr(0.5*(scale*ir->rlist - rint));
-        if (bIsotropic)
-        {
-            for(cg=cg0; cg<cg1; cg++)
-            {
-                svmul(scale,cg_cm[cg],cgsc);
-                a0 = cgs->index[cg];
-                a1 = cgs->index[cg+1];
-                for(a=a0; a<a1; a++)
-                {
-                    if (distance2(cgsc,x[a]) > hbuf2)
-                    {                    
-                        nBeyond++;
-                    }
-                }
-            }
-        }
-        else
-        {
-            /* Anistropic scaling */
-            for(cg=cg0; cg<cg1; cg++)
-            {
-                /* Since scale_tot contains the transpose of the scaling matrix,
-                 * we need to multiply with the transpose.
-                 */
-                tmvmul_ur0(scale_tot,cg_cm[cg],cgsc);
-                a0 = cgs->index[cg];
-                a1 = cgs->index[cg+1];
-                for(a=a0; a<a1; a++)
-                {
-                    if (distance2(cgsc,x[a]) > hbuf2)
-                    {
-                        nBeyond++;
-                    }
-                }
-            }
-        }
-    }
-    
-    return nBeyond;
-}
diff --git a/src/mdlib/pme.c b/src/mdlib/pme.c
deleted file mode 100644 (file)
index 622d15f..0000000
+++ /dev/null
@@ -1,2738 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-/* IMPORTANT FOR DEVELOPERS:
- *
- * Triclinic pme stuff isn't entirely trivial, and we've experienced
- * some bugs during development (many of them due to me). To avoid
- * this in the future, please check the following things if you make
- * changes in this file:
- *
- * 1. You should obtain identical (at least to the PME precision)
- *    energies, forces, and virial for
- *    a rectangular box and a triclinic one where the z (or y) axis is
- *    tilted a whole box side. For instance you could use these boxes:
- *
- *    rectangular       triclinic
- *     2  0  0           2  0  0
- *     0  2  0           0  2  0
- *     0  0  6           2  2  6
- *
- * 2. You should check the energy conservation in a triclinic box.
- *
- * It might seem an overkill, but better safe than sorry.
- * /Erik 001109
- */ 
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include "typedefs.h"
-#include "txtdump.h"
-#include "vec.h"
-#include "gmxcomplex.h"
-#include "smalloc.h"
-#include "futil.h"
-#include "coulomb.h"
-#include "gmx_fatal.h"
-#include "pme.h"
-#include "network.h"
-#include "physics.h"
-#include "nrnb.h"
-#include "copyrite.h"
-#include "gmx_wallcycle.h"
-#include "gmx_parallel_3dfft.h"
-#include "pdbio.h"
-
-#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
-#include "gmx_sse2_single.h"
-#endif
-
-#include "mpelogging.h"
-
-#define DFT_TOL 1e-7
-/* #define PRT_FORCE */
-/* conditions for on the fly time-measurement */
-/* #define TAKETIME (step > 1 && timesteps < 10) */
-#define TAKETIME FALSE
-
-#ifdef GMX_DOUBLE
-#define mpi_type MPI_DOUBLE
-#else
-#define mpi_type MPI_FLOAT
-#endif
-
-/* Internal datastructures */
-typedef struct {
-    int send_index0;
-    int send_nindex;
-    int recv_index0;
-    int recv_nindex;
-} pme_grid_comm_t;
-
-typedef struct {
-#ifdef GMX_MPI
-    MPI_Comm mpi_comm;
-#endif
-    int  nnodes,nodeid;
-    int  *s2g0;
-    int  *s2g1;
-    int  noverlap_nodes;
-    int  *send_id,*recv_id;
-    pme_grid_comm_t *comm_data;
-} pme_overlap_t;
-
-typedef struct {
-    int  dimind;            /* The index of the dimension, 0=x, 1=y */
-    int  nslab;
-    int  nodeid;
-#ifdef GMX_MPI
-    MPI_Comm mpi_comm;
-#endif
-
-    int  *node_dest;        /* The nodes to send x and q to with DD */
-    int  *node_src;         /* The nodes to receive x and q from with DD */
-    int  *buf_index;        /* Index for commnode into the buffers */
-
-    int  maxshift;
-
-    int  npd;
-    int  pd_nalloc;
-    int  *pd;
-    int  *count;            /* The number of atoms to send to each node */
-    int  *rcount;           /* The number of atoms to receive */
-
-    int  n;
-    int  nalloc;
-    rvec *x;
-    real *q;
-    rvec *f;
-    gmx_bool bSpread;           /* These coordinates are used for spreading */
-    int  pme_order;
-    splinevec theta,dtheta;
-    ivec *idx;
-    rvec *fractx;            /* Fractional coordinate relative to the
-                              * lower cell boundary 
-                              */
-} pme_atomcomm_t;
-
-typedef struct gmx_pme {
-    int  ndecompdim;         /* The number of decomposition dimensions */
-    int  nodeid;             /* Our nodeid in mpi->mpi_comm */
-    int  nodeid_major;
-    int  nodeid_minor;
-    int  nnodes;             /* The number of nodes doing PME */
-    int  nnodes_major;
-    int  nnodes_minor;
-
-    MPI_Comm mpi_comm;
-    MPI_Comm mpi_comm_d[2];  /* Indexed on dimension, 0=x, 1=y */
-#ifdef GMX_MPI
-    MPI_Datatype  rvec_mpi;  /* the pme vector's MPI type */
-#endif
-
-    gmx_bool bPPnode;            /* Node also does particle-particle forces */
-    gmx_bool bFEP;               /* Compute Free energy contribution */
-    int nkx,nky,nkz;         /* Grid dimensions */
-    int pme_order;
-    real epsilon_r;           
-    
-    real *  pmegridA;  /* Grids on which we do spreading/interpolation, includes overlap */
-    real *  pmegridB;
-    int     pmegrid_nx,pmegrid_ny,pmegrid_nz;
-    int     pmegrid_start_ix,pmegrid_start_iy,pmegrid_start_iz;    
-    
-    real *  pmegrid_sendbuf;
-    real *  pmegrid_recvbuf;
-    
-    real *fftgridA;             /* Grids for FFT. With 1D FFT decomposition this can be a pointer */
-    real *fftgridB;             /* inside the interpolation grid, but separate for 2D PME decomp. */
-    int   fftgrid_nx,fftgrid_ny,fftgrid_nz;
-    
-    t_complex *cfftgridA;             /* Grids for complex FFT data */
-    t_complex *cfftgridB;            
-    int   cfftgrid_nx,cfftgrid_ny,cfftgrid_nz;
-    
-    gmx_parallel_3dfft_t  pfft_setupA;
-    gmx_parallel_3dfft_t  pfft_setupB;
-    
-    int  *nnx,*nny,*nnz;
-    real *fshx,*fshy,*fshz;
-    
-    pme_atomcomm_t atc[2];  /* Indexed on decomposition index */
-    matrix    recipbox;
-    splinevec bsp_mod;
-    
-    pme_overlap_t overlap[2]; /* Indexed on dimension, 0=x, 1=y */
-
-
-    pme_atomcomm_t atc_energy; /* Only for gmx_pme_calc_energy */
-    
-    rvec *bufv;             /* Communication buffer */
-    real *bufr;             /* Communication buffer */
-    int  buf_nalloc;        /* The communication buffer size */
-
-    /* work data for solve_pme */
-    int      work_nalloc;
-    real *   work_mhx;
-    real *   work_mhy;
-    real *   work_mhz;
-    real *   work_m2;
-    real *   work_denom;
-    real *   work_tmp1_alloc;
-    real *   work_tmp1;
-    real *   work_m2inv;
-
-    /* Work data for PME_redist */
-    gmx_bool     redist_init;
-    int *    scounts; 
-    int *    rcounts;
-    int *    sdispls;
-    int *    rdispls;
-    int *    sidx;
-    int *    idxa;    
-    real *   redist_buf;
-    int      redist_buf_nalloc;
-    
-    /* Work data for sum_qgrid */
-    real *   sum_qgrid_tmp;
-    real *   sum_qgrid_dd_tmp;
-} t_gmx_pme;
-
-
-static void calc_interpolation_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
-{
-    int  i;
-    int  *idxptr,tix,tiy,tiz;
-    real *xptr,*fptr,tx,ty,tz;
-    real rxx,ryx,ryy,rzx,rzy,rzz;
-    int  nx,ny,nz;
-    int  start_ix,start_iy,start_iz;
-    
-    nx  = pme->nkx;
-    ny  = pme->nky;
-    nz  = pme->nkz;
-    
-    start_ix = pme->pmegrid_start_ix;
-    start_iy = pme->pmegrid_start_iy;
-    start_iz = pme->pmegrid_start_iz;
-    
-    rxx = pme->recipbox[XX][XX];
-    ryx = pme->recipbox[YY][XX];
-    ryy = pme->recipbox[YY][YY];
-    rzx = pme->recipbox[ZZ][XX];
-    rzy = pme->recipbox[ZZ][YY];
-    rzz = pme->recipbox[ZZ][ZZ];
-    
-    for(i=0; (i<atc->n); i++) {
-        xptr   = atc->x[i];
-        idxptr = atc->idx[i];
-        fptr   = atc->fractx[i];
-        
-        /* Fractional coordinates along box vectors, add 2.0 to make 100% sure we are positive for triclinic boxes */
-        tx = nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx + 2.0 );
-        ty = ny * (                  xptr[YY] * ryy + xptr[ZZ] * rzy + 2.0 );
-        tz = nz * (                                   xptr[ZZ] * rzz + 2.0 );
-        
-        tix = (int)(tx);
-        tiy = (int)(ty);
-        tiz = (int)(tz);
-        
-        /* Because decomposition only occurs in x and y,
-         * we never have a fraction correction in z.
-         */
-        fptr[XX] = tx - tix + pme->fshx[tix];
-        fptr[YY] = ty - tiy + pme->fshy[tiy];
-        fptr[ZZ] = tz - tiz;   
-
-        idxptr[XX] = pme->nnx[tix];
-        idxptr[YY] = pme->nny[tiy];
-        idxptr[ZZ] = pme->nnz[tiz];
-
-#ifdef DEBUG
-        range_check(idxptr[XX],0,pme->pmegrid_nx);
-        range_check(idxptr[YY],0,pme->pmegrid_ny);
-        range_check(idxptr[ZZ],0,pme->pmegrid_nz);
-#endif
-  }  
-}
-
-static void pme_calc_pidx(int natoms, matrix recipbox, rvec x[],
-                          pme_atomcomm_t *atc)
-{
-    int  nslab,i;
-    int  si;
-    real *xptr,s;
-    real rxx,ryx,rzx,ryy,rzy;
-    int *pd,*count;
-
-    /* Calculate PME task index (pidx) for each grid index.
-     * Here we always assign equally sized slabs to each node
-     * for load balancing reasons (the PME grid spacing is not used).
-     */
-    
-    nslab = atc->nslab;
-    pd    = atc->pd;
-    count = atc->count;
-
-    /* Reset the count */
-    for(i=0; i<nslab; i++)
-    {
-        count[i] = 0;
-    }
-    
-    if (atc->dimind == 0)
-    {
-        rxx = recipbox[XX][XX];
-        ryx = recipbox[YY][XX];
-        rzx = recipbox[ZZ][XX];
-        /* Calculate the node index in x-dimension */
-        for(i=0; (i<natoms); i++)
-        {
-            xptr   = x[i];
-            /* Fractional coordinates along box vectors */
-            s = nslab*(xptr[XX]*rxx + xptr[YY]*ryx + xptr[ZZ]*rzx);
-            si = (int)(s + 2*nslab) % nslab;
-            pd[i] = si;
-            count[si]++;
-        }
-    }
-    else
-    {
-        ryy = recipbox[YY][YY];
-        rzy = recipbox[ZZ][YY];
-        /* Calculate the node index in y-dimension */
-        for(i=0; (i<natoms); i++)
-        {
-            xptr   = x[i];
-            /* Fractional coordinates along box vectors */
-            s = nslab*(xptr[YY]*ryy + xptr[ZZ]*rzy);
-            si = (int)(s + 2*nslab) % nslab;
-            pd[i] = si;
-            count[si]++;
-        }
-    }
-}
-
-static void pme_realloc_atomcomm_things(pme_atomcomm_t *atc)
-{
-    int nalloc_old,i;
-    
-    /* We have to avoid a NULL pointer for atc->x to avoid
-     * possible fatal errors in MPI routines.
-     */
-    if (atc->n > atc->nalloc || atc->nalloc == 0)
-    {
-        nalloc_old = atc->nalloc;
-        atc->nalloc = over_alloc_dd(max(atc->n,1));
-        
-        if (atc->nslab > 1) {
-            srenew(atc->x,atc->nalloc);
-            srenew(atc->q,atc->nalloc);
-            srenew(atc->f,atc->nalloc);
-            for(i=nalloc_old; i<atc->nalloc; i++)
-            {
-                clear_rvec(atc->f[i]);
-            }
-        }
-        if (atc->bSpread) {
-            for(i=0;i<DIM;i++) {
-                srenew(atc->theta[i] ,atc->pme_order*atc->nalloc); 
-                srenew(atc->dtheta[i],atc->pme_order*atc->nalloc);
-            }
-            srenew(atc->fractx,atc->nalloc); 
-            srenew(atc->idx   ,atc->nalloc);
-        }
-    }
-}
-
-static void pmeredist_pd(gmx_pme_t pme, gmx_bool forw,
-                         int n, gmx_bool bXF, rvec *x_f, real *charge,
-                         pme_atomcomm_t *atc)
-/* Redistribute particle data for PME calculation */
-/* domain decomposition by x coordinate           */
-{
-    int *idxa;
-    int i, ii;
-    
-    if(FALSE == pme->redist_init) {
-        snew(pme->scounts,atc->nslab);
-        snew(pme->rcounts,atc->nslab);
-        snew(pme->sdispls,atc->nslab);
-        snew(pme->rdispls,atc->nslab);
-        snew(pme->sidx,atc->nslab);
-        pme->redist_init = TRUE;
-    }
-    if (n > pme->redist_buf_nalloc) {
-        pme->redist_buf_nalloc = over_alloc_dd(n);
-        srenew(pme->redist_buf,pme->redist_buf_nalloc*DIM);
-    }
-    
-    pme->idxa = atc->pd;
-
-#ifdef GMX_MPI
-    if (forw && bXF) {
-        /* forward, redistribution from pp to pme */ 
-        
-        /* Calculate send counts and exchange them with other nodes */
-        for(i=0; (i<atc->nslab); i++) pme->scounts[i]=0;
-        for(i=0; (i<n); i++) pme->scounts[pme->idxa[i]]++;
-        MPI_Alltoall( pme->scounts, 1, MPI_INT, pme->rcounts, 1, MPI_INT, atc->mpi_comm);
-        
-        /* Calculate send and receive displacements and index into send 
-           buffer */
-        pme->sdispls[0]=0;
-        pme->rdispls[0]=0;
-        pme->sidx[0]=0;
-        for(i=1; i<atc->nslab; i++) {
-            pme->sdispls[i]=pme->sdispls[i-1]+pme->scounts[i-1];
-            pme->rdispls[i]=pme->rdispls[i-1]+pme->rcounts[i-1];
-            pme->sidx[i]=pme->sdispls[i];
-        }
-        /* Total # of particles to be received */
-        atc->n = pme->rdispls[atc->nslab-1] + pme->rcounts[atc->nslab-1];
-        
-        pme_realloc_atomcomm_things(atc);
-        
-        /* Copy particle coordinates into send buffer and exchange*/
-        for(i=0; (i<n); i++) {
-            ii=DIM*pme->sidx[pme->idxa[i]];
-            pme->sidx[pme->idxa[i]]++;
-            pme->redist_buf[ii+XX]=x_f[i][XX];
-            pme->redist_buf[ii+YY]=x_f[i][YY];
-            pme->redist_buf[ii+ZZ]=x_f[i][ZZ];
-        }
-        MPI_Alltoallv(pme->redist_buf, pme->scounts, pme->sdispls, 
-                      pme->rvec_mpi, atc->x, pme->rcounts, pme->rdispls, 
-                      pme->rvec_mpi, atc->mpi_comm);
-    }
-    if (forw) {
-        /* Copy charge into send buffer and exchange*/
-        for(i=0; i<atc->nslab; i++) pme->sidx[i]=pme->sdispls[i];
-        for(i=0; (i<n); i++) {
-            ii=pme->sidx[pme->idxa[i]];
-            pme->sidx[pme->idxa[i]]++;
-            pme->redist_buf[ii]=charge[i];
-        }
-        MPI_Alltoallv(pme->redist_buf, pme->scounts, pme->sdispls, mpi_type,
-                      atc->q, pme->rcounts, pme->rdispls, mpi_type,
-                      atc->mpi_comm);
-    }
-    else { /* backward, redistribution from pme to pp */ 
-        MPI_Alltoallv(atc->f, pme->rcounts, pme->rdispls, pme->rvec_mpi,
-                      pme->redist_buf, pme->scounts, pme->sdispls, 
-                      pme->rvec_mpi, atc->mpi_comm);
-        
-        /* Copy data from receive buffer */
-        for(i=0; i<atc->nslab; i++)
-            pme->sidx[i] = pme->sdispls[i];
-        for(i=0; (i<n); i++) {
-            ii = DIM*pme->sidx[pme->idxa[i]];
-            x_f[i][XX] += pme->redist_buf[ii+XX];
-            x_f[i][YY] += pme->redist_buf[ii+YY];
-            x_f[i][ZZ] += pme->redist_buf[ii+ZZ];
-            pme->sidx[pme->idxa[i]]++;
-        }
-    }
-#endif 
-}
-
-static void pme_dd_sendrecv(pme_atomcomm_t *atc,
-                            gmx_bool bBackward,int shift,
-                            void *buf_s,int nbyte_s,
-                            void *buf_r,int nbyte_r)
-{
-#ifdef GMX_MPI
-    int dest,src;
-    MPI_Status stat;
-    
-    if (bBackward == FALSE) {
-        dest = atc->node_dest[shift];
-        src  = atc->node_src[shift];
-    } else {
-        dest = atc->node_src[shift];
-        src  = atc->node_dest[shift];
-    }
-    
-    if (nbyte_s > 0 && nbyte_r > 0) {
-        MPI_Sendrecv(buf_s,nbyte_s,MPI_BYTE,
-                     dest,shift,
-                     buf_r,nbyte_r,MPI_BYTE,
-                     src,shift,
-                     atc->mpi_comm,&stat);
-    } else if (nbyte_s > 0) {
-        MPI_Send(buf_s,nbyte_s,MPI_BYTE,
-                 dest,shift,
-                 atc->mpi_comm);
-    } else if (nbyte_r > 0) {
-        MPI_Recv(buf_r,nbyte_r,MPI_BYTE,
-                 src,shift,
-                 atc->mpi_comm,&stat);
-    }
-#endif
-}
-
-static void dd_pmeredist_x_q(gmx_pme_t pme, 
-                             int n, gmx_bool bX, rvec *x, real *charge,
-                             pme_atomcomm_t *atc)
-{
-    int *commnode,*buf_index;
-    int nnodes_comm,i,nsend,local_pos,buf_pos,node,scount,rcount;
-    
-    commnode  = atc->node_dest;
-    buf_index = atc->buf_index;
-    
-    nnodes_comm = min(2*atc->maxshift,atc->nslab-1);
-    
-    nsend = 0;
-    for(i=0; i<nnodes_comm; i++) {
-        buf_index[commnode[i]] = nsend;
-        nsend += atc->count[commnode[i]];
-    }
-    if (bX) {
-        if (atc->count[atc->nodeid] + nsend != n)
-            gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n"
-                      "This usually means that your system is not well equilibrated.",
-                      n - (atc->count[atc->nodeid] + nsend),
-                      pme->nodeid,'x'+atc->dimind);
-        
-        if (nsend > pme->buf_nalloc) {
-            pme->buf_nalloc = over_alloc_dd(nsend);
-            srenew(pme->bufv,pme->buf_nalloc);
-            srenew(pme->bufr,pme->buf_nalloc);
-        }
-        
-        atc->n = atc->count[atc->nodeid];
-        for(i=0; i<nnodes_comm; i++) {
-            scount = atc->count[commnode[i]];
-            /* Communicate the count */
-            if (debug)
-                fprintf(debug,"dimind %d PME node %d send to node %d: %d\n",
-                        atc->dimind,atc->nodeid,commnode[i],scount);
-            pme_dd_sendrecv(atc,FALSE,i,
-                            &scount,sizeof(int),
-                            &atc->rcount[i],sizeof(int));
-            atc->n += atc->rcount[i];
-        }
-        
-        pme_realloc_atomcomm_things(atc);
-    }
-    
-    local_pos = 0;
-    for(i=0; i<n; i++) {
-        node = atc->pd[i];
-        if (node == atc->nodeid) {
-            /* Copy direct to the receive buffer */
-            if (bX) {
-                copy_rvec(x[i],atc->x[local_pos]);
-            }
-            atc->q[local_pos] = charge[i];
-            local_pos++;
-        } else {
-            /* Copy to the send buffer */
-            if (bX) {
-                copy_rvec(x[i],pme->bufv[buf_index[node]]);
-            }
-            pme->bufr[buf_index[node]] = charge[i];
-            buf_index[node]++;
-        }
-    }
-    
-    buf_pos = 0;
-    for(i=0; i<nnodes_comm; i++) {
-        scount = atc->count[commnode[i]];
-        rcount = atc->rcount[i];
-        if (scount > 0 || rcount > 0) {
-            if (bX) {
-                /* Communicate the coordinates */
-                pme_dd_sendrecv(atc,FALSE,i,
-                                pme->bufv[buf_pos],scount*sizeof(rvec),
-                                atc->x[local_pos],rcount*sizeof(rvec));
-            }
-            /* Communicate the charges */
-            pme_dd_sendrecv(atc,FALSE,i,
-                            pme->bufr+buf_pos,scount*sizeof(real),
-                            atc->q+local_pos,rcount*sizeof(real));
-            buf_pos   += scount;
-            local_pos += atc->rcount[i];
-        }
-    }
-}
-
-static void dd_pmeredist_f(gmx_pme_t pme, pme_atomcomm_t *atc,
-                           int n, rvec *f,
-                           gmx_bool bAddF)
-{
-  int *commnode,*buf_index;
-  int nnodes_comm,local_pos,buf_pos,i,scount,rcount,node;
-
-  commnode  = atc->node_dest;
-  buf_index = atc->buf_index;
-
-  nnodes_comm = min(2*atc->maxshift,atc->nslab-1);
-
-  local_pos = atc->count[atc->nodeid];
-  buf_pos = 0;
-  for(i=0; i<nnodes_comm; i++) {
-    scount = atc->rcount[i];
-    rcount = atc->count[commnode[i]];
-    if (scount > 0 || rcount > 0) {
-      /* Communicate the forces */
-      pme_dd_sendrecv(atc,TRUE,i,
-                      atc->f[local_pos],scount*sizeof(rvec),
-                      pme->bufv[buf_pos],rcount*sizeof(rvec));
-      local_pos += scount;
-    }
-    buf_index[commnode[i]] = buf_pos;
-    buf_pos   += rcount;
-  }
-
-    local_pos = 0;
-    if (bAddF)
-    {
-        for(i=0; i<n; i++)
-        {
-            node = atc->pd[i];
-            if (node == atc->nodeid)
-            {
-                /* Add from the local force array */
-                rvec_inc(f[i],atc->f[local_pos]);
-                local_pos++;
-            }
-            else
-            {
-                /* Add from the receive buffer */
-                rvec_inc(f[i],pme->bufv[buf_index[node]]);
-                buf_index[node]++;
-            }
-        }
-    }
-    else
-    {
-        for(i=0; i<n; i++)
-        {
-            node = atc->pd[i];
-            if (node == atc->nodeid)
-            {
-                /* Copy from the local force array */
-                copy_rvec(atc->f[local_pos],f[i]);
-                local_pos++;
-            }
-            else
-            {
-                /* Copy from the receive buffer */
-                copy_rvec(pme->bufv[buf_index[node]],f[i]);
-                buf_index[node]++;
-            }
-        }
-    }
-}
-
-#ifdef GMX_MPI
-static void 
-gmx_sum_qgrid_dd(gmx_pme_t pme, real *grid, int direction)
-{
-    pme_overlap_t *overlap;
-    int send_index0,send_nindex;
-    int recv_index0,recv_nindex;
-    MPI_Status stat;
-    int i,j,k,ix,iy,iz,icnt;
-    int ipulse,send_id,recv_id,datasize;
-    real *p;
-    real *sendptr,*recvptr;
-    
-    /* Start with minor-rank communication. This is a bit of a pain since it is not contiguous */
-    overlap = &pme->overlap[1];
-    
-    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
-    {
-        /* Since we have already (un)wrapped the overlap in the z-dimension,
-         * we only have to communicate 0 to nkz (not pmegrid_nz).
-         */
-        if (direction==GMX_SUM_QGRID_FORWARD)
-        {
-            send_id = overlap->send_id[ipulse];
-            recv_id = overlap->recv_id[ipulse];
-            send_index0   = overlap->comm_data[ipulse].send_index0;
-            send_nindex   = overlap->comm_data[ipulse].send_nindex;
-            recv_index0   = overlap->comm_data[ipulse].recv_index0;
-            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
-        }
-        else
-        {
-            send_id = overlap->recv_id[ipulse];
-            recv_id = overlap->send_id[ipulse];
-            send_index0   = overlap->comm_data[ipulse].recv_index0;
-            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
-            recv_index0   = overlap->comm_data[ipulse].send_index0;
-            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
-        }
-
-        /* Copy data to contiguous send buffer */
-        if (debug)
-        {
-            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
-                    pme->nodeid,overlap->nodeid,send_id,
-                    pme->pmegrid_start_iy,
-                    send_index0-pme->pmegrid_start_iy,
-                    send_index0-pme->pmegrid_start_iy+send_nindex);
-        }
-        icnt = 0;
-        for(i=0;i<pme->pmegrid_nx;i++)
-        {
-            ix = i;
-            for(j=0;j<send_nindex;j++)
-            {
-                iy = j + send_index0 - pme->pmegrid_start_iy;
-                for(k=0;k<pme->nkz;k++)
-                {
-                    iz = k;
-                    pme->pmegrid_sendbuf[icnt++] = grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz];
-                }
-            }
-        }
-            
-        datasize      = pme->pmegrid_nx * pme->nkz;
-        
-        MPI_Sendrecv(pme->pmegrid_sendbuf,send_nindex*datasize,GMX_MPI_REAL,
-                     send_id,ipulse,
-                     pme->pmegrid_recvbuf,recv_nindex*datasize,GMX_MPI_REAL,
-                     recv_id,ipulse,
-                     overlap->mpi_comm,&stat);
-        
-        /* Get data from contiguous recv buffer */
-        if (debug)
-        {
-            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
-                    pme->nodeid,overlap->nodeid,recv_id,
-                    pme->pmegrid_start_iy,
-                    recv_index0-pme->pmegrid_start_iy,
-                    recv_index0-pme->pmegrid_start_iy+recv_nindex);
-        }
-        icnt = 0;
-        for(i=0;i<pme->pmegrid_nx;i++)
-        {
-            ix = i;
-            for(j=0;j<recv_nindex;j++)
-            {
-                iy = j + recv_index0 - pme->pmegrid_start_iy;
-                for(k=0;k<pme->nkz;k++)
-                {
-                    iz = k;
-                    if(direction==GMX_SUM_QGRID_FORWARD)
-                    {
-                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz] += pme->pmegrid_recvbuf[icnt++];
-                    }
-                    else
-                    {
-                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz]  = pme->pmegrid_recvbuf[icnt++];
-                    }
-                }
-            }
-        }
-    }
-    
-    /* Major dimension is easier, no copying required,
-     * but we might have to sum to separate array.
-     * Since we don't copy, we have to communicate up to pmegrid_nz,
-     * not nkz as for the minor direction.
-     */
-    overlap = &pme->overlap[0];
-    
-    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
-    {
-        if(direction==GMX_SUM_QGRID_FORWARD)
-        {
-            send_id = overlap->send_id[ipulse];
-            recv_id = overlap->recv_id[ipulse];
-            send_index0   = overlap->comm_data[ipulse].send_index0;
-            send_nindex   = overlap->comm_data[ipulse].send_nindex;
-            recv_index0   = overlap->comm_data[ipulse].recv_index0;
-            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
-            recvptr   = pme->pmegrid_recvbuf;
-        }
-        else
-        {
-            send_id = overlap->recv_id[ipulse];
-            recv_id = overlap->send_id[ipulse];
-            send_index0   = overlap->comm_data[ipulse].recv_index0;
-            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
-            recv_index0   = overlap->comm_data[ipulse].send_index0;
-            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
-            recvptr   = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
-        }
-                
-        sendptr       = grid + (send_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
-        datasize      = pme->pmegrid_ny * pme->pmegrid_nz;
-
-        if (debug)
-        {
-            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
-                    pme->nodeid,overlap->nodeid,send_id,
-                    pme->pmegrid_start_ix,
-                    send_index0-pme->pmegrid_start_ix,
-                    send_index0-pme->pmegrid_start_ix+send_nindex);
-            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
-                    pme->nodeid,overlap->nodeid,recv_id,
-                    pme->pmegrid_start_ix,
-                    recv_index0-pme->pmegrid_start_ix,
-                    recv_index0-pme->pmegrid_start_ix+recv_nindex);
-        }
-
-        MPI_Sendrecv(sendptr,send_nindex*datasize,GMX_MPI_REAL,
-                     send_id,ipulse,
-                     recvptr,recv_nindex*datasize,GMX_MPI_REAL,
-                     recv_id,ipulse,
-                     overlap->mpi_comm,&stat);
-        
-        /* ADD data from contiguous recv buffer */
-        if(direction==GMX_SUM_QGRID_FORWARD)
-        {        
-            p = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
-            for(i=0;i<recv_nindex*datasize;i++)
-            {
-                p[i] += pme->pmegrid_recvbuf[i];
-            }
-        }
-    }
-}
-#endif
-
-
-static int
-copy_pmegrid_to_fftgrid(gmx_pme_t pme, real *pmegrid, real *fftgrid)
-{
-    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
-    ivec    local_pme_size;
-    int     i,ix,iy,iz;
-    int     pmeidx,fftidx;
-
-    /* Dimensions should be identical for A/B grid, so we just use A here */
-    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
-                                   local_fft_ndata,
-                                   local_fft_offset,
-                                   local_fft_size);
-    
-    local_pme_size[0] = pme->pmegrid_nx;
-    local_pme_size[1] = pme->pmegrid_ny;
-    local_pme_size[2] = pme->pmegrid_nz;
-    
-    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
-     the offset is identical, and the PME grid always has more data (due to overlap)
-     */
-    {
-#ifdef DEBUG_PME
-        FILE *fp,*fp2;
-        char fn[STRLEN],format[STRLEN];
-        real val;
-        sprintf(fn,"pmegrid%d.pdb",pme->nodeid);
-        fp = ffopen(fn,"w");
-        sprintf(fn,"pmegrid%d.txt",pme->nodeid);
-        fp2 = ffopen(fn,"w");
-     sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
-#endif
-    for(ix=0;ix<local_fft_ndata[XX];ix++)
-    {
-        for(iy=0;iy<local_fft_ndata[YY];iy++)
-        {
-            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
-            {
-                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
-                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
-                fftgrid[fftidx] = pmegrid[pmeidx];
-#ifdef DEBUG_PME
-                val = 100*pmegrid[pmeidx];
-                if (pmegrid[pmeidx] != 0)
-                fprintf(fp,format,"ATOM",pmeidx,"CA","GLY",' ',pmeidx,' ',
-                        5.0*ix,5.0*iy,5.0*iz,1.0,val);
-                if (pmegrid[pmeidx] != 0)
-                    fprintf(fp2,"%-12s  %5d  %5d  %5d  %12.5e\n",
-                            "qgrid",
-                            pme->pmegrid_start_ix + ix,
-                            pme->pmegrid_start_iy + iy,
-                            pme->pmegrid_start_iz + iz,
-                            pmegrid[pmeidx]);
-#endif
-            }
-        }
-    }
-#ifdef DEBUG_PME
-    fclose(fp);
-    fclose(fp2);
-#endif
-    }
-    return 0;
-}
-
-
-static int
-copy_fftgrid_to_pmegrid(gmx_pme_t pme, real *fftgrid, real *pmegrid)
-{
-    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
-    ivec    local_pme_size;
-    int     i,ix,iy,iz;
-    int     pmeidx,fftidx;
-    
-    /* Dimensions should be identical for A/B grid, so we just use A here */
-    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
-                                   local_fft_ndata,
-                                   local_fft_offset,
-                                   local_fft_size);
-
-    local_pme_size[0] = pme->pmegrid_nx;
-    local_pme_size[1] = pme->pmegrid_ny;
-    local_pme_size[2] = pme->pmegrid_nz;
-    
-    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
-     the offset is identical, and the PME grid always has more data (due to overlap)
-     */
-    for(ix=0;ix<local_fft_ndata[XX];ix++)
-    {
-        for(iy=0;iy<local_fft_ndata[YY];iy++)
-        {
-            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
-            {
-                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
-                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
-                pmegrid[pmeidx] = fftgrid[fftidx];
-            }
-        }
-    }   
-    return 0;
-}
-
-
-static void
-wrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
-{
-    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
-
-    nx = pme->nkx;
-    ny = pme->nky;
-    nz = pme->nkz;
-
-    pnx = pme->pmegrid_nx;
-    pny = pme->pmegrid_ny;
-    pnz = pme->pmegrid_nz;
-
-    overlap = pme->pme_order - 1;
-
-    /* Add periodic overlap in z */
-    for(ix=0; ix<pnx; ix++)
-    {
-        for(iy=0; iy<pny; iy++)
-        {
-            for(iz=0; iz<overlap; iz++)
-            {
-                pmegrid[(ix*pny+iy)*pnz+iz] +=
-                    pmegrid[(ix*pny+iy)*pnz+nz+iz];
-            }
-        }
-    }
-
-    if (pme->nnodes_minor == 1)
-    {
-       for(ix=0; ix<pnx; ix++)
-       {
-           for(iy=0; iy<overlap; iy++)
-           {
-               for(iz=0; iz<nz; iz++)
-               {
-                   pmegrid[(ix*pny+iy)*pnz+iz] +=
-                       pmegrid[(ix*pny+ny+iy)*pnz+iz];
-               }
-           }
-       }
-    }
-     
-    if (pme->nnodes_major == 1)
-    {
-        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
-
-        for(ix=0; ix<overlap; ix++)
-        {
-            for(iy=0; iy<ny_x; iy++)
-            {
-                for(iz=0; iz<nz; iz++)
-                {
-                    pmegrid[(ix*pny+iy)*pnz+iz] +=
-                        pmegrid[((nx+ix)*pny+iy)*pnz+iz];
-                }
-            }
-        }
-    }
-}
-
-
-static void
-unwrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
-{
-    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
-
-    nx = pme->nkx;
-    ny = pme->nky;
-    nz = pme->nkz;
-
-    pnx = pme->pmegrid_nx;
-    pny = pme->pmegrid_ny;
-    pnz = pme->pmegrid_nz;
-
-    overlap = pme->pme_order - 1;
-
-    if (pme->nnodes_major == 1)
-    {
-        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
-
-        for(ix=0; ix<overlap; ix++)
-        {
-            for(iy=0; iy<ny_x; iy++)
-            {
-                for(iz=0; iz<nz; iz++)
-                {
-                    pmegrid[((nx+ix)*pny+iy)*pnz+iz] =
-                        pmegrid[(ix*pny+iy)*pnz+iz];
-                }
-            }
-        }
-    }
-
-    if (pme->nnodes_minor == 1)
-    {
-       for(ix=0; ix<pnx; ix++)
-       {
-           for(iy=0; iy<overlap; iy++)
-           {
-               for(iz=0; iz<nz; iz++)
-               {
-                   pmegrid[(ix*pny+ny+iy)*pnz+iz] =
-                       pmegrid[(ix*pny+iy)*pnz+iz];
-               }
-           }
-       }
-    }
-
-    /* Copy periodic overlap in z */
-    for(ix=0; ix<pnx; ix++)
-    {
-        for(iy=0; iy<pny; iy++)
-        {
-            for(iz=0; iz<overlap; iz++)
-            {
-                pmegrid[(ix*pny+iy)*pnz+nz+iz] =
-                    pmegrid[(ix*pny+iy)*pnz+iz];
-            }
-        }
-    }
-}
-
-
-/* This has to be a macro to enable full compiler optimization with xlC (and probably others too) */
-#define DO_BSPLINE(order)                            \
-for(ithx=0; (ithx<order); ithx++)                    \
-{                                                    \
-    index_x = (i0+ithx)*pny*pnz;                     \
-    valx    = qn*thx[ithx];                          \
-                                                     \
-    for(ithy=0; (ithy<order); ithy++)                \
-    {                                                \
-        valxy    = valx*thy[ithy];                   \
-        index_xy = index_x+(j0+ithy)*pnz;            \
-                                                     \
-        for(ithz=0; (ithz<order); ithz++)            \
-        {                                            \
-            index_xyz        = index_xy+(k0+ithz);   \
-            grid[index_xyz] += valxy*thz[ithz];      \
-        }                                            \
-    }                                                \
-}
-
-
-static void spread_q_bsplines(gmx_pme_t pme, pme_atomcomm_t *atc, 
-                              real *grid)
-{
-
-    /* spread charges from home atoms to local grid */
-    pme_overlap_t *ol;
-    int      b,i,nn,n,ithx,ithy,ithz,i0,j0,k0;
-    int *    idxptr;
-    int      order,norder,index_x,index_xy,index_xyz;
-    real     valx,valxy,qn;
-    real     *thx,*thy,*thz;
-    int      localsize, bndsize;
-  
-    int      pnx,pny,pnz,ndatatot;
-  
-    pnx = pme->pmegrid_nx;
-    pny = pme->pmegrid_ny;
-    pnz = pme->pmegrid_nz;
-    ndatatot = pnx*pny*pnz;
-    
-    for(i=0;i<ndatatot;i++)
-    {
-        grid[i] = 0;
-    }
-
-    order = pme->pme_order;
-
-    for(nn=0; (nn<atc->n);nn++) 
-    {
-        n      = nn;
-        qn     = atc->q[n];
-
-        if (qn != 0) 
-        {
-            idxptr = atc->idx[n];
-            norder = n*order;
-            
-            i0   = idxptr[XX]; 
-            j0   = idxptr[YY];
-            k0   = idxptr[ZZ];
-            thx = atc->theta[XX] + norder;
-            thy = atc->theta[YY] + norder;
-            thz = atc->theta[ZZ] + norder;
-            
-            switch (order) {
-            case 4:  DO_BSPLINE(4);     break;
-            case 5:  DO_BSPLINE(5);     break;
-            default: DO_BSPLINE(order); break;
-            }
-        }
-    }  
-}
-
-
-#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
-    /* Calculate exponentials through SSE in float precision */
-#define CALC_EXPONENTIALS(start,end,r_aligned)      \
-    {                                               \
-        __m128 tmp_sse;                             \
-        for(kx=0; kx<end; kx+=4)                    \
-        {                                           \
-            tmp_sse = _mm_load_ps(r_aligned+kx);    \
-            tmp_sse = gmx_mm_exp_ps(tmp_sse);       \
-            _mm_store_ps(r_aligned+kx,tmp_sse);     \
-        }                                           \
-    }
-#else
-#define CALC_EXPONENTIALS(start,end,r)          \
-    for(kx=start; kx<end; kx++)                 \
-    {                                           \
-        r[kx] = exp(r[kx]);                     \
-    }
-#endif
-
-
-static int solve_pme_yzx(gmx_pme_t pme,t_complex *grid,
-                         real ewaldcoeff,real vol,
-                         gmx_bool bEnerVir,real *mesh_energy,matrix vir)
-{
-    /* do recip sum over local cells in grid */
-    /* y major, z middle, x minor or continuous */
-    t_complex *p0;
-    int     kx,ky,kz,maxkx,maxky,maxkz;
-    int     nx,ny,nz,iy,iz,kxstart,kxend;
-    real    mx,my,mz;
-    real    factor=M_PI*M_PI/(ewaldcoeff*ewaldcoeff);
-    real    ets2,struct2,vfactor,ets2vf;
-    real    eterm,d1,d2,energy=0;
-    real    by,bz;
-    real    virxx=0,virxy=0,virxz=0,viryy=0,viryz=0,virzz=0;
-    real    rxx,ryx,ryy,rzx,rzy,rzz;
-       real    *mhx,*mhy,*mhz,*m2,*denom,*tmp1,*m2inv;
-    real    mhxk,mhyk,mhzk,m2k;
-    real    corner_fac;
-    ivec    complex_order;
-    ivec    local_ndata,local_offset,local_size;
-    
-    nx = pme->nkx;
-    ny = pme->nky;
-    nz = pme->nkz;
-    
-    /* Dimensions should be identical for A/B grid, so we just use A here */
-    gmx_parallel_3dfft_complex_limits(pme->pfft_setupA,
-                                      complex_order,
-                                      local_ndata,
-                                      local_offset,
-                                      local_size);
-    
-    rxx = pme->recipbox[XX][XX];
-    ryx = pme->recipbox[YY][XX];
-    ryy = pme->recipbox[YY][YY];
-    rzx = pme->recipbox[ZZ][XX];
-    rzy = pme->recipbox[ZZ][YY];
-    rzz = pme->recipbox[ZZ][ZZ];
-    
-    maxkx = (nx+1)/2;
-    maxky = (ny+1)/2;
-    maxkz = nz/2+1;
-       
-       mhx   = pme->work_mhx;
-       mhy   = pme->work_mhy;
-       mhz   = pme->work_mhz;
-       m2    = pme->work_m2;
-       denom = pme->work_denom;
-       tmp1  = pme->work_tmp1;
-       m2inv = pme->work_m2inv;        
-
-    for(iy=0;iy<local_ndata[YY];iy++)
-    {
-        ky = iy + local_offset[YY];
-        
-        if (ky < maxky) 
-        {
-            my = ky;
-        }
-        else 
-        {
-            my = (ky - ny);
-        }
-        
-        by = M_PI*vol*pme->bsp_mod[YY][ky];
-
-        for(iz=0;iz<local_ndata[ZZ];iz++)
-        {
-            kz = iz + local_offset[ZZ];
-            
-            mz = kz;
-
-            bz = pme->bsp_mod[ZZ][kz];
-            
-            /* 0.5 correction for corner points */
-                       corner_fac = 1;
-            if (kz == 0)
-                corner_fac = 0.5;
-            if (kz == (nz+1)/2)
-                corner_fac = 0.5;
-                      
-            p0 = grid + iy*local_size[ZZ]*local_size[XX] + iz*local_size[XX];
-            
-            /* We should skip the k-space point (0,0,0) */
-            if (local_offset[XX] > 0 ||
-                local_offset[YY] > 0 || ky > 0 ||
-                kz > 0)
-            {
-                kxstart = local_offset[XX];
-            }
-            else
-            {
-                kxstart = local_offset[XX] + 1;
-                p0++;
-            }
-            kxend = local_offset[XX] + local_ndata[XX];
-                       
-            if (bEnerVir)
-            {
-                /* More expensive inner loop, especially because of the storage
-                 * of the mh elements in array's.
-                 * Because x is the minor grid index, all mh elements
-                 * depend on kx for triclinic unit cells.
-                 */
-
-                /* Two explicit loops to avoid a conditional inside the loop */
-                for(kx=kxstart; kx<maxkx; kx++)
-                {
-                    mx = kx;
-                    
-                    mhxk      = mx * rxx;
-                    mhyk      = mx * ryx + my * ryy;
-                    mhzk      = mx * rzx + my * rzy + mz * rzz;
-                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
-                    mhx[kx]   = mhxk;
-                    mhy[kx]   = mhyk;
-                    mhz[kx]   = mhzk;
-                    m2[kx]    = m2k;
-                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
-                    tmp1[kx]  = -factor*m2k;
-                }
-                
-                for(kx=maxkx; kx<kxend; kx++)
-                {
-                    mx = (kx - nx);
-
-                    mhxk      = mx * rxx;
-                    mhyk      = mx * ryx + my * ryy;
-                    mhzk      = mx * rzx + my * rzy + mz * rzz;
-                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
-                    mhx[kx]   = mhxk;
-                    mhy[kx]   = mhyk;
-                    mhz[kx]   = mhzk;
-                    m2[kx]    = m2k;
-                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
-                    tmp1[kx]  = -factor*m2k;
-                }
-                
-                for(kx=kxstart; kx<kxend; kx++)
-                {
-                    m2inv[kx] = 1.0/m2[kx];
-                }
-                for(kx=kxstart; kx<kxend; kx++)
-                {
-                    denom[kx] = 1.0/denom[kx];
-                }
-
-                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
-
-                for(kx=kxstart; kx<kxend; kx++,p0++)
-                {
-                    d1      = p0->re;
-                    d2      = p0->im;
-                    
-                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
-                    
-                    p0->re  = d1*eterm;
-                    p0->im  = d2*eterm;
-                    
-                    struct2 = 2.0*(d1*d1+d2*d2);
-                    
-                    tmp1[kx] = eterm*struct2;
-                }
-                
-                for(kx=kxstart; kx<kxend; kx++)
-                {
-                    ets2     = corner_fac*tmp1[kx];
-                    vfactor  = (factor*m2[kx] + 1.0)*2.0*m2inv[kx];
-                    energy  += ets2;
-                    
-                    ets2vf   = ets2*vfactor;
-                    virxx   += ets2vf*mhx[kx]*mhx[kx] - ets2;
-                    virxy   += ets2vf*mhx[kx]*mhy[kx];
-                    virxz   += ets2vf*mhx[kx]*mhz[kx];
-                    viryy   += ets2vf*mhy[kx]*mhy[kx] - ets2;
-                    viryz   += ets2vf*mhy[kx]*mhz[kx];
-                    virzz   += ets2vf*mhz[kx]*mhz[kx] - ets2;
-                }
-            }
-            else
-            {
-                /* We don't need to calculate the energy and the virial.
-                 * In this case the triclinic overhead is small.
-                 */
-
-                /* Two explicit loops to avoid a conditional inside the loop */
-
-                for(kx=kxstart; kx<maxkx; kx++)
-                {
-                    mx = kx;
-                    
-                    mhxk      = mx * rxx;
-                    mhyk      = mx * ryx + my * ryy;
-                    mhzk      = mx * rzx + my * rzy + mz * rzz;
-                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
-                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
-                    tmp1[kx]  = -factor*m2k;
-                }
-                
-                for(kx=maxkx; kx<kxend; kx++)
-                {
-                    mx = (kx - nx);
-                    
-                    mhxk      = mx * rxx;
-                    mhyk      = mx * ryx + my * ryy;
-                    mhzk      = mx * rzx + my * rzy + mz * rzz;
-                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
-                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
-                    tmp1[kx]  = -factor*m2k;
-                }
-                
-                for(kx=kxstart; kx<kxend; kx++)
-                {
-                    denom[kx] = 1.0/denom[kx];
-                }
-
-                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
-               
-                for(kx=kxstart; kx<kxend; kx++,p0++)
-                {
-                    d1      = p0->re;
-                    d2      = p0->im;
-                    
-                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
-                    
-                    p0->re  = d1*eterm;
-                    p0->im  = d2*eterm;
-                }
-            }
-        }
-    }
-    
-    if (bEnerVir)
-    {
-        /* Update virial with local values.
-         * The virial is symmetric by definition.
-         * this virial seems ok for isotropic scaling, but I'm
-         * experiencing problems on semiisotropic membranes.
-         * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
-         */
-        vir[XX][XX] = 0.25*virxx;
-        vir[YY][YY] = 0.25*viryy;
-        vir[ZZ][ZZ] = 0.25*virzz;
-        vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
-        vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
-        vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
-        
-        /* This energy should be corrected for a charged system */
-        *mesh_energy = 0.5*energy;
-    }
-
-    /* Return the loop count */
-    return local_ndata[YY]*local_ndata[ZZ]*local_ndata[XX];
-}
-
-
-#define DO_FSPLINE(order)                      \
-for(ithx=0; (ithx<order); ithx++)              \
-{                                                                         \
-    index_x = (i0+ithx)*pny*pnz;               \
-    tx      = thx[ithx];                       \
-    dx      = dthx[ithx];                      \
-                                               \
-    for(ithy=0; (ithy<order); ithy++)          \
-    {                                                                             \
-        index_xy = index_x+(j0+ithy)*pnz;      \
-        ty       = thy[ithy];                  \
-        dy       = dthy[ithy];                 \
-        fxy1     = fz1 = 0;                    \
-                                               \
-        for(ithz=0; (ithz<order); ithz++)      \
-        {                                                                 \
-            gval  = grid[index_xy+(k0+ithz)];  \
-            fxy1 += thz[ithz]*gval;            \
-            fz1  += dthz[ithz]*gval;           \
-        }                                      \
-        fx += dx*ty*fxy1;                      \
-        fy += tx*dy*fxy1;                      \
-        fz += tx*ty*fz1;                       \
-    }                                          \
-}
-
-
-void gather_f_bsplines(gmx_pme_t pme,real *grid,
-                       gmx_bool bClearF,pme_atomcomm_t *atc,real scale)
-{
-    /* sum forces for local particles */  
-    int     nn,n,ithx,ithy,ithz,i0,j0,k0;
-    int     index_x,index_xy;
-    int     nx,ny,nz,pnx,pny,pnz;
-    int *   idxptr;
-    real    tx,ty,dx,dy,qn;
-    real    fx,fy,fz,gval;
-    real    fxy1,fz1;
-    real    *thx,*thy,*thz,*dthx,*dthy,*dthz;
-    int     norder;
-    real    rxx,ryx,ryy,rzx,rzy,rzz;
-    int     order;
-    
-    order = pme->pme_order;
-    thx   = atc->theta[XX];
-    thy   = atc->theta[YY];
-    thz   = atc->theta[ZZ];
-    dthx  = atc->dtheta[XX];
-    dthy  = atc->dtheta[YY];
-    dthz  = atc->dtheta[ZZ];
-    nx    = pme->nkx;
-    ny    = pme->nky;
-    nz    = pme->nkz;
-    pnx   = pme->pmegrid_nx;
-    pny   = pme->pmegrid_ny;
-    pnz   = pme->pmegrid_nz;
-    
-    rxx   = pme->recipbox[XX][XX];
-    ryx   = pme->recipbox[YY][XX];
-    ryy   = pme->recipbox[YY][YY];
-    rzx   = pme->recipbox[ZZ][XX];
-    rzy   = pme->recipbox[ZZ][YY];
-    rzz   = pme->recipbox[ZZ][ZZ];
-
-    for(nn=0; (nn<atc->n); nn++) 
-    {
-        n = nn;
-        qn      = scale*atc->q[n];
-        
-        if (bClearF) 
-        {
-            atc->f[n][XX] = 0;
-            atc->f[n][YY] = 0;
-            atc->f[n][ZZ] = 0;
-        }
-        if (qn != 0) 
-        {
-            fx     = 0;
-            fy     = 0;
-            fz     = 0;
-            idxptr = atc->idx[n];
-            norder = n*order;
-            
-            i0   = idxptr[XX]; 
-            j0   = idxptr[YY];
-            k0   = idxptr[ZZ];
-            
-            /* Pointer arithmetic alert, next six statements */
-            thx  = atc->theta[XX] + norder;
-            thy  = atc->theta[YY] + norder;
-            thz  = atc->theta[ZZ] + norder;
-            dthx = atc->dtheta[XX] + norder;
-            dthy = atc->dtheta[YY] + norder;
-            dthz = atc->dtheta[ZZ] + norder;
-            
-            switch (order) {
-            case 4:  DO_FSPLINE(4);     break;
-            case 5:  DO_FSPLINE(5);     break;
-            default: DO_FSPLINE(order); break;
-            }
-
-            atc->f[n][XX] += -qn*( fx*nx*rxx );
-            atc->f[n][YY] += -qn*( fx*nx*ryx + fy*ny*ryy );
-            atc->f[n][ZZ] += -qn*( fx*nx*rzx + fy*ny*rzy + fz*nz*rzz );
-        }
-    }
-    /* Since the energy and not forces are interpolated
-     * the net force might not be exactly zero.
-     * This can be solved by also interpolating F, but
-     * that comes at a cost.
-     * A better hack is to remove the net force every
-     * step, but that must be done at a higher level
-     * since this routine doesn't see all atoms if running
-     * in parallel. Don't know how important it is?  EL 990726
-     */
-}
-
-static real gather_energy_bsplines(gmx_pme_t pme,real *grid,
-                                   pme_atomcomm_t *atc)
-{
-    int     n,ithx,ithy,ithz,i0,j0,k0;
-    int     index_x,index_xy;
-    int *   idxptr;
-    real    energy,pot,tx,ty,qn,gval;
-    real    *thx,*thy,*thz;
-    int     norder;
-    int     order;
-    
-    
-    order = pme->pme_order;
-    
-    energy = 0;
-    for(n=0; (n<atc->n); n++) {
-        qn      = atc->q[n];
-        
-        if (qn != 0) {
-            idxptr = atc->idx[n];
-            norder = n*order;
-            
-            i0   = idxptr[XX]; 
-            j0   = idxptr[YY];
-            k0   = idxptr[ZZ];
-            
-            /* Pointer arithmetic alert, next three statements */
-            thx  = atc->theta[XX] + norder;
-            thy  = atc->theta[YY] + norder;
-            thz  = atc->theta[ZZ] + norder;
-
-            pot = 0;
-            for(ithx=0; (ithx<order); ithx++)
-            {
-                index_x = (i0+ithx)*pme->pmegrid_ny*pme->pmegrid_nz;
-                tx      = thx[ithx];
-
-                for(ithy=0; (ithy<order); ithy++)
-                {
-                    index_xy = index_x+(j0+ithy)*pme->pmegrid_nz;
-                    ty       = thy[ithy];
-
-                    for(ithz=0; (ithz<order); ithz++)
-                    {
-                        gval  = grid[index_xy+(k0+ithz)];
-                        pot  += tx*ty*thz[ithz]*gval;
-                    }
-
-                }
-            }
-
-            energy += pot*qn;
-        }
-    }
-
-    return energy;
-}
-
-void make_bsplines(splinevec theta,splinevec dtheta,int order,
-                   rvec fractx[],int nr,real charge[],
-                   gmx_bool bFreeEnergy)
-{
-    /* construct splines for local atoms */
-    int  i,j,k,l;
-    real dr,div;
-    real *data,*ddata,*xptr;
-    
-    for(i=0; (i<nr); i++) {
-        /* With free energy we do not use the charge check.
-         * In most cases this will be more efficient than calling make_bsplines
-         * twice, since usually more than half the particles have charges.
-         */
-        if (bFreeEnergy || charge[i] != 0.0) {
-            xptr = fractx[i];
-            for(j=0; (j<DIM); j++) {
-                dr  = xptr[j];
-                
-                /* dr is relative offset from lower cell limit */
-                data=&(theta[j][i*order]);
-                data[order-1]=0;
-                data[1]=dr;
-                data[0]=1-dr;
-                
-                for(k=3; (k<order); k++) {
-                    div=1.0/(k-1.0);    
-                    data[k-1]=div*dr*data[k-2];
-                    for(l=1; (l<(k-1)); l++) {
-                        data[k-l-1]=div*((dr+l)*data[k-l-2]+(k-l-dr)*
-                                         data[k-l-1]);
-                    }
-                    data[0]=div*(1-dr)*data[0];
-                }
-                /* differentiate */
-                ddata    = &(dtheta[j][i*order]);
-                ddata[0] = -data[0];
-                for(k=1; (k<order); k++) {
-                    ddata[k]=data[k-1]-data[k];
-                }
-                
-                div=1.0/(order-1);
-                data[order-1]=div*dr*data[order-2];
-                for(l=1; (l<(order-1)); l++) {
-                    data[order-l-1]=div*((dr+l)*data[order-l-2]+
-                                         (order-l-dr)*data[order-l-1]);
-                }
-                data[0]=div*(1-dr)*data[0]; 
-            }
-        }
-    }
-}
-
-
-void make_dft_mod(real *mod,real *data,int ndata)
-{
-  int i,j;
-  real sc,ss,arg;
-    
-  for(i=0;i<ndata;i++) {
-    sc=ss=0;
-    for(j=0;j<ndata;j++) {
-      arg=(2.0*M_PI*i*j)/ndata;
-      sc+=data[j]*cos(arg);
-      ss+=data[j]*sin(arg);
-    }
-    mod[i]=sc*sc+ss*ss;
-  }
-  for(i=0;i<ndata;i++)
-    if(mod[i]<1e-7)
-      mod[i]=(mod[i-1]+mod[i+1])*0.5;
-}
-
-
-
-void make_bspline_moduli(splinevec bsp_mod,int nx,int ny,int nz,int order)
-{
-  int nmax=max(nx,max(ny,nz));
-  real *data,*ddata,*bsp_data;
-  int i,k,l;
-  real div;
-    
-  snew(data,order);
-  snew(ddata,order);
-  snew(bsp_data,nmax);
-
-  data[order-1]=0;
-  data[1]=0;
-  data[0]=1;
-           
-  for(k=3;k<order;k++) {
-    div=1.0/(k-1.0);
-    data[k-1]=0;
-    for(l=1;l<(k-1);l++)
-      data[k-l-1]=div*(l*data[k-l-2]+(k-l)*data[k-l-1]);
-    data[0]=div*data[0];
-  }
-  /* differentiate */
-  ddata[0]=-data[0];
-  for(k=1;k<order;k++)
-    ddata[k]=data[k-1]-data[k];
-  div=1.0/(order-1);
-  data[order-1]=0;
-  for(l=1;l<(order-1);l++)
-    data[order-l-1]=div*(l*data[order-l-2]+(order-l)*data[order-l-1]);
-  data[0]=div*data[0]; 
-
-  for(i=0;i<nmax;i++)
-    bsp_data[i]=0;
-  for(i=1;i<=order;i++)
-    bsp_data[i]=data[i-1];
-    
-  make_dft_mod(bsp_mod[XX],bsp_data,nx);
-  make_dft_mod(bsp_mod[YY],bsp_data,ny);
-  make_dft_mod(bsp_mod[ZZ],bsp_data,nz);
-
-  sfree(data);
-  sfree(ddata);
-  sfree(bsp_data);
-}
-
-static void setup_coordinate_communication(pme_atomcomm_t *atc)
-{
-  int nslab,n,i;
-  int fw,bw;
-
-  nslab = atc->nslab;
-
-  n = 0;
-  for(i=1; i<=nslab/2; i++) {
-    fw = (atc->nodeid + i) % nslab;
-    bw = (atc->nodeid - i + nslab) % nslab;
-    if (n < nslab - 1) {
-      atc->node_dest[n] = fw;
-      atc->node_src[n]  = bw;
-      n++;
-    } 
-    if (n < nslab - 1) {
-      atc->node_dest[n] = bw;
-      atc->node_src[n]  = fw;
-      n++;
-    }
-  }
-}
-
-int gmx_pme_destroy(FILE *log,gmx_pme_t *pmedata)
-{
-    if(NULL != log)
-    {
-        fprintf(log,"Destroying PME data structures.\n");
-    }
-
-    sfree((*pmedata)->nnx);
-    sfree((*pmedata)->nny);
-    sfree((*pmedata)->nnz);
-       
-    sfree((*pmedata)->pmegridA);
-    sfree((*pmedata)->fftgridA);
-    sfree((*pmedata)->cfftgridA);
-    gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupA);
-    
-    if((*pmedata)->pmegridB)
-    {
-        sfree((*pmedata)->pmegridB);
-        sfree((*pmedata)->fftgridB);
-        sfree((*pmedata)->cfftgridB);
-        gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupB);
-    }
-    sfree((*pmedata)->work_mhz);
-    sfree((*pmedata)->work_m2);
-    sfree((*pmedata)->work_denom);
-    sfree((*pmedata)->work_tmp1_alloc);
-    sfree((*pmedata)->work_m2inv);
-       
-    sfree(*pmedata);
-    *pmedata = NULL;
-  
-  return 0;
-}
-
-static int mult_up(int n,int f)
-{
-    return ((n + f - 1)/f)*f;
-}
-
-
-static double pme_load_imbalance(gmx_pme_t pme)
-{
-    int    nma,nmi;
-    double n1,n2,n3;
-
-    nma = pme->nnodes_major;
-    nmi = pme->nnodes_minor;
-
-    n1 = mult_up(pme->nkx,nma)*mult_up(pme->nky,nmi)*pme->nkz;
-    n2 = mult_up(pme->nkx,nma)*mult_up(pme->nkz,nmi)*pme->nky;
-    n3 = mult_up(pme->nky,nma)*mult_up(pme->nkz,nmi)*pme->nkx;
-
-    /* pme_solve is roughly double the cost of an fft */
-
-    return (n1 + n2 + 3*n3)/(double)(6*pme->nkx*pme->nky*pme->nkz);
-}
-
-static void init_atomcomm(gmx_pme_t pme,pme_atomcomm_t *atc, t_commrec *cr,
-                          int dimind,gmx_bool bSpread)
-{
-    int nk,k,s;
-
-    atc->dimind = dimind;
-    atc->nslab  = 1;
-    atc->nodeid = 0;
-    atc->pd_nalloc = 0;
-#ifdef GMX_MPI
-    if (pme->nnodes > 1)
-    {
-        atc->mpi_comm = pme->mpi_comm_d[dimind];
-        MPI_Comm_size(atc->mpi_comm,&atc->nslab);
-        MPI_Comm_rank(atc->mpi_comm,&atc->nodeid);
-    }
-    if (debug)
-    {
-        fprintf(debug,"For PME atom communication in dimind %d: nslab %d rank %d\n",atc->dimind,atc->nslab,atc->nodeid);
-    }
-#endif
-
-    atc->bSpread   = bSpread;
-    atc->pme_order = pme->pme_order;
-
-    if (atc->nslab > 1)
-    {
-        /* These three allocations are not required for particle decomp. */
-        snew(atc->node_dest,atc->nslab);
-        snew(atc->node_src,atc->nslab);
-        setup_coordinate_communication(atc);
-        
-        snew(atc->count,atc->nslab);
-        snew(atc->rcount,atc->nslab);
-        snew(atc->buf_index,atc->nslab);
-    }
-}
-
-static void 
-init_overlap_comm(pme_overlap_t *  ol,
-                  int              norder,
-#ifdef GMX_MPI
-                  MPI_Comm         comm,  
-#endif
-                  int              nnodes, 
-                  int              nodeid,
-                  int              ndata)
-{
-    int lbnd,rbnd,maxlr,b,i;
-    int exten;
-    int nn,nk;
-    pme_grid_comm_t *pgc;
-    gmx_bool bCont;
-    int fft_start,fft_end,send_index1,recv_index1;
-    
-#ifdef GMX_MPI
-    ol->mpi_comm = comm;
-#endif
-    
-    ol->nnodes = nnodes;
-    ol->nodeid = nodeid;
-
-    /* Linear translation of the PME grid wo'nt affect reciprocal space
-     * calculations, so to optimize we only interpolate "upwards",
-     * which also means we only have to consider overlap in one direction.
-     * I.e., particles on this node might also be spread to grid indices
-     * that belong to higher nodes (modulo nnodes)
-     */
-
-    snew(ol->s2g0,ol->nnodes+1);
-    snew(ol->s2g1,ol->nnodes);
-    if (debug) { fprintf(debug,"PME slab boundaries:"); }
-    for(i=0; i<nnodes; i++) 
-    {
-        /* s2g0 the local interpolation grid start.
-         * s2g1 the local interpolation grid end.
-         * Because grid overlap communication only goes forward,
-         * the grid the slabs for fft's should be rounded down.
-         */
-        ol->s2g0[i] = ( i   *ndata + 0       )/nnodes;
-        ol->s2g1[i] = ((i+1)*ndata + nnodes-1)/nnodes + norder - 1;
-
-        if (debug)
-        {
-            fprintf(debug,"  %3d %3d",ol->s2g0[i],ol->s2g1[i]);
-        }
-    }
-    ol->s2g0[nnodes] = ndata;
-    if (debug) { fprintf(debug,"\n"); }
-
-    /* Determine with how many nodes we need to communicate the grid overlap */
-    b = 0;
-    do
-    {
-        b++;
-        bCont = FALSE;
-        for(i=0; i<nnodes; i++)
-        {
-            if ((i+b <  nnodes && ol->s2g1[i] > ol->s2g0[i+b]) ||
-                (i+b >= nnodes && ol->s2g1[i] > ol->s2g0[i+b-nnodes] + ndata))
-            {
-                bCont = TRUE;
-            }
-        }
-    }
-    while (bCont && b < nnodes);
-    ol->noverlap_nodes = b - 1;
-
-    snew(ol->send_id,ol->noverlap_nodes);
-    snew(ol->recv_id,ol->noverlap_nodes);
-    for(b=0; b<ol->noverlap_nodes; b++)
-    {
-        ol->send_id[b] = (ol->nodeid + (b + 1)) % ol->nnodes;
-        ol->recv_id[b] = (ol->nodeid - (b + 1) + ol->nnodes) % ol->nnodes;
-    }
-    snew(ol->comm_data, ol->noverlap_nodes);
-
-    for(b=0; b<ol->noverlap_nodes; b++)
-    {
-        pgc = &ol->comm_data[b];
-        /* Send */
-        fft_start        = ol->s2g0[ol->send_id[b]];
-        fft_end          = ol->s2g0[ol->send_id[b]+1];
-        if (ol->send_id[b] < nodeid)
-        {
-            fft_start += ndata;
-            fft_end   += ndata;
-        }
-        send_index1      = ol->s2g1[nodeid];
-        send_index1      = min(send_index1,fft_end);
-        pgc->send_index0 = fft_start;
-        pgc->send_nindex = max(0,send_index1 - pgc->send_index0);
-
-        /* We always start receiving to the first index of our slab */
-        fft_start        = ol->s2g0[ol->nodeid];
-        fft_end          = ol->s2g0[ol->nodeid+1];
-        recv_index1      = ol->s2g1[ol->recv_id[b]];
-        if (ol->recv_id[b] > nodeid)
-        {
-            recv_index1 -= ndata;
-        }
-        recv_index1      = min(recv_index1,fft_end);
-        pgc->recv_index0 = fft_start;
-        pgc->recv_nindex = max(0,recv_index1 - pgc->recv_index0);
-    }
-}
-
-static void
-make_gridindex5_to_localindex(int n,int local_start,int local_range,
-                              int **global_to_local,
-                              real **fraction_shift)
-{
-    int i;
-    int * gtl;
-    real * fsh;
-
-    snew(gtl,5*n);
-    snew(fsh,5*n);
-    for(i=0; (i<5*n); i++)
-    {
-        /* Determine the global to local grid index */
-        gtl[i] = (i - local_start + n) % n;
-        /* For coordinates that fall within the local grid the fraction
-         * is correct, we don't need to shift it.
-         */
-        fsh[i] = 0;
-        if (local_range < n)
-        {
-            /* Due to rounding issues i could be 1 beyond the lower or
-             * upper boundary of the local grid. Correct the index for this.
-             * If we shift the index, we need to shift the fraction by
-             * the same amount in the other direction to not affect
-             * the weights.
-             * Note that due to this shifting the weights at the end of
-             * the spline might change, but that will only involve values
-             * between zero and values close to the precision of a real,
-             * which is anyhow the accuracy of the whole mesh calculation.
-             */
-            /* With local_range=0 we should not change i=local_start */
-            if (i % n != local_start)
-            {
-                if (gtl[i] == n-1)
-                {
-                    gtl[i] = 0;
-                    fsh[i] = -1; 
-                }
-                else if (gtl[i] == local_range)
-                {
-                    gtl[i] = local_range - 1;
-                    fsh[i] = 1;
-                }
-            }
-        }
-    }
-
-    *global_to_local = gtl;
-    *fraction_shift  = fsh;
-}
-
-static void
-gmx_pme_check_grid_restrictions(FILE *fplog,char dim,int nnodes,int *nk)
-{
-    int nk_new;
-
-    if (*nk % nnodes != 0)
-    {
-        nk_new = nnodes*(*nk/nnodes + 1);
-
-        if (2*nk_new >= 3*(*nk))
-        {
-            gmx_fatal(FARGS,"The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). The grid size would have to be increased by more than 50%% to make the grid divisible. Change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).",
-                      dim,*nk,dim,nnodes,dim);
-        }
-        
-        if (fplog != NULL)
-        {
-            fprintf(fplog,"\nNOTE: The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). Increasing the PME grid size in dim %c to %d. This will increase the accuracy and will not decrease the performance significantly on this number of nodes. For optimal performance change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).\n\n",
-                    dim,*nk,dim,nnodes,dim,nk_new,dim);
-        }
-            
-        *nk = nk_new;
-    }
-}
-
-int gmx_pme_init(gmx_pme_t *         pmedata,
-                 t_commrec *         cr,
-                 int                 nnodes_major,
-                 int                 nnodes_minor,
-                 t_inputrec *        ir,
-                 int                 homenr,
-                 gmx_bool                bFreeEnergy,
-                 gmx_bool                bReproducible)
-{
-    gmx_pme_t pme=NULL;
-    
-    pme_atomcomm_t *atc;
-    int bufsizex,bufsizey,bufsize;
-    ivec ndata;
-    
-    if (debug)
-        fprintf(debug,"Creating PME data structures.\n");
-    snew(pme,1);
-        
-    pme->redist_init         = FALSE;
-    pme->sum_qgrid_tmp       = NULL;
-    pme->sum_qgrid_dd_tmp    = NULL;
-    pme->buf_nalloc          = 0;
-    pme->redist_buf_nalloc   = 0;
-    
-    pme->nnodes              = 1;
-    pme->bPPnode             = TRUE;
-    
-    pme->nnodes_major        = nnodes_major;
-    pme->nnodes_minor        = nnodes_minor;
-
-#ifdef GMX_MPI
-    if (nnodes_major*nnodes_minor > 1 && PAR(cr)) 
-    {
-        pme->mpi_comm        = cr->mpi_comm_mygroup;
-        
-        MPI_Comm_rank(pme->mpi_comm,&pme->nodeid);
-        MPI_Comm_size(pme->mpi_comm,&pme->nnodes);
-        if (pme->nnodes != nnodes_major*nnodes_minor)
-        {
-            gmx_incons("PME node count mismatch");
-        }
-    }
-#endif
-
-    if (pme->nnodes == 1)
-    {
-        pme->ndecompdim = 0;
-        pme->nodeid_major = 0;
-        pme->nodeid_minor = 0;
-    }
-    else
-    {
-        if (nnodes_minor == 1)
-        {
-#ifdef GMX_MPI
-            pme->mpi_comm_d[0] = pme->mpi_comm;
-            pme->mpi_comm_d[1] = NULL;
-#endif
-            pme->ndecompdim = 1;
-            pme->nodeid_major = pme->nodeid;
-            pme->nodeid_minor = 0;
-            
-        }
-        else if (nnodes_major == 1)
-        {
-#ifdef GMX_MPI
-            pme->mpi_comm_d[0] = NULL;
-            pme->mpi_comm_d[1] = pme->mpi_comm;
-#endif
-            pme->ndecompdim = 1;
-            pme->nodeid_major = 0;
-            pme->nodeid_minor = pme->nodeid;
-        }
-        else 
-        {
-            if (pme->nnodes % nnodes_major != 0)
-            {
-                gmx_incons("For 2D PME decomposition, #PME nodes must be divisible by the number of nodes in the major dimension");
-            }
-            pme->ndecompdim = 2;
-            
-#ifdef GMX_MPI
-            MPI_Comm_split(pme->mpi_comm,pme->nodeid % nnodes_minor,
-                           pme->nodeid,&pme->mpi_comm_d[0]);  /* My communicator along major dimension */
-            MPI_Comm_split(pme->mpi_comm,pme->nodeid/nnodes_minor,
-                           pme->nodeid,&pme->mpi_comm_d[1]);  /* My communicator along minor dimension */
-            
-            MPI_Comm_rank(pme->mpi_comm_d[0],&pme->nodeid_major);
-            MPI_Comm_size(pme->mpi_comm_d[0],&pme->nnodes_major);
-            MPI_Comm_rank(pme->mpi_comm_d[1],&pme->nodeid_minor);
-            MPI_Comm_size(pme->mpi_comm_d[1],&pme->nnodes_minor);
-#endif
-        }
-        pme->bPPnode = (cr->duty & DUTY_PP);
-    }
-    
-    if (ir->ePBC == epbcSCREW)
-    {
-        gmx_fatal(FARGS,"pme does not (yet) work with pbc = screw");
-    }
-    
-    pme->bFEP        = ((ir->efep != efepNO) && bFreeEnergy);
-    pme->nkx         = ir->nkx;
-    pme->nky         = ir->nky;
-    pme->nkz         = ir->nkz;
-    pme->pme_order   = ir->pme_order;
-    pme->epsilon_r   = ir->epsilon_r;
-    
-    /* Currently pme.c supports only the fft5d FFT code.
-     * Therefore the grid always needs to be divisible by nnodes.
-     * When the old 1D code is also supported again, change this check.
-     *
-     * This check should be done before calling gmx_pme_init
-     * and fplog should be passed iso stderr.
-     *
-    if (pme->ndecompdim >= 2)
-    */
-    if (pme->ndecompdim >= 1)
-    {
-        /*
-        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
-                                        'x',nnodes_major,&pme->nkx);
-        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
-                                        'y',nnodes_minor,&pme->nky);
-        */
-    }
-
-    if (pme->nkx <= pme->pme_order*(pme->nnodes_major > 1 ? 2 : 1) ||
-        pme->nky <= pme->pme_order*(pme->nnodes_minor > 1 ? 2 : 1) ||
-        pme->nkz <= pme->pme_order)
-    {
-        gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_order for x and/or y",pme->pme_order);
-    }
-
-    if (pme->nnodes > 1) {
-        double imbal;
-
-#ifdef GMX_MPI
-        MPI_Type_contiguous(DIM, mpi_type, &(pme->rvec_mpi));
-        MPI_Type_commit(&(pme->rvec_mpi));
-#endif
-        
-        /* Note that the charge spreading and force gathering, which usually
-         * takes about the same amount of time as FFT+solve_pme,
-         * is always fully load balanced
-         * (unless the charge distribution is inhomogeneous).
-         */
-        
-        imbal = pme_load_imbalance(pme);
-        if (imbal >= 1.2 && pme->nodeid_major == 0 && pme->nodeid_minor == 0)
-        {
-            fprintf(stderr,
-                    "\n"
-                    "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
-                    "      For optimal PME load balancing\n"
-                    "      PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes_x (%d)\n"
-                    "      and PME grid_y (%d) and grid_z (%d) should be divisible by #PME_nodes_y (%d)\n"
-                    "\n",
-                    (int)((imbal-1)*100 + 0.5),
-                    pme->nkx,pme->nky,pme->nnodes_major,
-                    pme->nky,pme->nkz,pme->nnodes_minor);
-        }
-    }
-
-    init_overlap_comm(&pme->overlap[0],pme->pme_order,
-#ifdef GMX_MPI
-                      pme->mpi_comm_d[0],
-#endif
-                      pme->nnodes_major,pme->nodeid_major,pme->nkx);
-    
-    init_overlap_comm(&pme->overlap[1],pme->pme_order,
-#ifdef GMX_MPI
-                      pme->mpi_comm_d[1],
-#endif
-                      pme->nnodes_minor,pme->nodeid_minor,pme->nky);
-    
-    snew(pme->bsp_mod[XX],pme->nkx);
-    snew(pme->bsp_mod[YY],pme->nky);
-    snew(pme->bsp_mod[ZZ],pme->nkz);
-    
-    /* Allocate data for the interpolation grid, including overlap */
-    pme->pmegrid_nx = pme->overlap[0].s2g1[pme->nodeid_major] -
-                      pme->overlap[0].s2g0[pme->nodeid_major];
-    pme->pmegrid_ny = pme->overlap[1].s2g1[pme->nodeid_minor] - 
-                      pme->overlap[1].s2g0[pme->nodeid_minor];
-    pme->pmegrid_nz = pme->nkz + pme->pme_order - 1;
-    
-    pme->pmegrid_start_ix = pme->overlap[0].s2g0[pme->nodeid_major];
-    pme->pmegrid_start_iy = pme->overlap[1].s2g0[pme->nodeid_minor];
-    pme->pmegrid_start_iz = 0;
-    
-    make_gridindex5_to_localindex(pme->nkx,
-                                  pme->pmegrid_start_ix,
-                                  pme->pmegrid_nx - (pme->pme_order-1),
-                                  &pme->nnx,&pme->fshx);
-    make_gridindex5_to_localindex(pme->nky,
-                                  pme->pmegrid_start_iy,
-                                  pme->pmegrid_ny - (pme->pme_order-1),
-                                  &pme->nny,&pme->fshy);
-    make_gridindex5_to_localindex(pme->nkz,
-                                  pme->pmegrid_start_iz,
-                                  pme->pmegrid_nz - (pme->pme_order-1),
-                                  &pme->nnz,&pme->fshz);
-    
-    snew(pme->pmegridA,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);
-    
-    /* For non-divisible grid we need pme_order iso pme_order-1 */
-    /* x overlap is copied in place: take padding into account.
-     * y is always copied through a buffer: we don't need padding in z,
-     * but we do need the overlap in x because of the communication order.
-     */
-    bufsizex = pme->pme_order*pme->pmegrid_ny*pme->pmegrid_nz;
-    bufsizey = pme->pme_order*pme->pmegrid_nx*pme->nkz;
-    bufsize  = (bufsizex>bufsizey) ? bufsizex : bufsizey;
-    
-    snew(pme->pmegrid_sendbuf,bufsize);
-    snew(pme->pmegrid_recvbuf,bufsize);
-    
-    ndata[0] = pme->nkx;
-    ndata[1] = pme->nky;
-    ndata[2] = pme->nkz;
-    
-    /* This routine will allocate the grid data to fit the FFTs */
-    gmx_parallel_3dfft_init(&pme->pfft_setupA,ndata,
-                            &pme->fftgridA,&pme->cfftgridA,
-                            pme->mpi_comm_d,
-                            pme->overlap[0].s2g0,pme->overlap[1].s2g0,
-                            bReproducible);
-    
-    if (bFreeEnergy)
-    {
-        snew(pme->pmegridB,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);    
-        gmx_parallel_3dfft_init(&pme->pfft_setupB,ndata,
-                                &pme->fftgridB,&pme->cfftgridB,
-                                pme->mpi_comm_d,
-                                pme->overlap[0].s2g0,pme->overlap[1].s2g0,
-                                bReproducible);
-    } else 
-    {
-        pme->pmegridB    = NULL;
-        pme->fftgridB    = NULL;
-        pme->cfftgridB   = NULL;
-    }
-    
-    make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
-    
-    /* Use atc[0] for spreading */
-    init_atomcomm(pme,&pme->atc[0],cr,nnodes_major > 1 ? 0 : 1,TRUE);
-    if (pme->ndecompdim >= 2)
-    {
-        init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
-    }
-    
-    if (pme->nnodes == 1) {
-        pme->atc[0].n = homenr;
-        pme_realloc_atomcomm_things(&pme->atc[0]);
-    }
-    
-    /* Use fft5d, order after FFT is y major, z, x minor */
-    pme->work_nalloc = pme->nkx;
-    snew(pme->work_mhx,pme->work_nalloc);
-    snew(pme->work_mhy,pme->work_nalloc);
-    snew(pme->work_mhz,pme->work_nalloc);
-    snew(pme->work_m2,pme->work_nalloc);
-    snew(pme->work_denom,pme->work_nalloc);
-    /* Allocate an aligned pointer for SSE operations, including 3 extra
-     * elements at the end since SSE operates on 4 elements at a time.
-     */
-    snew(pme->work_tmp1_alloc,pme->work_nalloc+8);
-    pme->work_tmp1 = (real *) (((size_t) pme->work_tmp1_alloc + 16) & (~((size_t) 15)));
-    snew(pme->work_m2inv,pme->work_nalloc);
-
-    *pmedata = pme;
-    
-    return 0;
-}
-
-static void spread_on_grid(gmx_pme_t pme,
-                           pme_atomcomm_t *atc,real *grid,
-                           gmx_bool bCalcSplines,gmx_bool bSpread)
-{    
-    if (bCalcSplines)
-    {
-    
-        /* Compute fftgrid index for all atoms,
-         * with help of some extra variables.
-         */
-        calc_interpolation_idx(pme,atc);
-        
-        /* make local bsplines  */
-        make_bsplines(atc->theta,atc->dtheta,pme->pme_order,
-                      atc->fractx,atc->n,atc->q,pme->bFEP);
-    }    
-    
-    if (bSpread)
-    {
-        /* put local atoms on grid. */
-        spread_q_bsplines(pme,atc,grid);
-    }
-}
-
-void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V)
-{
-    pme_atomcomm_t *atc;
-    real *grid;
-
-    if (pme->nnodes > 1)
-    {
-        gmx_incons("gmx_pme_calc_energy called in parallel");
-    }
-    if (pme->bFEP > 1)
-    {
-        gmx_incons("gmx_pme_calc_energy with free energy");
-    }
-
-    atc = &pme->atc_energy;
-    atc->nslab     = 1;
-    atc->bSpread   = TRUE;
-    atc->pme_order = pme->pme_order;
-    atc->n         = n;
-    pme_realloc_atomcomm_things(atc);
-    atc->x         = x;
-    atc->q         = q;
-    
-    /* We only use the A-charges grid */
-    grid = pme->pmegridA;
-
-    spread_on_grid(pme,atc,NULL,TRUE,FALSE);
-
-    *V = gather_energy_bsplines(pme,grid,atc);
-}
-
-
-static void reset_pmeonly_counters(t_commrec *cr,gmx_wallcycle_t wcycle,
-        t_nrnb *nrnb,t_inputrec *ir, gmx_large_int_t step_rel)
-{
-    /* Reset all the counters related to performance over the run */
-    wallcycle_stop(wcycle,ewcRUN);
-    wallcycle_reset_all(wcycle);
-    init_nrnb(nrnb);
-    ir->init_step += step_rel;
-    ir->nsteps    -= step_rel;
-    wallcycle_start(wcycle,ewcRUN);
-}
-
-
-int gmx_pmeonly(gmx_pme_t pme,
-                t_commrec *cr,    t_nrnb *nrnb,
-                gmx_wallcycle_t wcycle,
-                real ewaldcoeff,  gmx_bool bGatherOnly,
-                t_inputrec *ir)
-{
-    gmx_pme_pp_t pme_pp;
-    int  natoms;
-    matrix box;
-    rvec *x_pp=NULL,*f_pp=NULL;
-    real *chargeA=NULL,*chargeB=NULL;
-    real lambda=0;
-    int  maxshift_x=0,maxshift_y=0;
-    real energy,dvdlambda;
-    matrix vir;
-    float cycles;
-    int  count;
-    gmx_bool bEnerVir;
-    gmx_large_int_t step,step_rel;
-    
-    
-    pme_pp = gmx_pme_pp_init(cr);
-    
-    init_nrnb(nrnb);
-    
-    count = 0;
-    do /****** this is a quasi-loop over time steps! */
-    {
-        /* Domain decomposition */
-        natoms = gmx_pme_recv_q_x(pme_pp,
-                                  &chargeA,&chargeB,box,&x_pp,&f_pp,
-                                  &maxshift_x,&maxshift_y,
-                                  &pme->bFEP,&lambda,
-                                  &bEnerVir,
-                                  &step);
-        
-        if (natoms == -1) {
-            /* We should stop: break out of the loop */
-            break;
-        }
-        
-        step_rel = step - ir->init_step;
-        
-        if (count == 0)
-            wallcycle_start(wcycle,ewcRUN);
-        
-        wallcycle_start(wcycle,ewcPMEMESH);
-        
-        dvdlambda = 0;
-        clear_mat(vir);
-        gmx_pme_do(pme,0,natoms,x_pp,f_pp,chargeA,chargeB,box,
-                   cr,maxshift_x,maxshift_y,nrnb,wcycle,vir,ewaldcoeff,
-                   &energy,lambda,&dvdlambda,
-                   GMX_PME_DO_ALL_F | (bEnerVir ? GMX_PME_CALC_ENER_VIR : 0));
-        
-        cycles = wallcycle_stop(wcycle,ewcPMEMESH);
-        
-        gmx_pme_send_force_vir_ener(pme_pp,
-                                    f_pp,vir,energy,dvdlambda,
-                                    cycles);
-        
-        count++;
-
-        if (step_rel == wcycle_get_reset_counters(wcycle))
-        {
-            /* Reset all the counters related to performance over the run */
-            reset_pmeonly_counters(cr,wcycle,nrnb,ir,step_rel);
-            wcycle_set_reset_counters(wcycle, 0);
-        }
-        
-    } /***** end of quasi-loop, we stop with the break above */
-    while (TRUE);
-    
-    return 0;
-}
-
-int gmx_pme_do(gmx_pme_t pme,
-               int start,       int homenr,
-               rvec x[],        rvec f[],
-               real *chargeA,   real *chargeB,
-               matrix box,     t_commrec *cr,
-               int  maxshift_x, int maxshift_y,
-               t_nrnb *nrnb,    gmx_wallcycle_t wcycle,
-               matrix vir,      real ewaldcoeff,
-               real *energy,    real lambda, 
-               real *dvdlambda, int flags)
-{
-    int     q,d,i,j,ntot,npme;
-    int     nx,ny,nz;
-    int     n_d,local_ny;
-    int     loop_count;
-    pme_atomcomm_t *atc=NULL;
-    real *  grid=NULL;
-    real    *ptr;
-    rvec    *x_d,*f_d;
-    real    *charge=NULL,*q_d,vol;
-    real    energy_AB[2];
-    matrix  vir_AB[2];
-    gmx_bool    bClearF;
-    gmx_parallel_3dfft_t pfft_setup;
-    real *  fftgrid;
-    t_complex * cfftgrid;
-
-    if (pme->nnodes > 1) {
-        atc = &pme->atc[0];
-        atc->npd = homenr;
-        if (atc->npd > atc->pd_nalloc) {
-            atc->pd_nalloc = over_alloc_dd(atc->npd);
-            srenew(atc->pd,atc->pd_nalloc);
-        }
-        atc->maxshift = (atc->dimind==0 ? maxshift_x : maxshift_y);
-    }
-    else
-    {
-        /* This could be necessary for TPI */
-        pme->atc[0].n = homenr;
-    }
-    
-    for(q=0; q<(pme->bFEP ? 2 : 1); q++) {
-        if (q == 0) {
-            grid = pme->pmegridA;
-            fftgrid = pme->fftgridA;
-            cfftgrid = pme->cfftgridA;
-            pfft_setup = pme->pfft_setupA;
-            charge = chargeA+start;
-        } else {
-            grid = pme->pmegridB;
-            fftgrid = pme->fftgridB;
-            cfftgrid = pme->cfftgridB;
-            pfft_setup = pme->pfft_setupB;
-            charge = chargeB+start;
-        }
-        /* Unpack structure */
-        if (debug) {
-            fprintf(debug,"PME: nnodes = %d, nodeid = %d\n",
-                    cr->nnodes,cr->nodeid);
-            fprintf(debug,"Grid = %p\n",(void*)grid);
-            if (grid == NULL)
-                gmx_fatal(FARGS,"No grid!");
-        }
-        where();
-        
-        m_inv_ur0(box,pme->recipbox); 
-
-        if (pme->nnodes == 1) {
-            atc = &pme->atc[0];
-            if (DOMAINDECOMP(cr)) {
-                atc->n = homenr;
-                pme_realloc_atomcomm_things(atc);
-            }
-            atc->x = x;
-            atc->q = charge;
-            atc->f = f;
-        } else {
-            wallcycle_start(wcycle,ewcPME_REDISTXF);
-            for(d=pme->ndecompdim-1; d>=0; d--)
-            {
-                if (d == pme->ndecompdim-1)
-                {
-                    n_d = homenr;
-                    x_d = x + start;
-                    q_d = charge;
-                }
-                else
-                {
-                    n_d = pme->atc[d+1].n;
-                    x_d = atc->x;
-                    q_d = atc->q;
-                }
-                atc = &pme->atc[d];
-                atc->npd = n_d;
-                if (atc->npd > atc->pd_nalloc) {
-                    atc->pd_nalloc = over_alloc_dd(atc->npd);
-                    srenew(atc->pd,atc->pd_nalloc);
-                }
-                atc->maxshift = (atc->dimind==0 ? maxshift_x : maxshift_y);
-                pme_calc_pidx(n_d,pme->recipbox,x_d,atc);
-                where();
-                
-                GMX_BARRIER(cr->mpi_comm_mygroup);
-                /* Redistribute x (only once) and qA or qB */
-                if (DOMAINDECOMP(cr)) {
-                    dd_pmeredist_x_q(pme, n_d, q==0, x_d, q_d, atc);
-                } else {
-                    pmeredist_pd(pme, TRUE, n_d, q==0, x_d, q_d, atc);
-                }
-            }
-            where();
-
-            wallcycle_stop(wcycle,ewcPME_REDISTXF);
-        }
-        
-        if (debug)
-            fprintf(debug,"Node= %6d, pme local particles=%6d\n",
-                    cr->nodeid,atc->n);
-
-        if (flags & GMX_PME_SPREAD_Q)
-        {
-            wallcycle_start(wcycle,ewcPME_SPREADGATHER);
-
-            /* Spread the charges on a grid */
-            GMX_MPE_LOG(ev_spread_on_grid_start);
-            
-            /* Spread the charges on a grid */
-            spread_on_grid(pme,&pme->atc[0],grid,q==0,TRUE);
-            GMX_MPE_LOG(ev_spread_on_grid_finish);
-
-            if (q == 0)
-            {
-                inc_nrnb(nrnb,eNR_WEIGHTS,DIM*atc->n);
-            }
-            inc_nrnb(nrnb,eNR_SPREADQBSP,
-                     pme->pme_order*pme->pme_order*pme->pme_order*atc->n);
-
-            wrap_periodic_pmegrid(pme,grid);
-
-            /* sum contributions to local grid from other nodes */
-#ifdef GMX_MPI
-            if (pme->nnodes > 1) {
-                GMX_BARRIER(cr->mpi_comm_mygroup);
-                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_FORWARD);
-                where();
-            }
-#endif
-            where();
-
-            copy_pmegrid_to_fftgrid(pme,grid,fftgrid);
-
-            wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
-        }
-         
-        if (flags & GMX_PME_SOLVE)
-        {
-            /* do 3d-fft */ 
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_gmxfft3d_start);
-            wallcycle_start(wcycle,ewcPME_FFT);
-            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_REAL_TO_COMPLEX,fftgrid,cfftgrid);
-            wallcycle_stop(wcycle,ewcPME_FFT);
-            GMX_MPE_LOG(ev_gmxfft3d_finish);
-            where();
-            
-            /* solve in k-space for our local cells */
-            vol = det(box);
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_solve_pme_start);
-            wallcycle_start(wcycle,ewcPME_SOLVE);
-            loop_count =
-                solve_pme_yzx(pme,cfftgrid,ewaldcoeff,vol,
-                              flags & GMX_PME_CALC_ENER_VIR,
-                              &energy_AB[q],vir_AB[q]);
-            wallcycle_stop(wcycle,ewcPME_SOLVE);
-            where();
-            GMX_MPE_LOG(ev_solve_pme_finish);
-            inc_nrnb(nrnb,eNR_SOLVEPME,loop_count);
-        }
-
-        if ((flags & GMX_PME_CALC_F) ||
-            (flags & GMX_PME_CALC_POT))
-        {
-            
-            /* do 3d-invfft */
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_gmxfft3d_start);
-            where();
-            wallcycle_start(wcycle,ewcPME_FFT);
-            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_COMPLEX_TO_REAL,cfftgrid,fftgrid);
-            wallcycle_stop(wcycle,ewcPME_FFT);
-
-            where();
-            GMX_MPE_LOG(ev_gmxfft3d_finish);
-
-            if (pme->nodeid == 0)
-            {
-                ntot = pme->nkx*pme->nky*pme->nkz;
-                npme  = ntot*log((real)ntot)/log(2.0);
-                inc_nrnb(nrnb,eNR_FFT,2*npme);
-            }
-
-            wallcycle_start(wcycle,ewcPME_SPREADGATHER);
-
-            copy_fftgrid_to_pmegrid(pme,fftgrid,grid);
-
-            /* distribute local grid to all nodes */
-#ifdef GMX_MPI
-            if (pme->nnodes > 1) {
-                GMX_BARRIER(cr->mpi_comm_mygroup);
-                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_BACKWARD);
-            }
-#endif
-            where();
-
-            unwrap_periodic_pmegrid(pme,grid);
-        }
-
-        if (flags & GMX_PME_CALC_F)
-        {
-            /* interpolate forces for our local atoms */
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_gather_f_bsplines_start);
-
-            where();
-            
-            /* If we are running without parallelization,
-             * atc->f is the actual force array, not a buffer,
-             * therefore we should not clear it.
-             */
-            bClearF = (q == 0 && PAR(cr));
-            gather_f_bsplines(pme,grid,bClearF,&pme->atc[0],
-                              pme->bFEP ? (q==0 ? 1.0-lambda : lambda) : 1.0);
-            where();
-            
-            GMX_MPE_LOG(ev_gather_f_bsplines_finish);
-            
-            inc_nrnb(nrnb,eNR_GATHERFBSP,
-                     pme->pme_order*pme->pme_order*pme->pme_order*pme->atc[0].n);
-            wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
-       }
-    } /* of q-loop */
-    
-    if ((flags & GMX_PME_CALC_F) && pme->nnodes > 1) {
-        wallcycle_start(wcycle,ewcPME_REDISTXF);
-        for(d=0; d<pme->ndecompdim; d++)
-        {
-            atc = &pme->atc[d];
-            if (d == pme->ndecompdim - 1)
-            {
-                n_d = homenr;
-                f_d = f + start;
-            }
-            else
-            {
-                n_d = pme->atc[d+1].n;
-                f_d = pme->atc[d+1].f;
-            }
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            if (DOMAINDECOMP(cr)) {
-                dd_pmeredist_f(pme,atc,n_d,f_d,
-                               d==pme->ndecompdim-1 && pme->bPPnode);
-            } else {
-                pmeredist_pd(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
-            }
-        }
-
-        wallcycle_stop(wcycle,ewcPME_REDISTXF);
-    }
-    where();
-    
-    if (!pme->bFEP) {
-        *energy = energy_AB[0];
-        m_add(vir,vir_AB[0],vir);
-    } else {
-        *energy = (1.0-lambda)*energy_AB[0] + lambda*energy_AB[1];
-        *dvdlambda += energy_AB[1] - energy_AB[0];
-        for(i=0; i<DIM; i++)
-            for(j=0; j<DIM; j++)
-                vir[i][j] += (1.0-lambda)*vir_AB[0][i][j] + lambda*vir_AB[1][i][j];
-    }
-
-    if (debug)
-        fprintf(debug,"PME mesh energy: %g\n",*energy);
-    
-    return 0;
-}
diff --git a/src/mdlib/pme_pp.c b/src/mdlib/pme_pp.c
deleted file mode 100644 (file)
index 4d0e3d3..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include "typedefs.h"
-#include "smalloc.h"
-#include "gmx_fatal.h"
-#include "vec.h"
-#include "pme.h"
-#include "network.h"
-#include "domdec.h"
-#include "sighandler.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#include "mpelogging.h"
-
-#define PP_PME_CHARGE   (1<<0)
-#define PP_PME_CHARGEB  (1<<1)
-#define PP_PME_COORD    (1<<2)
-#define PP_PME_FEP      (1<<3)
-#define PP_PME_ENER_VIR (1<<4)
-#define PP_PME_FINISH   (1<<5)
-
-#define PME_PP_SIGSTOP     (1<<0)
-#define PME_PP_SIGSTOPNSS     (1<<1)
-
-typedef struct gmx_pme_pp {
-#ifdef GMX_MPI
-  MPI_Comm mpi_comm_mysim;
-#endif
-  int  nnode;        /* The number of PP node to communicate with  */
-  int  *node;        /* The PP node ranks                          */
-  int  node_peer;    /* The peer PP node rank                      */
-  int  *nat;         /* The number of atom for each PP node        */
-  int  flags_charge; /* The flags sent along with the last charges */
-  real *chargeA;
-  real *chargeB;
-  rvec *x;
-  rvec *f;
-  int  nalloc;
-#ifdef GMX_MPI
-  MPI_Request *req;
-  MPI_Status  *stat;
-#endif
-} t_gmx_pme_pp;
-
-typedef struct gmx_pme_comm_n_box {
-  int    natoms;
-  matrix box;
-  int    maxshift_x;
-  int    maxshift_y;
-  real   lambda;
-  int    flags;
-  gmx_large_int_t step;
-} gmx_pme_comm_n_box_t;
-
-typedef struct {
-  matrix vir;
-  real   energy;
-  real   dvdlambda;
-  float  cycles;
-  gmx_stop_cond_t stop_cond;
-} gmx_pme_comm_vir_ene_t;
-
-
-
-
-gmx_pme_pp_t gmx_pme_pp_init(t_commrec *cr)
-{
-  struct gmx_pme_pp *pme_pp;
-  int rank;
-
-  snew(pme_pp,1);
-
-#ifdef GMX_MPI
-  pme_pp->mpi_comm_mysim = cr->mpi_comm_mysim;
-  MPI_Comm_rank(cr->mpi_comm_mygroup,&rank);
-  get_pme_ddnodes(cr,rank,&pme_pp->nnode,&pme_pp->node,&pme_pp->node_peer);
-  snew(pme_pp->nat,pme_pp->nnode);
-  snew(pme_pp->req,2*pme_pp->nnode);
-  snew(pme_pp->stat,2*pme_pp->nnode);
-  pme_pp->nalloc = 0;
-  pme_pp->flags_charge = 0;
-#endif
-
-  return pme_pp;
-}
-
-/* This should be faster with a real non-blocking MPI implementation */
-/* #define GMX_PME_DELAYED_WAIT */
-
-static void gmx_pme_send_q_x_wait(gmx_domdec_t *dd)
-{
-#ifdef GMX_MPI
-  if (dd->nreq_pme) {
-    MPI_Waitall(dd->nreq_pme,dd->req_pme,MPI_STATUSES_IGNORE);
-    dd->nreq_pme = 0;
-  }
-#endif
-}
-
-static void gmx_pme_send_q_x(t_commrec *cr, int flags,
-                            real *chargeA, real *chargeB,
-                            matrix box, rvec *x,
-                            real lambda,
-                            int maxshift_x, int maxshift_y,
-                            gmx_large_int_t step)
-{
-  gmx_domdec_t *dd;
-  gmx_pme_comm_n_box_t *cnb;
-  int  n;
-
-  dd = cr->dd;
-  n = dd->nat_home;
-
-  if (debug)
-    fprintf(debug,"PP node %d sending to PME node %d: %d%s%s\n",
-           cr->sim_nodeid,dd->pme_nodeid,n,
-           flags & PP_PME_CHARGE ? " charges" : "",
-           flags & PP_PME_COORD  ? " coordinates" : "");
-
-#ifdef GMX_PME_DELAYED_WAIT
-  /* When can not use cnb until pending communication has finished */
-  gmx_pme_send_x_q_wait(dd);
-#endif
-
-  if (dd->pme_receive_vir_ener) {
-    /* Peer PP node: communicate all data */
-    if (dd->cnb == NULL)
-      snew(dd->cnb,1);
-    cnb = dd->cnb;
-
-    cnb->flags      = flags;
-    cnb->natoms     = n;
-    cnb->maxshift_x = maxshift_x;
-    cnb->maxshift_y = maxshift_y;
-    cnb->lambda     = lambda;
-    cnb->step       = step;
-    if (flags & PP_PME_COORD)
-      copy_mat(box,cnb->box);
-#ifdef GMX_MPI
-    MPI_Isend(cnb,sizeof(*cnb),MPI_BYTE,
-             dd->pme_nodeid,0,cr->mpi_comm_mysim,
-             &dd->req_pme[dd->nreq_pme++]);
-#endif
-  } else if (flags & PP_PME_CHARGE) {
-#ifdef GMX_MPI
-    /* Communicate only the number of atoms */
-    MPI_Isend(&n,sizeof(n),MPI_BYTE,
-             dd->pme_nodeid,0,cr->mpi_comm_mysim,
-             &dd->req_pme[dd->nreq_pme++]);
-#endif
-  }
-
-#ifdef GMX_MPI
-  if (n > 0) {
-    if (flags & PP_PME_CHARGE) {
-      MPI_Isend(chargeA,n*sizeof(real),MPI_BYTE,
-               dd->pme_nodeid,1,cr->mpi_comm_mysim,
-               &dd->req_pme[dd->nreq_pme++]);
-    }
-    if (flags & PP_PME_CHARGEB) {
-      MPI_Isend(chargeB,n*sizeof(real),MPI_BYTE,
-               dd->pme_nodeid,2,cr->mpi_comm_mysim,
-               &dd->req_pme[dd->nreq_pme++]);
-    }
-    if (flags & PP_PME_COORD) {
-      MPI_Isend(x[0],n*sizeof(rvec),MPI_BYTE,
-               dd->pme_nodeid,3,cr->mpi_comm_mysim,
-               &dd->req_pme[dd->nreq_pme++]);
-    }
-  }
-
-#ifndef GMX_PME_DELAYED_WAIT
-  /* Wait for the data to arrive */
-  /* We can skip this wait as we are sure x and q will not be modified
-   * before the next call to gmx_pme_send_x_q or gmx_pme_receive_f.
-   */
-  gmx_pme_send_q_x_wait(dd);
-#endif
-#endif
-}
-
-void gmx_pme_send_q(t_commrec *cr,
-                   gmx_bool bFreeEnergy, real *chargeA, real *chargeB,
-                   int maxshift_x, int maxshift_y)
-{
-  int flags;
-
-  flags = PP_PME_CHARGE;
-  if (bFreeEnergy)
-    flags |= PP_PME_CHARGEB;
-
-  gmx_pme_send_q_x(cr,flags,
-                  chargeA,chargeB,NULL,NULL,0,maxshift_x,maxshift_y,-1);
-}
-
-void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
-                   gmx_bool bFreeEnergy, real lambda,
-                   gmx_bool bEnerVir,
-                   gmx_large_int_t step)
-{
-  int flags;
-  
-  flags = PP_PME_COORD;
-  if (bFreeEnergy)
-    flags |= PP_PME_FEP;
-  if (bEnerVir)
-    flags |= PP_PME_ENER_VIR;
-
-  gmx_pme_send_q_x(cr,flags,NULL,NULL,box,x,lambda,0,0,step);
-}
-
-void gmx_pme_finish(t_commrec *cr)
-{
-  int flags;
-
-  flags = PP_PME_FINISH;
-
-  gmx_pme_send_q_x(cr,flags,NULL,NULL,NULL,NULL,0,0,0,-1);
-}
-
-int gmx_pme_recv_q_x(struct gmx_pme_pp *pme_pp,
-                     real **chargeA, real **chargeB,
-                     matrix box, rvec **x,rvec **f,
-                     int *maxshift_x, int *maxshift_y,
-                     gmx_bool *bFreeEnergy,real *lambda,
-                    gmx_bool *bEnerVir,
-                     gmx_large_int_t *step)
-{
-    gmx_pme_comm_n_box_t cnb;
-    int  nat=0,q,messages,sender;
-    real *charge_pp;
-
-    messages = 0;
-
-    /* avoid compiler warning about unused variable without MPI support */
-    cnb.flags = 0;     
-#ifdef GMX_MPI
-    do {
-        /* Receive the send count, box and time step from the peer PP node */
-        MPI_Recv(&cnb,sizeof(cnb),MPI_BYTE,
-                 pme_pp->node_peer,0,
-                 pme_pp->mpi_comm_mysim,MPI_STATUS_IGNORE);
-
-        if (debug)
-            fprintf(debug,"PME only node receiving:%s%s%s\n",
-                    (cnb.flags & PP_PME_CHARGE) ? " charges" : "",
-                        (cnb.flags & PP_PME_COORD ) ? " coordinates" : "",
-                            (cnb.flags & PP_PME_FINISH) ? " finish" : "");
-
-        if (cnb.flags & PP_PME_CHARGE) {
-            /* Receive the send counts from the other PP nodes */
-            for(sender=0; sender<pme_pp->nnode; sender++) {
-                if (pme_pp->node[sender] == pme_pp->node_peer) {
-                    pme_pp->nat[sender] = cnb.natoms;
-                } else {
-                    MPI_Irecv(&(pme_pp->nat[sender]),sizeof(pme_pp->nat[0]),
-                              MPI_BYTE,
-                              pme_pp->node[sender],0,
-                              pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
-                }
-            }
-            MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
-            messages = 0;
-
-            nat = 0;
-            for(sender=0; sender<pme_pp->nnode; sender++)
-                nat += pme_pp->nat[sender];
-
-            if (nat > pme_pp->nalloc) {
-                pme_pp->nalloc = over_alloc_dd(nat);
-                srenew(pme_pp->chargeA,pme_pp->nalloc);
-                if (cnb.flags & PP_PME_CHARGEB)
-                    srenew(pme_pp->chargeB,pme_pp->nalloc);
-                srenew(pme_pp->x,pme_pp->nalloc);
-                srenew(pme_pp->f,pme_pp->nalloc);
-            }
-
-            /* maxshift is sent when the charges are sent */
-            *maxshift_x = cnb.maxshift_x;
-            *maxshift_y = cnb.maxshift_y;
-
-            /* Receive the charges in place */
-            for(q=0; q<((cnb.flags & PP_PME_CHARGEB) ? 2 : 1); q++) {
-                if (q == 0)
-                    charge_pp = pme_pp->chargeA;
-                else
-                    charge_pp = pme_pp->chargeB;
-                nat = 0;
-                for(sender=0; sender<pme_pp->nnode; sender++) {
-                    if (pme_pp->nat[sender] > 0) {
-                        MPI_Irecv(charge_pp+nat,
-                                  pme_pp->nat[sender]*sizeof(real),
-                                  MPI_BYTE,
-                                  pme_pp->node[sender],1+q,
-                                  pme_pp->mpi_comm_mysim,
-                                  &pme_pp->req[messages++]);
-                        nat += pme_pp->nat[sender];
-                        if (debug)
-                            fprintf(debug,"Received from PP node %d: %d "
-                                "charges\n",
-                                    pme_pp->node[sender],pme_pp->nat[sender]);
-                    }
-                }
-            }
-
-            pme_pp->flags_charge = cnb.flags;
-        }
-
-        if (cnb.flags & PP_PME_COORD) {
-            if (!(pme_pp->flags_charge & PP_PME_CHARGE))
-                gmx_incons("PME-only node received coordinates before charges"
-                    );
-
-            /* The box, FE flag and lambda are sent along with the coordinates
-             *  */
-            copy_mat(cnb.box,box);
-            *bFreeEnergy = (cnb.flags & PP_PME_FEP);
-            *lambda      = cnb.lambda;
-           *bEnerVir    = (cnb.flags & PP_PME_ENER_VIR);
-
-            if (*bFreeEnergy && !(pme_pp->flags_charge & PP_PME_CHARGEB))
-                gmx_incons("PME-only node received free energy request, but "
-                    "did not receive B-state charges");
-
-            /* Receive the coordinates in place */
-            nat = 0;
-            for(sender=0; sender<pme_pp->nnode; sender++) {
-                if (pme_pp->nat[sender] > 0) {
-                    MPI_Irecv(pme_pp->x[nat],pme_pp->nat[sender]*sizeof(rvec),
-                              MPI_BYTE,
-                              pme_pp->node[sender],3,
-                              pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
-                    nat += pme_pp->nat[sender];
-                    if (debug)
-                        fprintf(debug,"Received from PP node %d: %d "
-                            "coordinates\n",
-                                pme_pp->node[sender],pme_pp->nat[sender]);
-                }
-            }
-        }
-
-        /* Wait for the coordinates and/or charges to arrive */
-        MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
-        messages = 0;
-    } while (!(cnb.flags & (PP_PME_COORD | PP_PME_FINISH)));
-
-    *step = cnb.step;
-#endif
-
-    *chargeA = pme_pp->chargeA;
-    *chargeB = pme_pp->chargeB;
-    *x       = pme_pp->x;
-    *f       = pme_pp->f;
-
-
-    return ((cnb.flags & PP_PME_FINISH) ? -1 : nat);
-}
-
-static void receive_virial_energy(t_commrec *cr,
-                                 matrix vir,real *energy,real *dvdlambda,
-                                 float *pme_cycles) 
-{
-  gmx_pme_comm_vir_ene_t cve;
-
-  if (cr->dd->pme_receive_vir_ener) {
-    if (debug)
-      fprintf(debug,
-             "PP node %d receiving from PME node %d: virial and energy\n",
-             cr->sim_nodeid,cr->dd->pme_nodeid);
-#ifdef GMX_MPI
-    MPI_Recv(&cve,sizeof(cve),MPI_BYTE,cr->dd->pme_nodeid,1,cr->mpi_comm_mysim,
-            MPI_STATUS_IGNORE);
-#else
-    memset(&cve,0,sizeof(cve));
-#endif
-       
-    m_add(vir,cve.vir,vir);
-    *energy = cve.energy;
-    *dvdlambda += cve.dvdlambda;
-    *pme_cycles = cve.cycles;
-
-    if ( cve.stop_cond != gmx_stop_cond_none )
-    {
-        gmx_set_stop_condition(cve.stop_cond);
-    }
-  } else {
-    *energy = 0;
-    *pme_cycles = 0;
-  }
-}
-
-void gmx_pme_receive_f(t_commrec *cr,
-                      rvec f[], matrix vir, 
-                      real *energy, real *dvdlambda,
-                      float *pme_cycles)
-{
-  int natoms,i;
-
-#ifdef GMX_PME_DELAYED_WAIT
-  /* Wait for the x request to finish */
-  gmx_pme_send_q_x_wait(cr->dd);
-#endif
-
-  natoms = cr->dd->nat_home;
-
-  if (natoms > cr->dd->pme_recv_f_alloc)
-  {
-      cr->dd->pme_recv_f_alloc = over_alloc_dd(natoms);
-      srenew(cr->dd->pme_recv_f_buf, cr->dd->pme_recv_f_alloc);
-  }
-
-#ifdef GMX_MPI  
-  MPI_Recv(cr->dd->pme_recv_f_buf[0], 
-           natoms*sizeof(rvec),MPI_BYTE,
-          cr->dd->pme_nodeid,0,cr->mpi_comm_mysim,
-          MPI_STATUS_IGNORE);
-#endif
-
-  for(i=0; i<natoms; i++)
-      rvec_inc(f[i],cr->dd->pme_recv_f_buf[i]);
-
-  
-  receive_virial_energy(cr,vir,energy,dvdlambda,pme_cycles);
-}
-
-void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
-                                rvec *f, matrix vir,
-                                real energy, real dvdlambda,
-                                float cycles)
-{
-  gmx_pme_comm_vir_ene_t cve; 
-  int messages,ind_start,ind_end,receiver;
-
-  cve.cycles = cycles;
-
-  /* Now the evaluated forces have to be transferred to the PP nodes */
-  messages = 0;
-  ind_end = 0;
-  for (receiver=0; receiver<pme_pp->nnode; receiver++) {
-    ind_start = ind_end;
-    ind_end   = ind_start + pme_pp->nat[receiver];
-#ifdef GMX_MPI
-    if (MPI_Isend(f[ind_start],(ind_end-ind_start)*sizeof(rvec),MPI_BYTE,
-                 pme_pp->node[receiver],0,
-                 pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]) != 0)
-      gmx_comm("MPI_Isend failed in do_pmeonly");
-#endif
-    }
-  
-  /* send virial and energy to our last PP node */
-  copy_mat(vir,cve.vir);
-  cve.energy    = energy;
-  cve.dvdlambda = dvdlambda;
-  /* check for the signals to send back to a PP node */
-  cve.stop_cond = gmx_get_stop_condition();
-  cve.cycles = cycles;
-  
-  if (debug)
-    fprintf(debug,"PME node sending to PP node %d: virial and energy\n",
-           pme_pp->node_peer);
-#ifdef GMX_MPI
-  MPI_Isend(&cve,sizeof(cve),MPI_BYTE,
-           pme_pp->node_peer,1,
-           pme_pp->mpi_comm_mysim,&pme_pp->req[messages++]);
-  
-  /* Wait for the forces to arrive */
-  MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
-#endif
-}
diff --git a/src/mdlib/sim_util.c b/src/mdlib/sim_util.c
deleted file mode 100644 (file)
index 60ef80e..0000000
+++ /dev/null
@@ -1,1534 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef GMX_CRAY_XT3
-#include<catamount/dclock.h>
-#endif
-
-
-#include <stdio.h>
-#include <time.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <math.h>
-#include "typedefs.h"
-#include "string2.h"
-#include "gmxfio.h"
-#include "smalloc.h"
-#include "names.h"
-#include "confio.h"
-#include "mvdata.h"
-#include "txtdump.h"
-#include "pbc.h"
-#include "chargegroup.h"
-#include "vec.h"
-#include "time.h"
-#include "nrnb.h"
-#include "mshift.h"
-#include "mdrun.h"
-#include "update.h"
-#include "physics.h"
-#include "main.h"
-#include "mdatoms.h"
-#include "force.h"
-#include "bondf.h"
-#include "pme.h"
-#include "pppm.h"
-#include "disre.h"
-#include "orires.h"
-#include "network.h"
-#include "calcmu.h"
-#include "constr.h"
-#include "xvgr.h"
-#include "trnio.h"
-#include "xtcio.h"
-#include "copyrite.h"
-
-#include "mpelogging.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "gmx_wallcycle.h"
-#include "genborn.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#include "qmmm.h"
-
-#if 0
-typedef struct gmx_timeprint {
-    
-} t_gmx_timeprint;
-#endif
-
-/* Portable version of ctime_r implemented in src/gmxlib/string2.c, but we do not want it declared in public installed headers */
-char *
-gmx_ctime_r(const time_t *clock,char *buf, int n);
-
-
-double
-gmx_gettime()
-{
-#ifdef HAVE_GETTIMEOFDAY
-       struct timeval t;
-       double seconds;
-       
-       gettimeofday(&t,NULL);
-       
-       seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
-       
-       return seconds;
-#else
-       double  seconds;
-       
-       seconds = time(NULL);
-       
-       return seconds;
-#endif
-}
-
-
-#define difftime(end,start) ((double)(end)-(double)(start))
-
-void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,   
-                t_inputrec *ir, t_commrec *cr)
-{
-    time_t finish;
-    char   timebuf[STRLEN];
-    double dt;
-    char buf[48];
-    
-#ifndef GMX_THREADS
-    if (!PAR(cr))
-#endif
-    {
-        fprintf(out,"\r");
-    }
-    fprintf(out,"step %s",gmx_step_str(step,buf));
-    if ((step >= ir->nstlist))
-    {
-        if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0))
-        {
-            /* We have done a full cycle let's update time_per_step */
-            runtime->last = gmx_gettime();
-            dt = difftime(runtime->last,runtime->real);
-            runtime->time_per_step = dt/(step - ir->init_step + 1);
-        }
-        dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
-        
-        if (ir->nsteps >= 0)
-        {
-            if (dt >= 300)
-            {    
-                finish = (time_t) (runtime->last + dt);
-                gmx_ctime_r(&finish,timebuf,STRLEN);
-                sprintf(buf,"%s",timebuf);
-                buf[strlen(buf)-1]='\0';
-                fprintf(out,", will finish %s",buf);
-            }
-            else
-                fprintf(out,", remaining runtime: %5d s          ",(int)dt);
-        }
-        else
-        {
-            fprintf(out," performance: %.1f ns/day    ",
-                    ir->delta_t/1000*24*60*60/runtime->time_per_step);
-        }
-    }
-#ifndef GMX_THREADS
-    if (PAR(cr))
-    {
-        fprintf(out,"\n");
-    }
-#endif
-
-    fflush(out);
-}
-
-#ifdef NO_CLOCK 
-#define clock() -1
-#endif
-
-static double set_proctime(gmx_runtime_t *runtime)
-{
-    double diff;
-#ifdef GMX_CRAY_XT3
-    double prev;
-
-    prev = runtime->proc;
-    runtime->proc = dclock();
-    
-    diff = runtime->proc - prev;
-#else
-    clock_t prev;
-
-    prev = runtime->proc;
-    runtime->proc = clock();
-
-    diff = (double)(runtime->proc - prev)/(double)CLOCKS_PER_SEC;
-#endif
-    if (diff < 0)
-    {
-        /* The counter has probably looped, ignore this data */
-        diff = 0;
-    }
-
-    return diff;
-}
-
-void runtime_start(gmx_runtime_t *runtime)
-{
-    runtime->real = gmx_gettime();
-    runtime->proc          = 0;
-    set_proctime(runtime);
-    runtime->realtime      = 0;
-    runtime->proctime      = 0;
-    runtime->last          = 0;
-    runtime->time_per_step = 0;
-}
-
-void runtime_end(gmx_runtime_t *runtime)
-{
-    double now;
-    
-    now = gmx_gettime();
-    
-    runtime->proctime += set_proctime(runtime);
-    runtime->realtime  = now - runtime->real;
-    runtime->real      = now;
-}
-
-void runtime_upd_proc(gmx_runtime_t *runtime)
-{
-    runtime->proctime += set_proctime(runtime);
-}
-
-void print_date_and_time(FILE *fplog,int nodeid,const char *title,
-                         const gmx_runtime_t *runtime)
-{
-    int i;
-    char timebuf[STRLEN];
-    char time_string[STRLEN];
-    time_t tmptime;
-
-    if (fplog)
-    {
-        if (runtime != NULL)
-        {
-            tmptime = (time_t) runtime->real;
-            gmx_ctime_r(&tmptime,timebuf,STRLEN);
-        }
-        else
-        {
-            tmptime = (time_t) gmx_gettime();
-            gmx_ctime_r(&tmptime,timebuf,STRLEN);
-        }
-        for(i=0; timebuf[i]>=' '; i++)
-        {
-            time_string[i]=timebuf[i];
-        }
-        time_string[i]='\0';
-
-        fprintf(fplog,"%s on node %d %s\n",title,nodeid,time_string);
-    }
-}
-
-static void sum_forces(int start,int end,rvec f[],rvec flr[])
-{
-  int i;
-  
-  if (gmx_debug_at) {
-    pr_rvecs(debug,0,"fsr",f+start,end-start);
-    pr_rvecs(debug,0,"flr",flr+start,end-start);
-  }
-  for(i=start; (i<end); i++)
-    rvec_inc(f[i],flr[i]);
-}
-
-/* 
- * calc_f_el calculates forces due to an electric field.
- *
- * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e 
- *
- * Et[] contains the parameters for the time dependent 
- * part of the field (not yet used). 
- * Ex[] contains the parameters for
- * the spatial dependent part of the field. You can have cool periodic
- * fields in principle, but only a constant field is supported
- * now. 
- * The function should return the energy due to the electric field
- * (if any) but for now returns 0.
- *
- * WARNING:
- * There can be problems with the virial.
- * Since the field is not self-consistent this is unavoidable.
- * For neutral molecules the virial is correct within this approximation.
- * For neutral systems with many charged molecules the error is small.
- * But for systems with a net charge or a few charged molecules
- * the error can be significant when the field is high.
- * Solution: implement a self-consitent electric field into PME.
- */
-static void calc_f_el(FILE *fp,int  start,int homenr,
-                      real charge[],rvec x[],rvec f[],
-                      t_cosines Ex[],t_cosines Et[],double t)
-{
-    rvec Ext;
-    real t0;
-    int  i,m;
-    
-    for(m=0; (m<DIM); m++)
-    {
-        if (Et[m].n > 0)
-        {
-            if (Et[m].n == 3)
-            {
-                t0 = Et[m].a[1];
-                Ext[m] = cos(Et[m].a[0]*(t-t0))*exp(-sqr(t-t0)/(2.0*sqr(Et[m].a[2])));
-            }
-            else
-            {
-                Ext[m] = cos(Et[m].a[0]*t);
-            }
-        }
-        else
-        {
-            Ext[m] = 1.0;
-        }
-        if (Ex[m].n > 0)
-        {
-            /* Convert the field strength from V/nm to MD-units */
-            Ext[m] *= Ex[m].a[0]*FIELDFAC;
-            for(i=start; (i<start+homenr); i++)
-                f[i][m] += charge[i]*Ext[m];
-        }
-        else
-        {
-            Ext[m] = 0;
-        }
-    }
-    if (fp != NULL)
-    {
-        fprintf(fp,"%10g  %10g  %10g  %10g #FIELD\n",t,
-                Ext[XX]/FIELDFAC,Ext[YY]/FIELDFAC,Ext[ZZ]/FIELDFAC);
-    }
-}
-
-static void calc_virial(FILE *fplog,int start,int homenr,rvec x[],rvec f[],
-                       tensor vir_part,t_graph *graph,matrix box,
-                       t_nrnb *nrnb,const t_forcerec *fr,int ePBC)
-{
-  int i,j;
-  tensor virtest;
-
-  /* The short-range virial from surrounding boxes */
-  clear_mat(vir_part);
-  calc_vir(fplog,SHIFTS,fr->shift_vec,fr->fshift,vir_part,ePBC==epbcSCREW,box);
-  inc_nrnb(nrnb,eNR_VIRIAL,SHIFTS);
-  
-  /* Calculate partial virial, for local atoms only, based on short range. 
-   * Total virial is computed in global_stat, called from do_md 
-   */
-  f_calc_vir(fplog,start,start+homenr,x,f,vir_part,graph,box);
-  inc_nrnb(nrnb,eNR_VIRIAL,homenr);
-
-  /* Add position restraint contribution */
-  for(i=0; i<DIM; i++) {
-    vir_part[i][i] += fr->vir_diag_posres[i];
-  }
-
-  /* Add wall contribution */
-  for(i=0; i<DIM; i++) {
-    vir_part[i][ZZ] += fr->vir_wall_z[i];
-  }
-
-  if (debug)
-    pr_rvecs(debug,0,"vir_part",vir_part,DIM);
-}
-
-static void print_large_forces(FILE *fp,t_mdatoms *md,t_commrec *cr,
-                              gmx_large_int_t step,real pforce,rvec *x,rvec *f)
-{
-  int  i;
-  real pf2,fn2;
-  char buf[STEPSTRSIZE];
-
-  pf2 = sqr(pforce);
-  for(i=md->start; i<md->start+md->homenr; i++) {
-    fn2 = norm2(f[i]);
-    /* We also catch NAN, if the compiler does not optimize this away. */
-    if (fn2 >= pf2 || fn2 != fn2) {
-      fprintf(fp,"step %s  atom %6d  x %8.3f %8.3f %8.3f  force %12.5e\n",
-             gmx_step_str(step,buf),
-             ddglatnr(cr->dd,i),x[i][XX],x[i][YY],x[i][ZZ],sqrt(fn2));
-    }
-  }
-}
-
-void do_force(FILE *fplog,t_commrec *cr,
-              t_inputrec *inputrec,
-              gmx_large_int_t step,t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-              gmx_localtop_t *top,
-              gmx_mtop_t *mtop,
-              gmx_groups_t *groups,
-              matrix box,rvec x[],history_t *hist,
-              rvec f[],
-              tensor vir_force,
-              t_mdatoms *mdatoms,
-              gmx_enerdata_t *enerd,t_fcdata *fcd,
-              real lambda,t_graph *graph,
-              t_forcerec *fr,gmx_vsite_t *vsite,rvec mu_tot,
-              double t,FILE *field,gmx_edsam_t ed,
-              gmx_bool bBornRadii,
-              int flags)
-{
-    int    cg0,cg1,i,j;
-    int    start,homenr;
-    double mu[2*DIM]; 
-    gmx_bool   bSepDVDL,bStateChanged,bNS,bFillGrid,bCalcCGCM,bBS;
-    gmx_bool   bDoLongRange,bDoForces,bSepLRF;
-    matrix boxs;
-    real   e,v,dvdl;
-    t_pbc  pbc;
-    float  cycles_ppdpme,cycles_pme,cycles_seppme,cycles_force;
-  
-    start  = mdatoms->start;
-    homenr = mdatoms->homenr;
-
-    bSepDVDL = (fr->bSepDVDL && do_per_step(step,inputrec->nstlog));
-
-    clear_mat(vir_force);
-
-    if (PARTDECOMP(cr))
-    {
-        pd_cg_range(cr,&cg0,&cg1);
-    }
-    else
-    {
-        cg0 = 0;
-        if (DOMAINDECOMP(cr))
-        {
-            cg1 = cr->dd->ncg_tot;
-        }
-        else
-        {
-            cg1 = top->cgs.nr;
-        }
-        if (fr->n_tpi > 0)
-        {
-            cg1--;
-        }
-    }
-
-    bStateChanged = (flags & GMX_FORCE_STATECHANGED);
-    bNS           = (flags & GMX_FORCE_NS) && (fr->bAllvsAll==FALSE); 
-    bFillGrid     = (bNS && bStateChanged);
-    bCalcCGCM     = (bFillGrid && !DOMAINDECOMP(cr));
-    bDoLongRange  = (fr->bTwinRange && bNS && (flags & GMX_FORCE_DOLR));
-    bDoForces     = (flags & GMX_FORCE_FORCES);
-    bSepLRF       = (bDoLongRange && bDoForces && (flags & GMX_FORCE_SEPLRF));
-
-    if (bStateChanged)
-    {
-        update_forcerec(fplog,fr,box);
-        
-        /* Calculate total (local) dipole moment in a temporary common array. 
-         * This makes it possible to sum them over nodes faster.
-         */
-        calc_mu(start,homenr,
-                x,mdatoms->chargeA,mdatoms->chargeB,mdatoms->nChargePerturbed,
-                mu,mu+DIM);
-    }
-  
-  if (fr->ePBC != epbcNONE) { 
-    /* Compute shift vectors every step,
-     * because of pressure coupling or box deformation!
-     */
-    if ((flags & GMX_FORCE_DYNAMICBOX) && bStateChanged)
-      calc_shifts(box,fr->shift_vec);
-    
-    if (bCalcCGCM) { 
-      put_charge_groups_in_box(fplog,cg0,cg1,fr->ePBC,box,
-                              &(top->cgs),x,fr->cg_cm);
-      inc_nrnb(nrnb,eNR_CGCM,homenr);
-      inc_nrnb(nrnb,eNR_RESETX,cg1-cg0);
-    } 
-    else if (EI_ENERGY_MINIMIZATION(inputrec->eI) && graph) {
-      unshift_self(graph,box,x);
-    }
-  } 
-  else if (bCalcCGCM) {
-    calc_cgcm(fplog,cg0,cg1,&(top->cgs),x,fr->cg_cm);
-    inc_nrnb(nrnb,eNR_CGCM,homenr);
-  }
-  
-  if (bCalcCGCM) {
-    if (PAR(cr)) {
-      move_cgcm(fplog,cr,fr->cg_cm);
-    }
-    if (gmx_debug_at)
-      pr_rvecs(debug,0,"cgcm",fr->cg_cm,top->cgs.nr);
-  }
-
-#ifdef GMX_MPI
-  if (!(cr->duty & DUTY_PME)) {
-    /* Send particle coordinates to the pme nodes.
-     * Since this is only implemented for domain decomposition
-     * and domain decomposition does not use the graph,
-     * we do not need to worry about shifting.
-     */    
-
-    wallcycle_start(wcycle,ewcPP_PMESENDX);
-    GMX_MPE_LOG(ev_send_coordinates_start);
-
-    bBS = (inputrec->nwall == 2);
-    if (bBS) {
-      copy_mat(box,boxs);
-      svmul(inputrec->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
-    }
-
-    gmx_pme_send_x(cr,bBS ? boxs : box,x,
-                   mdatoms->nChargePerturbed,lambda,
-                   ( flags & GMX_FORCE_VIRIAL),step);
-
-    GMX_MPE_LOG(ev_send_coordinates_finish);
-    wallcycle_stop(wcycle,ewcPP_PMESENDX);
-  }
-#endif /* GMX_MPI */
-
-    /* Communicate coordinates and sum dipole if necessary */
-    if (PAR(cr))
-    {
-        wallcycle_start(wcycle,ewcMOVEX);
-        if (DOMAINDECOMP(cr))
-        {
-            dd_move_x(cr->dd,box,x);
-        }
-        else
-        {
-            move_x(fplog,cr,GMX_LEFT,GMX_RIGHT,x,nrnb);
-        }
-        /* When we don't need the total dipole we sum it in global_stat */
-        if (bStateChanged && NEED_MUTOT(*inputrec))
-        {
-            gmx_sumd(2*DIM,mu,cr);
-        }
-        wallcycle_stop(wcycle,ewcMOVEX);
-    }
-    if (bStateChanged)
-    {
-        for(i=0; i<2; i++)
-        {
-            for(j=0;j<DIM;j++)
-            {
-                fr->mu_tot[i][j] = mu[i*DIM + j];
-            }
-        }
-    }
-    if (fr->efep == efepNO)
-    {
-        copy_rvec(fr->mu_tot[0],mu_tot);
-    }
-    else
-    {
-        for(j=0; j<DIM; j++)
-        {
-            mu_tot[j] =
-                (1.0 - lambda)*fr->mu_tot[0][j] + lambda*fr->mu_tot[1][j];
-        }
-    }
-
-    /* Reset energies */
-    reset_enerdata(&(inputrec->opts),fr,bNS,enerd,MASTER(cr));
-    clear_rvecs(SHIFTS,fr->fshift);
-
-    if (bNS)
-    {
-        wallcycle_start(wcycle,ewcNS);
-        
-        if (graph && bStateChanged)
-        {
-            /* Calculate intramolecular shift vectors to make molecules whole */
-            mk_mshift(fplog,graph,fr->ePBC,box,x);
-        }
-
-        /* Reset long range forces if necessary */
-        if (fr->bTwinRange)
-        {
-            /* Reset the (long-range) forces if necessary */
-            clear_rvecs(fr->natoms_force_constr,bSepLRF ? fr->f_twin : f);
-        }
-
-        /* Do the actual neighbour searching and if twin range electrostatics
-         * also do the calculation of long range forces and energies.
-         */
-        dvdl = 0; 
-        ns(fplog,fr,x,box,
-           groups,&(inputrec->opts),top,mdatoms,
-           cr,nrnb,lambda,&dvdl,&enerd->grpp,bFillGrid,
-           bDoLongRange,bDoForces,bSepLRF ? fr->f_twin : f);
-        if (bSepDVDL)
-        {
-            fprintf(fplog,sepdvdlformat,"LR non-bonded",0.0,dvdl);
-        }
-        enerd->dvdl_lin += dvdl;
-        
-        wallcycle_stop(wcycle,ewcNS);
-    }
-       
-    if (inputrec->implicit_solvent && bNS) 
-    {
-        make_gb_nblist(cr,inputrec->gb_algorithm,inputrec->rlist,
-                       x,box,fr,&top->idef,graph,fr->born);
-    }
-       
-    if (DOMAINDECOMP(cr))
-    {
-        if (!(cr->duty & DUTY_PME))
-        {
-            wallcycle_start(wcycle,ewcPPDURINGPME);
-            dd_force_flop_start(cr->dd,nrnb);
-        }
-    }
-       
-    /* Start the force cycle counter.
-     * This counter is stopped in do_forcelow_level.
-     * No parallel communication should occur while this counter is running,
-     * since that will interfere with the dynamic load balancing.
-     */
-    wallcycle_start(wcycle,ewcFORCE);
-    
-    if (bDoForces)
-    {
-        /* Reset forces for which the virial is calculated separately:
-         * PME/Ewald forces if necessary */
-        if (fr->bF_NoVirSum) 
-        {
-            if (flags & GMX_FORCE_VIRIAL)
-            {
-                fr->f_novirsum = fr->f_novirsum_alloc;
-                GMX_BARRIER(cr->mpi_comm_mygroup);
-                if (fr->bDomDec)
-                {
-                    clear_rvecs(fr->f_novirsum_n,fr->f_novirsum);
-                }
-                else
-                {
-                    clear_rvecs(homenr,fr->f_novirsum+start);
-                }
-                GMX_BARRIER(cr->mpi_comm_mygroup);
-            }
-            else
-            {
-                /* We are not calculating the pressure so we do not need
-                 * a separate array for forces that do not contribute
-                 * to the pressure.
-                 */
-                fr->f_novirsum = f;
-            }
-        }
-
-        if (bSepLRF)
-        {
-            /* Add the long range forces to the short range forces */
-            for(i=0; i<fr->natoms_force_constr; i++)
-            {
-                copy_rvec(fr->f_twin[i],f[i]);
-            }
-        }
-        else if (!(fr->bTwinRange && bNS))
-        {
-            /* Clear the short-range forces */
-            clear_rvecs(fr->natoms_force_constr,f);
-        }
-
-        clear_rvec(fr->vir_diag_posres);
-
-        GMX_BARRIER(cr->mpi_comm_mygroup);
-    }
-    if (inputrec->ePull == epullCONSTRAINT)
-    {
-        clear_pull_forces(inputrec->pull);
-    }
-
-    /* update QMMMrec, if necessary */
-    if(fr->bQMMM)
-    {
-        update_QMMMrec(cr,fr,x,mdatoms,box,top);
-    }
-
-    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
-    {
-        /* Position restraints always require full pbc */
-        set_pbc(&pbc,inputrec->ePBC,box);
-        v = posres(top->idef.il[F_POSRES].nr,top->idef.il[F_POSRES].iatoms,
-                   top->idef.iparams_posres,
-                   (const rvec*)x,fr->f_novirsum,fr->vir_diag_posres,
-                   inputrec->ePBC==epbcNONE ? NULL : &pbc,lambda,&dvdl,
-                   fr->rc_scaling,fr->ePBC,fr->posres_com,fr->posres_comB);
-        if (bSepDVDL)
-        {
-            fprintf(fplog,sepdvdlformat,
-                    interaction_function[F_POSRES].longname,v,dvdl);
-        }
-        enerd->term[F_POSRES] += v;
-        /* This linear lambda dependence assumption is only correct
-         * when only k depends on lambda,
-         * not when the reference position depends on lambda.
-         * grompp checks for this.
-         */
-        enerd->dvdl_lin += dvdl;
-        inc_nrnb(nrnb,eNR_POSRES,top->idef.il[F_POSRES].nr/2);
-    }
-
-    /* Compute the bonded and non-bonded energies and optionally forces */    
-    do_force_lowlevel(fplog,step,fr,inputrec,&(top->idef),
-                      cr,nrnb,wcycle,mdatoms,&(inputrec->opts),
-                      x,hist,f,enerd,fcd,mtop,top,fr->born,
-                      &(top->atomtypes),bBornRadii,box,
-                      lambda,graph,&(top->excls),fr->mu_tot,
-                      flags,&cycles_pme);
-    
-    cycles_force = wallcycle_stop(wcycle,ewcFORCE);
-    GMX_BARRIER(cr->mpi_comm_mygroup);
-    
-    if (ed)
-    {
-        do_flood(fplog,cr,x,f,ed,box,step);
-    }
-       
-    if (DOMAINDECOMP(cr))
-    {
-        dd_force_flop_stop(cr->dd,nrnb);
-        if (wcycle)
-        {
-            dd_cycles_add(cr->dd,cycles_force-cycles_pme,ddCyclF);
-        }
-    }
-    
-    if (bDoForces)
-    {
-        if (IR_ELEC_FIELD(*inputrec))
-        {
-            /* Compute forces due to electric field */
-            calc_f_el(MASTER(cr) ? field : NULL,
-                      start,homenr,mdatoms->chargeA,x,fr->f_novirsum,
-                      inputrec->ex,inputrec->et,t);
-        }
-        
-        /* Communicate the forces */
-        if (PAR(cr))
-        {
-            wallcycle_start(wcycle,ewcMOVEF);
-            if (DOMAINDECOMP(cr))
-            {
-                dd_move_f(cr->dd,f,fr->fshift);
-                /* Do we need to communicate the separate force array
-                 * for terms that do not contribute to the single sum virial?
-                 * Position restraints and electric fields do not introduce
-                 * inter-cg forces, only full electrostatics methods do.
-                 * When we do not calculate the virial, fr->f_novirsum = f,
-                 * so we have already communicated these forces.
-                 */
-                if (EEL_FULL(fr->eeltype) && cr->dd->n_intercg_excl &&
-                    (flags & GMX_FORCE_VIRIAL))
-                {
-                    dd_move_f(cr->dd,fr->f_novirsum,NULL);
-                }
-                if (bSepLRF)
-                {
-                    /* We should not update the shift forces here,
-                     * since f_twin is already included in f.
-                     */
-                    dd_move_f(cr->dd,fr->f_twin,NULL);
-                }
-            }
-            else
-            {
-                pd_move_f(cr,f,nrnb);
-                if (bSepLRF)
-                {
-                    pd_move_f(cr,fr->f_twin,nrnb);
-                }
-            }
-            wallcycle_stop(wcycle,ewcMOVEF);
-        }
-
-        /* If we have NoVirSum forces, but we do not calculate the virial,
-         * we sum fr->f_novirum=f later.
-         */
-        if (vsite && !(fr->bF_NoVirSum && !(flags & GMX_FORCE_VIRIAL)))
-        {
-            wallcycle_start(wcycle,ewcVSITESPREAD);
-            spread_vsite_f(fplog,vsite,x,f,fr->fshift,nrnb,
-                           &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
-            wallcycle_stop(wcycle,ewcVSITESPREAD);
-
-            if (bSepLRF)
-            {
-                wallcycle_start(wcycle,ewcVSITESPREAD);
-                spread_vsite_f(fplog,vsite,x,fr->f_twin,NULL,
-                               nrnb,
-                               &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
-                wallcycle_stop(wcycle,ewcVSITESPREAD);
-            }
-        }
-        
-        if (flags & GMX_FORCE_VIRIAL)
-        {
-            /* Calculation of the virial must be done after vsites! */
-            calc_virial(fplog,mdatoms->start,mdatoms->homenr,x,f,
-                        vir_force,graph,box,nrnb,fr,inputrec->ePBC);
-        }
-    }
-
-    if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F)
-    {
-        /* Calculate the center of mass forces, this requires communication,
-         * which is why pull_potential is called close to other communication.
-         * The virial contribution is calculated directly,
-         * which is why we call pull_potential after calc_virial.
-         */
-        set_pbc(&pbc,inputrec->ePBC,box);
-        dvdl = 0; 
-        enerd->term[F_COM_PULL] =
-            pull_potential(inputrec->ePull,inputrec->pull,mdatoms,&pbc,
-                           cr,t,lambda,x,f,vir_force,&dvdl);
-        if (bSepDVDL)
-        {
-            fprintf(fplog,sepdvdlformat,"Com pull",enerd->term[F_COM_PULL],dvdl);
-        }
-        enerd->dvdl_lin += dvdl;
-    }
-
-    if (PAR(cr) && !(cr->duty & DUTY_PME))
-    {
-        cycles_ppdpme = wallcycle_stop(wcycle,ewcPPDURINGPME);
-        dd_cycles_add(cr->dd,cycles_ppdpme,ddCyclPPduringPME);
-
-        /* In case of node-splitting, the PP nodes receive the long-range 
-         * forces, virial and energy from the PME nodes here.
-         */    
-        wallcycle_start(wcycle,ewcPP_PMEWAITRECVF);
-        dvdl = 0;
-        gmx_pme_receive_f(cr,fr->f_novirsum,fr->vir_el_recip,&e,&dvdl,
-                          &cycles_seppme);
-        if (bSepDVDL)
-        {
-            fprintf(fplog,sepdvdlformat,"PME mesh",e,dvdl);
-        }
-        enerd->term[F_COUL_RECIP] += e;
-        enerd->dvdl_lin += dvdl;
-        if (wcycle)
-        {
-            dd_cycles_add(cr->dd,cycles_seppme,ddCyclPME);
-        }
-        wallcycle_stop(wcycle,ewcPP_PMEWAITRECVF);
-    }
-
-    if (bDoForces && fr->bF_NoVirSum)
-    {
-        if (vsite)
-        {
-            /* Spread the mesh force on virtual sites to the other particles... 
-             * This is parallellized. MPI communication is performed
-             * if the constructing atoms aren't local.
-             */
-            wallcycle_start(wcycle,ewcVSITESPREAD);
-            spread_vsite_f(fplog,vsite,x,fr->f_novirsum,NULL,nrnb,
-                           &top->idef,fr->ePBC,fr->bMolPBC,graph,box,cr);
-            wallcycle_stop(wcycle,ewcVSITESPREAD);
-        }
-        if (flags & GMX_FORCE_VIRIAL)
-        {
-            /* Now add the forces, this is local */
-            if (fr->bDomDec)
-            {
-                sum_forces(0,fr->f_novirsum_n,f,fr->f_novirsum);
-            }
-            else
-            {
-                sum_forces(start,start+homenr,f,fr->f_novirsum);
-            }
-            if (EEL_FULL(fr->eeltype))
-            {
-                /* Add the mesh contribution to the virial */
-                m_add(vir_force,fr->vir_el_recip,vir_force);
-            }
-            if (debug)
-            {
-                pr_rvecs(debug,0,"vir_force",vir_force,DIM);
-            }
-        }
-    }
-    
-    /* Sum the potential energy terms from group contributions */
-    sum_epot(&(inputrec->opts),enerd);
-    
-    if (fr->print_force >= 0 && bDoForces)
-    {
-        print_large_forces(stderr,mdatoms,cr,step,fr->print_force,x,f);
-    }
-}
-
-void do_constrain_first(FILE *fplog,gmx_constr_t constr,
-                        t_inputrec *ir,t_mdatoms *md,
-                        t_state *state,rvec *f,
-                        t_graph *graph,t_commrec *cr,t_nrnb *nrnb,
-                        t_forcerec *fr, gmx_localtop_t *top, tensor shake_vir)
-{
-    int    i,m,start,end;
-    gmx_large_int_t step;
-    double mass,tmass,vcm[4];
-    real   dt=ir->delta_t;
-    real   dvdlambda;
-    rvec   *savex;
-    
-    snew(savex,state->natoms);
-
-    start = md->start;
-    end   = md->homenr + start;
-    
-    if (debug)
-        fprintf(debug,"vcm: start=%d, homenr=%d, end=%d\n",
-                start,md->homenr,end);
-    /* Do a first constrain to reset particles... */
-    step = ir->init_step;
-    if (fplog)
-    {
-        char buf[STEPSTRSIZE];
-        fprintf(fplog,"\nConstraining the starting coordinates (step %s)\n",
-                gmx_step_str(step,buf));
-    }
-    dvdlambda = 0;
-    
-    /* constrain the current position */
-    constrain(NULL,TRUE,FALSE,constr,&(top->idef),
-              ir,NULL,cr,step,0,md,
-              state->x,state->x,NULL,
-              state->box,state->lambda,&dvdlambda,
-              NULL,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
-    if (EI_VV(ir->eI)) 
-    {
-        /* constrain the inital velocity, and save it */
-        /* also may be useful if we need the ekin from the halfstep for velocity verlet */
-        /* might not yet treat veta correctly */
-        constrain(NULL,TRUE,FALSE,constr,&(top->idef),
-                  ir,NULL,cr,step,0,md,
-                  state->x,state->v,state->v,
-                  state->box,state->lambda,&dvdlambda,
-                  NULL,NULL,nrnb,econqVeloc,ir->epc==epcMTTK,state->veta,state->veta);
-    }
-    /* constrain the inital velocities at t-dt/2 */
-    if (EI_STATE_VELOCITY(ir->eI) && ir->eI!=eiVV)
-    {
-        for(i=start; (i<end); i++) 
-        {
-            for(m=0; (m<DIM); m++) 
-            {
-                /* Reverse the velocity */
-                state->v[i][m] = -state->v[i][m];
-                /* Store the position at t-dt in buf */
-                savex[i][m] = state->x[i][m] + dt*state->v[i][m];
-            }
-        }
-    /* Shake the positions at t=-dt with the positions at t=0                        
-     * as reference coordinates.                                                     
-         */
-        if (fplog)
-        {
-            char buf[STEPSTRSIZE];
-            fprintf(fplog,"\nConstraining the coordinates at t0-dt (step %s)\n",
-                    gmx_step_str(step,buf));
-        }
-        dvdlambda = 0;
-        constrain(NULL,TRUE,FALSE,constr,&(top->idef),
-                  ir,NULL,cr,step,-1,md,
-                  state->x,savex,NULL,
-                  state->box,state->lambda,&dvdlambda,
-                  state->v,NULL,nrnb,econqCoord,ir->epc==epcMTTK,state->veta,state->veta);
-        
-        for(i=start; i<end; i++) {
-            for(m=0; m<DIM; m++) {
-                /* Re-reverse the velocities */
-                state->v[i][m] = -state->v[i][m];
-            }
-        }
-    }
-    
-    for(m=0; (m<4); m++)
-        vcm[m] = 0;
-    for(i=start; i<end; i++) {
-        mass = md->massT[i];
-        for(m=0; m<DIM; m++) {
-            vcm[m] += state->v[i][m]*mass;
-        }
-        vcm[3] += mass;
-    }
-    
-    if (ir->nstcomm != 0 || debug) {
-        /* Compute the global sum of vcm */
-        if (debug)
-            fprintf(debug,"vcm: %8.3f  %8.3f  %8.3f,"
-                    " total mass = %12.5e\n",vcm[XX],vcm[YY],vcm[ZZ],vcm[3]);
-        if (PAR(cr))
-            gmx_sumd(4,vcm,cr);
-        tmass = vcm[3];
-        for(m=0; (m<DIM); m++)
-            vcm[m] /= tmass;
-        if (debug) 
-            fprintf(debug,"vcm: %8.3f  %8.3f  %8.3f,"
-                    " total mass = %12.5e\n",vcm[XX],vcm[YY],vcm[ZZ],tmass);
-        if (ir->nstcomm != 0) {
-            /* Now we have the velocity of center of mass, let's remove it */
-            for(i=start; (i<end); i++) {
-                for(m=0; (m<DIM); m++)
-                    state->v[i][m] -= vcm[m];
-            }
-
-        }
-    }
-    sfree(savex);
-}
-
-void calc_enervirdiff(FILE *fplog,int eDispCorr,t_forcerec *fr)
-{
-  double eners[2],virs[2],enersum,virsum,y0,f,g,h;
-  double r0,r1,r,rc3,rc9,ea,eb,ec,pa,pb,pc,pd;
-  double invscale,invscale2,invscale3;
-  int    ri0,ri1,ri,i,offstart,offset;
-  real   scale,*vdwtab; 
-
-  fr->enershiftsix = 0;
-  fr->enershifttwelve = 0;
-  fr->enerdiffsix = 0;
-  fr->enerdifftwelve = 0;
-  fr->virdiffsix = 0;
-  fr->virdifftwelve = 0;
-
-  if (eDispCorr != edispcNO) {
-    for(i=0; i<2; i++) {
-      eners[i] = 0;
-      virs[i]  = 0;
-    }
-    if ((fr->vdwtype == evdwSWITCH) || (fr->vdwtype == evdwSHIFT)) {
-      if (fr->rvdw_switch == 0)
-       gmx_fatal(FARGS,
-                 "With dispersion correction rvdw-switch can not be zero "
-                 "for vdw-type = %s",evdw_names[fr->vdwtype]);
-
-      scale  = fr->nblists[0].tab.scale;
-      vdwtab = fr->nblists[0].vdwtab;
-
-      /* Round the cut-offs to exact table values for precision */
-      ri0 = floor(fr->rvdw_switch*scale);
-      ri1 = ceil(fr->rvdw*scale);
-      r0  = ri0/scale;
-      r1  = ri1/scale;
-      rc3 = r0*r0*r0;
-      rc9  = rc3*rc3*rc3;
-
-      if (fr->vdwtype == evdwSHIFT) {
-       /* Determine the constant energy shift below rvdw_switch */
-       fr->enershiftsix    = (real)(-1.0/(rc3*rc3)) - vdwtab[8*ri0];
-       fr->enershifttwelve = (real)( 1.0/(rc9*rc3)) - vdwtab[8*ri0 + 4];
-      }
-      /* Add the constant part from 0 to rvdw_switch.
-       * This integration from 0 to rvdw_switch overcounts the number
-       * of interactions by 1, as it also counts the self interaction.
-       * We will correct for this later.
-       */
-      eners[0] += 4.0*M_PI*fr->enershiftsix*rc3/3.0;
-      eners[1] += 4.0*M_PI*fr->enershifttwelve*rc3/3.0;
-      
-      invscale = 1.0/(scale);  
-      invscale2 = invscale*invscale;
-      invscale3 = invscale*invscale2;
-
-      /* following summation derived from cubic spline definition,
-       Numerical Recipies in C, second edition, p. 113-116.  Exact
-       for the cubic spline.  We first calculate the negative of
-       the energy from rvdw to rvdw_switch, assuming that g(r)=1,
-       and then add the more standard, abrupt cutoff correction to
-       that result, yielding the long-range correction for a
-       switched function.  We perform both the pressure and energy
-       loops at the same time for simplicity, as the computational
-       cost is low. */
-      
-      for (i=0;i<2;i++) {
-        enersum = 0.0; virsum = 0.0;
-        if (i==0)
-         offstart = 0;
-       else
-         offstart = 4;
-       for (ri=ri0; ri<ri1; ri++) {
-          r = ri*invscale;
-          ea = invscale3;
-          eb = 2.0*invscale2*r;
-          ec = invscale*r*r;
-          
-          pa = invscale3;
-          pb = 3.0*invscale2*r;
-          pc = 3.0*invscale*r*r;
-          pd = r*r*r;
-          
-          /* this "8" is from the packing in the vdwtab array - perhaps
-           should be #define'ed? */
-          offset = 8*ri + offstart;
-          y0 = vdwtab[offset];
-          f = vdwtab[offset+1];
-          g = vdwtab[offset+2];
-          h = vdwtab[offset+3];
-         
-          enersum += y0*(ea/3 + eb/2 + ec) + f*(ea/4 + eb/3 + ec/2)+
-            g*(ea/5 + eb/4 + ec/3) + h*(ea/6 + eb/5 + ec/4);  
-          virsum  +=  f*(pa/4 + pb/3 + pc/2 + pd) + 
-            2*g*(pa/5 + pb/4 + pc/3 + pd/2) + 3*h*(pa/6 + pb/5 + pc/4 + pd/3);
-         
-        }
-        enersum *= 4.0*M_PI;
-        virsum  *= 4.0*M_PI; 
-        eners[i] -= enersum;
-        virs[i]  -= virsum;
-      }
-
-      /* now add the correction for rvdw_switch to infinity */
-      eners[0] += -4.0*M_PI/(3.0*rc3);
-      eners[1] +=  4.0*M_PI/(9.0*rc9);
-      virs[0]  +=  8.0*M_PI/rc3;
-      virs[1]  += -16.0*M_PI/(3.0*rc9);
-    } 
-    else if ((fr->vdwtype == evdwCUT) || (fr->vdwtype == evdwUSER)) {
-      if (fr->vdwtype == evdwUSER && fplog)
-       fprintf(fplog,
-               "WARNING: using dispersion correction with user tables\n");
-      rc3  = fr->rvdw*fr->rvdw*fr->rvdw;
-      rc9  = rc3*rc3*rc3;
-      eners[0] += -4.0*M_PI/(3.0*rc3);
-      eners[1] +=  4.0*M_PI/(9.0*rc9);
-      virs[0]  +=  8.0*M_PI/rc3;
-      virs[1]  += -16.0*M_PI/(3.0*rc9);
-    } else {
-      gmx_fatal(FARGS,
-               "Dispersion correction is not implemented for vdw-type = %s",
-               evdw_names[fr->vdwtype]);
-    }
-    fr->enerdiffsix    = eners[0];
-    fr->enerdifftwelve = eners[1];
-    /* The 0.5 is due to the Gromacs definition of the virial */
-    fr->virdiffsix     = 0.5*virs[0];
-    fr->virdifftwelve  = 0.5*virs[1];
-  }
-}
-
-void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,
-                   gmx_large_int_t step,int natoms,
-                   matrix box,real lambda,tensor pres,tensor virial,
-                   real *prescorr, real *enercorr, real *dvdlcorr)
-{
-    gmx_bool bCorrAll,bCorrPres;
-    real dvdlambda,invvol,dens,ninter,avcsix,avctwelve,enerdiff,svir=0,spres=0;
-    int  m;
-    
-    *prescorr = 0;
-    *enercorr = 0;
-    *dvdlcorr = 0;
-    
-    clear_mat(virial);
-    clear_mat(pres);
-    
-    if (ir->eDispCorr != edispcNO) {
-        bCorrAll  = (ir->eDispCorr == edispcAllEner ||
-                     ir->eDispCorr == edispcAllEnerPres);
-        bCorrPres = (ir->eDispCorr == edispcEnerPres ||
-                     ir->eDispCorr == edispcAllEnerPres);
-        
-        invvol = 1/det(box);
-        if (fr->n_tpi) 
-        {
-            /* Only correct for the interactions with the inserted molecule */
-            dens = (natoms - fr->n_tpi)*invvol;
-            ninter = fr->n_tpi;
-        } 
-        else 
-        {
-            dens = natoms*invvol;
-            ninter = 0.5*natoms;
-        }
-        
-        if (ir->efep == efepNO) 
-        {
-            avcsix    = fr->avcsix[0];
-            avctwelve = fr->avctwelve[0];
-        } 
-        else 
-        {
-            avcsix    = (1 - lambda)*fr->avcsix[0]    + lambda*fr->avcsix[1];
-            avctwelve = (1 - lambda)*fr->avctwelve[0] + lambda*fr->avctwelve[1];
-        }
-        
-        enerdiff = ninter*(dens*fr->enerdiffsix - fr->enershiftsix);
-        *enercorr += avcsix*enerdiff;
-        dvdlambda = 0.0;
-        if (ir->efep != efepNO) 
-        {
-            dvdlambda += (fr->avcsix[1] - fr->avcsix[0])*enerdiff;
-        }
-        if (bCorrAll) 
-        {
-            enerdiff = ninter*(dens*fr->enerdifftwelve - fr->enershifttwelve);
-            *enercorr += avctwelve*enerdiff;
-            if (fr->efep != efepNO) 
-            {
-                dvdlambda += (fr->avctwelve[1] - fr->avctwelve[0])*enerdiff;
-            }
-        }
-        
-        if (bCorrPres) 
-        {
-            svir = ninter*dens*avcsix*fr->virdiffsix/3.0;
-            if (ir->eDispCorr == edispcAllEnerPres)
-            {
-                svir += ninter*dens*avctwelve*fr->virdifftwelve/3.0;
-            }
-            /* The factor 2 is because of the Gromacs virial definition */
-            spres = -2.0*invvol*svir*PRESFAC;
-            
-            for(m=0; m<DIM; m++) {
-                virial[m][m] += svir;
-                pres[m][m] += spres;
-            }
-            *prescorr += spres;
-        }
-        
-        /* Can't currently control when it prints, for now, just print when degugging */
-        if (debug)
-        {
-            if (bCorrAll) {
-                fprintf(debug,"Long Range LJ corr.: <C6> %10.4e, <C12> %10.4e\n",
-                        avcsix,avctwelve);
-            }
-            if (bCorrPres) 
-            {
-                fprintf(debug,
-                        "Long Range LJ corr.: Epot %10g, Pres: %10g, Vir: %10g\n",
-                        *enercorr,spres,svir);
-            }
-            else
-            {
-                fprintf(debug,"Long Range LJ corr.: Epot %10g\n",*enercorr);
-            }
-        }
-        
-        if (fr->bSepDVDL && do_per_step(step,ir->nstlog))
-        {
-            fprintf(fplog,sepdvdlformat,"Dispersion correction",
-                    *enercorr,dvdlambda);
-        }
-        if (fr->efep != efepNO) 
-        {
-            *dvdlcorr += dvdlambda;
-        }
-    }
-}
-
-void do_pbc_first(FILE *fplog,matrix box,t_forcerec *fr,
-                 t_graph *graph,rvec x[])
-{
-  if (fplog)
-    fprintf(fplog,"Removing pbc first time\n");
-  calc_shifts(box,fr->shift_vec);
-  if (graph) {
-    mk_mshift(fplog,graph,fr->ePBC,box,x);
-    if (gmx_debug_at)
-      p_graph(debug,"do_pbc_first 1",graph);
-    shift_self(graph,box,x);
-    /* By doing an extra mk_mshift the molecules that are broken
-     * because they were e.g. imported from another software
-     * will be made whole again. Such are the healing powers
-     * of GROMACS.
-     */
-    mk_mshift(fplog,graph,fr->ePBC,box,x);
-    if (gmx_debug_at)
-      p_graph(debug,"do_pbc_first 2",graph);
-  }
-  if (fplog)
-    fprintf(fplog,"Done rmpbc\n");
-}
-
-static void low_do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
-                           gmx_mtop_t *mtop,rvec x[],
-                           gmx_bool bFirst)
-{
-  t_graph *graph;
-  int mb,as,mol;
-  gmx_molblock_t *molb;
-
-  if (bFirst && fplog)
-    fprintf(fplog,"Removing pbc first time\n");
-
-  snew(graph,1);
-  as = 0;
-  for(mb=0; mb<mtop->nmolblock; mb++) {
-    molb = &mtop->molblock[mb];
-    if (molb->natoms_mol == 1 || 
-       (!bFirst && mtop->moltype[molb->type].cgs.nr == 1)) {
-      /* Just one atom or charge group in the molecule, no PBC required */
-      as += molb->nmol*molb->natoms_mol;
-    } else {
-      /* Pass NULL iso fplog to avoid graph prints for each molecule type */
-      mk_graph_ilist(NULL,mtop->moltype[molb->type].ilist,
-                    0,molb->natoms_mol,FALSE,FALSE,graph);
-      
-      for(mol=0; mol<molb->nmol; mol++) {
-       mk_mshift(fplog,graph,ePBC,box,x+as);
-       
-       shift_self(graph,box,x+as);
-       /* The molecule is whole now.
-        * We don't need the second mk_mshift call as in do_pbc_first,
-        * since we no longer need this graph.
-        */
-       
-       as += molb->natoms_mol;
-      }
-      done_graph(graph);
-    }
-  }
-  sfree(graph);
-}
-
-void do_pbc_first_mtop(FILE *fplog,int ePBC,matrix box,
-                      gmx_mtop_t *mtop,rvec x[])
-{
-  low_do_pbc_mtop(fplog,ePBC,box,mtop,x,TRUE);
-}
-
-void do_pbc_mtop(FILE *fplog,int ePBC,matrix box,
-                gmx_mtop_t *mtop,rvec x[])
-{
-  low_do_pbc_mtop(fplog,ePBC,box,mtop,x,FALSE);
-}
-
-void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
-                t_inputrec *inputrec,
-                t_nrnb nrnb[],gmx_wallcycle_t wcycle,
-                gmx_runtime_t *runtime,
-                gmx_bool bWriteStat)
-{
-  int    i,j;
-  t_nrnb *nrnb_tot=NULL;
-  real   delta_t;
-  double nbfs,mflop;
-  double cycles[ewcNR];
-
-  wallcycle_sum(cr,wcycle,cycles);
-
-  if (cr->nnodes > 1) {
-    if (SIMMASTER(cr))
-      snew(nrnb_tot,1);
-#ifdef GMX_MPI
-    MPI_Reduce(nrnb->n,nrnb_tot->n,eNRNB,MPI_DOUBLE,MPI_SUM,
-               MASTERRANK(cr),cr->mpi_comm_mysim);
-#endif  
-  } else {
-    nrnb_tot = nrnb;
-  }
-    
-  if (SIMMASTER(cr)) {
-    print_flop(fplog,nrnb_tot,&nbfs,&mflop);
-    if (cr->nnodes > 1) {
-      sfree(nrnb_tot);
-    }
-  }
-
-  if ((cr->duty & DUTY_PP) && DOMAINDECOMP(cr)) {
-    print_dd_statistics(cr,inputrec,fplog);
-  }
-
-#ifdef GMX_MPI
-    if (PARTDECOMP(cr))
-    {
-        if (MASTER(cr))
-        {
-            t_nrnb     *nrnb_all;
-            int        s;
-            MPI_Status stat;
-
-            snew(nrnb_all,cr->nnodes);
-            nrnb_all[0] = *nrnb;
-            for(s=1; s<cr->nnodes; s++)
-            {
-                MPI_Recv(nrnb_all[s].n,eNRNB,MPI_DOUBLE,s,0,
-                         cr->mpi_comm_mysim,&stat);
-            }
-            pr_load(fplog,cr,nrnb_all);
-            sfree(nrnb_all);
-        }
-        else
-        {
-            MPI_Send(nrnb->n,eNRNB,MPI_DOUBLE,MASTERRANK(cr),0,
-                     cr->mpi_comm_mysim);
-        }
-    }
-#endif  
-
-  if (SIMMASTER(cr)) {
-    wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
-                    wcycle,cycles);
-
-    if (EI_DYNAMICS(inputrec->eI)) {
-      delta_t = inputrec->delta_t;
-    } else {
-      delta_t = 0;
-    }
-    
-    if (fplog) {
-        print_perf(fplog,runtime->proctime,runtime->realtime,
-                   cr->nnodes-cr->npmenodes,
-                   runtime->nsteps_done,delta_t,nbfs,mflop);
-    }
-    if (bWriteStat) {
-        print_perf(stderr,runtime->proctime,runtime->realtime,
-                   cr->nnodes-cr->npmenodes,
-                   runtime->nsteps_done,delta_t,nbfs,mflop);
-    }
-
-    /*
-    runtime=inputrec->nsteps*inputrec->delta_t;
-    if (bWriteStat) {
-      if (cr->nnodes == 1)
-       fprintf(stderr,"\n\n");
-      print_perf(stderr,nodetime,realtime,runtime,&ntot,
-                cr->nnodes-cr->npmenodes,FALSE);
-    }
-    wallcycle_print(fplog,cr->nnodes,cr->npmenodes,realtime,wcycle,cycles);
-    print_perf(fplog,nodetime,realtime,runtime,&ntot,cr->nnodes-cr->npmenodes,
-              TRUE);
-    if (PARTDECOMP(cr))
-      pr_load(fplog,cr,nrnb_all);
-    if (cr->nnodes > 1)
-      sfree(nrnb_all);
-    */
-  }
-}
-
-void init_md(FILE *fplog,
-             t_commrec *cr,t_inputrec *ir,const output_env_t oenv,
-             double *t,double *t0,
-             real *lambda,double *lam0,
-             t_nrnb *nrnb,gmx_mtop_t *mtop,
-             gmx_update_t *upd,
-             int nfile,const t_filenm fnm[],
-             gmx_mdoutf_t **outf,t_mdebin **mdebin,
-             tensor force_vir,tensor shake_vir,rvec mu_tot,
-             gmx_bool *bSimAnn,t_vcm **vcm, t_state *state, unsigned long Flags)
-{
-    int  i,j,n;
-    real tmpt,mod;
-       
-    /* Initial values */
-    *t = *t0       = ir->init_t;
-    if (ir->efep != efepNO)
-    {
-        *lam0 = ir->init_lambda;
-        *lambda = *lam0 + ir->init_step*ir->delta_lambda;
-    }
-    else
-    {
-        *lambda = *lam0   = 0.0;
-    } 
-
-    *bSimAnn=FALSE;
-    for(i=0;i<ir->opts.ngtc;i++)
-    {
-        /* set bSimAnn if any group is being annealed */
-        if(ir->opts.annealing[i]!=eannNO)
-        {
-            *bSimAnn = TRUE;
-        }
-    }
-    if (*bSimAnn)
-    {
-        update_annealing_target_temp(&(ir->opts),ir->init_t);
-    }
-    
-    if (upd)
-    {
-        *upd = init_update(fplog,ir);
-    }
-    
-    if (vcm != NULL)
-    {
-        *vcm = init_vcm(fplog,&mtop->groups,ir);
-    }
-    
-    if (EI_DYNAMICS(ir->eI) && !(Flags & MD_APPENDFILES))
-    {
-        if (ir->etc == etcBERENDSEN)
-        {
-            please_cite(fplog,"Berendsen84a");
-        }
-        if (ir->etc == etcVRESCALE)
-        {
-            please_cite(fplog,"Bussi2007a");
-        }
-    }
-    
-    init_nrnb(nrnb);
-    
-    if (nfile != -1)
-    {
-        *outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
-
-        *mdebin = init_mdebin((Flags & MD_APPENDFILES) ? NULL : (*outf)->fp_ene,
-                              mtop,ir, (*outf)->fp_dhdl);
-    }
-    
-    /* Initiate variables */  
-    clear_mat(force_vir);
-    clear_mat(shake_vir);
-    clear_rvec(mu_tot);
-    
-    debug_gmx();
-}
-
diff --git a/src/mdlib/tpi.c b/src/mdlib/tpi.c
deleted file mode 100644 (file)
index 8fb7353..0000000
+++ /dev/null
@@ -1,794 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <time.h>
-#include <math.h>
-#include "sysstuff.h"
-#include "string2.h"
-#include "network.h"
-#include "confio.h"
-#include "copyrite.h"
-#include "smalloc.h"
-#include "nrnb.h"
-#include "main.h"
-#include "chargegroup.h"
-#include "force.h"
-#include "macros.h"
-#include "random.h"
-#include "names.h"
-#include "gmx_fatal.h"
-#include "txtdump.h"
-#include "typedefs.h"
-#include "update.h"
-#include "random.h"
-#include "constr.h"
-#include "vec.h"
-#include "statutil.h"
-#include "tgroup.h"
-#include "mdebin.h"
-#include "vsite.h"
-#include "force.h"
-#include "mdrun.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "gmx_random.h"
-#include "physics.h"
-#include "xvgr.h"
-#include "mdatoms.h"
-#include "ns.h"
-#include "gmx_wallcycle.h"
-#include "mtop_util.h"
-#include "gmxfio.h"
-#include "pme.h"
-#include "gbutil.h"
-
-#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
-#if defined(GMX_DOUBLE)
-#include "gmx_sse2_double.h"
-#else
-#include "gmx_sse2_single.h"
-#endif
-#endif
-
-
-static void global_max(t_commrec *cr,int *n)
-{
-  int *sum,i;
-
-  snew(sum,cr->nnodes);
-  sum[cr->nodeid] = *n;
-  gmx_sumi(cr->nnodes,sum,cr);
-  for(i=0; i<cr->nnodes; i++)
-    *n = max(*n,sum[i]);
-  
-  sfree(sum);
-}
-
-static void realloc_bins(double **bin,int *nbin,int nbin_new)
-{
-  int i;
-
-  if (nbin_new != *nbin) {
-    srenew(*bin,nbin_new);
-    for(i=*nbin; i<nbin_new; i++)
-      (*bin)[i] = 0;
-    *nbin = nbin_new;
-  }
-}
-
-double do_tpi(FILE *fplog,t_commrec *cr,
-              int nfile, const t_filenm fnm[],
-              const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
-              int nstglobalcomm,
-              gmx_vsite_t *vsite,gmx_constr_t constr,
-              int stepout,
-              t_inputrec *inputrec,
-              gmx_mtop_t *top_global,t_fcdata *fcd,
-              t_state *state,
-              t_mdatoms *mdatoms,
-              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-              gmx_edsam_t ed,
-              t_forcerec *fr,
-              int repl_ex_nst,int repl_ex_seed,
-              real cpt_period,real max_hours,
-              const char *deviceOptions,
-              unsigned long Flags,
-              gmx_runtime_t *runtime)
-{
-  const char *TPI="Test Particle Insertion"; 
-  gmx_localtop_t *top;
-  gmx_groups_t *groups;
-  gmx_enerdata_t *enerd;
-  rvec   *f;
-  real   lambda,t,temp,beta,drmax,epot;
-  double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
-  t_trxstatus   *status;
-  t_trxframe rerun_fr;
-  gmx_bool   bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
-  tensor force_vir,shake_vir,vir,pres;
-  int    cg_tp,a_tp0,a_tp1,ngid,gid_tp,nener,e;
-  rvec   *x_mol;
-  rvec   mu_tot,x_init,dx,x_tp;
-  int    nnodes,frame,nsteps,step;
-  int    i,start,end;
-  gmx_rng_t tpi_rand;
-  FILE   *fp_tpi=NULL;
-  char   *ptr,*dump_pdb,**leg,str[STRLEN],str2[STRLEN];
-  double dbl,dump_ener;
-  gmx_bool   bCavity;
-  int    nat_cavity=0,d;
-  real   *mass_cavity=NULL,mass_tot;
-  int    nbin;
-  double invbinw,*bin,refvolshift,logV,bUlogV;
-  real dvdl,prescorr,enercorr,dvdlcorr;
-  gmx_bool bEnergyOutOfBounds;
-  const char *tpid_leg[2]={"direct","reweighted"};
-
-  /* Since there is no upper limit to the insertion energies,
-   * we need to set an upper limit for the distribution output.
-   */
-  real bU_bin_limit      = 50;
-  real bU_logV_bin_limit = bU_bin_limit + 10;
-
-  nnodes = cr->nnodes;
-
-  top = gmx_mtop_generate_local_top(top_global,inputrec);
-
-  groups = &top_global->groups;
-
-  bCavity = (inputrec->eI == eiTPIC);
-  if (bCavity) {
-    ptr = getenv("GMX_TPIC_MASSES");
-    if (ptr == NULL) {
-      nat_cavity = 1;
-    } else {
-      /* Read (multiple) masses from env var GMX_TPIC_MASSES,
-       * The center of mass of the last atoms is then used for TPIC.
-       */
-      nat_cavity = 0;
-      while (sscanf(ptr,"%lf%n",&dbl,&i) > 0) {
-       srenew(mass_cavity,nat_cavity+1);
-       mass_cavity[nat_cavity] = dbl;
-       fprintf(fplog,"mass[%d] = %f\n",
-               nat_cavity+1,mass_cavity[nat_cavity]);
-       nat_cavity++;
-       ptr += i;
-      }
-      if (nat_cavity == 0)
-       gmx_fatal(FARGS,"Found %d masses in GMX_TPIC_MASSES",nat_cavity);
-    }
-  }
-
-  /*
-  init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
-  state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
-  /* We never need full pbc for TPI */
-  fr->ePBC = epbcXYZ;
-  /* Determine the temperature for the Boltzmann weighting */
-  temp = inputrec->opts.ref_t[0];
-  if (fplog) {
-    for(i=1; (i<inputrec->opts.ngtc); i++) {
-      if (inputrec->opts.ref_t[i] != temp) {
-       fprintf(fplog,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
-       fprintf(stderr,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
-      }
-    }
-    fprintf(fplog,
-           "\n  The temperature for test particle insertion is %.3f K\n\n",
-           temp);
-  }
-  beta = 1.0/(BOLTZ*temp);
-
-  /* Number of insertions per frame */
-  nsteps = inputrec->nsteps; 
-
-  /* Use the same neighborlist with more insertions points
-   * in a sphere of radius drmax around the initial point
-   */
-  /* This should be a proper mdp parameter */
-  drmax = inputrec->rtpi;
-
-  /* An environment variable can be set to dump all configurations
-   * to pdb with an insertion energy <= this value.
-   */
-  dump_pdb = getenv("GMX_TPI_DUMP");
-  dump_ener = 0;
-  if (dump_pdb)
-    sscanf(dump_pdb,"%lf",&dump_ener);
-
-  atoms2md(top_global,inputrec,0,NULL,0,top_global->natoms,mdatoms);
-  update_mdatoms(mdatoms,inputrec->init_lambda);
-
-  snew(enerd,1);
-  init_enerdata(groups->grps[egcENER].nr,inputrec->n_flambda,enerd);
-  snew(f,top_global->natoms);
-
-  /* Print to log file  */
-  runtime_start(runtime);
-  print_date_and_time(fplog,cr->nodeid,
-                      "Started Test Particle Insertion",runtime); 
-  wallcycle_start(wcycle,ewcRUN);
-
-  /* The last charge group is the group to be inserted */
-  cg_tp = top->cgs.nr - 1;
-  a_tp0 = top->cgs.index[cg_tp];
-  a_tp1 = top->cgs.index[cg_tp+1];
-  if (debug)
-    fprintf(debug,"TPI cg %d, atoms %d-%d\n",cg_tp,a_tp0,a_tp1);
-  if (a_tp1 - a_tp0 > 1 &&
-      (inputrec->rlist < inputrec->rcoulomb ||
-       inputrec->rlist < inputrec->rvdw))
-    gmx_fatal(FARGS,"Can not do TPI for multi-atom molecule with a twin-range cut-off");
-  snew(x_mol,a_tp1-a_tp0);
-
-  bDispCorr = (inputrec->eDispCorr != edispcNO);
-  bCharge = FALSE;
-  for(i=a_tp0; i<a_tp1; i++) {
-    /* Copy the coordinates of the molecule to be insterted */
-    copy_rvec(state->x[i],x_mol[i-a_tp0]);
-    /* Check if we need to print electrostatic energies */
-    bCharge |= (mdatoms->chargeA[i] != 0 ||
-               (mdatoms->chargeB && mdatoms->chargeB[i] != 0));
-  }
-  bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype!=eelRF_NEC);
-
-  calc_cgcm(fplog,cg_tp,cg_tp+1,&(top->cgs),state->x,fr->cg_cm);
-  if (bCavity) {
-    if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog) {
-      fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
-      fprintf(stderr,"WARNING: Your TPI molecule is not centered at 0,0,0\n");
-    }
-  } else {
-    /* Center the molecule to be inserted at zero */
-     for(i=0; i<a_tp1-a_tp0; i++)
-      rvec_dec(x_mol[i],fr->cg_cm[cg_tp]);
-  }
-
-  if (fplog) {
-    fprintf(fplog,"\nWill insert %d atoms %s partial charges\n",
-           a_tp1-a_tp0,bCharge ? "with" : "without");
-    
-    fprintf(fplog,"\nWill insert %d times in each frame of %s\n",
-           nsteps,opt2fn("-rerun",nfile,fnm));
-  }
-  
-    if (!bCavity)
-    {
-        if (inputrec->nstlist > 1)
-        {
-            if (drmax==0 && a_tp1-a_tp0==1)
-            {
-                gmx_fatal(FARGS,"Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense",inputrec->nstlist,drmax);
-            }
-            if (fplog)
-            {
-                fprintf(fplog,"Will use the same neighborlist for %d insertions in a sphere of radius %f\n",inputrec->nstlist,drmax);
-            }
-        }
-    }
-    else
-    {
-        if (fplog)
-        {
-            fprintf(fplog,"Will insert randomly in a sphere of radius %f around the center of the cavity\n",drmax);
-        }
-    }
-
-  ngid = groups->grps[egcENER].nr;
-  gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
-  nener = 1 + ngid;
-  if (bDispCorr)
-    nener += 1;
-  if (bCharge) {
-    nener += ngid;
-    if (bRFExcl)
-      nener += 1;
-    if (EEL_FULL(fr->eeltype))
-      nener += 1;
-  }
-  snew(sum_UgembU,nener);
-
-  /* Initialize random generator */
-  tpi_rand = gmx_rng_init(inputrec->ld_seed);
-
-  if (MASTER(cr)) {
-    fp_tpi = xvgropen(opt2fn("-tpi",nfile,fnm),
-                     "TPI energies","Time (ps)",
-                     "(kJ mol\\S-1\\N) / (nm\\S3\\N)",oenv);
-    xvgr_subtitle(fp_tpi,"f. are averages over one frame",oenv);
-    snew(leg,4+nener);
-    e = 0;
-    sprintf(str,"-kT log(<Ve\\S-\\betaU\\N>/<V>)");
-    leg[e++] = strdup(str);
-    sprintf(str,"f. -kT log<e\\S-\\betaU\\N>");
-    leg[e++] = strdup(str);
-    sprintf(str,"f. <e\\S-\\betaU\\N>");
-    leg[e++] = strdup(str);
-    sprintf(str,"f. V");
-    leg[e++] = strdup(str);
-    sprintf(str,"f. <Ue\\S-\\betaU\\N>");
-    leg[e++] = strdup(str);
-    for(i=0; i<ngid; i++) {
-      sprintf(str,"f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
-             *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
-      leg[e++] = strdup(str);
-    }
-    if (bDispCorr) {
-      sprintf(str,"f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
-      leg[e++] = strdup(str);
-    }
-    if (bCharge) {
-      for(i=0; i<ngid; i++) {
-       sprintf(str,"f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
-               *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
-       leg[e++] = strdup(str);
-      }
-      if (bRFExcl) {
-       sprintf(str,"f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
-       leg[e++] = strdup(str);
-      }
-      if (EEL_FULL(fr->eeltype)) {
-       sprintf(str,"f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
-       leg[e++] = strdup(str);
-      }
-    }
-    xvgr_legend(fp_tpi,4+nener,(const char**)leg,oenv);
-    for(i=0; i<4+nener; i++)
-      sfree(leg[i]);
-    sfree(leg);
-  }
-  clear_rvec(x_init);
-  V_all = 0;
-  VembU_all = 0;
-
-  invbinw = 10;
-  nbin = 10;
-  snew(bin,nbin);
-
-  bNotLastFrame = read_first_frame(oenv,&status,opt2fn("-rerun",nfile,fnm),
-                                  &rerun_fr,TRX_NEED_X);
-  frame = 0;
-
-  if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
-      mdatoms->nr - (a_tp1 - a_tp0))
-    gmx_fatal(FARGS,"Number of atoms in trajectory (%d)%s "
-             "is not equal the number in the run input file (%d) "
-             "minus the number of atoms to insert (%d)\n",
-             rerun_fr.natoms,bCavity ? " minus one" : "",
-             mdatoms->nr,a_tp1-a_tp0);
-
-  refvolshift = log(det(rerun_fr.box));
-
-#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
-    /* Make sure we don't detect SSE overflow generated before this point */
-    gmx_mm_check_and_reset_overflow();
-#endif
-
-    while (bNotLastFrame)
-    {
-        lambda = rerun_fr.lambda;
-        t = rerun_fr.time;
-        
-        sum_embU = 0;
-        for(e=0; e<nener; e++)
-        {
-            sum_UgembU[e] = 0;
-        }
-        
-        /* Copy the coordinates from the input trajectory */
-        for(i=0; i<rerun_fr.natoms; i++)
-        {
-            copy_rvec(rerun_fr.x[i],state->x[i]);
-        }
-        
-        V = det(rerun_fr.box);
-        logV = log(V);
-        
-        bStateChanged = TRUE;
-        bNS = TRUE;
-        for(step=0; step<nsteps; step++)
-        {
-            /* In parallel all nodes generate all random configurations.
-             * In that way the result is identical to a single cpu tpi run.
-             */
-            if (!bCavity)
-            {
-                /* Random insertion in the whole volume */
-                bNS = (step % inputrec->nstlist == 0);
-                if (bNS)
-                {
-                    /* Generate a random position in the box */
-                    x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX];
-                    x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY];
-                    x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ];
-                }
-                if (inputrec->nstlist == 1)
-                {
-                    copy_rvec(x_init,x_tp);
-                }
-                else
-                {
-                    /* Generate coordinates within |dx|=drmax of x_init */
-                    do
-                    {
-                        dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                        dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                        dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                    }
-                    while (norm2(dx) > drmax*drmax);
-                    rvec_add(x_init,dx,x_tp);
-                }
-            }
-            else
-            {
-                /* Random insertion around a cavity location
-                 * given by the last coordinate of the trajectory.
-                 */
-                if (step == 0)
-                {
-                    if (nat_cavity == 1)
-                    {
-                        /* Copy the location of the cavity */
-                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1],x_init);
-                    }
-                    else
-                    {
-                        /* Determine the center of mass of the last molecule */
-                        clear_rvec(x_init);
-                        mass_tot = 0;
-                        for(i=0; i<nat_cavity; i++)
-                        {
-                            for(d=0; d<DIM; d++)
-                            {
-                                x_init[d] +=
-                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
-                            }
-                            mass_tot += mass_cavity[i];
-                        }
-                        for(d=0; d<DIM; d++)
-                        {
-                            x_init[d] /= mass_tot;
-                        }
-                    }
-                }
-                /* Generate coordinates within |dx|=drmax of x_init */
-                do
-                {
-                    dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                    dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                    dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
-                }
-                while (norm2(dx) > drmax*drmax);
-                rvec_add(x_init,dx,x_tp);
-            }
-            
-            if (a_tp1 - a_tp0 == 1)
-            {
-                /* Insert a single atom, just copy the insertion location */
-       copy_rvec(x_tp,state->x[a_tp0]);
-            }
-            else
-            {
-                /* Copy the coordinates from the top file */
-                for(i=a_tp0; i<a_tp1; i++)
-                {
-                    copy_rvec(x_mol[i-a_tp0],state->x[i]);
-                }
-                /* Rotate the molecule randomly */
-                rotate_conf(a_tp1-a_tp0,state->x+a_tp0,NULL,
-                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
-                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
-                            2*M_PI*gmx_rng_uniform_real(tpi_rand));
-                /* Shift to the insertion location */
-                for(i=a_tp0; i<a_tp1; i++)
-                {
-                    rvec_inc(state->x[i],x_tp);
-                }
-            }
-            
-            /* Check if this insertion belongs to this node */
-            bOurStep = TRUE;
-            if (PAR(cr))
-            {
-                switch (inputrec->eI)
-                {
-                case eiTPI:
-                    bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid);
-                    break;
-                case eiTPIC:
-                    bOurStep = (step % nnodes == cr->nodeid);
-                    break;
-                default:
-                    gmx_fatal(FARGS,"Unknown integrator %s",ei_names[inputrec->eI]);
-                }
-            }
-            if (bOurStep)
-            {
-                /* Clear some matrix variables  */
-                clear_mat(force_vir); 
-                clear_mat(shake_vir);
-                clear_mat(vir);
-                clear_mat(pres);
-                
-                /* Set the charge group center of mass of the test particle */
-                copy_rvec(x_init,fr->cg_cm[top->cgs.nr-1]);
-                
-                /* Calc energy (no forces) on new positions.
-                 * Since we only need the intermolecular energy
-                 * and the RF exclusion terms of the inserted molecule occur
-                 * within a single charge group we can pass NULL for the graph.
-                 * This also avoids shifts that would move charge groups
-                 * out of the box.
-                 *
-                 * Some checks above ensure than we can not have
-                 * twin-range interactions together with nstlist > 1,
-                 * therefore we do not need to remember the LR energies.
-                 */
-                /* Make do_force do a single node force calculation */
-                cr->nnodes = 1;
-                do_force(fplog,cr,inputrec,
-                         step,nrnb,wcycle,top,top_global,&top_global->groups,
-                         rerun_fr.box,state->x,&state->hist,
-                         f,force_vir,mdatoms,enerd,fcd,
-                         lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
-                         GMX_FORCE_NONBONDED |
-                         (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) |
-                         (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); 
-                cr->nnodes = nnodes;
-                bStateChanged = FALSE;
-                bNS = FALSE;
-                
-                /* Calculate long range corrections to pressure and energy */
-                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box,
-                              lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr);
-                /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
-                enerd->term[F_DISPCORR] = enercorr;
-                enerd->term[F_EPOT] += enercorr;
-                enerd->term[F_PRES] += prescorr;
-                enerd->term[F_DVDL] += dvdlcorr;
-
-                epot = enerd->term[F_EPOT];
-                bEnergyOutOfBounds = FALSE;
-#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
-                /* With SSE the energy can overflow, check for this */
-                if (gmx_mm_check_and_reset_overflow())
-                {
-                    if (debug)
-                    {
-                        fprintf(debug,"Found an SSE overflow, assuming the energy is out of bounds\n");
-                    }
-                    bEnergyOutOfBounds = TRUE;
-                }
-#endif
-                /* If the compiler doesn't optimize this check away
-                 * we catch the NAN energies.
-                 * The epot>GMX_REAL_MAX check catches inf values,
-                 * which should nicely result in embU=0 through the exp below,
-                 * but it does not hurt to check anyhow.
-                 */
-                /* Non-bonded Interaction usually diverge at r=0.
-                 * With tabulated interaction functions the first few entries
-                 * should be capped in a consistent fashion between
-                 * repulsion, dispersion and Coulomb to avoid accidental
-                 * negative values in the total energy.
-                 * The table generation code in tables.c does this.
-                 * With user tbales the user should take care of this.
-                 */
-                if (epot != epot || epot > GMX_REAL_MAX)
-                {
-                    bEnergyOutOfBounds = TRUE;
-                }
-                if (bEnergyOutOfBounds)
-                {
-                    if (debug)
-                    {
-                        fprintf(debug,"\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n",t,step,epot);
-                    }
-                    embU = 0;
-                }
-                else
-                {
-                    embU = exp(-beta*epot);
-                    sum_embU += embU;
-                    /* Determine the weighted energy contributions of each energy group */
-                    e = 0;
-                    sum_UgembU[e++] += epot*embU;
-                    if (fr->bBHAM)
-                    {
-                        for(i=0; i<ngid; i++)
-                        {
-                            sum_UgembU[e++] +=
-                                (enerd->grpp.ener[egBHAMSR][GID(i,gid_tp,ngid)] +
-                                 enerd->grpp.ener[egBHAMLR][GID(i,gid_tp,ngid)])*embU;
-                        }
-                    }
-                    else
-                    {
-                        for(i=0; i<ngid; i++)
-                        {
-                            sum_UgembU[e++] +=
-                                (enerd->grpp.ener[egLJSR][GID(i,gid_tp,ngid)] +
-                                 enerd->grpp.ener[egLJLR][GID(i,gid_tp,ngid)])*embU;
-                        }
-                    }
-                    if (bDispCorr)
-                    {
-                        sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
-                    }
-                    if (bCharge)
-                    {
-                        for(i=0; i<ngid; i++)
-                        {
-                            sum_UgembU[e++] +=
-                                (enerd->grpp.ener[egCOULSR][GID(i,gid_tp,ngid)] +
-                                 enerd->grpp.ener[egCOULLR][GID(i,gid_tp,ngid)])*embU;
-                        }
-                        if (bRFExcl)
-                        {
-                            sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
-                        }
-                        if (EEL_FULL(fr->eeltype))
-                        {
-                            sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
-                        }
-                    }
-                }
-                
-                if (embU == 0 || beta*epot > bU_bin_limit)
-                {
-                    bin[0]++;
-                }
-                else
-                {
-                    i = (int)((bU_logV_bin_limit
-                               - (beta*epot - logV + refvolshift))*invbinw
-                              + 0.5);
-                    if (i < 0)
-                    {
-                        i = 0;
-                    }
-                    if (i >= nbin)
-                    {
-                        realloc_bins(&bin,&nbin,i+10);
-                    }
-                    bin[i]++;
-                }
-                
-                if (debug)
-                {
-                    fprintf(debug,"TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
-                            step,epot,x_tp[XX],x_tp[YY],x_tp[ZZ]);
-                }
-
-                if (dump_pdb && epot <= dump_ener)
-                {
-                    sprintf(str,"t%g_step%d.pdb",t,step);
-                    sprintf(str2,"t: %f step %d ener: %f",t,step,epot);
-                    write_sto_conf_mtop(str,str2,top_global,state->x,state->v,
-                                        inputrec->ePBC,state->box);
-                }
-            }
-        }
-        
-        if (PAR(cr))
-        {
-            /* When running in parallel sum the energies over the processes */
-            gmx_sumd(1,    &sum_embU, cr);
-            gmx_sumd(nener,sum_UgembU,cr);
-        }
-
-        frame++;
-        V_all += V;
-        VembU_all += V*sum_embU/nsteps;
-        
-        if (fp_tpi)
-        {
-            if (bVerbose || frame%10==0 || frame<10)
-            {
-                fprintf(stderr,"mu %10.3e <mu> %10.3e\n",
-                        -log(sum_embU/nsteps)/beta,-log(VembU_all/V_all)/beta);
-            }
-            
-            fprintf(fp_tpi,"%10.3f %12.5e %12.5e %12.5e %12.5e",
-                    t,
-                    VembU_all==0 ? 20/beta : -log(VembU_all/V_all)/beta,
-                    sum_embU==0  ? 20/beta : -log(sum_embU/nsteps)/beta,
-                    sum_embU/nsteps,V);
-            for(e=0; e<nener; e++)
-            {
-                fprintf(fp_tpi," %12.5e",sum_UgembU[e]/nsteps);
-            }
-            fprintf(fp_tpi,"\n");
-            fflush(fp_tpi);
-        }
-        
-        bNotLastFrame = read_next_frame(oenv, status,&rerun_fr);
-    } /* End of the loop  */
-    runtime_end(runtime);
-
-    close_trj(status);
-
-    if (fp_tpi != NULL)
-    {
-        gmx_fio_fclose(fp_tpi);
-    }
-
-    if (fplog != NULL)
-    {
-        fprintf(fplog,"\n");
-        fprintf(fplog,"  <V>  = %12.5e nm^3\n",V_all/frame);
-        fprintf(fplog,"  <mu> = %12.5e kJ/mol\n",-log(VembU_all/V_all)/beta);
-    }
-  
-    /* Write the Boltzmann factor histogram */
-    if (PAR(cr))
-    {
-        /* When running in parallel sum the bins over the processes */
-        i = nbin;
-        global_max(cr,&i);
-        realloc_bins(&bin,&nbin,i);
-        gmx_sumd(nbin,bin,cr);
-    }
-    if (MASTER(cr))
-    {
-        fp_tpi = xvgropen(opt2fn("-tpid",nfile,fnm),
-                          "TPI energy distribution",
-                          "\\betaU - log(V/<V>)","count",oenv);
-        sprintf(str,"number \\betaU > %g: %9.3e",bU_bin_limit,bin[0]);
-        xvgr_subtitle(fp_tpi,str,oenv);
-        xvgr_legend(fp_tpi,2,(const char **)tpid_leg,oenv);
-        for(i=nbin-1; i>0; i--)
-        {
-            bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
-            fprintf(fp_tpi,"%6.2f %10d %12.5e\n",
-                    bUlogV,
-                    (int)(bin[i]+0.5),
-                    bin[i]*exp(-bUlogV)*V_all/VembU_all);
-        }
-        gmx_fio_fclose(fp_tpi);
-    }
-    sfree(bin);
-
-    sfree(sum_UgembU);
-
-    runtime->nsteps_done = frame*inputrec->nsteps;
-
-    return 0;
-}
diff --git a/src/ngmx/.cvsignore b/src/ngmx/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/ngmx/.gitignore b/src/ngmx/.gitignore
new file mode 100644 (file)
index 0000000..43a470b
--- /dev/null
@@ -0,0 +1,4 @@
+g_highway
+g_logo
+g_xrama
+ngmx
index 1721941b6afddc751243f0f8dd2044b2fb21a6ce..fbf185b9a5f679a350b1b698b012a07a1b6d671e 100644 (file)
@@ -19,7 +19,7 @@ set(NGMX_PROGRAMS
 
 foreach(PROG ${NGMX_PROGRAMS})
         add_executable(${PROG} ${PROG}.c ${NGMX_COMMON_SOURCE})
-        target_link_libraries(${PROG} gmx ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})        
+        target_link_libraries(${PROG} libgromacs ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})        
         set_target_properties(${PROG} PROPERTIES OUTPUT_NAME "${PROG}${GMX_BINARY_SUFFIX}")
 endforeach(PROG) 
 
diff --git a/src/programs/CMakeLists.txt b/src/programs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6ec3383
--- /dev/null
@@ -0,0 +1,11 @@
+add_subdirectory(mdrun)
+if (NOT GMX_FAHCORE)
+    add_subdirectory(g_ana)
+    add_subdirectory(g_protonate)
+    add_subdirectory(g_x2top)
+    add_subdirectory(gmxcheck)
+    add_subdirectory(gmxdump)
+    add_subdirectory(grompp)
+    add_subdirectory(pdb2gmx)
+    add_subdirectory(tpbconv)
+endif (NOT GMX_FAHCORE)
diff --git a/src/programs/g_ana/.gitignore b/src/programs/g_ana/.gitignore
new file mode 100644 (file)
index 0000000..e25cc71
--- /dev/null
@@ -0,0 +1 @@
+g_ana
diff --git a/src/programs/g_ana/CMakeLists.txt b/src/programs/g_ana/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7491aca
--- /dev/null
@@ -0,0 +1,6 @@
+add_executable(g_ana g_ana.cpp)
+target_link_libraries(g_ana libgromacs)
+set_target_properties(g_ana PROPERTIES OUTPUT_NAME "g_ana${GMX_BINARY_SUFFIX}")
+
+install(TARGETS g_ana
+        RUNTIME DESTINATION ${BIN_INSTALL_DIR})
diff --git a/src/programs/g_ana/g_ana.cpp b/src/programs/g_ana/g_ana.cpp
new file mode 100644 (file)
index 0000000..ee8ca55
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \brief
+ * Implements the g_ana tool.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#include <memory>
+
+#include <copyrite.h>
+
+#include "gromacs/fatalerror.h"
+#include "gromacs/trajectoryanalysis/analysismodule.h"
+#include "gromacs/trajectoryanalysis/cmdlinerunner.h"
+#include "gromacs/trajectoryanalysis/modules.h"
+
+int
+main(int argc, char *argv[])
+{
+    try
+    {
+        if (argc < 2)
+        {
+            CopyRight(stderr, argv[0]);
+            GMX_THROW(gmx::InvalidInputError("Not enough command-line arguments"));
+        }
+
+        std::auto_ptr<gmx::TrajectoryAnalysisModule>
+            mod(gmx::createTrajectoryAnalysisModule(argv[1]));
+        if (mod.get() == NULL)
+        {
+            CopyRight(stderr, argv[0]);
+            GMX_THROW(gmx::InvalidInputError(
+                      "Unknown analysis module given as the first command-line argument"));
+        }
+        --argc;
+        ++argv;
+
+        gmx::TrajectoryAnalysisCommandLineRunner runner(mod.get());
+        return runner.run(argc, argv);
+    }
+    catch (std::exception &ex)
+    {
+        fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
+        return 1;
+    }
+}
diff --git a/src/programs/g_protonate/CMakeLists.txt b/src/programs/g_protonate/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fd296b0
--- /dev/null
@@ -0,0 +1,8 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+file(GLOB PROTONATE_SOURCES g_protonate.c)
+
+add_executable(g_protonate ${PROTONATE_SOURCES})
+target_link_libraries(g_protonate ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(g_protonate PROPERTIES OUTPUT_NAME "g_protonate${GMX_BINARY_SUFFIX}")
+install(TARGETS g_protonate DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/g_x2top/CMakeLists.txt b/src/programs/g_x2top/CMakeLists.txt
new file mode 100644 (file)
index 0000000..58a639d
--- /dev/null
@@ -0,0 +1,8 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+file(GLOB X2TOP_SOURCES g_x2top.c nm2type.c)
+
+add_executable(g_x2top ${X2TOP_SOURCES})
+target_link_libraries(g_x2top ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(g_x2top PROPERTIES OUTPUT_NAME "g_x2top${GMX_BINARY_SUFFIX}")
+install(TARGETS g_x2top DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/gmxcheck/CMakeLists.txt b/src/programs/gmxcheck/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a88639b
--- /dev/null
@@ -0,0 +1,6 @@
+file(GLOB GMXCHECK_SOURCES gmxcheck.c tpbcmp.c)
+
+add_executable(gmxcheck ${GMXCHECK_SOURCES})
+target_link_libraries(gmxcheck ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(gmxcheck PROPERTIES OUTPUT_NAME "gmxcheck${GMX_BINARY_SUFFIX}")
+install(TARGETS gmxcheck DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/gmxdump/CMakeLists.txt b/src/programs/gmxdump/CMakeLists.txt
new file mode 100644 (file)
index 0000000..76225fe
--- /dev/null
@@ -0,0 +1,6 @@
+file(GLOB GMXDUMP_SOURCES gmxdump.c)
+
+add_executable(gmxdump ${GMXDUMP_SOURCES})
+target_link_libraries(gmxdump ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(gmxdump PROPERTIES OUTPUT_NAME "gmxdump${GMX_BINARY_SUFFIX}")
+install(TARGETS gmxdump DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/grompp/CMakeLists.txt b/src/programs/grompp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..70869e4
--- /dev/null
@@ -0,0 +1,8 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+file(GLOB GROMPP_SOURCES *.c)
+
+add_executable(grompp ${GROMPP_SOURCES})
+target_link_libraries(grompp ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(grompp PROPERTIES OUTPUT_NAME "grompp${GMX_BINARY_SUFFIX}")
+install(TARGETS grompp DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/grompp/grompp.c b/src/programs/grompp/grompp.c
new file mode 100644 (file)
index 0000000..19c181f
--- /dev/null
@@ -0,0 +1,1600 @@
+/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.03
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "macros.h"
+#include "string2.h"
+#include "readir.h"
+#include "toputil.h"
+#include "topio.h"
+#include "confio.h"
+#include "copyrite.h"
+#include "readir.h"
+#include "symtab.h"
+#include "names.h"
+#include "grompp.h"
+#include "random.h"
+#include "vec.h"
+#include "futil.h"
+#include "statutil.h"
+#include "splitter.h"
+#include "sortwater.h"
+#include "convparm.h"
+#include "gmx_fatal.h"
+#include "warninp.h"
+#include "index.h"
+#include "gmxfio.h"
+#include "trnio.h"
+#include "tpxio.h"
+#include "vsite_parm.h"
+#include "txtdump.h"
+#include "calcgrid.h"
+#include "add_par.h"
+#include "enxio.h"
+#include "perf_est.h"
+#include "compute_io.h"
+#include "gpp_atomtype.h"
+#include "gpp_tomorse.h"
+#include "mtop_util.h"
+#include "genborn.h"
+
+static int rm_interactions(int ifunc,int nrmols,t_molinfo mols[])
+{
+  int  i,n;
+  
+  n=0;
+  /* For all the molecule types */
+  for(i=0; i<nrmols; i++) {
+    n += mols[i].plist[ifunc].nr;
+    mols[i].plist[ifunc].nr=0;
+  }
+  return n;
+}
+
+static int check_atom_names(const char *fn1, const char *fn2, 
+                           gmx_mtop_t *mtop, t_atoms *at)
+{
+  int mb,m,i,j,nmismatch;
+  t_atoms *tat;
+#define MAXMISMATCH 20
+
+  if (mtop->natoms != at->nr)
+    gmx_incons("comparing atom names");
+  
+  nmismatch=0;
+  i = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    tat = &mtop->moltype[mtop->molblock[mb].type].atoms;
+    for(m=0; m<mtop->molblock[mb].nmol; m++) {
+      for(j=0; j < tat->nr; j++) {
+       if (strcmp( *(tat->atomname[j]) , *(at->atomname[i]) ) != 0) {
+         if (nmismatch < MAXMISMATCH) {
+           fprintf(stderr,
+                   "Warning: atom name %d in %s and %s does not match (%s - %s)\n",
+                   i+1, fn1, fn2, *(tat->atomname[j]), *(at->atomname[i]));
+         } else if (nmismatch == MAXMISMATCH) {
+           fprintf(stderr,"(more than %d non-matching atom names)\n",MAXMISMATCH);
+         }
+         nmismatch++;
+       }
+       i++;
+      }
+    }
+  }
+
+  return nmismatch;
+}
+
+static void check_eg_vs_cg(gmx_mtop_t *mtop)
+{
+  int astart,mb,m,cg,j,firstj;
+  unsigned char firsteg,eg;
+  gmx_moltype_t *molt;
+  
+  /* Go through all the charge groups and make sure all their
+   * atoms are in the same energy group.
+   */
+  
+  astart = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    molt = &mtop->moltype[mtop->molblock[mb].type];
+    for(m=0; m<mtop->molblock[mb].nmol; m++) {
+      for(cg=0; cg<molt->cgs.nr;cg++) {
+       /* Get the energy group of the first atom in this charge group */
+       firstj = astart + molt->cgs.index[cg];
+       firsteg = ggrpnr(&mtop->groups,egcENER,firstj);
+       for(j=molt->cgs.index[cg]+1;j<molt->cgs.index[cg+1];j++) {
+         eg = ggrpnr(&mtop->groups,egcENER,astart+j);
+         if(eg != firsteg) {
+           gmx_fatal(FARGS,"atoms %d and %d in charge group %d of molecule type '%s' are in different energy groups",
+                     firstj+1,astart+j+1,cg+1,*molt->name);
+         }
+       }
+      }
+      astart += molt->atoms.nr;
+    }
+  }  
+}
+
+static void check_cg_sizes(const char *topfn,t_block *cgs,warninp_t wi)
+{
+    int  maxsize,cg;
+    char warn_buf[STRLEN];
+
+    maxsize = 0;
+    for(cg=0; cg<cgs->nr; cg++)
+    {
+        maxsize = max(maxsize,cgs->index[cg+1]-cgs->index[cg]);
+    }
+    
+    if (maxsize > MAX_CHARGEGROUP_SIZE)
+    {
+        gmx_fatal(FARGS,"The largest charge group contains %d atoms. The maximum is %d.",maxsize,MAX_CHARGEGROUP_SIZE);
+    }
+    else if (maxsize > 10)
+    {
+        set_warning_line(wi,topfn,-1);
+        sprintf(warn_buf,
+                "The largest charge group contains %d atoms.\n"
+                "Since atoms only see each other when the centers of geometry of the charge groups they belong to are within the cut-off distance, too large charge groups can lead to serious cut-off artifacts.\n"
+                "For efficiency and accuracy, charge group should consist of a few atoms.\n"
+                "For all-atom force fields use: CH3, CH2, CH, NH2, NH, OH, CO2, CO, etc.",
+                maxsize);
+        warning_note(wi,warn_buf);
+    }
+}
+
+static void check_bonds_timestep(gmx_mtop_t *mtop,double dt,warninp_t wi)
+{
+    /* This check is not intended to ensure accurate integration,
+     * rather it is to signal mistakes in the mdp settings.
+     * A common mistake is to forget to turn on constraints
+     * for MD after energy minimization with flexible bonds.
+     * This check can also detect too large time steps for flexible water
+     * models, but such errors will often be masked by the constraints
+     * mdp options, which turns flexible water into water with bond constraints,
+     * but without an angle constraint. Unfortunately such incorrect use
+     * of water models can not easily be detected without checking
+     * for specific model names.
+     *
+     * The stability limit of leap-frog or velocity verlet is 4.44 steps
+     * per oscillational period.
+     * But accurate bonds distributions are lost far before that limit.
+     * To allow relatively common schemes (although not common with Gromacs)
+     * of dt=1 fs without constraints and dt=2 fs with only H-bond constraints
+     * we set the note limit to 10.
+     */
+    int       min_steps_warn=5;
+    int       min_steps_note=10;
+    t_iparams *ip;
+    int       molt;
+    gmx_moltype_t *moltype,*w_moltype;
+    t_atom    *atom;
+    t_ilist   *ilist,*ilb,*ilc,*ils;
+    int       ftype;
+    int       i,a1,a2,w_a1,w_a2,j;
+    real      twopi2,limit2,fc,re,m1,m2,period2,w_period2;
+    gmx_bool  bFound,bWater,bWarn;
+    char      warn_buf[STRLEN];
+
+    ip = mtop->ffparams.iparams;
+
+    twopi2 = sqr(2*M_PI);
+
+    limit2 = sqr(min_steps_note*dt);
+
+    w_a1 = w_a2 = -1;
+    w_period2 = -1.0;
+    
+    w_moltype = NULL;
+    for(molt=0; molt<mtop->nmoltype; molt++)
+    {
+        moltype = &mtop->moltype[molt];
+        atom  = moltype->atoms.atom;
+        ilist = moltype->ilist;
+        ilc = &ilist[F_CONSTR];
+        ils = &ilist[F_SETTLE];
+        for(ftype=0; ftype<F_NRE; ftype++)
+        {
+            if (!(ftype == F_BONDS || ftype == F_G96BONDS || ftype == F_HARMONIC))
+            {
+                continue;
+            }
+            
+            ilb = &ilist[ftype];
+            for(i=0; i<ilb->nr; i+=3)
+            {
+                fc = ip[ilb->iatoms[i]].harmonic.krA;
+                re = ip[ilb->iatoms[i]].harmonic.rA;
+                if (ftype == F_G96BONDS)
+                {
+                    /* Convert squared sqaure fc to harmonic fc */
+                    fc = 2*fc*re;
+                }
+                a1 = ilb->iatoms[i+1];
+                a2 = ilb->iatoms[i+2];
+                m1 = atom[a1].m;
+                m2 = atom[a2].m;
+                if (fc > 0 && m1 > 0 && m2 > 0)
+                {
+                    period2 = twopi2*m1*m2/((m1 + m2)*fc);
+                }
+                else
+                {
+                    period2 = GMX_FLOAT_MAX;
+                }
+                if (debug)
+                {
+                    fprintf(debug,"fc %g m1 %g m2 %g period %g\n",
+                            fc,m1,m2,sqrt(period2));
+                }
+                if (period2 < limit2)
+                {
+                    bFound = FALSE;
+                    for(j=0; j<ilc->nr; j+=3)
+                    {
+                        if ((ilc->iatoms[j+1] == a1 && ilc->iatoms[j+2] == a2) ||
+                            (ilc->iatoms[j+1] == a2 && ilc->iatoms[j+2] == a1))
+                            {
+                                bFound = TRUE;
+                            }
+                        }
+                    for(j=0; j<ils->nr; j+=2)
+                    {
+                        if ((a1 >= ils->iatoms[j+1] && a1 < ils->iatoms[j+1]+3) &&
+                            (a2 >= ils->iatoms[j+1] && a2 < ils->iatoms[j+1]+3))
+                        {
+                            bFound = TRUE;
+                        }
+                    }
+                    if (!bFound &&
+                        (w_moltype == NULL || period2 < w_period2))
+                    {
+                        w_moltype = moltype;
+                        w_a1      = a1;
+                        w_a2      = a2;
+                        w_period2 = period2;
+                    }
+                }
+            }
+        }
+    }
+    
+    if (w_moltype != NULL)
+    {
+        bWarn = (w_period2 < sqr(min_steps_warn*dt));
+        /* A check that would recognize most water models */
+        bWater = ((*w_moltype->atoms.atomname[0])[0] == 'O' &&
+                  w_moltype->atoms.nr <= 5);
+        sprintf(warn_buf,"The bond in molecule-type %s between atoms %d %s and %d %s has an estimated oscillational period of %.1e ps, which is less than %d times the time step of %.1e ps.\n"
+                "%s",
+                *w_moltype->name,
+                w_a1+1,*w_moltype->atoms.atomname[w_a1],
+                w_a2+1,*w_moltype->atoms.atomname[w_a2],
+                sqrt(w_period2),bWarn ? min_steps_warn : min_steps_note,dt,
+                bWater ?
+                "Maybe you asked for fexible water." :
+                "Maybe you forgot to change the constraints mdp option.");
+        if (bWarn)
+        {
+            warning(wi,warn_buf);
+        }
+        else
+        {
+            warning_note(wi,warn_buf);
+        }
+    }
+}
+
+static void check_vel(gmx_mtop_t *mtop,rvec v[])
+{
+  gmx_mtop_atomloop_all_t aloop;
+  t_atom *atom;
+  int a;
+
+  aloop = gmx_mtop_atomloop_all_init(mtop);
+  while (gmx_mtop_atomloop_all_next(aloop,&a,&atom)) {
+    if (atom->ptype == eptShell ||
+       atom->ptype == eptBond  ||
+       atom->ptype == eptVSite) {
+      clear_rvec(v[a]);
+    }
+  }
+}
+
+static gmx_bool nint_ftype(gmx_mtop_t *mtop,t_molinfo *mi,int ftype)
+{
+  int nint,mb;
+
+  nint = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    nint += mtop->molblock[mb].nmol*mi[mtop->molblock[mb].type].plist[ftype].nr;
+  }
+
+  return nint;
+}
+
+/* This routine reorders the molecule type array
+ * in the order of use in the molblocks,
+ * unused molecule types are deleted.
+ */
+static void renumber_moltypes(gmx_mtop_t *sys,
+                             int *nmolinfo,t_molinfo **molinfo)
+{
+  int *order,norder,i;
+  int mb,mi;
+  t_molinfo *minew;
+
+  snew(order,*nmolinfo);
+  norder = 0;
+  for(mb=0; mb<sys->nmolblock; mb++) {
+    for(i=0; i<norder; i++) {
+      if (order[i] == sys->molblock[mb].type) {
+       break;
+      }
+    }
+    if (i == norder) {
+      /* This type did not occur yet, add it */
+      order[norder] = sys->molblock[mb].type;
+      /* Renumber the moltype in the topology */
+      norder++;
+    }
+    sys->molblock[mb].type = i;
+  }
+  
+  /* We still need to reorder the molinfo structs */
+  snew(minew,norder);
+  for(mi=0; mi<*nmolinfo; mi++) {
+    for(i=0; i<norder; i++) {
+      if (order[i] == mi) {
+       break;
+      }
+    }
+    if (i == norder) {
+      done_mi(&(*molinfo)[mi]);
+    } else {
+      minew[i] = (*molinfo)[mi];
+    }
+  }
+  sfree(*molinfo);
+
+  *nmolinfo = norder;
+  *molinfo  = minew;
+}
+
+static void molinfo2mtop(int nmi,t_molinfo *mi,gmx_mtop_t *mtop)
+{
+  int m;
+  gmx_moltype_t *molt;
+
+  mtop->nmoltype = nmi;
+  snew(mtop->moltype,nmi);
+  for(m=0; m<nmi; m++) {
+    molt = &mtop->moltype[m];
+    molt->name  = mi[m].name;
+    molt->atoms = mi[m].atoms;
+    /* ilists are copied later */
+    molt->cgs   = mi[m].cgs;
+    molt->excls = mi[m].excls;
+  }
+}
+
+static void
+new_status(const char *topfile,const char *topppfile,const char *confin,
+           t_gromppopts *opts,t_inputrec *ir,gmx_bool bZero,
+           gmx_bool bGenVel,gmx_bool bVerbose,t_state *state,
+           gpp_atomtype_t atype,gmx_mtop_t *sys,
+           int *nmi,t_molinfo **mi,t_params plist[],
+           int *comb,double *reppow,real *fudgeQQ,
+           gmx_bool bMorse,
+           warninp_t wi)
+{
+  t_molinfo   *molinfo=NULL;
+  int         nmolblock;
+  gmx_molblock_t *molblock,*molbs;
+  t_atoms     *confat;
+  int         mb,i,nrmols,nmismatch;
+  char        buf[STRLEN];
+  gmx_bool        bGB=FALSE;
+  char        warn_buf[STRLEN];
+
+  init_mtop(sys);
+
+  /* Set gmx_boolean for GB */
+  if(ir->implicit_solvent)
+    bGB=TRUE;
+  
+  /* TOPOLOGY processing */
+  sys->name = do_top(bVerbose,topfile,topppfile,opts,bZero,&(sys->symtab),
+                     plist,comb,reppow,fudgeQQ,
+                     atype,&nrmols,&molinfo,ir,
+                     &nmolblock,&molblock,bGB,
+                     wi);
+  
+  sys->nmolblock = 0;
+  snew(sys->molblock,nmolblock);
+  
+  sys->natoms = 0;
+  for(mb=0; mb<nmolblock; mb++) {
+    if (sys->nmolblock > 0 &&
+       molblock[mb].type == sys->molblock[sys->nmolblock-1].type) {
+      /* Merge consecutive blocks with the same molecule type */
+      sys->molblock[sys->nmolblock-1].nmol += molblock[mb].nmol;
+      sys->natoms += molblock[mb].nmol*sys->molblock[sys->nmolblock-1].natoms_mol;
+    } else if (molblock[mb].nmol > 0) {
+      /* Add a new molblock to the topology */
+      molbs = &sys->molblock[sys->nmolblock];
+      *molbs = molblock[mb];
+      molbs->natoms_mol = molinfo[molbs->type].atoms.nr;
+      molbs->nposres_xA = 0;
+      molbs->nposres_xB = 0;
+      sys->natoms += molbs->nmol*molbs->natoms_mol;
+      sys->nmolblock++;
+    }
+  }
+  if (sys->nmolblock == 0) {
+    gmx_fatal(FARGS,"No molecules were defined in the system");
+  }
+
+  renumber_moltypes(sys,&nrmols,&molinfo);
+
+  if (bMorse)
+    convert_harmonics(nrmols,molinfo,atype);
+
+  if (ir->eDisre == edrNone) {
+    i = rm_interactions(F_DISRES,nrmols,molinfo);
+    if (i > 0) {
+      set_warning_line(wi,"unknown",-1);
+      sprintf(warn_buf,"disre = no, removed %d distance restraints",i);
+      warning_note(wi,warn_buf);
+    }
+  }
+  if (opts->bOrire == FALSE) {
+    i = rm_interactions(F_ORIRES,nrmols,molinfo);
+    if (i > 0) {
+      set_warning_line(wi,"unknown",-1);
+      sprintf(warn_buf,"orire = no, removed %d orientation restraints",i);
+      warning_note(wi,warn_buf);
+    }
+  }
+  if (opts->bDihre == FALSE) {
+    i = rm_interactions(F_DIHRES,nrmols,molinfo);
+    if (i > 0) {
+      set_warning_line(wi,"unknown",-1);
+      sprintf(warn_buf,"dihre = no, removed %d dihedral restraints",i);
+      warning_note(wi,warn_buf);
+    }
+  }
+  
+  /* Copy structures from msys to sys */
+  molinfo2mtop(nrmols,molinfo,sys);
+
+  gmx_mtop_finalize(sys);
+  /* COORDINATE file processing */
+  if (bVerbose) 
+    fprintf(stderr,"processing coordinates...\n");
+
+  get_stx_coordnum(confin,&state->natoms);
+  if (state->natoms != sys->natoms)
+    gmx_fatal(FARGS,"number of coordinates in coordinate file (%s, %d)\n"
+               "             does not match topology (%s, %d)",
+             confin,state->natoms,topfile,sys->natoms);
+  else {
+    /* make space for coordinates and velocities */
+    char title[STRLEN];
+    snew(confat,1);
+    init_t_atoms(confat,state->natoms,FALSE);
+    init_state(state,state->natoms,0,0,0);
+    read_stx_conf(confin,title,confat,state->x,state->v,NULL,state->box);
+    /* This call fixes the box shape for runs with pressure scaling */
+    set_box_rel(ir,state);
+
+    nmismatch = check_atom_names(topfile, confin, sys, confat);
+    free_t_atoms(confat,TRUE);
+    sfree(confat);
+    
+    if (nmismatch) {
+      sprintf(buf,"%d non-matching atom name%s\n"
+             "atom names from %s will be used\n"
+             "atom names from %s will be ignored\n",
+             nmismatch,(nmismatch == 1) ? "" : "s",topfile,confin);
+      warning(wi,buf);
+    }    
+    if (bVerbose) 
+      fprintf(stderr,"double-checking input for internal consistency...\n");
+    double_check(ir,state->box,nint_ftype(sys,molinfo,F_CONSTR),wi);
+  }
+
+  if (bGenVel) {
+    real *mass;
+    gmx_mtop_atomloop_all_t aloop;
+    t_atom *atom;
+
+    snew(mass,state->natoms);
+    aloop = gmx_mtop_atomloop_all_init(sys);
+    while (gmx_mtop_atomloop_all_next(aloop,&i,&atom)) {
+      mass[i] = atom->m;
+    }
+
+    if (opts->seed == -1) {
+      opts->seed = make_seed();
+      fprintf(stderr,"Setting gen_seed to %d\n",opts->seed);
+    }
+    maxwell_speed(opts->tempi,opts->seed,sys,state->v);
+
+    stop_cm(stdout,state->natoms,mass,state->x,state->v);
+    sfree(mass);
+  }
+
+  *nmi = nrmols;
+  *mi  = molinfo;
+}
+
+static void copy_state(const char *slog,t_trxframe *fr,
+                       gmx_bool bReadVel,t_state *state,
+                       double *use_time)
+{
+    int i;
+
+    if (fr->not_ok & FRAME_NOT_OK)
+    {
+        gmx_fatal(FARGS,"Can not start from an incomplete frame");
+    }
+    if (!fr->bX)
+    {
+        gmx_fatal(FARGS,"Did not find a frame with coordinates in file %s",
+                  slog);
+    }
+
+    for(i=0; i<state->natoms; i++)
+    {
+        copy_rvec(fr->x[i],state->x[i]);
+    }
+    if (bReadVel)
+    {
+        if (!fr->bV)
+        {
+            gmx_incons("Trajecory frame unexpectedly does not contain velocities");
+        }
+        for(i=0; i<state->natoms; i++)
+        {
+            copy_rvec(fr->v[i],state->v[i]);
+        }
+    }
+    if (fr->bBox)
+    {
+        copy_mat(fr->box,state->box);
+    }
+
+    *use_time = fr->time;
+}
+
+static void cont_status(const char *slog,const char *ener,
+                       gmx_bool bNeedVel,gmx_bool bGenVel, real fr_time,
+                       t_inputrec *ir,t_state *state,
+                       gmx_mtop_t *sys,
+                        const output_env_t oenv)
+     /* If fr_time == -1 read the last frame available which is complete */
+{
+    gmx_bool bReadVel;
+    t_trxframe  fr;
+    t_trxstatus *fp;
+    int i;
+    double use_time;
+
+    bReadVel = (bNeedVel && !bGenVel);
+
+    fprintf(stderr,
+            "Reading Coordinates%s and Box size from old trajectory\n",
+            bReadVel ? ", Velocities" : "");
+    if (fr_time == -1)
+    {
+        fprintf(stderr,"Will read whole trajectory\n");
+    }
+    else
+    {
+        fprintf(stderr,"Will read till time %g\n",fr_time);
+    }
+    if (!bReadVel)
+    {
+        if (bGenVel)
+        {
+            fprintf(stderr,"Velocities generated: "
+                    "ignoring velocities in input trajectory\n");
+        }
+        read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X);
+    }
+    else
+    {
+        read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X | TRX_NEED_V);
+        
+        if (!fr.bV)
+        {
+            fprintf(stderr,
+                    "\n"
+                    "WARNING: Did not find a frame with velocities in file %s,\n"
+                    "         all velocities will be set to zero!\n\n",slog);
+            for(i=0; i<sys->natoms; i++)
+            {
+                clear_rvec(state->v[i]);
+            }
+            close_trj(fp);
+            /* Search for a frame without velocities */
+            bReadVel = FALSE;
+            read_first_frame(oenv,&fp,slog,&fr,TRX_NEED_X);
+        }
+    }
+
+    state->natoms = fr.natoms;
+
+    if (sys->natoms != state->natoms)
+    {
+        gmx_fatal(FARGS,"Number of atoms in Topology "
+                  "is not the same as in Trajectory");
+    }
+    copy_state(slog,&fr,bReadVel,state,&use_time);
+
+    /* Find the appropriate frame */
+    while ((fr_time == -1 || fr.time < fr_time) &&
+           read_next_frame(oenv,fp,&fr))
+    {
+        copy_state(slog,&fr,bReadVel,state,&use_time);
+    }
+  
+    close_trj(fp);
+
+    /* Set the relative box lengths for preserving the box shape.
+     * Note that this call can lead to differences in the last bit
+     * with respect to using tpbconv to create a [TT].tpx[tt] file.
+     */
+    set_box_rel(ir,state);
+
+    fprintf(stderr,"Using frame at t = %g ps\n",use_time);
+    fprintf(stderr,"Starting time for run is %g ps\n",ir->init_t); 
+  
+    if ((ir->epc != epcNO  || ir->etc ==etcNOSEHOOVER) && ener)
+    {
+        get_enx_state(ener,use_time,&sys->groups,ir,state);
+        preserve_box_shape(ir,state->box_rel,state->boxv);
+    }
+}
+
+static void read_posres(gmx_mtop_t *mtop,t_molinfo *molinfo,gmx_bool bTopB,
+                        char *fn,
+                        int rc_scaling, int ePBC, 
+                        rvec com,
+                        warninp_t wi)
+{
+  gmx_bool   bFirst = TRUE;
+  rvec   *x,*v,*xp;
+  dvec   sum;
+  double totmass;
+  t_atoms dumat;
+  matrix box,invbox;
+  int    natoms,npbcdim=0;
+  char   warn_buf[STRLEN],title[STRLEN];
+  int    a,i,ai,j,k,mb,nat_molb;
+  gmx_molblock_t *molb;
+  t_params *pr;
+  t_atom *atom;
+
+  get_stx_coordnum(fn,&natoms);
+  if (natoms != mtop->natoms) {
+    sprintf(warn_buf,"The number of atoms in %s (%d) does not match the number of atoms in the topology (%d). Will assume that the first %d atoms in the topology and %s match.",fn,natoms,mtop->natoms,min(mtop->natoms,natoms),fn);
+    warning(wi,warn_buf);
+  }
+  snew(x,natoms);
+  snew(v,natoms);
+  init_t_atoms(&dumat,natoms,FALSE);
+  read_stx_conf(fn,title,&dumat,x,v,NULL,box);
+  
+  npbcdim = ePBC2npbcdim(ePBC);
+  clear_rvec(com);
+  if (rc_scaling != erscNO) {
+    copy_mat(box,invbox);
+    for(j=npbcdim; j<DIM; j++) {
+      clear_rvec(invbox[j]);
+      invbox[j][j] = 1;
+    }
+    m_inv_ur0(invbox,invbox);
+  }
+
+  /* Copy the reference coordinates to mtop */
+  clear_dvec(sum);
+  totmass = 0;
+  a = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    molb = &mtop->molblock[mb];
+    nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
+    pr = &(molinfo[molb->type].plist[F_POSRES]);
+    if (pr->nr > 0) {
+      atom = mtop->moltype[molb->type].atoms.atom;
+      for(i=0; (i<pr->nr); i++) {
+       ai=pr->param[i].AI;
+       if (ai >= natoms) {
+         gmx_fatal(FARGS,"Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n",
+                   ai+1,*molinfo[molb->type].name,fn,natoms);
+       }
+       if (rc_scaling == erscCOM) {
+         /* Determine the center of mass of the posres reference coordinates */
+         for(j=0; j<npbcdim; j++) {
+           sum[j] += atom[ai].m*x[a+ai][j];
+         }
+         totmass  += atom[ai].m;
+       }
+      }
+      if (!bTopB) {
+       molb->nposres_xA = nat_molb;
+       snew(molb->posres_xA,molb->nposres_xA);
+       for(i=0; i<nat_molb; i++) {
+         copy_rvec(x[a+i],molb->posres_xA[i]);
+       }
+      } else {
+       molb->nposres_xB = nat_molb;
+       snew(molb->posres_xB,molb->nposres_xB);
+       for(i=0; i<nat_molb; i++) {
+         copy_rvec(x[a+i],molb->posres_xB[i]);
+       }
+      }
+    }
+    a += nat_molb;
+  }
+  if (rc_scaling == erscCOM) {
+    if (totmass == 0)
+      gmx_fatal(FARGS,"The total mass of the position restraint atoms is 0");
+    for(j=0; j<npbcdim; j++)
+      com[j] = sum[j]/totmass;
+    fprintf(stderr,"The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n",com[XX],com[YY],com[ZZ]);
+  }
+
+  if (rc_scaling != erscNO) {
+    for(mb=0; mb<mtop->nmolblock; mb++) {
+      molb = &mtop->molblock[mb];
+      nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
+      if (molb->nposres_xA > 0 || molb->nposres_xB > 0) {
+       xp = (!bTopB ? molb->posres_xA : molb->posres_xB);
+       for(i=0; i<nat_molb; i++) {
+         for(j=0; j<npbcdim; j++) {
+           if (rc_scaling == erscALL) {
+             /* Convert from Cartesian to crystal coordinates */
+             xp[i][j] *= invbox[j][j];
+             for(k=j+1; k<npbcdim; k++) {
+               xp[i][j] += invbox[k][j]*xp[i][k];
+             }
+           } else if (rc_scaling == erscCOM) {
+             /* Subtract the center of mass */
+             xp[i][j] -= com[j];
+           }
+         }
+       }
+      }
+    }
+
+    if (rc_scaling == erscCOM) {
+      /* Convert the COM from Cartesian to crystal coordinates */
+      for(j=0; j<npbcdim; j++) {
+       com[j] *= invbox[j][j];
+       for(k=j+1; k<npbcdim; k++) {
+         com[j] += invbox[k][j]*com[k];
+       }
+      }
+    }
+  }
+  
+  free_t_atoms(&dumat,TRUE);
+  sfree(x);
+  sfree(v);
+}
+
+static void gen_posres(gmx_mtop_t *mtop,t_molinfo *mi,
+                       char *fnA, char *fnB,
+                       int rc_scaling, int ePBC,
+                       rvec com, rvec comB,
+                       warninp_t wi)
+{
+  int i,j;
+
+  read_posres  (mtop,mi,FALSE,fnA,rc_scaling,ePBC,com,wi);
+  if (strcmp(fnA,fnB) != 0) {
+      read_posres(mtop,mi,TRUE ,fnB,rc_scaling,ePBC,comB,wi);
+  }
+}
+
+static void set_wall_atomtype(gpp_atomtype_t at,t_gromppopts *opts,
+                             t_inputrec *ir)
+{
+  int i;
+
+  if (ir->nwall > 0)
+    fprintf(stderr,"Searching the wall atom type(s)\n");
+  for(i=0; i<ir->nwall; i++)
+    ir->wall_atomtype[i] = get_atomtype_type(opts->wall_atomtype[i],at);
+}
+
+static int nrdf_internal(t_atoms *atoms)
+{
+  int i,nmass,nrdf;
+
+  nmass = 0;
+  for(i=0; i<atoms->nr; i++) {
+    /* Vsite ptype might not be set here yet, so also check the mass */
+    if ((atoms->atom[i].ptype == eptAtom ||
+        atoms->atom[i].ptype == eptNucleus)
+       && atoms->atom[i].m > 0) {
+      nmass++;
+    }
+  }
+  switch (nmass) {
+  case 0:  nrdf = 0; break;
+  case 1:  nrdf = 0; break;
+  case 2:  nrdf = 1; break;
+  default: nrdf = nmass*3 - 6; break;
+  }
+  
+  return nrdf;
+}
+
+void
+spline1d( double        dx,
+                double *      y,
+                int           n,
+                double *      u,
+                double *      y2 )
+{
+    int i;
+    double p,q;
+       
+    y2[0] = 0.0;
+    u[0]  = 0.0;
+       
+    for(i=1;i<n-1;i++)
+    {
+               p = 0.5*y2[i-1]+2.0;
+        y2[i] = -0.5/p;
+        q = (y[i+1]-2.0*y[i]+y[i-1])/dx;
+               u[i] = (3.0*q/dx-0.5*u[i-1])/p;
+    }
+       
+    y2[n-1] = 0.0;
+       
+    for(i=n-2;i>=0;i--)
+    {
+        y2[i] = y2[i]*y2[i+1]+u[i];
+    }
+}
+
+
+void
+interpolate1d( double     xmin,
+                         double     dx,
+                         double *   ya,
+                         double *   y2a,
+                         double     x,
+                         double *   y,
+                         double *   y1)
+{
+    int ix;
+    double a,b;
+       
+    ix = (x-xmin)/dx;
+       
+    a = (xmin+(ix+1)*dx-x)/dx;
+    b = (x-xmin-ix*dx)/dx;
+       
+    *y  = a*ya[ix]+b*ya[ix+1]+((a*a*a-a)*y2a[ix]+(b*b*b-b)*y2a[ix+1])*(dx*dx)/6.0;
+    *y1 = (ya[ix+1]-ya[ix])/dx-(3.0*a*a-1.0)/6.0*dx*y2a[ix]+(3.0*b*b-1.0)/6.0*dx*y2a[ix+1];
+}
+
+
+void
+setup_cmap (int              grid_spacing,
+                       int              nc,
+                       real *           grid ,
+                       gmx_cmap_t *     cmap_grid)
+{
+       double *tmp_u,*tmp_u2,*tmp_yy,*tmp_y1,*tmp_t2,*tmp_grid;
+       
+    int    i,j,k,ii,jj,kk,idx;
+       int    offset;
+    double dx,xmin,v,v1,v2,v12;
+    double phi,psi;
+       
+       snew(tmp_u,2*grid_spacing);
+       snew(tmp_u2,2*grid_spacing);
+       snew(tmp_yy,2*grid_spacing);
+       snew(tmp_y1,2*grid_spacing);
+       snew(tmp_t2,2*grid_spacing*2*grid_spacing);
+       snew(tmp_grid,2*grid_spacing*2*grid_spacing);
+       
+    dx = 360.0/grid_spacing;
+    xmin = -180.0-dx*grid_spacing/2;
+       
+       for(kk=0;kk<nc;kk++)
+       {
+               /* Compute an offset depending on which cmap we are using                                 
+                * Offset will be the map number multiplied with the grid_spacing * grid_spacing * 2      
+                */
+               offset = kk * grid_spacing * grid_spacing * 2;
+               
+               for(i=0;i<2*grid_spacing;i++)
+               {
+                       ii=(i+grid_spacing-grid_spacing/2)%grid_spacing;
+                       
+                       for(j=0;j<2*grid_spacing;j++)
+                       {
+                               jj=(j+grid_spacing-grid_spacing/2)%grid_spacing;
+                               tmp_grid[i*grid_spacing*2+j] = grid[offset+ii*grid_spacing+jj];
+                       }
+               }
+               
+               for(i=0;i<2*grid_spacing;i++)
+               {
+                       spline1d(dx,&(tmp_grid[2*grid_spacing*i]),2*grid_spacing,tmp_u,&(tmp_t2[2*grid_spacing*i]));
+               }
+               
+               for(i=grid_spacing/2;i<grid_spacing+grid_spacing/2;i++)
+               {
+                       ii = i-grid_spacing/2;
+                       phi = ii*dx-180.0;
+                       
+                       for(j=grid_spacing/2;j<grid_spacing+grid_spacing/2;j++)
+                       {
+                               jj = j-grid_spacing/2;
+                               psi = jj*dx-180.0;
+                               
+                               for(k=0;k<2*grid_spacing;k++)
+                               {
+                                       interpolate1d(xmin,dx,&(tmp_grid[2*grid_spacing*k]),
+                                                                 &(tmp_t2[2*grid_spacing*k]),psi,&tmp_yy[k],&tmp_y1[k]);
+                               }
+                               
+                               spline1d(dx,tmp_yy,2*grid_spacing,tmp_u,tmp_u2);
+                               interpolate1d(xmin,dx,tmp_yy,tmp_u2,phi,&v,&v1);
+                               spline1d(dx,tmp_y1,2*grid_spacing,tmp_u,tmp_u2);
+                               interpolate1d(xmin,dx,tmp_y1,tmp_u2,phi,&v2,&v12);
+                               
+                               idx = ii*grid_spacing+jj;
+                               cmap_grid->cmapdata[kk].cmap[idx*4] = grid[offset+ii*grid_spacing+jj];
+                               cmap_grid->cmapdata[kk].cmap[idx*4+1] = v1;
+                               cmap_grid->cmapdata[kk].cmap[idx*4+2] = v2;
+                               cmap_grid->cmapdata[kk].cmap[idx*4+3] = v12;
+                       }
+               }
+       }
+}                              
+                               
+void init_cmap_grid(gmx_cmap_t *cmap_grid, int ngrid, int grid_spacing)
+{
+       int i,k,nelem;
+       
+       cmap_grid->ngrid        = ngrid;
+       cmap_grid->grid_spacing = grid_spacing;
+       nelem                   = cmap_grid->grid_spacing*cmap_grid->grid_spacing;
+       
+       snew(cmap_grid->cmapdata,ngrid);
+       
+       for(i=0;i<cmap_grid->ngrid;i++)
+       {
+               snew(cmap_grid->cmapdata[i].cmap,4*nelem);
+       }
+}
+
+
+static int count_constraints(gmx_mtop_t *mtop,t_molinfo *mi,warninp_t wi)
+{
+  int count,count_mol,i,mb;
+  gmx_molblock_t *molb;
+  t_params *plist;
+  char buf[STRLEN];
+
+  count = 0;
+  for(mb=0; mb<mtop->nmolblock; mb++) {
+    count_mol = 0;
+    molb  = &mtop->molblock[mb];
+    plist = mi[molb->type].plist;
+      
+    for(i=0; i<F_NRE; i++) {
+      if (i == F_SETTLE)
+       count_mol += 3*plist[i].nr;
+      else if (interaction_function[i].flags & IF_CONSTRAINT)
+       count_mol += plist[i].nr;
+    }
+      
+    if (count_mol > nrdf_internal(&mi[molb->type].atoms)) {
+      sprintf(buf,
+             "Molecule type '%s' has %d constraints.\n"
+             "For stability and efficiency there should not be more constraints than internal number of degrees of freedom: %d.\n",
+             *mi[molb->type].name,count_mol,
+             nrdf_internal(&mi[molb->type].atoms));
+      warning(wi,buf);
+    }
+    count += molb->nmol*count_mol;
+  }
+
+  return count;
+}
+
+static void check_gbsa_params_charged(gmx_mtop_t *sys, gpp_atomtype_t atype)
+{
+    int i,nmiss,natoms,mt;
+    real q;
+    const t_atoms *atoms;
+  
+    nmiss = 0;
+    for(mt=0;mt<sys->nmoltype;mt++)
+    {
+        atoms  = &sys->moltype[mt].atoms;
+        natoms = atoms->nr;
+
+        for(i=0;i<natoms;i++)
+        {
+            q = atoms->atom[i].q;
+            if ((get_atomtype_radius(atoms->atom[i].type,atype)    == 0  ||
+                 get_atomtype_vol(atoms->atom[i].type,atype)       == 0  ||
+                 get_atomtype_surftens(atoms->atom[i].type,atype)  == 0  ||
+                 get_atomtype_gb_radius(atoms->atom[i].type,atype) == 0  ||
+                 get_atomtype_S_hct(atoms->atom[i].type,atype)     == 0) &&
+                q != 0)
+            {
+                fprintf(stderr,"\nGB parameter(s) zero for atom type '%s' while charge is %g\n",
+                        get_atomtype_name(atoms->atom[i].type,atype),q);
+                nmiss++;
+            }
+        }
+    }
+
+    if (nmiss > 0)
+    {
+        gmx_fatal(FARGS,"Can't do GB electrostatics; the implicit_genborn_params section of the forcefield has parameters with value zero for %d atomtypes that occur as charged atoms.",nmiss);
+    }
+}
+
+
+static void check_gbsa_params(t_inputrec *ir,gpp_atomtype_t atype)
+{
+    int  nmiss,i;
+
+    /* If we are doing GBSA, check that we got the parameters we need
+     * This checking is to see if there are GBSA paratmeters for all
+     * atoms in the force field. To go around this for testing purposes
+     * comment out the nerror++ counter temporarily
+     */
+    nmiss = 0;
+    for(i=0;i<get_atomtype_ntypes(atype);i++)
+    {
+        if (get_atomtype_radius(i,atype)    < 0 ||
+            get_atomtype_vol(i,atype)       < 0 ||
+            get_atomtype_surftens(i,atype)  < 0 ||
+            get_atomtype_gb_radius(i,atype) < 0 ||
+            get_atomtype_S_hct(i,atype)     < 0)
+        {
+            fprintf(stderr,"\nGB parameter(s) missing or negative for atom type '%s'\n",
+                    get_atomtype_name(i,atype));
+            nmiss++;
+        }
+    }
+    
+    if (nmiss > 0)
+    {
+        gmx_fatal(FARGS,"Can't do GB electrostatics; the implicit_genborn_params section of the forcefield is missing parameters for %d atomtypes or they might be negative.",nmiss);
+    }
+  
+}
+
+int main (int argc, char *argv[])
+{
+  static const char *desc[] = {
+    "The gromacs preprocessor",
+    "reads a molecular topology file, checks the validity of the",
+    "file, expands the topology from a molecular description to an atomic",
+    "description. The topology file contains information about",
+    "molecule types and the number of molecules, the preprocessor",
+    "copies each molecule as needed. ",
+    "There is no limitation on the number of molecule types. ",
+    "Bonds and bond-angles can be converted into constraints, separately",
+    "for hydrogens and heavy atoms.",
+    "Then a coordinate file is read and velocities can be generated",
+    "from a Maxwellian distribution if requested.",
+    "[TT]grompp[tt] also reads parameters for the [TT]mdrun[tt] ",
+    "(eg. number of MD steps, time step, cut-off), and others such as",
+    "NEMD parameters, which are corrected so that the net acceleration",
+    "is zero.",
+    "Eventually a binary file is produced that can serve as the sole input",
+    "file for the MD program.[PAR]",
+    
+    "[TT]grompp[tt] uses the atom names from the topology file. The atom names",
+    "in the coordinate file (option [TT]-c[tt]) are only read to generate",
+    "warnings when they do not match the atom names in the topology.",
+    "Note that the atom names are irrelevant for the simulation as",
+    "only the atom types are used for generating interaction parameters.[PAR]",
+
+    "[TT]grompp[tt] uses a built-in preprocessor to resolve includes, macros, ",
+    "etc. The preprocessor supports the following keywords:[PAR]",
+    "#ifdef VARIABLE[BR]",
+    "#ifndef VARIABLE[BR]",
+    "#else[BR]",
+    "#endif[BR]",
+    "#define VARIABLE[BR]",
+    "#undef VARIABLE[BR]"
+    "#include \"filename\"[BR]",
+    "#include <filename>[PAR]",
+    "The functioning of these statements in your topology may be modulated by",
+    "using the following two flags in your [TT].mdp[tt] file:[PAR]",
+    "[TT]define = -DVARIABLE1 -DVARIABLE2[BR]",
+    "include = -I/home/john/doe[tt][BR]",
+    "For further information a C-programming textbook may help you out.",
+    "Specifying the [TT]-pp[tt] flag will get the pre-processed",
+    "topology file written out so that you can verify its contents.[PAR]",
+   
+    /* cpp has been unnecessary for some time, hasn't it?
+        "If your system does not have a C-preprocessor, you can still",
+        "use [TT]grompp[tt], but you do not have access to the features ",
+        "from the cpp. Command line options to the C-preprocessor can be given",
+        "in the [TT].mdp[tt] file. See your local manual (man cpp).[PAR]",
+    */
+    
+    "When using position restraints a file with restraint coordinates",
+    "can be supplied with [TT]-r[tt], otherwise restraining will be done",
+    "with respect to the conformation from the [TT]-c[tt] option.",
+    "For free energy calculation the the coordinates for the B topology",
+    "can be supplied with [TT]-rb[tt], otherwise they will be equal to",
+    "those of the A topology.[PAR]",
+    
+    "Starting coordinates can be read from trajectory with [TT]-t[tt].",
+    "The last frame with coordinates and velocities will be read,",
+    "unless the [TT]-time[tt] option is used. Only if this information",
+    "is absent will the coordinates in the [TT]-c[tt] file be used.",
+    "Note that these velocities will not be used when [TT]gen_vel = yes[tt]",
+    "in your [TT].mdp[tt] file. An energy file can be supplied with",
+    "[TT]-e[tt] to read Nose-Hoover and/or Parrinello-Rahman coupling",
+    "variables.[PAR]",
+
+    "[TT]grompp[tt] can be used to restart simulations (preserving",
+    "continuity) by supplying just a checkpoint file with [TT]-t[tt].",
+    "However, for simply changing the number of run steps to extend",
+    "a run, using [TT]tpbconv[tt] is more convenient than [TT]grompp[tt].",
+    "You then supply the old checkpoint file directly to [TT]mdrun[tt]",
+    "with [TT]-cpi[tt]. If you wish to change the ensemble or things",
+    "like output frequency, then supplying the checkpoint file to",
+    "[TT]grompp[tt] with [TT]-t[tt] along with a new [TT].mdp[tt] file",
+    "with [TT]-f[tt] is the recommended procedure.[PAR]",
+
+    "By default, all bonded interactions which have constant energy due to",
+    "virtual site constructions will be removed. If this constant energy is",
+    "not zero, this will result in a shift in the total energy. All bonded",
+    "interactions can be kept by turning off [TT]-rmvsbds[tt]. Additionally,",
+    "all constraints for distances which will be constant anyway because",
+    "of virtual site constructions will be removed. If any constraints remain",
+    "which involve virtual sites, a fatal error will result.[PAR]"
+    
+    "To verify your run input file, please take note of all warnings",
+    "on the screen, and correct where necessary. Do also look at the contents",
+    "of the [TT]mdout.mdp[tt] file; this contains comment lines, as well as",
+    "the input that [TT]grompp[tt] has read. If in doubt, you can start [TT]grompp[tt]",
+    "with the [TT]-debug[tt] option which will give you more information",
+    "in a file called [TT]grompp.log[tt] (along with real debug info). You",
+    "can see the contents of the run input file with the [TT]gmxdump[tt]",
+    "program. [TT]gmxcheck[tt] can be used to compare the contents of two",
+    "run input files.[PAR]"
+
+    "The [TT]-maxwarn[tt] option can be used to override warnings printed",
+    "by [TT]grompp[tt] that otherwise halt output. In some cases, warnings are",
+    "harmless, but usually they are not. The user is advised to carefully",
+    "interpret the output messages before attempting to bypass them with",
+    "this option."
+  };
+  t_gromppopts *opts;
+  gmx_mtop_t   *sys;
+  int          nmi;
+  t_molinfo    *mi;
+  gpp_atomtype_t atype;
+  t_inputrec   *ir;
+  int          natoms,nvsite,comb,mt;
+  t_params     *plist;
+  t_state      state;
+  matrix       box;
+  real         max_spacing,fudgeQQ;
+  double       reppow;
+  char         fn[STRLEN],fnB[STRLEN];
+  const char   *mdparin;
+  int          ntype;
+  gmx_bool         bNeedVel,bGenVel;
+  gmx_bool         have_atomnumber;
+  int             n12,n13,n14;
+  t_params     *gb_plist = NULL;
+  gmx_genborn_t *born = NULL;
+  output_env_t oenv;
+  gmx_bool         bVerbose = FALSE;
+  warninp_t    wi;
+  char         warn_buf[STRLEN];
+
+  t_filenm fnm[] = {
+    { efMDP, NULL,  NULL,        ffREAD  },
+    { efMDP, "-po", "mdout",     ffWRITE },
+    { efSTX, "-c",  NULL,        ffREAD  },
+    { efSTX, "-r",  NULL,        ffOPTRD },
+    { efSTX, "-rb", NULL,        ffOPTRD },
+    { efNDX, NULL,  NULL,        ffOPTRD },
+    { efTOP, NULL,  NULL,        ffREAD  },
+    { efTOP, "-pp", "processed", ffOPTWR },
+    { efTPX, "-o",  NULL,        ffWRITE },
+    { efTRN, "-t",  NULL,        ffOPTRD },
+    { efEDR, "-e",  NULL,        ffOPTRD },
+    { efTRN, "-ref","rotref",    ffOPTRW }
+  };
+#define NFILE asize(fnm)
+
+  /* Command line options */
+  static gmx_bool bRenum=TRUE;
+  static gmx_bool bRmVSBds=TRUE,bZero=FALSE;
+  static int  i,maxwarn=0;
+  static real fr_time=-1;
+  t_pargs pa[] = {
+    { "-v",       FALSE, etBOOL,{&bVerbose},  
+      "Be loud and noisy" },
+    { "-time",    FALSE, etREAL, {&fr_time},
+      "Take frame at or first after this time." },
+    { "-rmvsbds",FALSE, etBOOL, {&bRmVSBds},
+      "Remove constant bonded interactions with virtual sites" },
+    { "-maxwarn", FALSE, etINT,  {&maxwarn},
+      "Number of allowed warnings during input processing. Not for normal use and may generate unstable systems" },
+    { "-zero",    FALSE, etBOOL, {&bZero},
+      "Set parameters for bonded interactions without defaults to zero instead of generating an error" },
+    { "-renum",   FALSE, etBOOL, {&bRenum},
+      "Renumber atomtypes and minimize number of atomtypes" }
+  };
+  
+  CopyRight(stdout,argv[0]);
+  
+  /* Initiate some variables */
+  snew(ir,1);
+  snew(opts,1);
+  init_ir(ir,opts);
+  
+  /* Parse the command line */
+  parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
+                    asize(desc),desc,0,NULL,&oenv);
+  
+  wi = init_warning(TRUE,maxwarn);
+  
+  /* PARAMETER file processing */
+  mdparin = opt2fn("-f",NFILE,fnm);
+  set_warning_line(wi,mdparin,-1);    
+  get_ir(mdparin,opt2fn("-po",NFILE,fnm),ir,opts,wi);
+  
+  if (bVerbose) 
+    fprintf(stderr,"checking input for internal consistency...\n");
+  check_ir(mdparin,ir,opts,wi);
+
+  if (ir->ld_seed == -1) {
+    ir->ld_seed = make_seed();
+    fprintf(stderr,"Setting the LD random seed to %d\n",ir->ld_seed);
+  }
+
+  bNeedVel = EI_STATE_VELOCITY(ir->eI);
+  bGenVel  = (bNeedVel && opts->bGenVel);
+
+  snew(plist,F_NRE);
+  init_plist(plist);
+  snew(sys,1);
+  atype = init_atomtype();
+  if (debug)
+    pr_symtab(debug,0,"Just opened",&sys->symtab);
+    
+  strcpy(fn,ftp2fn(efTOP,NFILE,fnm));
+  if (!gmx_fexist(fn)) 
+    gmx_fatal(FARGS,"%s does not exist",fn);
+  new_status(fn,opt2fn_null("-pp",NFILE,fnm),opt2fn("-c",NFILE,fnm),
+            opts,ir,bZero,bGenVel,bVerbose,&state,
+            atype,sys,&nmi,&mi,plist,&comb,&reppow,&fudgeQQ,
+            opts->bMorse,
+            wi);
+  
+  if (debug)
+    pr_symtab(debug,0,"After new_status",&sys->symtab);
+  
+  if (count_constraints(sys,mi,wi) && (ir->eConstrAlg == econtSHAKE)) {
+    if (ir->eI == eiCG || ir->eI == eiLBFGS) {
+        sprintf(warn_buf,"Can not do %s with %s, use %s",
+                EI(ir->eI),econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+        warning_error(wi,warn_buf);
+    }
+    if (ir->bPeriodicMols) {
+        sprintf(warn_buf,"Can not do periodic molecules with %s, use %s",
+                econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+        warning_error(wi,warn_buf);
+    }
+  }
+
+  /* If we are doing QM/MM, check that we got the atom numbers */
+  have_atomnumber = TRUE;
+  for (i=0; i<get_atomtype_ntypes(atype); i++) {
+    have_atomnumber = have_atomnumber && (get_atomtype_atomnumber(i,atype) >= 0);
+  }
+  if (!have_atomnumber && ir->bQMMM)
+  {
+      warning_error(wi,
+                    "\n"
+                    "It appears as if you are trying to run a QM/MM calculation, but the force\n"
+                    "field you are using does not contain atom numbers fields. This is an\n"
+                    "optional field (introduced in Gromacs 3.3) for general runs, but mandatory\n"
+                    "for QM/MM. The good news is that it is easy to add - put the atom number as\n"
+                    "an integer just before the mass column in ffXXXnb.itp.\n"
+                    "NB: United atoms have the same atom numbers as normal ones.\n\n"); 
+  }
+
+  /* Check for errors in the input now, since they might cause problems
+   * during processing further down.
+   */
+  check_warning_error(wi,FARGS);
+
+  if (opt2bSet("-r",NFILE,fnm))
+    sprintf(fn,"%s",opt2fn("-r",NFILE,fnm));
+  else
+    sprintf(fn,"%s",opt2fn("-c",NFILE,fnm));
+  if (opt2bSet("-rb",NFILE,fnm))
+    sprintf(fnB,"%s",opt2fn("-rb",NFILE,fnm));
+  else
+    strcpy(fnB,fn);
+
+    if (nint_ftype(sys,mi,F_POSRES) > 0)
+    {
+        if (bVerbose)
+        {
+            fprintf(stderr,"Reading position restraint coords from %s",fn);
+            if (strcmp(fn,fnB) == 0)
+            {
+                fprintf(stderr,"\n");
+            }
+            else
+            {
+                fprintf(stderr," and %s\n",fnB);
+                if (ir->efep != efepNO && ir->n_flambda > 0)
+                {
+                    warning_error(wi,"Can not change the position restraint reference coordinates with lambda togther with foreign lambda calculation.");
+                }
+            }
+        }
+        gen_posres(sys,mi,fn,fnB,
+                   ir->refcoord_scaling,ir->ePBC,
+                   ir->posres_com,ir->posres_comB,
+                   wi);
+    }
+               
+  nvsite = 0;
+  /* set parameters for virtual site construction (not for vsiten) */
+  for(mt=0; mt<sys->nmoltype; mt++) {
+    nvsite +=
+      set_vsites(bVerbose, &sys->moltype[mt].atoms, atype, mi[mt].plist);
+  }
+  /* now throw away all obsolete bonds, angles and dihedrals: */
+  /* note: constraints are ALWAYS removed */
+  if (nvsite) {
+    for(mt=0; mt<sys->nmoltype; mt++) {
+      clean_vsite_bondeds(mi[mt].plist,sys->moltype[mt].atoms.nr,bRmVSBds);
+    }
+  }
+  
+       /* If we are using CMAP, setup the pre-interpolation grid */
+       if(plist->ncmap>0)
+       {
+               init_cmap_grid(&sys->ffparams.cmap_grid, plist->nc, plist->grid_spacing);
+               setup_cmap(plist->grid_spacing, plist->nc, plist->cmap,&sys->ffparams.cmap_grid);
+       }
+       
+  set_wall_atomtype(atype,opts,ir);
+  if (bRenum) {
+    renum_atype(plist, sys, ir->wall_atomtype, atype, bVerbose);
+    ntype = get_atomtype_ntypes(atype);
+  }
+
+    if (ir->implicit_solvent != eisNO)
+    {
+        /* Now we have renumbered the atom types, we can check the GBSA params */
+        check_gbsa_params(ir,atype);
+      
+      /* Check that all atoms that have charge and/or LJ-parameters also have 
+       * sensible GB-parameters
+       */
+      check_gbsa_params_charged(sys,atype);
+    }
+
+       /* PELA: Copy the atomtype data to the topology atomtype list */
+       copy_atomtype_atomtypes(atype,&(sys->atomtypes));
+
+       if (debug)
+    pr_symtab(debug,0,"After renum_atype",&sys->symtab);
+
+  if (bVerbose) 
+    fprintf(stderr,"converting bonded parameters...\n");
+       
+  ntype = get_atomtype_ntypes(atype);
+  convert_params(ntype, plist, mi, comb, reppow, fudgeQQ, sys);
+       
+  if (debug)
+    pr_symtab(debug,0,"After convert_params",&sys->symtab);
+
+  /* set ptype to VSite for virtual sites */
+  for(mt=0; mt<sys->nmoltype; mt++) {
+    set_vsites_ptype(FALSE,&sys->moltype[mt]);
+  }
+  if (debug) {
+    pr_symtab(debug,0,"After virtual sites",&sys->symtab);
+  }
+  /* Check velocity for virtual sites and shells */
+  if (bGenVel) {
+    check_vel(sys,state.v);
+  }
+    
+  /* check masses */
+  check_mol(sys,wi);
+  
+  for(i=0; i<sys->nmoltype; i++) {
+      check_cg_sizes(ftp2fn(efTOP,NFILE,fnm),&sys->moltype[i].cgs,wi);
+  }
+
+  if (EI_DYNAMICS(ir->eI) && ir->eI != eiBD)
+  {
+      check_bonds_timestep(sys,ir->delta_t,wi);
+  }
+
+  if (EI_ENERGY_MINIMIZATION(ir->eI) && 0 == ir->nsteps)
+  {
+      warning_note(wi,"Zero-step energy minimization will alter the coordinates before calculating the energy. If you just want the energy of a single point, try zero-step MD (with unconstrained_start = yes). To do multiple single-point energy evaluations of different configurations of the same topology, use mdrun -rerun.");
+  }
+
+  check_warning_error(wi,FARGS);
+       
+  if (bVerbose) 
+    fprintf(stderr,"initialising group options...\n");
+  do_index(mdparin,ftp2fn_null(efNDX,NFILE,fnm),
+           sys,bVerbose,ir,
+           bGenVel ? state.v : NULL,
+           wi);
+  
+  /* Init the temperature coupling state */
+  init_gtc_state(&state,ir->opts.ngtc,0,ir->opts.nhchainlength);
+
+  if (bVerbose)
+    fprintf(stderr,"Checking consistency between energy and charge groups...\n");
+  check_eg_vs_cg(sys);
+  
+  if (debug)
+    pr_symtab(debug,0,"After index",&sys->symtab);
+  triple_check(mdparin,ir,sys,wi);
+  close_symtab(&sys->symtab);
+  if (debug)
+    pr_symtab(debug,0,"After close",&sys->symtab);
+
+  /* make exclusions between QM atoms */
+  if (ir->bQMMM) {
+    generate_qmexcl(sys,ir);
+  }
+
+  if (ftp2bSet(efTRN,NFILE,fnm)) {
+    if (bVerbose)
+      fprintf(stderr,"getting data from old trajectory ...\n");
+    cont_status(ftp2fn(efTRN,NFILE,fnm),ftp2fn_null(efEDR,NFILE,fnm),
+               bNeedVel,bGenVel,fr_time,ir,&state,sys,oenv);
+  }
+
+    if (ir->ePBC==epbcXY && ir->nwall!=2)
+    {
+        clear_rvec(state.box[ZZ]);
+    }
+  
+    if (ir->rlist > 0)
+    {
+        set_warning_line(wi,mdparin,-1);
+        check_chargegroup_radii(sys,ir,state.x,wi);
+    }
+
+  if (EEL_FULL(ir->coulombtype)) {
+    /* Calculate the optimal grid dimensions */
+    copy_mat(state.box,box);
+    if (ir->ePBC==epbcXY && ir->nwall==2)
+      svmul(ir->wall_ewald_zfac,box[ZZ],box[ZZ]);
+    max_spacing = calc_grid(stdout,box,opts->fourierspacing,
+                            &(ir->nkx),&(ir->nky),&(ir->nkz));
+    if ((ir->coulombtype == eelPPPM) && (max_spacing > 0.1)) {
+        set_warning_line(wi,mdparin,-1);
+        warning_note(wi,"Grid spacing larger then 0.1 while using PPPM.");
+    }
+  }
+
+  if (ir->ePull != epullNO)
+    set_pull_init(ir,sys,state.x,state.box,oenv,opts->pull_start);
+  
+  if (ir->bRot)
+  {
+      set_reference_positions(ir->rot,sys,state.x,state.box,
+                              opt2fn("-ref",NFILE,fnm),opt2bSet("-ref",NFILE,fnm),
+                              wi);
+  }
+
+  /*  reset_multinr(sys); */
+  
+  if (EEL_PME(ir->coulombtype)) {
+    float ratio = pme_load_estimate(sys,ir,state.box);
+    fprintf(stderr,"Estimate for the relative computational load of the PME mesh part: %.2f\n",ratio);
+    /* With free energy we might need to do PME both for the A and B state
+     * charges. This will double the cost, but the optimal performance will
+     * then probably be at a slightly larger cut-off and grid spacing.
+     */
+    if ((ir->efep == efepNO && ratio > 1.0/2.0) ||
+        (ir->efep != efepNO && ratio > 2.0/3.0)) {
+        warning_note(wi,
+                     "The optimal PME mesh load for parallel simulations is below 0.5\n"
+                  "and for highly parallel simulations between 0.25 and 0.33,\n"
+                  "for higher performance, increase the cut-off and the PME grid spacing");
+    }
+  }
+
+    {
+        char warn_buf[STRLEN];
+        double cio = compute_io(ir,sys->natoms,&sys->groups,F_NRE,1);
+        sprintf(warn_buf,"This run will generate roughly %.0f Mb of data",cio);
+        if (cio > 2000) {
+            set_warning_line(wi,mdparin,-1);
+            warning_note(wi,warn_buf);
+        } else {
+            printf("%s\n",warn_buf);
+        }
+    }
+       
+  if (bVerbose) 
+    fprintf(stderr,"writing run input file...\n");
+
+  done_warning(wi,FARGS);
+
+  state.lambda = ir->init_lambda;
+  write_tpx_state(ftp2fn(efTPX,NFILE,fnm),ir,&state,sys);
+  
+  thanx(stderr);
+  
+  return 0;
+}
diff --git a/src/programs/mdrun/.gitignore b/src/programs/mdrun/.gitignore
new file mode 100644 (file)
index 0000000..d4822df
--- /dev/null
@@ -0,0 +1 @@
+mdrun
diff --git a/src/programs/mdrun/CMakeLists.txt b/src/programs/mdrun/CMakeLists.txt
new file mode 100644 (file)
index 0000000..774b6f6
--- /dev/null
@@ -0,0 +1,50 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+set(MDRUN_SOURCES
+    do_gct.c    gctio.c         genalg.c    ionize.c
+    md.c        md_openmm.c     mdrun.c     membed.c
+    repl_ex.c   runner.c        xutils.c)
+
+if(GMX_OPENMM) 
+    add_subdirectory(gmx_gpu_utils)
+    include_directories(./gmx_gpu_utils ${OpenMM_INCLUDE_DIR})
+    link_directories(${OpenMM_LIBRARY_DIR}) 
+    # with this define no evn.var. is needed with OPENMM_PLUGIN_DIR
+    # if the same OpenMM installation is used for running and building 
+    add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" ) 
+    file(TO_CMAKE_PATH ${OpenMM_PLUGIN_DIR} _path)
+    add_library(openmm_api_wrapper STATIC openmm_wrapper.cpp)
+    target_link_libraries(openmm_api_wrapper gmx_gpu_utils ${OpenMM_LIBRARIES})
+    set(GMX_OPENMM_LIBRARIES openmm_api_wrapper gmx_gpu_utils ${OpenMM_LIBRARIES})   
+endif(GMX_OPENMM)
+
+if(GMX_FAHCORE)
+    add_library(fahcore ${MDRUN_SOURCES})
+else(GMX_FAHCORE)
+    add_executable(mdrun ${MDRUN_SOURCES})
+    target_link_libraries(mdrun ${GMX_EXTRA_LIBRARIES} libgromacs ${GMX_OPENMM_LIBRARIES})
+    set_target_properties(mdrun PROPERTIES OUTPUT_NAME "mdrun${GMX_BINARY_SUFFIX}")
+    install(TARGETS mdrun DESTINATION ${BIN_INSTALL_DIR} COMPONENT mdrun)
+
+    if(GMX_OPENMM AND MSVC)
+        set_target_properties(mdrun PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT")
+    endif()
+
+    # Create the custom install-mdrun target
+    if (BUILD_SHARED_LIBS)
+        # If shared libraries are used, we need to install the libraries in
+        # addition to the mdrun binary.
+        add_custom_target(install-mdrun
+            COMMAND ${CMAKE_COMMAND} -DCOMPONENT=libraries
+                    -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
+            COMMAND ${CMAKE_COMMAND} -DCOMPONENT=mdrun
+                    -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
+            COMMENT "Installing mdrun")
+    else (BUILD_SHARED_LIBS)
+        add_custom_target(install-mdrun
+            COMMAND ${CMAKE_COMMAND} -DCOMPONENT=mdrun
+                    -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
+            COMMENT "Installing mdrun")
+    endif (BUILD_SHARED_LIBS)
+    add_dependencies(install-mdrun mdrun)
+endif(GMX_FAHCORE)
diff --git a/src/programs/mdrun/gctio.c b/src/programs/mdrun/gctio.c
new file mode 100644 (file)
index 0000000..f093647
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "typedefs.h"
+#include "xmdrun.h"
+#include "futil.h"
+#include "xvgr.h"
+#include "macros.h"
+#include "physics.h"
+#include "network.h"
+#include "smalloc.h"
+#include "string2.h"
+#include "readinp.h"
+#include "filenm.h"
+#include "names.h"
+#include "gmxfio.h"
+
+const char *eoNames[eoNR] = { 
+  "Pres", "Epot", "Vir", "Dist", "Mu", "Force", "Fx", "Fy", "Fz",
+  "Px", "Py", "Pz",
+  "Polarizability", "Dipole", "Memory", "UseEinter", "UseVirial",
+  "CombinationRule"
+};
+
+static int Name2eo(char *s)
+{
+  int i,res;
+  
+  res=-1;
+  
+  for(i=0; (i<eoNR); i++)
+    if (gmx_strcasecmp(s,eoNames[i]) == 0) {
+      res=i;
+      fprintf(stderr,"Coupling to observable %d (%s)\n",res,eoNames[res]);
+      break;
+    }
+  
+  return res;
+}
+
+#define  block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
+#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
+#define   snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
+
+static void low_comm_tcr(t_commrec *cr,t_coupl_rec *tcr)
+{
+  nblock_bc(cr,eoObsNR,tcr->ref_value);
+  
+  block_bc(cr,tcr->nLJ);
+  snew_bc(cr,tcr->tcLJ,tcr->nLJ);
+  nblock_bc(cr,tcr->nLJ,tcr->tcLJ);
+  
+  block_bc(cr,tcr->nBU);
+  snew_bc(cr,tcr->tcBU,tcr->nBU);
+  nblock_bc(cr,tcr->nBU,tcr->tcBU);
+  
+  block_bc(cr,tcr->nQ);
+  snew_bc(cr,tcr->tcQ,tcr->nQ);
+  nblock_bc(cr,tcr->nQ,tcr->tcQ);
+  
+  block_bc(cr,tcr->nmemory);
+  block_bc(cr,tcr->bInter);
+  block_bc(cr,tcr->bVirial);
+  block_bc(cr,tcr->combrule);
+}
+
+void comm_tcr(FILE *log,t_commrec *cr,t_coupl_rec **tcr)
+{
+  if (!MASTER(cr))
+    snew(*tcr,1);
+  
+  low_comm_tcr(cr,*tcr);
+} 
+
+static void clear_lj(t_coupl_LJ *tc)
+{
+  tc->at_i   = 0;
+  tc->at_j   = 0;
+  tc->eObs   = -1;
+  tc->bPrint = TRUE;
+  tc->c6     = 0.0;
+  tc->c12    = 0.0;
+  tc->xi_6   = 0.0;
+  tc->xi_12  = 0.0;
+}
+
+static void clear_bu(t_coupl_BU *tc)
+{
+  tc->at_i   = 0;
+  tc->at_j   = 0;
+  tc->eObs   = -1;
+  tc->bPrint = TRUE;
+  tc->a      = 0.0;
+  tc->b      = 0.0;
+  tc->c      = 0.0;
+  tc->xi_a   = 0.0;
+  tc->xi_b   = 0.0;
+  tc->xi_c   = 0.0;
+}
+
+static void clear_q(t_coupl_Q *tc)
+{
+  tc->at_i   = 0;
+  tc->eObs   = -1;
+  tc->bPrint = TRUE;
+  tc->Q      = 0.0;
+  tc->xi_Q   = 0.0;
+}
+
+void copy_ff(t_coupl_rec *tcr,t_forcerec *fr,t_mdatoms *md,t_idef *idef)
+{
+  int        i,j,ati,atj,type;
+  t_coupl_LJ *tclj;
+  t_coupl_BU *tcbu;
+  t_coupl_Q  *tcq;
+  
+  /* Save values for printing */
+  for(i=0; (i<tcr->nLJ); i++) {
+    tclj = &(tcr->tcLJ[i]);
+    
+    ati  = tclj->at_i;
+    atj  = tclj->at_j;
+    if (atj == -1)
+      atj = ati;
+    tclj->c6  = C6(fr->nbfp,fr->ntype,ati,atj);
+    tclj->c12 = C12(fr->nbfp,fr->ntype,ati,atj);
+  }
+  
+  for(i=0; (i<tcr->nBU); i++) {
+    tcbu = &(tcr->tcBU[i]);
+    
+    ati  = tcbu->at_i;
+    atj  = tcbu->at_j;
+    if (atj == -1)
+      atj = ati;
+    tcbu->a = BHAMA(fr->nbfp,fr->ntype,ati,atj);
+    tcbu->b = BHAMB(fr->nbfp,fr->ntype,ati,atj);
+    tcbu->c = BHAMC(fr->nbfp,fr->ntype,ati,atj);
+  }
+  
+  for(i=0; (i<tcr->nQ); i++) {
+    tcq = &(tcr->tcQ[i]);
+    for(j=0; (j<md->nr); j++) {
+      if (md->typeA[j] == tcq->at_i) {
+       tcr->tcQ[i].Q = md->chargeA[j];
+       break;
+      }
+    }
+  }
+  for(i=0; (i<tcr->nIP); i++) {
+    /* Let's just copy the whole struct !*/
+    type = tcr->tIP[i].type;
+    tcr->tIP[i].iprint=idef->iparams[type];
+  }
+}
+
+void write_gct(const char *fn,t_coupl_rec *tcr,t_idef *idef)
+{
+  FILE *fp;
+  int  i,ftype;
+  
+  fp=gmx_fio_fopen(fn,"w");
+  nice_header(fp,fn);
+  fprintf(fp,"%-15s = %12g  ; Reference pressure for coupling\n",
+         eoNames[eoPres],tcr->ref_value[eoPres]);
+  fprintf(fp,"%-15s = %12g  ; Reference potential energy\n",
+         eoNames[eoEpot],tcr->ref_value[eoEpot]);
+  fprintf(fp,"%-15s = %12g  ; Reference distance\n",
+         eoNames[eoDist],tcr->ref_value[eoDist]);
+  fprintf(fp,"%-15s = %12g  ; Reference dipole\n",
+         eoNames[eoMu],tcr->ref_value[eoMu]);
+  fprintf(fp,"%-15s = %12g  ; Reference force\n",
+         eoNames[eoForce],tcr->ref_value[eoForce]);
+  fprintf(fp,"%-15s = %12g  ; Reference force in X dir\n",
+         eoNames[eoFx],tcr->ref_value[eoFx]);
+  fprintf(fp,"%-15s = %12g  ; Reference force in Y dir\n",
+         eoNames[eoFy],tcr->ref_value[eoFy]);
+  fprintf(fp,"%-15s = %12g  ; Reference force in Z dir\n",
+         eoNames[eoFz],tcr->ref_value[eoFz]);
+  fprintf(fp,"%-15s = %12g  ; Reference pres in X dir\n",
+         eoNames[eoPx],tcr->ref_value[eoPx]);
+  fprintf(fp,"%-15s = %12g  ; Reference pres in Y dir\n",
+         eoNames[eoPy],tcr->ref_value[eoPy]);
+  fprintf(fp,"%-15s = %12g  ; Reference pres in Z dir\n",
+         eoNames[eoPz],tcr->ref_value[eoPz]);
+  fprintf(fp,"%-15s = %12g  ; Polarizability used for the Epot correction\n",
+         eoNames[eoPolarizability],tcr->ref_value[eoPolarizability]);
+  fprintf(fp,"%-15s = %12g  ; Gas phase dipole moment used for Epot correction\n", 
+         eoNames[eoDipole],tcr->ref_value[eoDipole]);
+  fprintf(fp,"%-15s = %12d  ; Memory for coupling. Makes it converge faster.\n",
+         eoNames[eoMemory],tcr->nmemory);
+  fprintf(fp,"%-15s = %12s  ; Use intermolecular Epot only (LJ+Coul)\n",
+         eoNames[eoInter],yesno_names[tcr->bInter]);
+  fprintf(fp,"%-15s = %12s  ; Use virial iso pressure\n",
+         eoNames[eoUseVirial],yesno_names[tcr->bVirial]);
+  fprintf(fp,"%-15s = %12d  ; Combination rule, same coding as in grompp.\n",
+         eoNames[eoCombRule],tcr->combrule);
+  
+  fprintf(fp,"\n; Q-Coupling   %6s  %12s\n","type","xi");
+  for(i=0; (i<tcr->nQ); i++) {
+    fprintf(fp,"%-8s = %8s  %6d  %12g\n",
+           "Q",eoNames[tcr->tcQ[i].eObs],tcr->tcQ[i].at_i,tcr->tcQ[i].xi_Q);
+  }
+  
+  fprintf(fp,"\n; %8s %8s  %6s  %6s  %12s  %12s\n","Couple","To",
+         "i-type","j-type","xi-c6","xi-c12");
+  fprintf(fp,"; j-type == -1 means mixing rules will be applied!\n");
+  for(i=0; (i<tcr->nLJ); i++) {
+    fprintf(fp,"%-8s = %8s  %6d  %6d  %12g  %12g\n",
+           "LJ",eoNames[tcr->tcLJ[i].eObs],
+           tcr->tcLJ[i].at_i,tcr->tcLJ[i].at_j,
+           tcr->tcLJ[i].xi_6,tcr->tcLJ[i].xi_12);
+  }
+  
+  fprintf(fp,"\n; %8s %8s  %6s  %6s  %12s  %12s  %12s\n","Couple","To",
+         "i-type","j-type","xi-A","xi-B","xi-C");
+  fprintf(fp,"; j-type == -1 means mixing rules will be applied!\n");
+  for(i=0; (i<tcr->nBU); i++) {
+    fprintf(fp,"%-8s = %8s  %6d  %6d  %12g  %12g  %12g\n",
+           "BU",eoNames[tcr->tcBU[i].eObs],
+           tcr->tcBU[i].at_i,tcr->tcBU[i].at_j,
+           tcr->tcBU[i].xi_a,tcr->tcBU[i].xi_b,tcr->tcBU[i].xi_c);
+  }
+  
+  fprintf(fp,"\n; More Coupling\n");
+  for(i=0; (i<tcr->nIP); i++) {
+    ftype=idef->functype[tcr->tIP[i].type];
+    switch (ftype) {
+    case F_BONDS:
+      fprintf(fp,"%-15s = %-8s  %4d  %12g  %12g\n",
+             "Bonds",eoNames[tcr->tIP[i].eObs],tcr->tIP[i].type,
+             tcr->tIP[i].xi.harmonic.krA,
+             tcr->tIP[i].xi.harmonic.rA);
+      break;
+    default:
+      fprintf(stderr,"ftype %s not supported (yet)\n",
+             interaction_function[ftype].longname);
+    }
+  }
+  gmx_fio_fclose(fp);
+}
+
+static gmx_bool add_lj(int *nLJ,t_coupl_LJ **tcLJ,char *s,gmx_bool bObsUsed[])
+{
+  int       j,ati,atj,eo;
+  char      buf[256];
+  double    xi6,xi12;
+  
+  if (sscanf(s,"%s%d%d%lf%lf",buf,&ati,&atj,&xi6,&xi12) != 5) 
+    return TRUE;
+  if ((eo=Name2eo(buf)) == -1)
+    gmx_fatal(FARGS,"Invalid observable for LJ coupling: %s",buf);
+  
+  for(j=0; (j<*nLJ); j++) {
+    if ((((*tcLJ)[j].at_i == ati) && ((*tcLJ)[j].at_j == atj)) &&
+       ((*tcLJ)[j].xi_6 || (*tcLJ)[j].xi_12) &&
+       ((*tcLJ)[j].eObs == eo))
+      break;
+  }
+  if (j == *nLJ) {
+    ++(*nLJ);
+    srenew((*tcLJ),*nLJ);
+  }
+  else
+    fprintf(stderr,"\n*** WARNING: overwriting entry for LJ coupling '%s'\n",s);
+  
+  clear_lj(&((*tcLJ)[j]));
+  if (((*tcLJ)[j].eObs = eo) == -1) {
+    gmx_fatal(FARGS,"Invalid observable for LJ coupling: %s",buf);
+  }
+  (*tcLJ)[j].at_i   = ati;
+  (*tcLJ)[j].at_j   = atj;
+  (*tcLJ)[j].xi_6   = xi6;
+  (*tcLJ)[j].xi_12  = xi12;
+  bObsUsed[eo] = TRUE;
+  
+  return FALSE;
+}
+
+static gmx_bool add_bu(int *nBU,t_coupl_BU **tcBU,char *s,gmx_bool bObsUsed[])
+{
+  int       j,ati,atj,eo;
+  char      buf[256];
+  double    xia,xib,xic;
+  
+  if (sscanf(s,"%s%d%d%lf%lf%lf",buf,&ati,&atj,&xia,&xib,&xic) != 6) 
+    return TRUE;
+  if ((eo=Name2eo(buf)) == -1)
+    gmx_fatal(FARGS,"Invalid observable for BU coupling: %s",buf);
+  
+  for(j=0; (j<*nBU); j++) {
+    if ((((*tcBU)[j].at_i == ati) && ((*tcBU)[j].at_j == atj)) &&
+       ((*tcBU)[j].xi_a || (*tcBU)[j].xi_b || (*tcBU)[j].xi_c ) &&
+       ((*tcBU)[j].eObs == eo))
+      break;
+  }
+  if (j == *nBU) {
+    ++(*nBU);
+    srenew((*tcBU),*nBU);
+  }
+  else
+    fprintf(stderr,"\n*** WARNING: overwriting entry for BU coupling '%s'\n",s);
+  
+  clear_bu(&((*tcBU)[j]));
+  if (((*tcBU)[j].eObs = eo) == -1) {
+    gmx_fatal(FARGS,"Invalid observable for BU coupling: %s",buf);
+  }
+  (*tcBU)[j].at_i   = ati;
+  (*tcBU)[j].at_j   = atj;
+  (*tcBU)[j].xi_a   = xia;
+  (*tcBU)[j].xi_b   = xib;
+  (*tcBU)[j].xi_c   = xic;
+  bObsUsed[eo] = TRUE;
+
+  return FALSE;
+}
+
+static gmx_bool add_ip(int *nIP,t_coupl_iparams **tIP,char *s,int ftype,gmx_bool bObsUsed[])
+{
+  int    i,eo,type;
+  char   buf[256];
+  double kb,b0;
+  
+  switch (ftype) {
+  case F_BONDS:
+    /* Pick out the type */
+    if (sscanf(s,"%s%d",buf,&type) != 2)
+      return TRUE;
+    if ((eo=Name2eo(buf)) == -1)
+      gmx_fatal(FARGS,"Invalid observable for IP coupling: %s",buf);
+      
+    /* Check whether this entry is there already */
+    for(i=0; (i<*nIP); i++) {
+      if ((*tIP)[i].type == type)
+       break;
+    }
+    if (i < *nIP) {
+      fprintf(stderr,"*** WARNING: overwriting entry for type %d\n",type);
+    }
+    else {
+      i=*nIP;
+      srenew((*tIP),i+1);
+      (*nIP)++;
+    }
+    if (sscanf(s,"%s%d%lf%lf",buf,&type,&kb,&b0) != 4)
+      return TRUE;
+    (*tIP)[i].type=type;
+    (*tIP)[i].eObs=eo;
+    (*tIP)[i].xi.harmonic.krA = kb;
+    (*tIP)[i].xi.harmonic.rA  = b0;
+    bObsUsed[eo] = TRUE;
+    break;
+  default:
+    fprintf(stderr,"ftype %s not supported (yet)\n",
+           interaction_function[ftype].longname);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static gmx_bool add_q(int *nQ,t_coupl_Q **tcQ,char *s,gmx_bool bObsUsed[])
+{
+  int       j,ati,eo;
+  char      buf[256];
+  double    xiQ;
+  
+  if (sscanf(s,"%s%d%lf",buf,&ati,&xiQ) != 3) 
+    return TRUE;
+  
+  for(j=0; (j<*nQ); j++) {
+    if ((*tcQ)[j].at_i == ati)
+      break;
+  }
+  if (j == *nQ) {
+    ++(*nQ);
+    srenew((*tcQ),*nQ);
+  }
+  else
+    fprintf(stderr,"\n*** WARNING: overwriting entry for Q coupling '%s'\n",s);
+  
+  clear_q(&((*tcQ)[j]));
+  eo = (*tcQ)[j].eObs = Name2eo(buf);
+  if ((*tcQ)[j].eObs == -1) {
+    gmx_fatal(FARGS,"Invalid observable for Q coupling: %s",buf);
+  }
+  (*tcQ)[j].at_i   = ati;
+  (*tcQ)[j].xi_Q  = xiQ;
+  bObsUsed[eo] = TRUE;
+  
+  return FALSE;
+}
+
+void read_gct(const char *fn,t_coupl_rec *tcr)
+{
+  warninp_t wi;
+  t_inpfile *inp;
+  int       i,j,ninp,nQ,nLJ,nBU,nIP;
+  gmx_bool      bWrong;
+  
+  wi = init_warning(FALSE,0);
+
+  inp=read_inpfile(fn,&ninp,NULL,wi);
+
+  for(i=0; (i<eoObsNR); i++) {
+    tcr->bObsUsed[i] = FALSE;
+    RTYPE (eoNames[i], tcr->ref_value[i],      0.0);
+  }
+  ITYPE (eoNames[eoMemory],     tcr->nmemory,   1);
+  ETYPE (eoNames[eoInter],      tcr->bInter,    yesno_names);
+  ETYPE (eoNames[eoUseVirial],  tcr->bVirial,   yesno_names);
+  ITYPE (eoNames[eoCombRule],   tcr->combrule,  1);
+  tcr->tcLJ=NULL;
+  tcr->tcBU=NULL;
+  tcr->tcQ=NULL;
+  tcr->tIP=NULL;
+  nQ=nLJ=nBU=nIP=0;
+  
+  for(i=0; (i<ninp); i++) {
+    bWrong=FALSE;
+    if (gmx_strcasecmp(inp[i].name,"LJ") == 0) 
+      bWrong=add_lj(&nLJ,&(tcr->tcLJ),inp[i].value,tcr->bObsUsed);
+    else if (gmx_strcasecmp(inp[i].name,"BU") == 0) 
+      bWrong=add_bu(&nBU,&(tcr->tcBU),inp[i].value,tcr->bObsUsed);
+    else if (gmx_strcasecmp(inp[i].name,"Q") == 0) 
+      bWrong=add_q(&nQ,&(tcr->tcQ),inp[i].value,tcr->bObsUsed);
+    else if (gmx_strcasecmp(inp[i].name,"Bonds") == 0)
+      bWrong=add_ip(&nIP,&(tcr->tIP),inp[i].value,F_BONDS,tcr->bObsUsed);
+      
+    if (bWrong)
+      fprintf(stderr,"Wrong line in %s: '%s = %s'\n",
+             fn,inp[i].name,inp[i].value);
+    /*sfree(inp[i].name);
+      sfree(inp[i].value);*/
+  }
+  /* Check which ones have to be printed */
+  for(i=1; (i<nQ); i++)
+    for(j=0; (j<i); j++) {
+      if (tcr->tcQ[i].at_i == tcr->tcQ[j].at_i)
+       tcr->tcQ[j].bPrint=FALSE;
+    }
+  for(i=1; (i<nLJ); i++)
+    for(j=0; (j<i); j++) {
+      if (((tcr->tcLJ[i].at_i == tcr->tcLJ[j].at_i) &&
+          (tcr->tcLJ[i].at_j == tcr->tcLJ[j].at_j)) ||
+         ((tcr->tcLJ[i].at_i == tcr->tcLJ[j].at_j) &&
+          (tcr->tcLJ[i].at_j == tcr->tcLJ[j].at_i))) 
+       tcr->tcLJ[j].bPrint=FALSE;
+    }
+  
+  for(i=1; (i<nBU); i++)
+    for(j=0; (j<i); j++) {
+      if (((tcr->tcBU[i].at_i == tcr->tcBU[j].at_i) &&
+          (tcr->tcBU[i].at_j == tcr->tcBU[j].at_j)) ||
+         ((tcr->tcBU[i].at_i == tcr->tcBU[j].at_j) &&
+          (tcr->tcBU[i].at_j == tcr->tcBU[j].at_i))) 
+       tcr->tcBU[j].bPrint=FALSE;
+    }
+  
+  tcr->nQ  = nQ;
+  tcr->nLJ = nLJ;
+  tcr->nBU = nBU;
+  tcr->nIP = nIP;
+  
+  sfree(inp);
+
+  done_warning(wi,FARGS);
+}
+
diff --git a/src/programs/mdrun/md.c b/src/programs/mdrun/md.c
new file mode 100644 (file)
index 0000000..49f0571
--- /dev/null
@@ -0,0 +1,1866 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+/* _isnan() */
+#include <float.h>
+#endif
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "vec.h"
+#include "statutil.h"
+#include "vcm.h"
+#include "mdebin.h"
+#include "nrnb.h"
+#include "calcmu.h"
+#include "index.h"
+#include "vsite.h"
+#include "update.h"
+#include "ns.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "mdrun.h"
+#include "confio.h"
+#include "network.h"
+#include "pull.h"
+#include "xvgr.h"
+#include "physics.h"
+#include "names.h"
+#include "xmdrun.h"
+#include "ionize.h"
+#include "disre.h"
+#include "orires.h"
+#include "dihre.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdatoms.h"
+#include "repl_ex.h"
+#include "qmmm.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "topsort.h"
+#include "coulomb.h"
+#include "constr.h"
+#include "shellfc.h"
+#include "compute_io.h"
+#include "mvdata.h"
+#include "checkpoint.h"
+#include "mtop_util.h"
+#include "sighandler.h"
+#include "membed.h"
+#include "string2.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#ifdef GMX_FAHCORE
+#include "corewrap.h"
+#endif
+
+
+double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+             int nstglobalcomm,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int stepout,t_inputrec *ir,
+             gmx_mtop_t *top_global,
+             t_fcdata *fcd,
+             t_state *state_global,
+             t_mdatoms *mdatoms,
+             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+             gmx_edsam_t ed,t_forcerec *fr,
+             int repl_ex_nst,int repl_ex_seed,gmx_membed_t *membed,
+             real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             gmx_runtime_t *runtime)
+{
+    gmx_mdoutf_t *outf;
+    gmx_large_int_t step,step_rel;
+    double     run_time;
+    double     t,t0,lam0;
+    gmx_bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
+    gmx_bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
+               bFirstStep,bStateFromTPX,bInitStep,bLastStep,
+               bBornRadii,bStartingFromCpt;
+    gmx_bool       bDoDHDL=FALSE;
+    gmx_bool       do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
+               bForceUpdate=FALSE,bCPT;
+    int        mdof_flags;
+    gmx_bool       bMasterState;
+    int        force_flags,cglo_flags;
+    tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
+    int        i,m;
+    t_trxstatus *status;
+    rvec       mu_tot;
+    t_vcm      *vcm;
+    t_state    *bufstate=NULL;   
+    matrix     *scale_tot,pcoupl_mu,M,ebox;
+    gmx_nlheur_t nlh;
+    t_trxframe rerun_fr;
+    gmx_repl_ex_t repl_ex=NULL;
+    int        nchkpt=1;
+
+    gmx_localtop_t *top;       
+    t_mdebin *mdebin=NULL;
+    t_state    *state=NULL;
+    rvec       *f_global=NULL;
+    int        n_xtc=-1;
+    rvec       *x_xtc=NULL;
+    gmx_enerdata_t *enerd;
+    rvec       *f=NULL;
+    gmx_global_stat_t gstat;
+    gmx_update_t upd=NULL;
+    t_graph    *graph=NULL;
+    globsig_t   gs;
+
+    gmx_bool        bFFscan;
+    gmx_groups_t *groups;
+    gmx_ekindata_t *ekind, *ekind_save;
+    gmx_shellfc_t shellfc;
+    int         count,nconverged=0;
+    real        timestep=0;
+    double      tcount=0;
+    gmx_bool        bIonize=FALSE;
+    gmx_bool        bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
+    gmx_bool        bAppend;
+    gmx_bool        bResetCountersHalfMaxH=FALSE;
+    gmx_bool        bVV,bIterations,bFirstIterate,bTemp,bPres,bTrotter;
+    real        temp0,mu_aver=0,dvdl;
+    int         a0,a1,gnx=0,ii;
+    atom_id     *grpindex=NULL;
+    char        *grpname;
+    t_coupl_rec *tcr=NULL;
+    rvec        *xcopy=NULL,*vcopy=NULL,*cbuf=NULL;
+    matrix      boxcopy={{0}},lastbox;
+       tensor      tmpvir;
+       real        fom,oldfom,veta_save,pcurr,scalevir,tracevir;
+       real        vetanew = 0;
+    double      cycles;
+       real        saved_conserved_quantity = 0;
+    real        last_ekin = 0;
+       int         iter_i;
+       t_extmass   MassQ;
+    int         **trotter_seq; 
+    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+    int         handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
+    gmx_iterate_t iterate;
+    gmx_large_int_t multisim_nsteps=-1; /* number of steps to do  before first multisim 
+                                          simulation stops. If equal to zero, don't
+                                          communicate any more between multisims.*/
+#ifdef GMX_FAHCORE
+    /* Temporary addition for FAHCORE checkpointing */
+    int chkpt_ret;
+#endif
+
+    /* Check for special mdrun options */
+    bRerunMD = (Flags & MD_RERUN);
+    bIonize  = (Flags & MD_IONIZE);
+    bFFscan  = (Flags & MD_FFSCAN);
+    bAppend  = (Flags & MD_APPENDFILES);
+    if (Flags & MD_RESETCOUNTERSHALFWAY)
+    {
+        if (ir->nsteps > 0)
+        {
+            /* Signal to reset the counters half the simulation steps. */
+            wcycle_set_reset_counters(wcycle,ir->nsteps/2);
+        }
+        /* Signal to reset the counters halfway the simulation time. */
+        bResetCountersHalfMaxH = (max_hours > 0);
+    }
+
+    /* md-vv uses averaged full step velocities for T-control 
+       md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
+       md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
+    bVV = EI_VV(ir->eI);
+    if (bVV) /* to store the initial velocities while computing virial */
+    {
+        snew(cbuf,top_global->natoms);
+    }
+    /* all the iteratative cases - only if there are constraints */ 
+    bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
+    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));        
+    
+    if (bRerunMD)
+    {
+        /* Since we don't know if the frames read are related in any way,
+         * rebuild the neighborlist at every step.
+         */
+        ir->nstlist       = 1;
+        ir->nstcalcenergy = 1;
+        nstglobalcomm     = 1;
+    }
+
+    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
+
+    nstglobalcomm = check_nstglobalcomm(fplog,cr,nstglobalcomm,ir);
+    bGStatEveryStep = (nstglobalcomm == 1);
+
+    if (!bGStatEveryStep && ir->nstlist == -1 && fplog != NULL)
+    {
+        fprintf(fplog,
+                "To reduce the energy communication with nstlist = -1\n"
+                "the neighbor list validity should not be checked at every step,\n"
+                "this means that exact integration is not guaranteed.\n"
+                "The neighbor list validity is checked after:\n"
+                "  <n.list life time> - 2*std.dev.(n.list life time)  steps.\n"
+                "In most cases this will result in exact integration.\n"
+                "This reduces the energy communication by a factor of 2 to 3.\n"
+                "If you want less energy communication, set nstlist > 3.\n\n");
+    }
+
+    if (bRerunMD || bFFscan)
+    {
+        ir->nstxtcout = 0;
+    }
+    groups = &top_global->groups;
+
+    /* Initial values */
+    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+            nrnb,top_global,&upd,
+            nfile,fnm,&outf,&mdebin,
+            force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
+
+    clear_mat(total_vir);
+    clear_mat(pres);
+    /* Energy terms and groups */
+    snew(enerd,1);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+    if (DOMAINDECOMP(cr))
+    {
+        f = NULL;
+    }
+    else
+    {
+        snew(f,top_global->natoms);
+    }
+
+    /* Kinetic energy data */
+    snew(ekind,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind);
+    /* needed for iteration of constraints */
+    snew(ekind_save,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
+    /* Copy the cos acceleration to the groups struct */    
+    ekind->cosacc.cos_accel = ir->cos_accel;
+
+    gstat = global_stat_init(ir);
+    debug_gmx();
+
+    /* Check for polarizable models and flexible constraints */
+    shellfc = init_shell_flexcon(fplog,
+                                 top_global,n_flexible_constraints(constr),
+                                 (ir->bContinuation || 
+                                  (DOMAINDECOMP(cr) && !MASTER(cr))) ?
+                                 NULL : state_global->x);
+
+    if (DEFORM(*ir))
+    {
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
+#endif
+        set_deform_reference_box(upd,
+                                 deform_init_init_step_tpx,
+                                 deform_init_box_tpx);
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
+#endif
+    }
+
+    {
+        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
+        if ((io > 2000) && MASTER(cr))
+            fprintf(stderr,
+                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
+                    io);
+    }
+
+    if (DOMAINDECOMP(cr)) {
+        top = dd_init_local_top(top_global);
+
+        snew(state,1);
+        dd_init_local_state(cr->dd,state_global,state);
+
+        if (DDMASTER(cr->dd) && ir->nstfout) {
+            snew(f_global,state_global->natoms);
+        }
+    } else {
+        if (PAR(cr)) {
+            /* Initialize the particle decomposition and split the topology */
+            top = split_system(fplog,top_global,ir,cr);
+
+            pd_cg_range(cr,&fr->cg0,&fr->hcg);
+            pd_at_range(cr,&a0,&a1);
+        } else {
+            top = gmx_mtop_generate_local_top(top_global,ir);
+
+            a0 = 0;
+            a1 = top_global->natoms;
+        }
+
+        state = partdec_init_local_state(cr,state_global);
+        f_global = f;
+
+        atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+
+        if (vsite) {
+            set_vsite_top(vsite,top,mdatoms,cr);
+        }
+
+        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
+            graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+        }
+
+        if (shellfc) {
+            make_local_shells(cr,mdatoms,shellfc);
+        }
+
+        if (ir->pull && PAR(cr)) {
+            dd_make_local_pull_groups(NULL,ir->pull,mdatoms);
+        }
+    }
+
+    if (DOMAINDECOMP(cr))
+    {
+        /* Distribute the charge groups over the nodes from the master node */
+        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
+                            state_global,top_global,ir,
+                            state,&f,mdatoms,top,fr,
+                            vsite,shellfc,constr,
+                            nrnb,wcycle,FALSE);
+    }
+
+    update_mdatoms(mdatoms,state->lambda);
+
+    if (MASTER(cr))
+    {
+        if (opt2bSet("-cpi",nfile,fnm))
+        {
+            /* Update mdebin with energy history if appending to output files */
+            if ( Flags & MD_APPENDFILES )
+            {
+                restore_energyhistory_from_state(mdebin,&state_global->enerhist);
+            }
+            else
+            {
+                /* We might have read an energy history from checkpoint,
+                 * free the allocated memory and reset the counts.
+                 */
+                done_energyhistory(&state_global->enerhist);
+                init_energyhistory(&state_global->enerhist);
+            }
+        }
+        /* Set the initial energy history in state by updating once */
+        update_energyhistory(&state_global->enerhist,mdebin);
+    }  
+
+    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
+        /* Set the random state if we read a checkpoint file */
+        set_stochd_state(upd,state);
+    }
+
+    /* Initialize constraints */
+    if (constr) {
+        if (!DOMAINDECOMP(cr))
+            set_constraints(constr,top,ir,mdatoms,cr);
+    }
+
+    /* Check whether we have to GCT stuff */
+    bTCR = ftp2bSet(efGCT,nfile,fnm);
+    if (bTCR) {
+        if (MASTER(cr)) {
+            fprintf(stderr,"Will do General Coupling Theory!\n");
+        }
+        gnx = top_global->mols.nr;
+        snew(grpindex,gnx);
+        for(i=0; (i<gnx); i++) {
+            grpindex[i] = i;
+        }
+    }
+
+    if (repl_ex_nst > 0)
+    {
+        /* We need to be sure replica exchange can only occur
+         * when the energies are current */
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                        "repl_ex_nst",&repl_ex_nst);
+        /* This check needs to happen before inter-simulation
+         * signals are initialized, too */
+    }
+    if (repl_ex_nst > 0 && MASTER(cr))
+        repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
+                                        repl_ex_nst,repl_ex_seed);
+
+    if (!ir->bContinuation && !bRerunMD)
+    {
+        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
+        {
+            /* Set the velocities of frozen particles to zero */
+            for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+            {
+                for(m=0; m<DIM; m++)
+                {
+                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
+                    {
+                        state->v[i][m] = 0;
+                    }
+                }
+            }
+        }
+
+        if (constr)
+        {
+            /* Constrain the initial coordinates and velocities */
+            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
+                               graph,cr,nrnb,fr,top,shake_vir);
+        }
+        if (vsite)
+        {
+            /* Construct the virtual sites for the initial configuration */
+            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
+                             top->idef.iparams,top->idef.il,
+                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+        }
+    }
+
+    debug_gmx();
+  
+    /* I'm assuming we need global communication the first time! MRS */
+    cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
+                  | (bVV ? CGLO_PRESSURE:0)
+                  | (bVV ? CGLO_CONSTRAINT:0)
+                  | (bRerunMD ? CGLO_RERUNMD:0)
+                  | ((Flags & MD_READ_EKIN) ? CGLO_READEKIN:0));
+    
+    bSumEkinhOld = FALSE;
+    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                    constr,NULL,FALSE,state->box,
+                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
+    if (ir->eI == eiVVAK) {
+        /* a second call to get the half step temperature initialized as well */ 
+        /* we do the same call as above, but turn the pressure off -- internally to 
+           compute_globals, this is recognized as a velocity verlet half-step 
+           kinetic energy calculation.  This minimized excess variables, but 
+           perhaps loses some logic?*/
+        
+        compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                        wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                        constr,NULL,FALSE,state->box,
+                        top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                        cglo_flags &~ CGLO_PRESSURE);
+    }
+    
+    /* Calculate the initial half step temperature, and save the ekinh_old */
+    if (!(Flags & MD_STARTFROMCPT)) 
+    {
+        for(i=0; (i<ir->opts.ngtc); i++) 
+        {
+            copy_mat(ekind->tcstat[i].ekinh,ekind->tcstat[i].ekinh_old);
+        } 
+    }
+    if (ir->eI != eiVV) 
+    {
+        enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
+                                     and there is no previous step */
+    }
+    temp0 = enerd->term[F_TEMP];
+    
+    /* if using an iterative algorithm, we need to create a working directory for the state. */
+    if (bIterations) 
+    {
+            bufstate = init_bufstate(state);
+    }
+    if (bFFscan) 
+    {
+        snew(xcopy,state->natoms);
+        snew(vcopy,state->natoms);
+        copy_rvecn(state->x,xcopy,0,state->natoms);
+        copy_rvecn(state->v,vcopy,0,state->natoms);
+        copy_mat(state->box,boxcopy);
+    } 
+    
+    /* need to make an initiation call to get the Trotter variables set, as well as other constants for non-trotter
+       temperature control */
+    trotter_seq = init_npt_vars(ir,state,&MassQ,bTrotter);
+    
+    if (MASTER(cr))
+    {
+        if (constr && !ir->bContinuation && ir->eConstrAlg == econtLINCS)
+        {
+            fprintf(fplog,
+                    "RMS relative constraint deviation after constraining: %.2e\n",
+                    constr_rmsd(constr,FALSE));
+        }
+        fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
+        if (bRerunMD)
+        {
+            fprintf(stderr,"starting md rerun '%s', reading coordinates from"
+                    " input trajectory '%s'\n\n",
+                    *(top_global->name),opt2fn("-rerun",nfile,fnm));
+            if (bVerbose)
+            {
+                fprintf(stderr,"Calculated time to finish depends on nsteps from "
+                        "run input file,\nwhich may not correspond to the time "
+                        "needed to process input trajectory.\n\n");
+            }
+        }
+        else
+        {
+            char tbuf[20];
+            fprintf(stderr,"starting mdrun '%s'\n",
+                    *(top_global->name));
+            if (ir->nsteps >= 0)
+            {
+                sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
+            }
+            else
+            {
+                sprintf(tbuf,"%s","infinite");
+            }
+            if (ir->init_step > 0)
+            {
+                fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
+                        gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
+                        gmx_step_str(ir->init_step,sbuf2),
+                        ir->init_step*ir->delta_t);
+            }
+            else
+            {
+                fprintf(stderr,"%s steps, %s ps.\n",
+                        gmx_step_str(ir->nsteps,sbuf),tbuf);
+            }
+        }
+        fprintf(fplog,"\n");
+    }
+
+    /* Set and write start time */
+    runtime_start(runtime);
+    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
+    wallcycle_start(wcycle,ewcRUN);
+    if (fplog)
+        fprintf(fplog,"\n");
+
+    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
+#ifdef GMX_FAHCORE
+    chkpt_ret=fcCheckPointParallel( cr->nodeid,
+                                    NULL,0);
+    if ( chkpt_ret == 0 ) 
+        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", 0 );
+#endif
+
+    debug_gmx();
+    /***********************************************************
+     *
+     *             Loop over MD steps 
+     *
+     ************************************************************/
+
+    /* if rerunMD then read coordinates and velocities from input trajectory */
+    if (bRerunMD)
+    {
+        if (getenv("GMX_FORCE_UPDATE"))
+        {
+            bForceUpdate = TRUE;
+        }
+
+        rerun_fr.natoms = 0;
+        if (MASTER(cr))
+        {
+            bNotLastFrame = read_first_frame(oenv,&status,
+                                             opt2fn("-rerun",nfile,fnm),
+                                             &rerun_fr,TRX_NEED_X | TRX_READ_V);
+            if (rerun_fr.natoms != top_global->natoms)
+            {
+                gmx_fatal(FARGS,
+                          "Number of atoms in trajectory (%d) does not match the "
+                          "run input file (%d)\n",
+                          rerun_fr.natoms,top_global->natoms);
+            }
+            if (ir->ePBC != epbcNONE)
+            {
+                if (!rerun_fr.bBox)
+                {
+                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+                }
+                if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+                {
+                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+                }
+            }
+        }
+
+        if (PAR(cr))
+        {
+            rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+        }
+
+        if (ir->ePBC != epbcNONE)
+        {
+            /* Set the shift vectors.
+             * Necessary here when have a static box different from the tpr box.
+             */
+            calc_shifts(rerun_fr.box,fr->shift_vec);
+        }
+    }
+
+    /* loop over MD steps or if rerunMD to end of input trajectory */
+    bFirstStep = TRUE;
+    /* Skip the first Nose-Hoover integration when we get the state from tpx */
+    bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
+    bInitStep = bFirstStep && (bStateFromTPX || bVV);
+    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
+    bLastStep    = FALSE;
+    bSumEkinhOld = FALSE;
+    bExchanged   = FALSE;
+
+    init_global_signals(&gs,cr,ir,repl_ex_nst);
+
+    step = ir->init_step;
+    step_rel = 0;
+
+    if (ir->nstlist == -1)
+    {
+        init_nlistheuristics(&nlh,bGStatEveryStep,step);
+    }
+
+    if (MULTISIM(cr) && (repl_ex_nst <=0 ))
+    {
+        /* check how many steps are left in other sims */
+        multisim_nsteps=get_multisim_nsteps(cr, ir->nsteps);
+    }
+
+
+    /* and stop now if we should */
+    bLastStep = (bRerunMD || (ir->nsteps >= 0 && step_rel > ir->nsteps) ||
+                 ((multisim_nsteps >= 0) && (step_rel >= multisim_nsteps )));
+    while (!bLastStep || (bRerunMD && bNotLastFrame)) {
+
+        wallcycle_start(wcycle,ewcSTEP);
+
+        if (bRerunMD) {
+            if (rerun_fr.bStep) {
+                step = rerun_fr.step;
+                step_rel = step - ir->init_step;
+            }
+            if (rerun_fr.bTime) {
+                t = rerun_fr.time;
+            }
+            else
+            {
+                t = step;
+            }
+        } 
+        else 
+        {
+            bLastStep = (step_rel == ir->nsteps);
+            t = t0 + step*ir->delta_t;
+        }
+
+        if (ir->efep != efepNO)
+        {
+            if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
+            {
+                state_global->lambda = rerun_fr.lambda;
+            }
+            else
+            {
+                state_global->lambda = lam0 + step*ir->delta_lambda;
+            }
+            state->lambda = state_global->lambda;
+            bDoDHDL = do_per_step(step,ir->nstdhdl);
+        }
+
+        if (bSimAnn) 
+        {
+            update_annealing_target_temp(&(ir->opts),t);
+        }
+
+        if (bRerunMD)
+        {
+            if (!(DOMAINDECOMP(cr) && !MASTER(cr)))
+            {
+                for(i=0; i<state_global->natoms; i++)
+                {
+                    copy_rvec(rerun_fr.x[i],state_global->x[i]);
+                }
+                if (rerun_fr.bV)
+                {
+                    for(i=0; i<state_global->natoms; i++)
+                    {
+                        copy_rvec(rerun_fr.v[i],state_global->v[i]);
+                    }
+                }
+                else
+                {
+                    for(i=0; i<state_global->natoms; i++)
+                    {
+                        clear_rvec(state_global->v[i]);
+                    }
+                    if (bRerunWarnNoV)
+                    {
+                        fprintf(stderr,"\nWARNING: Some frames do not contain velocities.\n"
+                                "         Ekin, temperature and pressure are incorrect,\n"
+                                "         the virial will be incorrect when constraints are present.\n"
+                                "\n");
+                        bRerunWarnNoV = FALSE;
+                    }
+                }
+            }
+            copy_mat(rerun_fr.box,state_global->box);
+            copy_mat(state_global->box,state->box);
+
+            if (vsite && (Flags & MD_RERUN_VSITE))
+            {
+                if (DOMAINDECOMP(cr))
+                {
+                    gmx_fatal(FARGS,"Vsite recalculation with -rerun is not implemented for domain decomposition, use particle decomposition");
+                }
+                if (graph)
+                {
+                    /* Following is necessary because the graph may get out of sync
+                     * with the coordinates if we only have every N'th coordinate set
+                     */
+                    mk_mshift(fplog,graph,fr->ePBC,state->box,state->x);
+                    shift_self(graph,state->box,state->x);
+                }
+                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+                                 top->idef.iparams,top->idef.il,
+                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+                if (graph)
+                {
+                    unshift_self(graph,state->box,state->x);
+                }
+            }
+        }
+
+        /* Stop Center of Mass motion */
+        bStopCM = (ir->comm_mode != ecmNO && do_per_step(step,ir->nstcomm));
+
+        /* Copy back starting coordinates in case we're doing a forcefield scan */
+        if (bFFscan)
+        {
+            for(ii=0; (ii<state->natoms); ii++)
+            {
+                copy_rvec(xcopy[ii],state->x[ii]);
+                copy_rvec(vcopy[ii],state->v[ii]);
+            }
+            copy_mat(boxcopy,state->box);
+        }
+
+        if (bRerunMD)
+        {
+            /* for rerun MD always do Neighbour Searching */
+            bNS = (bFirstStep || ir->nstlist != 0);
+            bNStList = bNS;
+        }
+        else
+        {
+            /* Determine whether or not to do Neighbour Searching and LR */
+            bNStList = (ir->nstlist > 0  && step % ir->nstlist == 0);
+            
+            bNS = (bFirstStep || bExchanged || bNStList ||
+                   (ir->nstlist == -1 && nlh.nabnsb > 0));
+
+            if (bNS && ir->nstlist == -1)
+            {
+                set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
+            }
+        } 
+
+        /* check whether we should stop because another simulation has 
+           stopped. */
+        if (MULTISIM(cr))
+        {
+            if ( (multisim_nsteps >= 0) &&  (step_rel >= multisim_nsteps)  &&  
+                 (multisim_nsteps != ir->nsteps) )  
+            {
+                if (bNS)
+                {
+                    if (MASTER(cr))
+                    {
+                        fprintf(stderr, 
+                                "Stopping simulation %d because another one has finished\n",
+                                cr->ms->sim);
+                    }
+                    bLastStep=TRUE;
+                    gs.sig[eglsCHKPT] = 1;
+                }
+            }
+        }
+
+        /* < 0 means stop at next step, > 0 means stop at next NS step */
+        if ( (gs.set[eglsSTOPCOND] < 0 ) ||
+             ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
+        {
+            bLastStep = TRUE;
+        }
+
+        /* Determine whether or not to update the Born radii if doing GB */
+        bBornRadii=bFirstStep;
+        if (ir->implicit_solvent && (step % ir->nstgbradii==0))
+        {
+            bBornRadii=TRUE;
+        }
+        
+        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
+        do_verbose = bVerbose &&
+                  (step % stepout == 0 || bFirstStep || bLastStep);
+
+        if (bNS && !(bFirstStep && ir->bContinuation && !bRerunMD))
+        {
+            if (bRerunMD)
+            {
+                bMasterState = TRUE;
+            }
+            else
+            {
+                bMasterState = FALSE;
+                /* Correct the new box if it is too skewed */
+                if (DYNAMIC_BOX(*ir))
+                {
+                    if (correct_box(fplog,step,state->box,graph))
+                    {
+                        bMasterState = TRUE;
+                    }
+                }
+                if (DOMAINDECOMP(cr) && bMasterState)
+                {
+                    dd_collect_state(cr->dd,state,state_global);
+                }
+            }
+
+            if (DOMAINDECOMP(cr))
+            {
+                /* Repartition the domain decomposition */
+                wallcycle_start(wcycle,ewcDOMDEC);
+                dd_partition_system(fplog,step,cr,
+                                    bMasterState,nstglobalcomm,
+                                    state_global,top_global,ir,
+                                    state,&f,mdatoms,top,fr,
+                                    vsite,shellfc,constr,
+                                    nrnb,wcycle,do_verbose);
+                wallcycle_stop(wcycle,ewcDOMDEC);
+                /* If using an iterative integrator, reallocate space to match the decomposition */
+            }
+        }
+
+        if (MASTER(cr) && do_log && !bFFscan)
+        {
+            print_ebin_header(fplog,step,t,state->lambda);
+        }
+
+        if (ir->efep != efepNO)
+        {
+            update_mdatoms(mdatoms,state->lambda); 
+        }
+
+        if (bRerunMD && rerun_fr.bV)
+        {
+            
+            /* We need the kinetic energy at minus the half step for determining
+             * the full step kinetic energy and possibly for T-coupling.*/
+            /* This may not be quite working correctly yet . . . . */
+            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                            wcycle,enerd,NULL,NULL,NULL,NULL,mu_tot,
+                            constr,NULL,FALSE,state->box,
+                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                            CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
+        }
+        clear_mat(force_vir);
+        
+        /* Ionize the atoms if necessary */
+        if (bIonize)
+        {
+            ionize(fplog,oenv,mdatoms,top_global,t,ir,state->x,state->v,
+                   mdatoms->start,mdatoms->start+mdatoms->homenr,state->box,cr);
+        }
+        
+        /* Update force field in ffscan program */
+        if (bFFscan)
+        {
+            if (update_forcefield(fplog,
+                                  nfile,fnm,fr,
+                                  mdatoms->nr,state->x,state->box)) {
+                if (gmx_parallel_env_initialized())
+                {
+                    gmx_finalize();
+                }
+                exit(0);
+            }
+        }
+
+        /* We write a checkpoint at this MD step when:
+         * either at an NS step when we signalled through gs,
+         * or at the last step (but not when we do not want confout),
+         * but never at the first step or with rerun.
+         */
+        bCPT = (((gs.set[eglsCHKPT] && (bNS || ir->nstlist == 0)) ||
+                 (bLastStep && (Flags & MD_CONFOUT))) &&
+                step > ir->init_step && !bRerunMD);
+        if (bCPT)
+        {
+            gs.set[eglsCHKPT] = 0;
+        }
+
+        /* Determine the energy and pressure:
+         * at nstcalcenergy steps and at energy output steps (set below).
+         */
+        bNstEner = do_per_step(step,ir->nstcalcenergy);
+        bCalcEnerPres =
+            (bNstEner ||
+             (ir->epc != epcNO && do_per_step(step,ir->nstpcouple)));
+
+        /* Do we need global communication ? */
+        bGStat = (bCalcEnerPres || bStopCM ||
+                  do_per_step(step,nstglobalcomm) ||
+                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (do_ene || do_log)
+        {
+            bCalcEnerPres = TRUE;
+            bGStat        = TRUE;
+        }
+        
+        /* these CGLO_ options remain the same throughout the iteration */
+        cglo_flags = ((bRerunMD ? CGLO_RERUNMD : 0) |
+                      (bStopCM ? CGLO_STOPCM : 0) |
+                      (bGStat ? CGLO_GSTAT : 0)
+            );
+        
+        force_flags = (GMX_FORCE_STATECHANGED |
+                       ((DYNAMIC_BOX(*ir) || bRerunMD) ? GMX_FORCE_DYNAMICBOX : 0) |
+                       GMX_FORCE_ALLFORCES |
+                       (bNStList ? GMX_FORCE_DOLR : 0) |
+                       GMX_FORCE_SEPLRF |
+                       (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
+                       (bDoDHDL ? GMX_FORCE_DHDL : 0)
+            );
+        
+        if (shellfc)
+        {
+            /* Now is the time to relax the shells */
+            count=relax_shell_flexcon(fplog,cr,bVerbose,bFFscan ? step+1 : step,
+                                      ir,bNS,force_flags,
+                                      bStopCM,top,top_global,
+                                      constr,enerd,fcd,
+                                      state,f,force_vir,mdatoms,
+                                      nrnb,wcycle,graph,groups,
+                                      shellfc,fr,bBornRadii,t,mu_tot,
+                                      state->natoms,&bConverged,vsite,
+                                      outf->fp_field);
+            tcount+=count;
+
+            if (bConverged)
+            {
+                nconverged++;
+            }
+        }
+        else
+        {
+            /* The coordinates (x) are shifted (to get whole molecules)
+             * in do_force.
+             * This is parallellized as well, and does communication too. 
+             * Check comments in sim_util.c
+             */
+        
+            do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
+                     state->box,state->x,&state->hist,
+                     f,force_vir,mdatoms,enerd,fcd,
+                     state->lambda,graph,
+                     fr,vsite,mu_tot,t,outf->fp_field,ed,bBornRadii,
+                     (bNS ? GMX_FORCE_NS : 0) | force_flags);
+        }
+        
+        if (bTCR)
+        {
+            mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
+                                   mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
+        }
+        
+        if (bTCR && bFirstStep)
+        {
+            tcr=init_coupling(fplog,nfile,fnm,cr,fr,mdatoms,&(top->idef));
+            fprintf(fplog,"Done init_coupling\n"); 
+            fflush(fplog);
+        }
+        
+        if (bVV && !bStartingFromCpt && !bRerunMD)
+        /*  ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
+        {
+            if (ir->eI==eiVV && bInitStep) 
+            {
+                /* if using velocity verlet with full time step Ekin,
+                 * take the first half step only to compute the 
+                 * virial for the first step. From there,
+                 * revert back to the initial coordinates
+                 * so that the input is actually the initial step.
+                 */
+                copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
+            } else {
+                /* this is for NHC in the Ekin(t+dt/2) version of vv */
+                trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ1);            
+            }
+
+            update_coords(fplog,step,ir,mdatoms,state,
+                          f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                          ekind,M,wcycle,upd,bInitStep,etrtVELOCITY1,
+                          cr,nrnb,constr,&top->idef);
+            
+            if (bIterations)
+            {
+                gmx_iterate_init(&iterate,bIterations && !bInitStep);
+            }
+            /* for iterations, we save these vectors, as we will be self-consistently iterating
+               the calculations */
+
+            /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
+            
+            /* save the state */
+            if (bIterations && iterate.bIterate) { 
+                copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+            }
+            
+            bFirstIterate = TRUE;
+            while (bFirstIterate || (bIterations && iterate.bIterate))
+            {
+                if (bIterations && iterate.bIterate) 
+                {
+                    copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+                    if (bFirstIterate && bTrotter) 
+                    {
+                        /* The first time through, we need a decent first estimate
+                           of veta(t+dt) to compute the constraints.  Do
+                           this by computing the box volume part of the
+                           trotter integration at this time. Nothing else
+                           should be changed by this routine here.  If
+                           !(first time), we start with the previous value
+                           of veta.  */
+                        
+                        veta_save = state->veta;
+                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ0);
+                        vetanew = state->veta;
+                        state->veta = veta_save;
+                    } 
+                } 
+                
+                bOK = TRUE;
+                if ( !bRerunMD || rerun_fr.bV || bForceUpdate) {  /* Why is rerun_fr.bV here?  Unclear. */
+                    dvdl = 0;
+                    
+                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                       &top->idef,shake_vir,NULL,
+                                       cr,nrnb,wcycle,upd,constr,
+                                       bInitStep,TRUE,bCalcEnerPres,vetanew);
+                    
+                    if (!bOK && !bFFscan)
+                    {
+                        gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+                    }
+                    
+                } 
+                else if (graph)
+                { /* Need to unshift here if a do_force has been
+                     called in the previous step */
+                    unshift_self(graph,state->box,state->x);
+                }
+                
+                
+                /* if VV, compute the pressure and constraints */
+                /* For VV2, we strictly only need this if using pressure
+                 * control, but we really would like to have accurate pressures
+                 * printed out.
+                 * Think about ways around this in the future?
+                 * For now, keep this choice in comments.
+                 */
+                /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
+                    /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
+                bPres = TRUE;
+                bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
+                compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                                wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                                constr,NULL,FALSE,state->box,
+                                top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                                cglo_flags 
+                                | CGLO_ENERGY 
+                                | (bTemp ? CGLO_TEMPERATURE:0) 
+                                | (bPres ? CGLO_PRESSURE : 0) 
+                                | (bPres ? CGLO_CONSTRAINT : 0)
+                                | ((bIterations && iterate.bIterate) ? CGLO_ITERATE : 0)  
+                                | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+                                | CGLO_SCALEEKIN 
+                    );
+                /* explanation of above: 
+                   a) We compute Ekin at the full time step
+                   if 1) we are using the AveVel Ekin, and it's not the
+                   initial step, or 2) if we are using AveEkin, but need the full
+                   time step kinetic energy for the pressure (always true now, since we want accurate statistics).
+                   b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in 
+                   EkinAveVel because it's needed for the pressure */
+                
+                /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
+                if (!bInitStep) 
+                {
+                    if (bTrotter)
+                    {
+                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ2);
+                    } 
+                    else 
+                    {
+                        update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
+                    }
+                }
+                
+                if (bIterations &&
+                    done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+                                   state->veta,&vetanew)) 
+                {
+                    break;
+                }
+                bFirstIterate = FALSE;
+            }
+
+            if (bTrotter && !bInitStep) {
+                copy_mat(shake_vir,state->svir_prev);
+                copy_mat(force_vir,state->fvir_prev);
+                if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
+                    /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
+                    enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,NULL,(ir->eI==eiVV),FALSE,FALSE);
+                    enerd->term[F_EKIN] = trace(ekind->ekin);
+                }
+            }
+            /* if it's the initial step, we performed this first step just to get the constraint virial */
+            if (bInitStep && ir->eI==eiVV) {
+                copy_rvecn(cbuf,state->v,0,state->natoms);
+            }
+            
+            if (fr->bSepDVDL && fplog && do_log) 
+            {
+                fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+            }
+            enerd->term[F_DHDL_CON] += dvdl;
+        }
+    
+        /* MRS -- now done iterating -- compute the conserved quantity */
+        if (bVV) {
+            saved_conserved_quantity = compute_conserved_from_auxiliary(ir,state,&MassQ);
+            if (ir->eI==eiVV) 
+            {
+                last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
+            }
+            if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres)) 
+            {
+                saved_conserved_quantity -= enerd->term[F_DISPCORR];
+            }
+        }
+        
+        /* ########  END FIRST UPDATE STEP  ############## */
+        /* ########  If doing VV, we now have v(dt) ###### */
+        
+        /* ################## START TRAJECTORY OUTPUT ################# */
+        
+        /* Now we have the energies and forces corresponding to the 
+         * coordinates at time t. We must output all of this before
+         * the update.
+         * for RerunMD t is read from input trajectory
+         */
+        mdof_flags = 0;
+        if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
+        if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
+        if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
+        if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
+        if (bCPT) { mdof_flags |= MDOF_CPT; };
+
+#if defined(GMX_FAHCORE) || defined(GMX_WRITELASTSTEP)
+        if (bLastStep)
+        {
+            /* Enforce writing positions and velocities at end of run */
+            mdof_flags |= (MDOF_X | MDOF_V);
+        }
+#endif
+#ifdef GMX_FAHCORE
+        if (MASTER(cr))
+            fcReportProgress( ir->nsteps, step );
+
+        /* sync bCPT and fc record-keeping */
+        if (bCPT && MASTER(cr))
+            fcRequestCheckPoint();
+#endif
+        
+        if (mdof_flags != 0)
+        {
+            wallcycle_start(wcycle,ewcTRAJ);
+            if (bCPT)
+            {
+                if (state->flags & (1<<estLD_RNG))
+                {
+                    get_stochd_state(upd,state);
+                }
+                if (MASTER(cr))
+                {
+                    if (bSumEkinhOld)
+                    {
+                        state_global->ekinstate.bUpToDate = FALSE;
+                    }
+                    else
+                    {
+                        update_ekinstate(&state_global->ekinstate,ekind);
+                        state_global->ekinstate.bUpToDate = TRUE;
+                    }
+                    update_energyhistory(&state_global->enerhist,mdebin);
+                }
+            }
+            write_traj(fplog,cr,outf,mdof_flags,top_global,
+                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
+            if (bCPT)
+            {
+                nchkpt++;
+                bCPT = FALSE;
+            }
+            debug_gmx();
+            if (bLastStep && step_rel == ir->nsteps &&
+                (Flags & MD_CONFOUT) && MASTER(cr) &&
+                !bRerunMD && !bFFscan)
+            {
+                /* x and v have been collected in write_traj,
+                 * because a checkpoint file will always be written
+                 * at the last step.
+                 */
+                fprintf(stderr,"\nWriting final coordinates.\n");
+                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols &&
+                    DOMAINDECOMP(cr))
+                {
+                    /* Make molecules whole only for confout writing */
+                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
+                }
+                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+                                    *top_global->name,top_global,
+                                    state_global->x,state_global->v,
+                                    ir->ePBC,state->box);
+                debug_gmx();
+            }
+            wallcycle_stop(wcycle,ewcTRAJ);
+        }
+        
+        /* kludge -- virial is lost with restart for NPT control. Must restart */
+        if (bStartingFromCpt && bVV) 
+        {
+            copy_mat(state->svir_prev,shake_vir);
+            copy_mat(state->fvir_prev,force_vir);
+        }
+        /*  ################## END TRAJECTORY OUTPUT ################ */
+        
+        /* Determine the wallclock run time up till now */
+        run_time = gmx_gettime() - (double)runtime->real;
+
+        /* Check whether everything is still allright */    
+        if (((int)gmx_get_stop_condition() > handled_stop_condition)
+#ifdef GMX_THREADS
+            && MASTER(cr)
+#endif
+            )
+        {
+            /* this is just make gs.sig compatible with the hack 
+               of sending signals around by MPI_Reduce with together with
+               other floats */
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+                gs.sig[eglsSTOPCOND]=1;
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+                gs.sig[eglsSTOPCOND]=-1;
+            /* < 0 means stop at next step, > 0 means stop at next NS step */
+            if (fplog)
+            {
+                fprintf(fplog,
+                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                        gmx_get_signal_name(),
+                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+                fflush(fplog);
+            }
+            fprintf(stderr,
+                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                    gmx_get_signal_name(),
+                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+            fflush(stderr);
+            handled_stop_condition=(int)gmx_get_stop_condition();
+        }
+        else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
+                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
+                 gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
+        {
+            /* Signal to terminate the run */
+            gs.sig[eglsSTOPCOND] = 1;
+            if (fplog)
+            {
+                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+            }
+            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+        }
+
+        if (bResetCountersHalfMaxH && MASTER(cr) &&
+            run_time > max_hours*60.0*60.0*0.495)
+        {
+            gs.sig[eglsRESETCOUNTERS] = 1;
+        }
+
+        if (ir->nstlist == -1 && !bRerunMD)
+        {
+            /* When bGStatEveryStep=FALSE, global_stat is only called
+             * when we check the atom displacements, not at NS steps.
+             * This means that also the bonded interaction count check is not
+             * performed immediately after NS. Therefore a few MD steps could
+             * be performed with missing interactions.
+             * But wrong energies are never written to file,
+             * since energies are only written after global_stat
+             * has been called.
+             */
+            if (step >= nlh.step_nscheck)
+            {
+                nlh.nabnsb = natoms_beyond_ns_buffer(ir,fr,&top->cgs,
+                                                     nlh.scale_tot,state->x);
+            }
+            else
+            {
+                /* This is not necessarily true,
+                 * but step_nscheck is determined quite conservatively.
+                 */
+                nlh.nabnsb = 0;
+            }
+        }
+
+        /* In parallel we only have to check for checkpointing in steps
+         * where we do global communication,
+         *  otherwise the other nodes don't know.
+         */
+        if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
+                           cpt_period >= 0 &&
+                           (cpt_period == 0 || 
+                            run_time >= nchkpt*cpt_period*60.0)) &&
+            gs.set[eglsCHKPT] == 0)
+        {
+            gs.sig[eglsCHKPT] = 1;
+        }
+  
+        if (bIterations)
+        {
+            gmx_iterate_init(&iterate,bIterations);
+        }
+    
+        /* for iterations, we save these vectors, as we will be redoing the calculations */
+        if (bIterations && iterate.bIterate) 
+        {
+            copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+        }
+        bFirstIterate = TRUE;
+        while (bFirstIterate || (bIterations && iterate.bIterate))
+        {
+            /* We now restore these vectors to redo the calculation with improved extended variables */    
+            if (bIterations) 
+            { 
+                copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+            }
+
+            /* We make the decision to break or not -after- the calculation of Ekin and Pressure,
+               so scroll down for that logic */
+            
+            /* #########   START SECOND UPDATE STEP ################# */
+            /* Box is changed in update() when we do pressure coupling,
+             * but we should still use the old box for energy corrections and when
+             * writing it to the energy file, so it matches the trajectory files for
+             * the same timestep above. Make a copy in a separate array.
+             */
+            copy_mat(state->box,lastbox);
+
+            bOK = TRUE;
+            if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
+            {
+                wallcycle_start(wcycle,ewcUPDATE);
+                dvdl = 0;
+                /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
+                if (bTrotter) 
+                {
+                    if (bIterations && iterate.bIterate) 
+                    {
+                        if (bFirstIterate) 
+                        {
+                            scalevir = 1;
+                        }
+                        else 
+                        {
+                            /* we use a new value of scalevir to converge the iterations faster */
+                            scalevir = tracevir/trace(shake_vir);
+                        }
+                        msmul(shake_vir,scalevir,shake_vir); 
+                        m_add(force_vir,shake_vir,total_vir);
+                        clear_mat(shake_vir);
+                    }
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ3);
+                /* We can only do Berendsen coupling after we have summed
+                 * the kinetic energy or virial. Since the happens
+                 * in global_state after update, we should only do it at
+                 * step % nstlist = 1 with bGStatEveryStep=FALSE.
+                 */
+                }
+                else 
+                {
+                    update_tcouple(fplog,step,ir,state,ekind,wcycle,upd,&MassQ,mdatoms);
+                    update_pcouple(fplog,step,ir,state,pcoupl_mu,M,wcycle,
+                                   upd,bInitStep);
+                }
+
+                if (bVV)
+                {
+                    /* velocity half-step update */
+                    update_coords(fplog,step,ir,mdatoms,state,f,
+                                  fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                                  ekind,M,wcycle,upd,FALSE,etrtVELOCITY2,
+                                  cr,nrnb,constr,&top->idef);
+                }
+
+                /* Above, initialize just copies ekinh into ekin,
+                 * it doesn't copy position (for VV),
+                 * and entire integrator for MD.
+                 */
+                
+                if (ir->eI==eiVVAK) 
+                {
+                    copy_rvecn(state->x,cbuf,0,state->natoms);
+                }
+                
+                update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                              ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+                wallcycle_stop(wcycle,ewcUPDATE);
+
+                update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                   &top->idef,shake_vir,force_vir,
+                                   cr,nrnb,wcycle,upd,constr,
+                                   bInitStep,FALSE,bCalcEnerPres,state->veta);  
+                
+                if (ir->eI==eiVVAK) 
+                {
+                    /* erase F_EKIN and F_TEMP here? */
+                    /* just compute the kinetic energy at the half step to perform a trotter step */
+                    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                                    constr,NULL,FALSE,lastbox,
+                                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                                    cglo_flags | CGLO_TEMPERATURE    
+                        );
+                    wallcycle_start(wcycle,ewcUPDATE);
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq,ettTSEQ4);            
+                    /* now we know the scaling, we can compute the positions again again */
+                    copy_rvecn(cbuf,state->x,0,state->natoms);
+
+                    update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                                  ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+                    wallcycle_stop(wcycle,ewcUPDATE);
+
+                    /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
+                    /* are the small terms in the shake_vir here due
+                     * to numerical errors, or are they important
+                     * physically? I'm thinking they are just errors, but not completely sure. 
+                     * For now, will call without actually constraining, constr=NULL*/
+                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                       &top->idef,tmp_vir,force_vir,
+                                       cr,nrnb,wcycle,upd,NULL,
+                                       bInitStep,FALSE,bCalcEnerPres,
+                                       state->veta);  
+                }
+                if (!bOK && !bFFscan) 
+                {
+                    gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+                }
+                
+                if (fr->bSepDVDL && fplog && do_log) 
+                {
+                    fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+                }
+                enerd->term[F_DHDL_CON] += dvdl;
+            } 
+            else if (graph) 
+            {
+                /* Need to unshift here */
+                unshift_self(graph,state->box,state->x);
+            }
+
+            if (vsite != NULL) 
+            {
+                wallcycle_start(wcycle,ewcVSITECONSTR);
+                if (graph != NULL) 
+                {
+                    shift_self(graph,state->box,state->x);
+                }
+                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+                                 top->idef.iparams,top->idef.il,
+                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+                
+                if (graph != NULL) 
+                {
+                    unshift_self(graph,state->box,state->x);
+                }
+                wallcycle_stop(wcycle,ewcVSITECONSTR);
+            }
+            
+            /* ############## IF NOT VV, Calculate globals HERE, also iterate constraints ############ */
+            if (ir->nstlist == -1 && bFirstIterate)
+            {
+                gs.sig[eglsNABNSB] = nlh.nabnsb;
+            }
+            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                            wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                            constr,
+                            bFirstIterate ? &gs : NULL, 
+                            (step_rel % gs.nstms == 0) && 
+                                (multisim_nsteps<0 || (step_rel<multisim_nsteps)),
+                            lastbox,
+                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                            cglo_flags 
+                            | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0) 
+                            | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0) 
+                            | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0) 
+                            | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0) 
+                            | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+                            | CGLO_CONSTRAINT 
+                );
+            if (ir->nstlist == -1 && bFirstIterate)
+            {
+                nlh.nabnsb = gs.set[eglsNABNSB];
+                gs.set[eglsNABNSB] = 0;
+            }
+            /* bIterate is set to keep it from eliminating the old ekin kinetic energy terms */
+            /* #############  END CALC EKIN AND PRESSURE ################# */
+        
+            /* Note: this is OK, but there are some numerical precision issues with using the convergence of
+               the virial that should probably be addressed eventually. state->veta has better properies,
+               but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
+               generate the new shake_vir, but test the veta value for convergence.  This will take some thought. */
+
+            if (bIterations && 
+                done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+                               trace(shake_vir),&tracevir)) 
+            {
+                break;
+            }
+            bFirstIterate = FALSE;
+        }
+
+        update_box(fplog,step,ir,mdatoms,state,graph,f,
+                   ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
+        
+        /* ################# END UPDATE STEP 2 ################# */
+        /* #### We now have r(t+dt) and v(t+dt/2)  ############# */
+    
+        /* The coordinates (x) were unshifted in update */
+        if (bFFscan && (shellfc==NULL || bConverged))
+        {
+            if (print_forcefield(fplog,enerd->term,mdatoms->homenr,
+                                 f,NULL,xcopy,
+                                 &(top_global->mols),mdatoms->massT,pres))
+            {
+                if (gmx_parallel_env_initialized())
+                {
+                    gmx_finalize();
+                }
+                fprintf(stderr,"\n");
+                exit(0);
+            }
+        }
+        if (!bGStat)
+        {
+            /* We will not sum ekinh_old,                                                            
+             * so signal that we still have to do it.                                                
+             */
+            bSumEkinhOld = TRUE;
+        }
+        
+        if (bTCR)
+        {
+            /* Only do GCT when the relaxation of shells (minimization) has converged,
+             * otherwise we might be coupling to bogus energies. 
+             * In parallel we must always do this, because the other sims might
+             * update the FF.
+             */
+
+            /* Since this is called with the new coordinates state->x, I assume
+             * we want the new box state->box too. / EL 20040121
+             */
+            do_coupling(fplog,oenv,nfile,fnm,tcr,t,step,enerd->term,fr,
+                        ir,MASTER(cr),
+                        mdatoms,&(top->idef),mu_aver,
+                        top_global->mols.nr,cr,
+                        state->box,total_vir,pres,
+                        mu_tot,state->x,f,bConverged);
+            debug_gmx();
+        }
+
+        /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
+        
+        /* sum up the foreign energy and dhdl terms */
+        sum_dhdl(enerd,state->lambda,ir);
+
+        /* use the directly determined last velocity, not actually the averaged half steps */
+        if (bTrotter && ir->eI==eiVV) 
+        {
+            enerd->term[F_EKIN] = last_ekin;
+        }
+        enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
+        
+        if (bVV)
+        {
+            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + saved_conserved_quantity;
+        }
+        else 
+        {
+            enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + compute_conserved_from_auxiliary(ir,state,&MassQ);
+        }
+        /* Check for excessively large energies */
+        if (bIonize) 
+        {
+#ifdef GMX_DOUBLE
+            real etot_max = 1e200;
+#else
+            real etot_max = 1e30;
+#endif
+            if (fabs(enerd->term[F_ETOT]) > etot_max) 
+            {
+                fprintf(stderr,"Energy too large (%g), giving up\n",
+                        enerd->term[F_ETOT]);
+            }
+        }
+        /* #########  END PREPARING EDR OUTPUT  ###########  */
+        
+        /* Time for performance */
+        if (((step % stepout) == 0) || bLastStep) 
+        {
+            runtime_upd_proc(runtime);
+        }
+        
+        /* Output stuff */
+        if (MASTER(cr))
+        {
+            gmx_bool do_dr,do_or;
+            
+            if (!(bStartingFromCpt && (EI_VV(ir->eI)))) 
+            {
+                if (bNstEner)
+                {
+                    upd_mdebin(mdebin,bDoDHDL, TRUE,
+                               t,mdatoms->tmass,enerd,state,lastbox,
+                               shake_vir,force_vir,total_vir,pres,
+                               ekind,mu_tot,constr);
+                }
+                else
+                {
+                    upd_mdebin_step(mdebin);
+                }
+                
+                do_dr  = do_per_step(step,ir->nstdisreout);
+                do_or  = do_per_step(step,ir->nstorireout);
+                
+                print_ebin(outf->fp_ene,do_ene,do_dr,do_or,do_log?fplog:NULL,
+                           step,t,
+                           eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
+            }
+            if (ir->ePull != epullNO)
+            {
+                pull_print_output(ir->pull,step,t);
+            }
+            
+            if (do_per_step(step,ir->nstlog))
+            {
+                if(fflush(fplog) != 0)
+                {
+                    gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
+                }
+            }
+        }
+
+
+        /* Remaining runtime */
+        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
+        {
+            if (shellfc) 
+            {
+                fprintf(stderr,"\n");
+            }
+            print_time(stderr,runtime,step,ir,cr);
+        }
+
+        /* Replica exchange */
+        bExchanged = FALSE;
+        if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
+            do_per_step(step,repl_ex_nst)) 
+        {
+            bExchanged = replica_exchange(fplog,cr,repl_ex,
+                                          state_global,enerd->term,
+                                          state,step,t);
+
+            if (bExchanged && DOMAINDECOMP(cr)) 
+            {
+                dd_partition_system(fplog,step,cr,TRUE,1,
+                                    state_global,top_global,ir,
+                                    state,&f,mdatoms,top,fr,
+                                    vsite,shellfc,constr,
+                                    nrnb,wcycle,FALSE);
+            }
+        }
+        
+        bFirstStep = FALSE;
+        bInitStep = FALSE;
+        bStartingFromCpt = FALSE;
+
+        /* #######  SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
+        /* With all integrators, except VV, we need to retain the pressure
+         * at the current step for coupling at the next step.
+         */
+        if ((state->flags & (1<<estPRES_PREV)) &&
+            (bGStatEveryStep ||
+             (ir->nstpcouple > 0 && step % ir->nstpcouple == 0)))
+        {
+            /* Store the pressure in t_state for pressure coupling
+             * at the next MD step.
+             */
+            copy_mat(pres,state->pres_prev);
+        }
+        
+        /* #######  END SET VARIABLES FOR NEXT ITERATION ###### */
+
+        if ( (membed!=NULL) && (!bLastStep) )
+            rescale_membed(step_rel,membed,state_global->x);
+        
+        if (bRerunMD) 
+        {
+            if (MASTER(cr))
+            {
+                /* read next frame from input trajectory */
+                bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+            }
+
+            if (PAR(cr))
+            {
+                rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+            }
+        }
+        
+        if (!bRerunMD || !rerun_fr.bStep)
+        {
+            /* increase the MD step number */
+            step++;
+            step_rel++;
+        }
+        
+        cycles = wallcycle_stop(wcycle,ewcSTEP);
+        if (DOMAINDECOMP(cr) && wcycle)
+        {
+            dd_cycles_add(cr->dd,cycles,ddCyclStep);
+        }
+        
+        if (step_rel == wcycle_get_reset_counters(wcycle) ||
+            gs.set[eglsRESETCOUNTERS] != 0)
+        {
+            /* Reset all the counters related to performance over the run */
+            reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
+            wcycle_set_reset_counters(wcycle,-1);
+            /* Correct max_hours for the elapsed time */
+            max_hours -= run_time/(60.0*60.0);
+            bResetCountersHalfMaxH = FALSE;
+            gs.set[eglsRESETCOUNTERS] = 0;
+        }
+
+    }
+    /* End of main MD loop */
+    debug_gmx();
+    
+    /* Stop the time */
+    runtime_end(runtime);
+    
+    if (bRerunMD && MASTER(cr))
+    {
+        close_trj(status);
+    }
+    
+    if (!(cr->duty & DUTY_PME))
+    {
+        /* Tell the PME only node to finish */
+        gmx_pme_finish(cr);
+    }
+    
+    if (MASTER(cr))
+    {
+        if (ir->nstcalcenergy > 0 && !bRerunMD) 
+        {
+            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+        }
+    }
+
+    done_mdoutf(outf);
+
+    debug_gmx();
+
+    if (ir->nstlist == -1 && nlh.nns > 0 && fplog)
+    {
+        fprintf(fplog,"Average neighborlist lifetime: %.1f steps, std.dev.: %.1f steps\n",nlh.s1/nlh.nns,sqrt(nlh.s2/nlh.nns - sqr(nlh.s1/nlh.nns)));
+        fprintf(fplog,"Average number of atoms that crossed the half buffer length: %.1f\n\n",nlh.ab/nlh.nns);
+    }
+    
+    if (shellfc && fplog)
+    {
+        fprintf(fplog,"Fraction of iterations that converged:           %.2f %%\n",
+                (nconverged*100.0)/step_rel);
+        fprintf(fplog,"Average number of force evaluations per MD step: %.2f\n\n",
+                tcount/step_rel);
+    }
+    
+    if (repl_ex_nst > 0 && MASTER(cr))
+    {
+        print_replica_exchange_statistics(fplog,repl_ex);
+    }
+    
+    runtime->nsteps_done = step_rel;
+    
+    return 0;
+}
diff --git a/src/programs/mdrun/md_openmm.c b/src/programs/mdrun/md_openmm.c
new file mode 100644 (file)
index 0000000..6f88d53
--- /dev/null
@@ -0,0 +1,579 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+/* _isnan() */
+#include <float.h>
+#endif
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "vec.h"
+#include "statutil.h"
+#include "vcm.h"
+#include "mdebin.h"
+#include "nrnb.h"
+#include "calcmu.h"
+#include "index.h"
+#include "vsite.h"
+#include "update.h"
+#include "ns.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "mdrun.h"
+#include "confio.h"
+#include "network.h"
+#include "pull.h"
+#include "xvgr.h"
+#include "physics.h"
+#include "names.h"
+#include "xmdrun.h"
+#include "ionize.h"
+#include "disre.h"
+#include "orires.h"
+#include "dihre.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdatoms.h"
+#include "qmmm.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "topsort.h"
+#include "coulomb.h"
+#include "constr.h"
+#include "compute_io.h"
+#include "mvdata.h"
+#include "checkpoint.h"
+#include "mtop_util.h"
+#include "sighandler.h"
+#include "genborn.h"
+#include "string2.h"
+#include "copyrite.h"
+#include "membed.h"
+
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+/* include even when OpenMM not used to force compilation of do_md_openmm */
+#include "openmm_wrapper.h"
+
+double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+                    const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+                    int nstglobalcomm,
+                    gmx_vsite_t *vsite,gmx_constr_t constr,
+                    int stepout,t_inputrec *ir,
+                    gmx_mtop_t *top_global,
+                    t_fcdata *fcd,
+                    t_state *state_global,
+                    t_mdatoms *mdatoms,
+                    t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                    gmx_edsam_t ed,t_forcerec *fr,
+                    int repl_ex_nst,int repl_ex_seed,
+                    gmx_membed_t *membed,
+                    real cpt_period,real max_hours,
+                    const char *deviceOptions,
+                    unsigned long Flags,
+                    gmx_runtime_t *runtime)
+{
+    gmx_mdoutf_t *outf;
+    gmx_large_int_t step,step_rel;
+    double     run_time;
+    double     t,t0,lam0;
+    gmx_bool       bSimAnn,
+    bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
+    gmx_bool       bInitStep=TRUE;
+    gmx_bool       do_ene,do_log, do_verbose,
+    bX,bV,bF,bCPT;
+    tensor     force_vir,shake_vir,total_vir,pres;
+    int        i,m;
+    int        mdof_flags;
+    rvec       mu_tot;
+    t_vcm      *vcm;
+    int        nchkpt=1;
+    gmx_localtop_t *top;
+    t_mdebin *mdebin=NULL;
+    t_state    *state=NULL;
+    rvec       *f_global=NULL;
+    int        n_xtc=-1;
+    rvec       *x_xtc=NULL;
+    gmx_enerdata_t *enerd;
+    rvec       *f=NULL;
+    gmx_global_stat_t gstat;
+    gmx_update_t upd=NULL;
+    t_graph    *graph=NULL;
+    globsig_t   gs;
+
+    gmx_groups_t *groups;
+    gmx_ekindata_t *ekind, *ekind_save;
+    gmx_bool        bAppend;
+    int         a0,a1;
+    matrix      lastbox;
+    real        reset_counters=0,reset_counters_now=0;
+    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+    int         handled_stop_condition=gmx_stop_cond_none; 
+
+    const char *ommOptions = NULL;
+    void   *openmmData;
+
+#ifdef GMX_DOUBLE
+    /* Checks in cmake should prevent the compilation in double precision
+     * with OpenMM, but just to be sure we check here.
+     */
+    gmx_fatal(FARGS,"Compilation was performed in double precision, but OpenMM only supports single precision. If you want to use to OpenMM, compile in single precision.");
+#endif
+
+    bAppend  = (Flags & MD_APPENDFILES);
+    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
+
+    groups = &top_global->groups;
+
+    /* Initial values */
+    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+            nrnb,top_global,&upd,
+            nfile,fnm,&outf,&mdebin,
+            force_vir,shake_vir,mu_tot,&bSimAnn,&vcm,state_global,Flags);
+
+    clear_mat(total_vir);
+    clear_mat(pres);
+    /* Energy terms and groups */
+    snew(enerd,1);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+    snew(f,top_global->natoms);
+
+    /* Kinetic energy data */
+    snew(ekind,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind);
+    /* needed for iteration of constraints */
+    snew(ekind_save,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
+    /* Copy the cos acceleration to the groups struct */
+    ekind->cosacc.cos_accel = ir->cos_accel;
+
+    gstat = global_stat_init(ir);
+    debug_gmx();
+
+    {
+        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
+        if ((io > 2000) && MASTER(cr))
+            fprintf(stderr,
+                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
+                    io);
+    }
+
+    top = gmx_mtop_generate_local_top(top_global,ir);
+
+    a0 = 0;
+    a1 = top_global->natoms;
+
+    state = partdec_init_local_state(cr,state_global);
+    f_global = f;
+
+    atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+
+    if (vsite)
+    {
+        set_vsite_top(vsite,top,mdatoms,cr);
+    }
+
+    if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
+    {
+        graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+    }
+
+    update_mdatoms(mdatoms,state->lambda);
+
+    if (deviceOptions[0]=='\0')
+    {
+        /* empty options, which should default to OpenMM in this build */
+        ommOptions=deviceOptions;
+    }
+    else
+    {
+        if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
+        {
+            gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
+        }
+        else
+        {
+            ommOptions=strchr(deviceOptions,':');
+            if (NULL!=ommOptions)
+            {
+                /* Increase the pointer to skip the colon */
+                ommOptions++;
+            }
+        }
+    }
+
+    openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state);
+    please_cite(fplog,"Friedrichs2009");
+
+    if (MASTER(cr))
+    {
+        /* Update mdebin with energy history if appending to output files */
+        if ( Flags & MD_APPENDFILES )
+        {
+            restore_energyhistory_from_state(mdebin,&state_global->enerhist);
+        }
+        /* Set the initial energy history in state to zero by updating once */
+        update_energyhistory(&state_global->enerhist,mdebin);
+    }
+
+    if (constr)
+    {
+        set_constraints(constr,top,ir,mdatoms,cr);
+    }
+
+    if (!ir->bContinuation)
+    {
+        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
+        {
+            /* Set the velocities of frozen particles to zero */
+            for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+            {
+                for (m=0; m<DIM; m++)
+                {
+                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
+                    {
+                        state->v[i][m] = 0;
+                    }
+                }
+            }
+        }
+
+        if (constr)
+        {
+            /* Constrain the initial coordinates and velocities */
+            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
+                               graph,cr,nrnb,fr,top,shake_vir);
+        }
+        if (vsite)
+        {
+            /* Construct the virtual sites for the initial configuration */
+            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
+                             top->idef.iparams,top->idef.il,
+                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+        }
+    }
+
+    debug_gmx();
+
+    if (MASTER(cr))
+    {
+        char tbuf[20];
+        fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
+        fprintf(stderr,"starting mdrun '%s'\n",
+                *(top_global->name));
+        if (ir->nsteps >= 0)
+        {
+            sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
+        }
+        else
+        {
+            sprintf(tbuf,"%s","infinite");
+        }
+        if (ir->init_step > 0)
+        {
+            fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
+                    gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
+                    gmx_step_str(ir->init_step,sbuf2),
+                    ir->init_step*ir->delta_t);
+        }
+        else
+        {
+            fprintf(stderr,"%s steps, %s ps.\n",
+                    gmx_step_str(ir->nsteps,sbuf),tbuf);
+        }
+    }
+
+    fprintf(fplog,"\n");
+
+    /* Set and write start time */
+    runtime_start(runtime);
+    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
+    wallcycle_start(wcycle,ewcRUN);
+    if (fplog)
+        fprintf(fplog,"\n");
+
+    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
+
+    debug_gmx();
+    /***********************************************************
+     *
+     *             Loop over MD steps
+     *
+     ************************************************************/
+
+    /* loop over MD steps or if rerunMD to end of input trajectory */
+    bFirstStep = TRUE;
+    /* Skip the first Nose-Hoover integration when we get the state from tpx */
+    bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
+    bInitStep = bFirstStep && bStateFromTPX;
+    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
+    bLastStep = FALSE;
+
+    init_global_signals(&gs,cr,ir,repl_ex_nst);
+
+    step = ir->init_step;
+    step_rel = 0;
+
+    while (!bLastStep)
+    {
+        wallcycle_start(wcycle,ewcSTEP);
+
+        bLastStep = (step_rel == ir->nsteps);
+        t = t0 + step*ir->delta_t;
+
+        if (gs.set[eglsSTOPCOND] != 0)
+        {
+            bLastStep = TRUE;
+        }
+
+        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
+        do_verbose = bVerbose &&
+                     (step % stepout == 0 || bFirstStep || bLastStep);
+
+        if (MASTER(cr) && do_log)
+        {
+            print_ebin_header(fplog,step,t,state->lambda);
+        }
+
+        clear_mat(force_vir);
+
+        /* We write a checkpoint at this MD step when:
+         * either when we signalled through gs (in OpenMM NS works different),
+         * or at the last step (but not when we do not want confout),
+         * but never at the first step.
+         */
+        bCPT = ((gs.set[eglsCHKPT] ||
+                 (bLastStep && (Flags & MD_CONFOUT))) &&
+                step > ir->init_step );
+        if (bCPT)
+        {
+            gs.set[eglsCHKPT] = 0;
+        }
+
+        /* Now we have the energies and forces corresponding to the
+         * coordinates at time t. We must output all of this before
+         * the update.
+         * for RerunMD t is read from input trajectory
+         */
+        mdof_flags = 0;
+        if (do_per_step(step,ir->nstxout))
+        {
+            mdof_flags |= MDOF_X;
+        }
+        if (do_per_step(step,ir->nstvout))
+        {
+            mdof_flags |= MDOF_V;
+        }
+        if (do_per_step(step,ir->nstfout))
+        {
+            mdof_flags |= MDOF_F;
+        }
+        if (do_per_step(step,ir->nstxtcout))
+        {
+            mdof_flags |= MDOF_XTC;
+        }
+        if (bCPT)
+        {
+            mdof_flags |= MDOF_CPT;
+        };
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (mdof_flags != 0 || do_ene || do_log)
+        {
+            wallcycle_start(wcycle,ewcTRAJ);
+            bF = (mdof_flags & MDOF_F);
+            bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT));
+            bV = (mdof_flags & (MDOF_V | MDOF_CPT));
+
+            openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, bF, do_ene);
+
+            upd_mdebin(mdebin,FALSE,TRUE,
+                       t,mdatoms->tmass,enerd,state,lastbox,
+                       shake_vir,force_vir,total_vir,pres,
+                       ekind,mu_tot,constr);
+            print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
+                       step,t,
+                       eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
+            write_traj(fplog,cr,outf,mdof_flags,top_global,
+                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
+            if (bCPT)
+            {
+                nchkpt++;
+                bCPT = FALSE;
+            }
+            debug_gmx();
+            if (bLastStep && step_rel == ir->nsteps &&
+                    (Flags & MD_CONFOUT) && MASTER(cr))
+            {
+                /* x and v have been collected in write_traj,
+                 * because a checkpoint file will always be written
+                 * at the last step.
+                 */
+                fprintf(stderr,"\nWriting final coordinates.\n");
+                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
+                {
+                    /* Make molecules whole only for confout writing */
+                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
+                }
+                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+                                    *top_global->name,top_global,
+                                    state_global->x,state_global->v,
+                                    ir->ePBC,state->box);
+                debug_gmx();
+            }
+            wallcycle_stop(wcycle,ewcTRAJ);
+        }
+
+        /* Determine the wallclock run time up till now */
+        run_time = gmx_gettime() - (double)runtime->real;
+
+        /* Check whether everything is still allright */
+        if (((int)gmx_get_stop_condition() > handled_stop_condition)
+#ifdef GMX_THREADS
+            && MASTER(cr)
+#endif
+            )
+        {
+           /* this is just make gs.sig compatible with the hack 
+               of sending signals around by MPI_Reduce with together with
+               other floats */
+            /* NOTE: this only works for serial code. For code that allows
+               MPI nodes to propagate their condition, see kernel/md.c*/
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+                gs.set[eglsSTOPCOND]=1;
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+                gs.set[eglsSTOPCOND]=1;
+            /* < 0 means stop at next step, > 0 means stop at next NS step */
+            if (fplog)
+            {
+                fprintf(fplog,
+                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                        gmx_get_signal_name(),
+                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+                fflush(fplog);
+            }
+            fprintf(stderr,
+                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                    gmx_get_signal_name(),
+                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+            fflush(stderr);
+            handled_stop_condition=(int)gmx_get_stop_condition();
+        }
+        else if (MASTER(cr) &&
+                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
+                 gs.set[eglsSTOPCOND] == 0)
+        {
+            /* Signal to terminate the run */
+            gs.set[eglsSTOPCOND] = 1;
+            if (fplog)
+            {
+                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+            }
+            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+        }
+
+        /* checkpoints */
+        if (MASTER(cr) && (cpt_period >= 0 &&
+                           (cpt_period == 0 ||
+                            run_time >= nchkpt*cpt_period*60.0)) &&
+                gs.set[eglsCHKPT] == 0)
+        {
+            gs.set[eglsCHKPT] = 1;
+        }
+
+        /* Time for performance */
+        if (((step % stepout) == 0) || bLastStep)
+        {
+            runtime_upd_proc(runtime);
+        }
+
+        if (do_per_step(step,ir->nstlog))
+        {
+            if (fflush(fplog) != 0)
+            {
+                gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
+            }
+        }
+
+        /* Remaining runtime */
+        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
+        {
+            print_time(stderr,runtime,step,ir,cr);
+        }
+
+        bFirstStep = FALSE;
+        bInitStep = FALSE;
+        bStartingFromCpt = FALSE;
+        step++;
+        step_rel++;
+
+        openmm_take_one_step(openmmData);
+    }
+    /* End of main MD loop */
+    debug_gmx();
+
+    /* Stop the time */
+    runtime_end(runtime);
+
+    if (MASTER(cr))
+    {
+        if (ir->nstcalcenergy > 0) 
+        {
+            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+        }
+    }
+
+    openmm_cleanup(fplog, openmmData);
+
+    done_mdoutf(outf);
+
+    debug_gmx();
+
+    runtime->nsteps_done = step_rel;
+
+    return 0;
+}
diff --git a/src/programs/mdrun/md_openmm.h b/src/programs/mdrun/md_openmm.h
new file mode 100644 (file)
index 0000000..60fc5ff
--- /dev/null
@@ -0,0 +1,56 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifndef _MD_OPENMM_H
+#define _MD_OPENMM_H
+
+double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+             const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
+             int nstglobalcomm,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int stepout,t_inputrec *ir,
+             gmx_mtop_t *top_global,
+             t_fcdata *fcd,
+             t_state *state_global,
+             t_mdatoms *mdatoms,
+             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+             gmx_edsam_t ed,t_forcerec *fr,
+             int repl_ex_nst,int repl_ex_seed,
+             gmx_membed_t *membed,
+             real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             gmx_runtime_t *runtime);
+
+#endif /* _MD_OPENMM_H */
diff --git a/src/programs/mdrun/mdrun.c b/src/programs/mdrun/mdrun.c
new file mode 100644 (file)
index 0000000..6a4f890
--- /dev/null
@@ -0,0 +1,701 @@
+/*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "typedefs.h"
+#include "macros.h"
+#include "copyrite.h"
+#include "main.h"
+#include "statutil.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "smalloc.h"
+#include "edsam.h"
+#include "mdrun.h"
+#include "xmdrun.h"
+#include "checkpoint.h"
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+/* afm stuf */
+#include "pull.h"
+
+int main(int argc,char *argv[])
+{
+  const char *desc[] = {
+ #ifdef GMX_OPENMM
+    "This is an experimental release of GROMACS for accelerated",
+       "Molecular Dynamics simulations on GPU processors. Support is provided",
+       "by the OpenMM library (https://simtk.org/home/openmm).[PAR]",
+       "*Warning*[BR]",
+       "This release is targeted at developers and advanced users and",
+       "care should be taken before production use. The following should be",
+       "noted before using the program:[PAR]",
+       " * The current release runs only on modern nVidia GPU hardware with CUDA support.",
+       "Make sure that the necessary CUDA drivers and libraries for your operating system",
+       "are already installed. The CUDA SDK also should be installed in order to compile",
+       "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]",
+       " * Multiple GPU cards are not supported.[PAR]",
+       " * Only a small subset of the GROMACS features and options are supported on the GPUs.",
+       "See below for a detailed list.[PAR]",
+       " * Consumer level GPU cards are known to often have problems with faulty memory.",
+       "It is recommended that a full memory check of the cards is done at least once",
+       "(for example, using the memtest=full option).",
+       "A partial memory check (for example, memtest=15) before and",
+       "after the simulation run would help spot",
+       "problems resulting from processor overheating.[PAR]",
+       " * The maximum size of the simulated systems depends on the available",
+       "GPU memory,for example, a GTX280 with 1GB memory has been tested with systems",
+       "of up to about 100,000 atoms.[PAR]",
+       " * In order to take a full advantage of the GPU platform features, many algorithms",
+       "have been implemented in a very different way than they are on the CPUs.",
+       "Therefore numercal correspondence between properties of the state of",
+       "simulated systems should not be expected. Moreover, the values will likely vary",
+       "when simulations are done on different GPU hardware.[PAR]",
+       " * Frequent retrieval of system state information such as",
+       "trajectory coordinates and energies can greatly influence the performance",
+       "of the program due to slow CPU<->GPU memory transfer speed.[PAR]",
+       " * MD algorithms are complex, and although the Gromacs code is highly tuned for them,",
+       "they often do not translate very well onto the streaming architetures.",
+       "Realistic expectations about the achievable speed-up from test with GTX280:",
+       "For small protein systems in implicit solvent using all-vs-all kernels the acceleration",
+       "can be as high as 20 times, but in most other setups involving cutoffs and PME the",
+       "acceleration is usually only ~4 times relative to a 3GHz CPU.[PAR]",
+       "Supported features:[PAR]",
+       " * Integrators: md/md-vv/md-vv-avek, sd/sd1 and bd.\n",
+       " * Long-range interactions (option coulombtype): Reaction-Field, Ewald, PME, and cut-off (for Implicit Solvent only)\n",
+       " * Temperature control: Supported only with the md/md-vv/md-vv-avek, sd/sd1 and bd integrators.\n",
+       " * Pressure control: Supported.\n",
+       " * Implicit solvent: Supported.\n",
+       "A detailed description can be found on the GROMACS website:\n",
+       "http://www.gromacs.org/gpu[PAR]",
+/* From the original mdrun documentaion */
+    "The [TT]mdrun[tt] program reads the run input file ([TT]-s[tt])",
+    "and distributes the topology over nodes if needed.",
+    "[TT]mdrun[tt] produces at least four output files.",
+    "A single log file ([TT]-g[tt]) is written, unless the option",
+    "[TT]-seppot[tt] is used, in which case each node writes a log file.",
+    "The trajectory file ([TT]-o[tt]), contains coordinates, velocities and",
+    "optionally forces.",
+    "The structure file ([TT]-c[tt]) contains the coordinates and",
+    "velocities of the last step.",
+    "The energy file ([TT]-e[tt]) contains energies, the temperature,",
+    "pressure, etc, a lot of these things are also printed in the log file.",
+    "Optionally coordinates can be written to a compressed trajectory file",
+    "([TT]-x[tt]).[PAR]",
+/* openmm specific information */
+       "Usage with OpenMM:[BR]",
+       "[TT]mdrun -device \"OpenMM:platform=Cuda,memtest=15,deviceid=0,force-device=no\"[tt][PAR]",
+       "Options:[PAR]",
+       "      [TT]platform[tt] = Cuda\t\t:\tThe only available value. OpenCL support will be available in future.\n",
+       "      [TT]memtest[tt] = 15\t\t:\tRun a partial, random GPU memory test for the given amount of seconds. A full test",
+       "(recommended!) can be run with \"memtest=full\". Memory testing can be disabled with \"memtest=off\".\n",
+       "      [TT]deviceid[tt] = 0\t\t:\tSpecify the target device when multiple cards are present.",
+       "Only one card can be used at any given time though.\n",
+       "      [TT]force-device[tt] = no\t\t:\tIf set to \"yes\" [TT]mdrun[tt]  will be forced to execute on",
+       "hardware that is not officially supported. GPU acceleration can also be achieved on older",
+       "but Cuda capable cards, although the simulation might be too slow, and the memory limits too strict.",
+#else
+    "The [TT]mdrun[tt] program is the main computational chemistry engine",
+    "within GROMACS. Obviously, it performs Molecular Dynamics simulations,",
+    "but it can also perform Stochastic Dynamics, Energy Minimization,",
+    "test particle insertion or (re)calculation of energies.",
+    "Normal mode analysis is another option. In this case [TT]mdrun[tt]",
+    "builds a Hessian matrix from single conformation.",
+    "For usual Normal Modes-like calculations, make sure that",
+    "the structure provided is properly energy-minimized.",
+    "The generated matrix can be diagonalized by [TT]g_nmeig[tt].[PAR]",
+    "The [TT]mdrun[tt] program reads the run input file ([TT]-s[tt])",
+    "and distributes the topology over nodes if needed.",
+    "[TT]mdrun[tt] produces at least four output files.",
+    "A single log file ([TT]-g[tt]) is written, unless the option",
+    "[TT]-seppot[tt] is used, in which case each node writes a log file.",
+    "The trajectory file ([TT]-o[tt]), contains coordinates, velocities and",
+    "optionally forces.",
+    "The structure file ([TT]-c[tt]) contains the coordinates and",
+    "velocities of the last step.",
+    "The energy file ([TT]-e[tt]) contains energies, the temperature,",
+    "pressure, etc, a lot of these things are also printed in the log file.",
+    "Optionally coordinates can be written to a compressed trajectory file",
+    "([TT]-x[tt]).[PAR]",
+    "The option [TT]-dhdl[tt] is only used when free energy calculation is",
+    "turned on.[PAR]",
+    "When [TT]mdrun[tt] is started using MPI with more than 1 node, parallelization",
+    "is used. By default domain decomposition is used, unless the [TT]-pd[tt]",
+    "option is set, which selects particle decomposition.[PAR]",
+    "With domain decomposition, the spatial decomposition can be set",
+    "with option [TT]-dd[tt]. By default [TT]mdrun[tt] selects a good decomposition.",
+    "The user only needs to change this when the system is very inhomogeneous.",
+    "Dynamic load balancing is set with the option [TT]-dlb[tt],",
+    "which can give a significant performance improvement,",
+    "especially for inhomogeneous systems. The only disadvantage of",
+    "dynamic load balancing is that runs are no longer binary reproducible,",
+    "but in most cases this is not important.",
+    "By default the dynamic load balancing is automatically turned on",
+    "when the measured performance loss due to load imbalance is 5% or more.",
+    "At low parallelization these are the only important options",
+    "for domain decomposition.",
+    "At high parallelization the options in the next two sections",
+    "could be important for increasing the performace.",
+    "[PAR]",
+    "When PME is used with domain decomposition, separate nodes can",
+    "be assigned to do only the PME mesh calculation;",
+    "this is computationally more efficient starting at about 12 nodes.",
+    "The number of PME nodes is set with option [TT]-npme[tt],",
+    "this can not be more than half of the nodes.",
+    "By default [TT]mdrun[tt] makes a guess for the number of PME",
+    "nodes when the number of nodes is larger than 11 or performance wise",
+    "not compatible with the PME grid x dimension.",
+    "But the user should optimize npme. Performance statistics on this issue",
+    "are written at the end of the log file.",
+    "For good load balancing at high parallelization, the PME grid x and y",
+    "dimensions should be divisible by the number of PME nodes",
+    "(the simulation will run correctly also when this is not the case).",
+    "[PAR]",
+    "This section lists all options that affect the domain decomposition.",
+    "[PAR]",
+    "Option [TT]-rdd[tt] can be used to set the required maximum distance",
+    "for inter charge-group bonded interactions.",
+    "Communication for two-body bonded interactions below the non-bonded",
+    "cut-off distance always comes for free with the non-bonded communication.",
+    "Atoms beyond the non-bonded cut-off are only communicated when they have",
+    "missing bonded interactions; this means that the extra cost is minor",
+    "and nearly indepedent of the value of [TT]-rdd[tt].",
+    "With dynamic load balancing option [TT]-rdd[tt] also sets",
+    "the lower limit for the domain decomposition cell sizes.",
+    "By default [TT]-rdd[tt] is determined by [TT]mdrun[tt] based on",
+    "the initial coordinates. The chosen value will be a balance",
+    "between interaction range and communication cost.",
+    "[PAR]",
+    "When inter charge-group bonded interactions are beyond",
+    "the bonded cut-off distance, [TT]mdrun[tt] terminates with an error message.",
+    "For pair interactions and tabulated bonds",
+    "that do not generate exclusions, this check can be turned off",
+    "with the option [TT]-noddcheck[tt].",
+    "[PAR]",
+    "When constraints are present, option [TT]-rcon[tt] influences",
+    "the cell size limit as well.",
+    "Atoms connected by NC constraints, where NC is the LINCS order plus 1,",
+    "should not be beyond the smallest cell size. A error message is",
+    "generated when this happens and the user should change the decomposition",
+    "or decrease the LINCS order and increase the number of LINCS iterations.",
+    "By default [TT]mdrun[tt] estimates the minimum cell size required for P-LINCS",
+    "in a conservative fashion. For high parallelization it can be useful",
+    "to set the distance required for P-LINCS with the option [TT]-rcon[tt].",
+    "[PAR]",
+    "The [TT]-dds[tt] option sets the minimum allowed x, y and/or z scaling",
+    "of the cells with dynamic load balancing. [TT]mdrun[tt] will ensure that",
+    "the cells can scale down by at least this factor. This option is used",
+    "for the automated spatial decomposition (when not using [TT]-dd[tt])",
+    "as well as for determining the number of grid pulses, which in turn",
+    "sets the minimum allowed cell size. Under certain circumstances",
+    "the value of [TT]-dds[tt] might need to be adjusted to account for",
+    "high or low spatial inhomogeneity of the system.",
+    "[PAR]",
+    "The option [TT]-gcom[tt] can be used to only do global communication",
+    "every n steps.",
+    "This can improve performance for highly parallel simulations",
+    "where this global communication step becomes the bottleneck.",
+    "For a global thermostat and/or barostat the temperature",
+    "and/or pressure will also only be updated every [TT]-gcom[tt] steps.",
+    "By default it is set to the minimum of nstcalcenergy and nstlist.[PAR]",
+    "With [TT]-rerun[tt] an input trajectory can be given for which ",
+    "forces and energies will be (re)calculated. Neighbor searching will be",
+    "performed for every frame, unless [TT]nstlist[tt] is zero",
+    "(see the [TT].mdp[tt] file).[PAR]",
+    "ED (essential dynamics) sampling is switched on by using the [TT]-ei[tt]",
+    "flag followed by an [TT].edi[tt] file.",
+    "The [TT].edi[tt] file can be produced using options in the essdyn",
+    "menu of the WHAT IF program. [TT]mdrun[tt] produces a [TT].edo[tt] file that",
+    "contains projections of positions, velocities and forces onto selected",
+    "eigenvectors.[PAR]",
+    "When user-defined potential functions have been selected in the",
+    "[TT].mdp[tt] file the [TT]-table[tt] option is used to pass [TT]mdrun[tt]",
+    "a formatted table with potential functions. The file is read from",
+    "either the current directory or from the [TT]GMXLIB[tt] directory.",
+    "A number of pre-formatted tables are presented in the [TT]GMXLIB[tt] dir,",
+    "for 6-8, 6-9, 6-10, 6-11, 6-12 Lennard-Jones potentials with",
+    "normal Coulomb.",
+    "When pair interactions are present, a separate table for pair interaction",
+    "functions is read using the [TT]-tablep[tt] option.[PAR]",
+    "When tabulated bonded functions are present in the topology,",
+    "interaction functions are read using the [TT]-tableb[tt] option.",
+    "For each different tabulated interaction type the table file name is",
+    "modified in a different way: before the file extension an underscore is",
+    "appended, then a 'b' for bonds, an 'a' for angles or a 'd' for dihedrals",
+    "and finally the table number of the interaction type.[PAR]",
+    "The options [TT]-px[tt] and [TT]-pf[tt] are used for writing pull COM",
+    "coordinates and forces when pulling is selected",
+    "in the [TT].mdp[tt] file.[PAR]",
+    "With [TT]-multi[tt] or [TT]-multidir[tt], multiple systems can be ",
+    "simulated in parallel.",
+    "As many input files/directories are required as the number of systems. ",
+    "The [TT]-multidir[tt] option takes a list of directories (one for each ",
+    "system) and runs in each of them, using the input/output file names, ",
+    "such as specified by e.g. the [TT]-s[tt] option, relative to these ",
+    "directories.",
+    "With [TT]-multi[tt], the system number is appended to the run input ",
+    "and each output filename, for instance [TT]topol.tpr[tt] becomes",
+    "[TT]topol0.tpr[tt], [TT]topol1.tpr[tt] etc.",
+    "The number of nodes per system is the total number of nodes",
+    "divided by the number of systems.",
+    "One use of this option is for NMR refinement: when distance",
+    "or orientation restraints are present these can be ensemble averaged",
+    "over all the systems.[PAR]",
+    "With [TT]-replex[tt] replica exchange is attempted every given number",
+    "of steps. The number of replicas is set with the [TT]-multi[tt] or ",
+    "[TT]-multidir[tt] option, described above.",
+    "All run input files should use a different coupling temperature,",
+    "the order of the files is not important. The random seed is set with",
+    "[TT]-reseed[tt]. The velocities are scaled and neighbor searching",
+    "is performed after every exchange.[PAR]",
+    "Finally some experimental algorithms can be tested when the",
+    "appropriate options have been given. Currently under",
+    "investigation are: polarizability and X-ray bombardments.",
+    "[PAR]",
+    "The option [TT]-membed[dd] does what used to be g_membed, i.e. embed",
+    "a protein into a membrane. The data file should contain the options",
+    "that where passed to g_membed before. The [TT]-mn[tt] and [TT]-mp[tt]",
+    "both apply to this as well.",
+    "[PAR]",
+    "The option [TT]-pforce[tt] is useful when you suspect a simulation",
+    "crashes due to too large forces. With this option coordinates and",
+    "forces of atoms with a force larger than a certain value will",
+    "be printed to stderr.",
+    "[PAR]",
+    "Checkpoints containing the complete state of the system are written",
+    "at regular intervals (option [TT]-cpt[tt]) to the file [TT]-cpo[tt],",
+    "unless option [TT]-cpt[tt] is set to -1.",
+    "The previous checkpoint is backed up to [TT]state_prev.cpt[tt] to",
+    "make sure that a recent state of the system is always available,",
+    "even when the simulation is terminated while writing a checkpoint.",
+    "With [TT]-cpnum[tt] all checkpoint files are kept and appended",
+    "with the step number.",
+    "A simulation can be continued by reading the full state from file",
+    "with option [TT]-cpi[tt]. This option is intelligent in the way that",
+    "if no checkpoint file is found, Gromacs just assumes a normal run and",
+    "starts from the first step of the [TT].tpr[tt] file. By default the output",
+    "will be appending to the existing output files. The checkpoint file",
+    "contains checksums of all output files, such that you will never",
+    "loose data when some output files are modified, corrupt or removed.",
+    "There are three scenarios with [TT]-cpi[tt]:[PAR]",
+    "[TT]*[tt] no files with matching names are present: new output files are written[PAR]",
+    "[TT]*[tt] all files are present with names and checksums matching those stored",
+    "in the checkpoint file: files are appended[PAR]",
+    "[TT]*[tt] otherwise no files are modified and a fatal error is generated[PAR]",
+    "With [TT]-noappend[tt] new output files are opened and the simulation",
+    "part number is added to all output file names.",
+    "Note that in all cases the checkpoint file itself is not renamed",
+    "and will be overwritten, unless its name does not match",
+    "the [TT]-cpo[tt] option.",
+    "[PAR]",
+    "With checkpointing the output is appended to previously written",
+    "output files, unless [TT]-noappend[tt] is used or none of the previous",
+    "output files are present (except for the checkpoint file).",
+    "The integrity of the files to be appended is verified using checksums",
+    "which are stored in the checkpoint file. This ensures that output can",
+    "not be mixed up or corrupted due to file appending. When only some",
+    "of the previous output files are present, a fatal error is generated",
+    "and no old output files are modified and no new output files are opened.",
+    "The result with appending will be the same as from a single run.",
+    "The contents will be binary identical, unless you use a different number",
+    "of nodes or dynamic load balancing or the FFT library uses optimizations",
+    "through timing.",
+    "[PAR]",
+    "With option [TT]-maxh[tt] a simulation is terminated and a checkpoint",
+    "file is written at the first neighbor search step where the run time",
+    "exceeds [TT]-maxh[tt]*0.99 hours.",
+    "[PAR]",
+    "When [TT]mdrun[tt] receives a TERM signal, it will set nsteps to the current",
+    "step plus one. When [TT]mdrun[tt] receives an INT signal (e.g. when ctrl+C is",
+    "pressed), it will stop after the next neighbor search step ",
+    "(with nstlist=0 at the next step).",
+    "In both cases all the usual output will be written to file.",
+    "When running with MPI, a signal to one of the [TT]mdrun[tt] processes",
+    "is sufficient, this signal should not be sent to mpirun or",
+    "the [TT]mdrun[tt] process that is the parent of the others.",
+    "[PAR]",
+    "When [TT]mdrun[tt] is started with MPI, it does not run niced by default."
+#endif
+  };
+  t_commrec    *cr;
+  t_filenm fnm[] = {
+    { efTPX, NULL,      NULL,       ffREAD },
+    { efTRN, "-o",      NULL,       ffWRITE },
+    { efXTC, "-x",      NULL,       ffOPTWR },
+    { efCPT, "-cpi",    NULL,       ffOPTRD },
+    { efCPT, "-cpo",    NULL,       ffOPTWR },
+    { efSTO, "-c",      "confout",  ffWRITE },
+    { efEDR, "-e",      "ener",     ffWRITE },
+    { efLOG, "-g",      "md",       ffWRITE },
+    { efXVG, "-dhdl",   "dhdl",     ffOPTWR },
+    { efXVG, "-field",  "field",    ffOPTWR },
+    { efXVG, "-table",  "table",    ffOPTRD },
+    { efXVG, "-tablep", "tablep",   ffOPTRD },
+    { efXVG, "-tableb", "table",    ffOPTRD },
+    { efTRX, "-rerun",  "rerun",    ffOPTRD },
+    { efXVG, "-tpi",    "tpi",      ffOPTWR },
+    { efXVG, "-tpid",   "tpidist",  ffOPTWR },
+    { efEDI, "-ei",     "sam",      ffOPTRD },
+    { efEDO, "-eo",     "sam",      ffOPTWR },
+    { efGCT, "-j",      "wham",     ffOPTRD },
+    { efGCT, "-jo",     "bam",      ffOPTWR },
+    { efXVG, "-ffout",  "gct",      ffOPTWR },
+    { efXVG, "-devout", "deviatie", ffOPTWR },
+    { efXVG, "-runav",  "runaver",  ffOPTWR },
+    { efXVG, "-px",     "pullx",    ffOPTWR },
+    { efXVG, "-pf",     "pullf",    ffOPTWR },
+    { efXVG, "-ro",     "rotation", ffOPTWR },
+    { efLOG, "-ra",     "rotangles",ffOPTWR },
+    { efLOG, "-rs",     "rotslabs", ffOPTWR },
+    { efLOG, "-rt",     "rottorque",ffOPTWR },
+    { efMTX, "-mtx",    "nm",       ffOPTWR },
+    { efNDX, "-dn",     "dipole",   ffOPTWR },
+    { efDAT, "-membed", "membed",   ffOPTRD },
+    { efTOP, "-mp",     "membed",   ffOPTRD },
+    { efNDX, "-mn",     "membed",   ffOPTRD },
+    { efRND, "-multidir",NULL,      ffOPTRDMULT}
+  };
+#define NFILE asize(fnm)
+
+  /* Command line options ! */
+  gmx_bool bCart        = FALSE;
+  gmx_bool bPPPME       = FALSE;
+  gmx_bool bPartDec     = FALSE;
+  gmx_bool bDDBondCheck = TRUE;
+  gmx_bool bDDBondComm  = TRUE;
+  gmx_bool bVerbose     = FALSE;
+  gmx_bool bCompact     = TRUE;
+  gmx_bool bSepPot      = FALSE;
+  gmx_bool bRerunVSite  = FALSE;
+  gmx_bool bIonize      = FALSE;
+  gmx_bool bConfout     = TRUE;
+  gmx_bool bReproducible = FALSE;
+    
+  int  npme=-1;
+  int  nmultisim=0;
+  int  nstglobalcomm=-1;
+  int  repl_ex_nst=0;
+  int  repl_ex_seed=-1;
+  int  nstepout=100;
+  int  nthreads=0; /* set to determine # of threads automatically */
+  int  resetstep=-1;
+  
+  rvec realddxyz={0,0,0};
+  const char *ddno_opt[ddnoNR+1] =
+    { NULL, "interleave", "pp_pme", "cartesian", NULL };
+    const char *dddlb_opt[] =
+    { NULL, "auto", "no", "yes", NULL };
+  real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
+  char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
+  real cpt_period=15.0,max_hours=-1;
+  gmx_bool bAppendFiles=TRUE;
+  gmx_bool bKeepAndNumCPT=FALSE;
+  gmx_bool bResetCountersHalfWay=FALSE;
+  output_env_t oenv=NULL;
+  const char *deviceOptions = "";
+
+  t_pargs pa[] = {
+
+    { "-pd",      FALSE, etBOOL,{&bPartDec},
+      "Use particle decompostion" },
+    { "-dd",      FALSE, etRVEC,{&realddxyz},
+      "Domain decomposition grid, 0 is optimize" },
+#ifdef GMX_THREADS
+    { "-nt",      FALSE, etINT, {&nthreads},
+      "Number of threads to start (0 is guess)" },
+#endif
+    { "-npme",    FALSE, etINT, {&npme},
+      "Number of separate nodes to be used for PME, -1 is guess" },
+    { "-ddorder", FALSE, etENUM, {ddno_opt},
+      "DD node order" },
+    { "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
+      "Check for all bonded interactions with DD" },
+    { "-ddbondcomm", FALSE, etBOOL, {&bDDBondComm},
+      "HIDDENUse special bonded atom communication when [TT]-rdd[tt] > cut-off" },
+    { "-rdd",     FALSE, etREAL, {&rdd},
+      "The maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
+    { "-rcon",    FALSE, etREAL, {&rconstr},
+      "Maximum distance for P-LINCS (nm), 0 is estimate" },
+    { "-dlb",     FALSE, etENUM, {dddlb_opt},
+      "Dynamic load balancing (with DD)" },
+    { "-dds",     FALSE, etREAL, {&dlb_scale},
+      "Minimum allowed dlb scaling of the DD cell size" },
+    { "-ddcsx",   FALSE, etSTR, {&ddcsx},
+      "HIDDENThe DD cell sizes in x" },
+    { "-ddcsy",   FALSE, etSTR, {&ddcsy},
+      "HIDDENThe DD cell sizes in y" },
+    { "-ddcsz",   FALSE, etSTR, {&ddcsz},
+      "HIDDENThe DD cell sizes in z" },
+    { "-gcom",    FALSE, etINT,{&nstglobalcomm},
+      "Global communication frequency" },
+    { "-v",       FALSE, etBOOL,{&bVerbose},  
+      "Be loud and noisy" },
+    { "-compact", FALSE, etBOOL,{&bCompact},  
+      "Write a compact log file" },
+    { "-seppot",  FALSE, etBOOL, {&bSepPot},
+      "Write separate V and dVdl terms for each interaction type and node to the log file(s)" },
+    { "-pforce",  FALSE, etREAL, {&pforce},
+      "Print all forces larger than this (kJ/mol nm)" },
+    { "-reprod",  FALSE, etBOOL,{&bReproducible},  
+      "Try to avoid optimizations that affect binary reproducibility" },
+    { "-cpt",     FALSE, etREAL, {&cpt_period},
+      "Checkpoint interval (minutes)" },
+    { "-cpnum",   FALSE, etBOOL, {&bKeepAndNumCPT},
+      "Keep and number checkpoint files" },
+    { "-append",  FALSE, etBOOL, {&bAppendFiles},
+      "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
+    { "-maxh",   FALSE, etREAL, {&max_hours},
+      "Terminate after 0.99 times this time (hours)" },
+    { "-multi",   FALSE, etINT,{&nmultisim}, 
+      "Do multiple simulations in parallel" },
+    { "-replex",  FALSE, etINT, {&repl_ex_nst}, 
+      "Attempt replica exchange every # steps" },
+    { "-reseed",  FALSE, etINT, {&repl_ex_seed}, 
+      "Seed for replica exchange, -1 is generate a seed" },
+    { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
+      "HIDDENRecalculate virtual site coordinates with [TT]-rerun[tt]" },
+    { "-ionize",  FALSE, etBOOL,{&bIonize},
+      "Do a simulation including the effect of an X-Ray bombardment on your system" },
+    { "-confout", FALSE, etBOOL, {&bConfout},
+      "HIDDENWrite the last configuration with [TT]-c[tt] and force checkpointing at the last step" },
+    { "-stepout", FALSE, etINT, {&nstepout},
+      "HIDDENFrequency of writing the remaining runtime" },
+    { "-resetstep", FALSE, etINT, {&resetstep},
+      "HIDDENReset cycle counters after these many time steps" },
+    { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
+      "HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt]" }
+#ifdef GMX_OPENMM
+    ,
+    { "-device",  FALSE, etSTR, {&deviceOptions},
+      "Device option string" }
+#endif
+  };
+  gmx_edsam_t  ed;
+  unsigned long Flags, PCA_Flags;
+  ivec     ddxyz;
+  int      dd_node_order;
+  gmx_bool     bAddPart;
+  FILE     *fplog,*fptest;
+  int      sim_part,sim_part_fn;
+  const char *part_suffix=".part";
+  char     suffix[STRLEN];
+  int      rc;
+  char **multidir=NULL;
+
+
+  cr = init_par(&argc,&argv);
+
+  if (MASTER(cr))
+    CopyRight(stderr, argv[0]);
+
+  PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
+              | (MASTER(cr) ? 0 : PCA_QUIET));
+  
+
+  /* Comment this in to do fexist calls only on master
+   * works not with rerun or tables at the moment
+   * also comment out the version of init_forcerec in md.c 
+   * with NULL instead of opt2fn
+   */
+  /*
+     if (!MASTER(cr))
+     {
+     PCA_Flags |= PCA_NOT_READ_NODE;
+     }
+     */
+
+  parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
+                    asize(desc),desc,0,NULL, &oenv);
+
+
+
+  /* we set these early because they might be used in init_multisystem() 
+     Note that there is the potential for npme>nnodes until the number of
+     threads is set later on, if there's thread parallelization. That shouldn't
+     lead to problems. */ 
+  dd_node_order = nenum(ddno_opt);
+  cr->npmenodes = npme;
+
+#ifndef GMX_THREADS
+  nthreads=1;
+#endif
+
+  /* now check the -multi and -multidir option */
+  if (opt2bSet("-multidir", NFILE, fnm))
+  {
+      int i;
+      if (nmultisim > 0)
+      {
+          gmx_fatal(FARGS, "mdrun -multi and -multidir options are mutually exclusive.");
+      }
+      nmultisim = opt2fns(&multidir, "-multidir", NFILE, fnm);
+  }
+
+
+  if (repl_ex_nst != 0 && nmultisim < 2)
+      gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
+
+  if (nmultisim > 1) {
+#ifndef GMX_THREADS
+    gmx_bool bParFn = (multidir == NULL);
+    init_multisystem(cr, nmultisim, multidir, NFILE, fnm, bParFn);
+#else
+    gmx_fatal(FARGS,"mdrun -multi is not supported with the thread library.Please compile GROMACS with MPI support");
+#endif
+  }
+
+  bAddPart = !bAppendFiles;
+
+  /* Check if there is ANY checkpoint file available */        
+  sim_part    = 1;
+  sim_part_fn = sim_part;
+  if (opt2bSet("-cpi",NFILE,fnm))
+  {
+      if (bSepPot && bAppendFiles)
+      {
+          gmx_fatal(FARGS,"Output file appending is not supported with -seppot");
+      }
+
+      bAppendFiles =
+                read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
+                                                              fnm,cr),
+                                                &sim_part_fn,NULL,cr,
+                                                bAppendFiles,NFILE,fnm,
+                                                part_suffix,&bAddPart);
+      if (sim_part_fn==0 && MASTER(cr))
+      {
+          fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
+      }
+      else
+      {
+          sim_part = sim_part_fn + 1;
+      }
+
+      if (MULTISIM(cr) && MASTER(cr))
+      {
+          check_multi_int(stdout,cr->ms,sim_part,"simulation part");
+      }
+  } 
+  else
+  {
+      bAppendFiles = FALSE;
+  }
+
+  if (!bAppendFiles)
+  {
+      sim_part_fn = sim_part;
+  }
+
+  if (bAddPart)
+  {
+      /* Rename all output files (except checkpoint files) */
+      /* create new part name first (zero-filled) */
+      sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
+
+      add_suffix_to_output_names(fnm,NFILE,suffix);
+      if (MASTER(cr))
+      {
+          fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
+      }
+  }
+
+  Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
+  Flags = Flags | (bSepPot       ? MD_SEPPOT       : 0);
+  Flags = Flags | (bIonize       ? MD_IONIZE       : 0);
+  Flags = Flags | (bPartDec      ? MD_PARTDEC      : 0);
+  Flags = Flags | (bDDBondCheck  ? MD_DDBONDCHECK  : 0);
+  Flags = Flags | (bDDBondComm   ? MD_DDBONDCOMM   : 0);
+  Flags = Flags | (bConfout      ? MD_CONFOUT      : 0);
+  Flags = Flags | (bRerunVSite   ? MD_RERUN_VSITE  : 0);
+  Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
+  Flags = Flags | (bAppendFiles  ? MD_APPENDFILES  : 0); 
+  Flags = Flags | (bKeepAndNumCPT ? MD_KEEPANDNUMCPT : 0); 
+  Flags = Flags | (sim_part>1    ? MD_STARTFROMCPT : 0); 
+  Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
+
+
+  /* We postpone opening the log file if we are appending, so we can 
+     first truncate the old log file and append to the correct position 
+     there instead.  */
+  if ((MASTER(cr) || bSepPot) && !bAppendFiles) 
+  {
+      gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
+      CopyRight(fplog,argv[0]);
+      please_cite(fplog,"Hess2008b");
+      please_cite(fplog,"Spoel2005a");
+      please_cite(fplog,"Lindahl2001a");
+      please_cite(fplog,"Berendsen95a");
+  }
+  else if (!MASTER(cr) && bSepPot)
+  {
+      gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
+  }
+  else
+  {
+      fplog = NULL;
+  }
+
+  ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
+  ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
+  ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
+
+  rc = mdrunner(nthreads, fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,
+                nstglobalcomm, ddxyz,dd_node_order,rdd,rconstr,
+                dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
+                nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
+                pforce, cpt_period,max_hours,deviceOptions,Flags);
+
+  if (gmx_parallel_env_initialized())
+      gmx_finalize();
+
+  if (MULTIMASTER(cr)) {
+      thanx(stderr);
+  }
+
+  /* Log file has to be closed in mdrunner if we are appending to it 
+     (fplog not set here) */
+  if (MASTER(cr) && !bAppendFiles) 
+  {
+      gmx_log_close(fplog);
+  }
+
+  return rc;
+}
+
diff --git a/src/programs/mdrun/membed.c b/src/programs/mdrun/membed.c
new file mode 100644 (file)
index 0000000..073325a
--- /dev/null
@@ -0,0 +1,1175 @@
+/*
+ * $Id: mdrun.c,v 1.139.2.9 2009/05/04 16:13:29 hess Exp $
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "vec.h"
+#include "statutil.h"
+#include "macros.h"
+#include "copyrite.h"
+#include "main.h"
+#include "futil.h"
+#include "edsam.h"
+#include "index.h"
+#include "physics.h"
+#include "names.h"
+#include "mtop_util.h"
+#include "tpxio.h"
+#include "string2.h"
+#include "membed.h"
+#include "pbc.h"
+#include "readinp.h"
+
+typedef struct {
+       int             id;
+       char    *name;
+       int     nr;
+       int     natoms;     /*nr of atoms per lipid*/
+       int     mol1;       /*id of the first lipid molecule*/
+       real    area;
+} lip_t;
+
+typedef struct {
+       char    *name;
+       t_block mem_at;
+       int             *mol_id;
+       int             nmol;
+       real    lip_area;
+       real    zmin;
+       real    zmax;
+       real    zmed;
+} mem_t;
+
+typedef struct {
+       int             *mol;
+       int             *block;
+       int     nr;
+} rm_t;
+
+int search_string(char *s,int ng,char ***gn)
+{
+       int i;
+
+       for(i=0; (i<ng); i++)
+               if (gmx_strcasecmp(s,*gn[i]) == 0)
+                       return i;
+
+       gmx_fatal(FARGS,"Group %s not found in indexfile.\nMaybe you have non-default groups in your mdp file, while not using the '-n' option of grompp.\nIn that case use the '-n' option.\n",s);
+
+       return -1;
+}
+
+int get_mol_id(int at,int nmblock,gmx_molblock_t *mblock, int *type, int *block)
+{
+       int mol_id=0;
+       int i;
+
+       for(i=0;i<nmblock;i++)
+       {
+               if(at<(mblock[i].nmol*mblock[i].natoms_mol))
+               {
+                       mol_id+=at/mblock[i].natoms_mol;
+                       *type = mblock[i].type;
+                       *block = i;
+                       return mol_id;
+               } else {
+                       at-= mblock[i].nmol*mblock[i].natoms_mol;
+                       mol_id+=mblock[i].nmol;
+               }
+       }
+
+       gmx_fatal(FARGS,"Something is wrong in mol ids, at %d, mol_id %d",at,mol_id);
+
+       return -1;
+}
+
+int get_block(int mol_id,int nmblock,gmx_molblock_t *mblock)
+{
+       int i;
+       int nmol=0;
+
+       for(i=0;i<nmblock;i++)
+       {
+               nmol+=mblock[i].nmol;
+               if(mol_id<nmol)
+                       return i;
+       }
+
+       gmx_fatal(FARGS,"mol_id %d larger than total number of molecules %d.\n",mol_id,nmol);
+
+       return -1;
+}
+
+int get_tpr_version(const char *infile)
+{
+       char    buf[STRLEN];
+       gmx_bool        bDouble;
+       int     precision,fver;
+        t_fileio *fio;
+
+       fio = open_tpx(infile,"r");
+       gmx_fio_checktype(fio);
+
+       precision = sizeof(real);
+
+       gmx_fio_do_string(fio,buf);
+       if (strncmp(buf,"VERSION",7))
+               gmx_fatal(FARGS,"Can not read file %s,\n"
+                               "             this file is from a Gromacs version which is older than 2.0\n"
+                               "             Make a new one with grompp or use a gro or pdb file, if possible",
+                               gmx_fio_getname(fio));
+       gmx_fio_do_int(fio,precision);
+       bDouble = (precision == sizeof(double));
+       if ((precision != sizeof(float)) && !bDouble)
+               gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
+                               "instead of %d or %d",
+                               gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+       gmx_fio_setprecision(fio,bDouble);
+       fprintf(stderr,"Reading file %s, %s (%s precision)\n",
+                       gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
+
+       gmx_fio_do_int(fio,fver);
+
+       close_tpx(fio);
+
+       return fver;
+}
+
+int get_mtype_list(t_block *at, gmx_mtop_t *mtop, t_block *tlist)
+{
+       int i,j,nr,mol_id;
+        int type=0,block=0;
+       gmx_bool bNEW;
+
+       nr=0;
+       snew(tlist->index,at->nr);
+       for (i=0;i<at->nr;i++)
+       {
+               bNEW=TRUE;
+               mol_id = get_mol_id(at->index[i],mtop->nmolblock,mtop->molblock,&type,&block);
+               for(j=0;j<nr;j++)
+               {
+                       if(tlist->index[j]==type)
+                               bNEW=FALSE;
+               }
+               if(bNEW==TRUE)
+               {
+                       tlist->index[nr]=type;
+                       nr++;
+               }
+       }
+
+       srenew(tlist->index,nr);
+       return nr;
+}
+
+void check_types(t_block *ins_at,t_block *rest_at,gmx_mtop_t *mtop)
+{
+       t_block         *ins_mtype,*rest_mtype;
+       int                     i,j;
+
+       snew(ins_mtype,1);
+       snew(rest_mtype,1);
+    ins_mtype->nr  = get_mtype_list(ins_at , mtop, ins_mtype );
+    rest_mtype->nr = get_mtype_list(rest_at, mtop, rest_mtype);
+
+    for(i=0;i<ins_mtype->nr;i++)
+    {
+       for(j=0;j<rest_mtype->nr;j++)
+       {
+               if(ins_mtype->index[i]==rest_mtype->index[j])
+                       gmx_fatal(FARGS,"Moleculetype %s is found both in the group to insert and the rest of the system.\n"
+                                       "1. Your *.ndx and *.top do not match\n"
+                                       "2. You are inserting some molecules of type %s (for example xray-solvent), while\n"
+                                       "the same moleculetype is also used in the rest of the system (solvent box). Because\n"
+                                       "we need to exclude all interactions between the atoms in the group to\n"
+                                       "insert, the same moleculetype can not be used in both groups. Change the\n"
+                                       "moleculetype of the molecules %s in the inserted group. Do not forget to provide\n"
+                                       "an appropriate *.itp file",*(mtop->moltype[rest_mtype->index[j]].name),
+                                       *(mtop->moltype[rest_mtype->index[j]].name),*(mtop->moltype[rest_mtype->index[j]].name));
+       }
+    }
+
+    sfree(ins_mtype->index);
+    sfree(rest_mtype->index);
+    sfree(ins_mtype);
+    sfree(rest_mtype);
+}
+
+void get_input(const char *membed_input, real *xy_fac, real *xy_max, real *z_fac, real *z_max,
+               int *it_xy, int *it_z, real *probe_rad, int *low_up_rm, int *maxwarn, 
+               int *pieces, gmx_bool *bALLOW_ASYMMETRY)
+{
+    warninp_t wi;
+    t_inpfile *inp;
+    int       ninp;
+
+    wi = init_warning(TRUE,0);
+    
+    inp = read_inpfile(membed_input, &ninp, NULL, wi);
+    ITYPE ("nxy", *it_xy, 1000);
+    ITYPE ("nz", *it_z, 0);
+    RTYPE ("xyinit", *xy_fac, 0.5);
+    RTYPE ("xyend", *xy_max, 1.0);
+    RTYPE ("zinit", *z_fac, 1.0);
+    RTYPE ("zend", *z_max, 1.0);
+    RTYPE ("rad", *probe_rad, 0.22);
+    ITYPE ("ndiff", *low_up_rm, 0);
+    ITYPE ("maxwarn", *maxwarn, 0);
+    ITYPE ("pieces", *pieces, 1);
+    EETYPE("asymmetry", *bALLOW_ASYMMETRY, yesno_names);
+    write_inpfile(membed_input,ninp,inp,FALSE,wi);
+}
+
+int init_ins_at(t_block *ins_at,t_block *rest_at,t_state *state, pos_ins_t *pos_ins,gmx_groups_t *groups,int ins_grp_id, real xy_max)
+{
+       int i,gid,c=0;
+       real x,xmin,xmax,y,ymin,ymax,z,zmin,zmax;
+
+       snew(rest_at->index,state->natoms);
+
+       xmin=xmax=state->x[ins_at->index[0]][XX];
+       ymin=ymax=state->x[ins_at->index[0]][YY];
+       zmin=zmax=state->x[ins_at->index[0]][ZZ];
+
+       for(i=0;i<state->natoms;i++)
+       {
+               gid = groups->grpnr[egcFREEZE][i];
+               if(groups->grps[egcFREEZE].nm_ind[gid]==ins_grp_id)
+               {
+                       x=state->x[i][XX];
+                       if (x<xmin)                     xmin=x;
+                       if (x>xmax)                     xmax=x;
+                       y=state->x[i][YY];
+                       if (y<ymin)                             ymin=y;
+                       if (y>ymax)                             ymax=y;
+                       z=state->x[i][ZZ];
+                       if (z<zmin)                             zmin=z;
+                       if (z>zmax)                             zmax=z;
+               } else {
+                       rest_at->index[c]=i;
+                       c++;
+               }
+       }
+
+       rest_at->nr=c;
+       srenew(rest_at->index,c);
+
+       if(xy_max>1.000001)
+       {
+               pos_ins->xmin[XX]=xmin-((xmax-xmin)*xy_max-(xmax-xmin))/2;
+               pos_ins->xmin[YY]=ymin-((ymax-ymin)*xy_max-(ymax-ymin))/2;
+
+               pos_ins->xmax[XX]=xmax+((xmax-xmin)*xy_max-(xmax-xmin))/2;
+               pos_ins->xmax[YY]=ymax+((ymax-ymin)*xy_max-(ymax-ymin))/2;
+       } else {
+               pos_ins->xmin[XX]=xmin;
+               pos_ins->xmin[YY]=ymin;
+
+               pos_ins->xmax[XX]=xmax;
+               pos_ins->xmax[YY]=ymax;
+       }
+
+       /* 6.0 is estimated thickness of bilayer */
+       if( (zmax-zmin) < 6.0 )
+       {
+               pos_ins->xmin[ZZ]=zmin+(zmax-zmin)/2.0-3.0;
+               pos_ins->xmax[ZZ]=zmin+(zmax-zmin)/2.0+3.0;
+       } else {
+               pos_ins->xmin[ZZ]=zmin;
+               pos_ins->xmax[ZZ]=zmax;
+       }
+
+       return c;
+}
+
+real est_prot_area(pos_ins_t *pos_ins,rvec *r,t_block *ins_at, mem_t *mem_p)
+{
+       real x,y,dx=0.15,dy=0.15,area=0.0;
+       real add;
+       int c,at;
+
+       for(x=pos_ins->xmin[XX];x<pos_ins->xmax[XX];x+=dx)
+       {
+               for(y=pos_ins->xmin[YY];y<pos_ins->xmax[YY];y+=dy)
+               {
+                       c=0;
+                       add=0.0;
+                       do
+                       {
+                               at=ins_at->index[c];
+                               if ( (r[at][XX]>=x) && (r[at][XX]<x+dx) &&
+                                               (r[at][YY]>=y) && (r[at][YY]<y+dy) &&
+                                               (r[at][ZZ]>mem_p->zmin+1.0) && (r[at][ZZ]<mem_p->zmax-1.0) )
+                                       add=1.0;
+                               c++;
+                       } while ( (c<ins_at->nr) && (add<0.5) );
+                       area+=add;
+               }
+       }
+       area=area*dx*dy;
+
+       return area;
+}
+
+void init_lip(matrix box, gmx_mtop_t *mtop, lip_t *lip)
+{
+       int i;
+       real mem_area;
+       int mol1=0;
+
+       mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+       for(i=0;i<mtop->nmolblock;i++)
+       {
+               if(mtop->molblock[i].type == lip->id)
+               {
+                       lip->nr=mtop->molblock[i].nmol;
+                       lip->natoms=mtop->molblock[i].natoms_mol;
+               }
+       }
+       lip->area=2.0*mem_area/(double)lip->nr;
+
+       for (i=0;i<lip->id;i++)
+               mol1+=mtop->molblock[i].nmol;
+       lip->mol1=mol1;
+}
+
+int init_mem_at(mem_t *mem_p, gmx_mtop_t *mtop, rvec *r, matrix box, pos_ins_t *pos_ins)
+{
+       int i,j,at,mol,nmol,nmolbox,count;
+       t_block *mem_a;
+       real z,zmin,zmax,mem_area;
+       gmx_bool bNew;
+       atom_id *mol_id;
+       int type=0,block=0;
+
+       nmol=count=0;
+       mem_a=&(mem_p->mem_at);
+       snew(mol_id,mem_a->nr);
+/*     snew(index,mem_a->nr); */
+       zmin=pos_ins->xmax[ZZ];
+       zmax=pos_ins->xmin[ZZ];
+       for(i=0;i<mem_a->nr;i++)
+       {
+               at=mem_a->index[i];
+               if(     (r[at][XX]>pos_ins->xmin[XX]) && (r[at][XX]<pos_ins->xmax[XX]) &&
+                       (r[at][YY]>pos_ins->xmin[YY]) && (r[at][YY]<pos_ins->xmax[YY]) &&
+                       (r[at][ZZ]>pos_ins->xmin[ZZ]) && (r[at][ZZ]<pos_ins->xmax[ZZ]) )
+               {
+                       mol = get_mol_id(at,mtop->nmolblock,mtop->molblock,&type,&block);
+
+                       bNew=TRUE;
+                       for(j=0;j<nmol;j++)
+                               if(mol == mol_id[j])
+                                       bNew=FALSE;
+
+                       if(bNew)
+                       {
+                               mol_id[nmol]=mol;
+                               nmol++;
+                       }
+
+                       z=r[at][ZZ];
+                       if(z<zmin)                                      zmin=z;
+                       if(z>zmax)                                      zmax=z;
+
+/*                     index[count]=at;*/
+                       count++;
+               }
+       }
+
+       mem_p->nmol=nmol;
+       srenew(mol_id,nmol);
+       mem_p->mol_id=mol_id;
+/*     srenew(index,count);*/
+/*     mem_p->mem_at.nr=count;*/
+/*     sfree(mem_p->mem_at.index);*/
+/*     mem_p->mem_at.index=index;*/
+
+       if((zmax-zmin)>(box[ZZ][ZZ]-0.5))
+               gmx_fatal(FARGS,"Something is wrong with your membrane. Max and min z values are %f and %f.\n"
+                               "Maybe your membrane is not centered in the box, but located at the box edge in the z-direction,\n"
+                               "so that one membrane is distributed over two periodic box images. Another possibility is that\n"
+                               "your water layer is not thick enough.\n",zmax,zmin);
+       mem_p->zmin=zmin;
+       mem_p->zmax=zmax;
+       mem_p->zmed=(zmax-zmin)/2+zmin;
+
+       /*number of membrane molecules in protein box*/
+       nmolbox = count/mtop->molblock[block].natoms_mol;
+       /*mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+       mem_p->lip_area = 2.0*mem_area/(double)mem_p->nmol;*/
+       mem_area = (pos_ins->xmax[XX]-pos_ins->xmin[XX])*(pos_ins->xmax[YY]-pos_ins->xmin[YY]);
+       mem_p->lip_area = 2.0*mem_area/(double)nmolbox;
+
+       return mem_p->mem_at.nr;
+}
+
+void init_resize(t_block *ins_at,rvec *r_ins,pos_ins_t *pos_ins,mem_t *mem_p,rvec *r, gmx_bool bALLOW_ASYMMETRY)
+{
+       int i,j,at,c,outsidesum,gctr=0;
+    int idxsum=0;
+
+    /*sanity check*/
+    for (i=0;i<pos_ins->pieces;i++)
+          idxsum+=pos_ins->nidx[i];
+    if (idxsum!=ins_at->nr)
+          gmx_fatal(FARGS,"Piecewise sum of inserted atoms not same as size of group selected to insert.");
+
+    snew(pos_ins->geom_cent,pos_ins->pieces);
+    for (i=0;i<pos_ins->pieces;i++)
+    {
+       c=0;
+       outsidesum=0;
+       for(j=0;j<DIM;j++)
+               pos_ins->geom_cent[i][j]=0;
+
+       for(j=0;j<DIM;j++)
+               pos_ins->geom_cent[i][j]=0;
+       for (j=0;j<pos_ins->nidx[i];j++)
+       {
+               at=pos_ins->subindex[i][j];
+               copy_rvec(r[at],r_ins[gctr]);
+               if( (r_ins[gctr][ZZ]<mem_p->zmax) && (r_ins[gctr][ZZ]>mem_p->zmin) )
+               {
+                       rvec_inc(pos_ins->geom_cent[i],r_ins[gctr]);
+                       c++;
+               }
+               else
+                       outsidesum++;
+               gctr++;
+       }
+       if (c>0)
+               svmul(1/(double)c,pos_ins->geom_cent[i],pos_ins->geom_cent[i]);
+       if (!bALLOW_ASYMMETRY)
+               pos_ins->geom_cent[i][ZZ]=mem_p->zmed;
+
+       fprintf(stderr,"Embedding piece %d with center of geometry: %f %f %f\n",i,pos_ins->geom_cent[i][XX],pos_ins->geom_cent[i][YY],pos_ins->geom_cent[i][ZZ]);
+    }
+    fprintf(stderr,"\n");
+}
+
+void resize(rvec *r_ins, rvec *r, pos_ins_t *pos_ins,rvec fac)
+{
+       int i,j,k,at,c=0;
+       for (k=0;k<pos_ins->pieces;k++)
+               for(i=0;i<pos_ins->nidx[k];i++)
+               {
+                       at=pos_ins->subindex[k][i];
+                       for(j=0;j<DIM;j++)
+                               r[at][j]=pos_ins->geom_cent[k][j]+fac[j]*(r_ins[c][j]-pos_ins->geom_cent[k][j]);
+                       c++;
+               }
+}
+
+int gen_rm_list(rm_t *rm_p,t_block *ins_at,t_block *rest_at,t_pbc *pbc, gmx_mtop_t *mtop,
+               rvec *r, rvec *r_ins, mem_t *mem_p, pos_ins_t *pos_ins, real probe_rad, int low_up_rm, gmx_bool bALLOW_ASYMMETRY)
+{
+       int i,j,k,l,at,at2,mol_id;
+        int type=0,block=0;
+       int nrm,nupper,nlower;
+       real r_min_rad,z_lip,min_norm;
+       gmx_bool bRM;
+       rvec dr,dr_tmp;
+       real *dist;
+       int *order;
+
+       r_min_rad=probe_rad*probe_rad;
+       snew(rm_p->mol,mtop->mols.nr);
+       snew(rm_p->block,mtop->mols.nr);
+       nrm=nupper=0;
+       nlower=low_up_rm;
+       for(i=0;i<ins_at->nr;i++)
+       {
+               at=ins_at->index[i];
+               for(j=0;j<rest_at->nr;j++)
+               {
+                       at2=rest_at->index[j];
+                       pbc_dx(pbc,r[at],r[at2],dr);
+
+                       if(norm2(dr)<r_min_rad)
+                       {
+                               mol_id = get_mol_id(at2,mtop->nmolblock,mtop->molblock,&type,&block);
+                               bRM=TRUE;
+                               for(l=0;l<nrm;l++)
+                                       if(rm_p->mol[l]==mol_id)
+                                               bRM=FALSE;
+                               if(bRM)
+                               {
+                                       /*fprintf(stderr,"%d wordt toegevoegd\n",mol_id);*/
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       z_lip=0.0;
+                                       for(l=0;l<mem_p->nmol;l++)
+                                       {
+                                               if(mol_id==mem_p->mol_id[l])
+                                               {
+                                                       for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+                                                               z_lip+=r[k][ZZ];
+                                                       z_lip/=mtop->molblock[block].natoms_mol;
+                                                       if(z_lip<mem_p->zmed)
+                                                               nlower++;
+                                                       else
+                                                               nupper++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*make sure equal number of lipids from upper and lower layer are removed */
+       if( (nupper!=nlower) && (!bALLOW_ASYMMETRY) )
+       {
+               snew(dist,mem_p->nmol);
+               snew(order,mem_p->nmol);
+               for(i=0;i<mem_p->nmol;i++)
+               {
+                       at = mtop->mols.index[mem_p->mol_id[i]];
+                       pbc_dx(pbc,r[at],pos_ins->geom_cent[0],dr);
+                       if (pos_ins->pieces>1)
+                       {
+                               /*minimum dr value*/
+                               min_norm=norm2(dr);
+                               for (k=1;k<pos_ins->pieces;k++)
+                               {
+                                       pbc_dx(pbc,r[at],pos_ins->geom_cent[k],dr_tmp);
+                                       if (norm2(dr_tmp) < min_norm)
+                                       {
+                                               min_norm=norm2(dr_tmp);
+                                               copy_rvec(dr_tmp,dr);
+                                       }
+                               }
+                       }
+                       dist[i]=dr[XX]*dr[XX]+dr[YY]*dr[YY];
+                       j=i-1;
+                       while (j>=0 && dist[i]<dist[order[j]])
+                       {
+                               order[j+1]=order[j];
+                               j--;
+                       }
+                       order[j+1]=i;
+               }
+
+               i=0;
+               while(nupper!=nlower)
+               {
+                       mol_id=mem_p->mol_id[order[i]];
+                       block=get_block(mol_id,mtop->nmolblock,mtop->molblock);
+
+                       bRM=TRUE;
+                       for(l=0;l<nrm;l++)
+                               if(rm_p->mol[l]==mol_id)
+                                       bRM=FALSE;
+                       if(bRM)
+                       {
+                               z_lip=0;
+                               for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+                                       z_lip+=r[k][ZZ];
+                               z_lip/=mtop->molblock[block].natoms_mol;
+                               if(nupper>nlower && z_lip<mem_p->zmed)
+                               {
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       nlower++;
+                               }
+                               else if (nupper<nlower && z_lip>mem_p->zmed)
+                               {
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       nupper++;
+                               }
+                       }
+                       i++;
+
+                       if(i>mem_p->nmol)
+                               gmx_fatal(FARGS,"Trying to remove more lipid molecules than there are in the membrane");
+               }
+               sfree(dist);
+               sfree(order);
+       }
+
+       rm_p->nr=nrm;
+       srenew(rm_p->mol,nrm);
+       srenew(rm_p->block,nrm);
+
+       return nupper+nlower;
+}
+
+void rm_group(t_inputrec *ir, gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state *state, t_block *ins_at, pos_ins_t *pos_ins)
+{
+       int i,j,k,n,rm,mol_id,at,block;
+       rvec *x_tmp,*v_tmp;
+       atom_id *list,*new_mols;
+       unsigned char  *new_egrp[egcNR];
+       gmx_bool bRM;
+
+       snew(list,state->natoms);
+       n=0;
+       for(i=0;i<rm_p->nr;i++)
+       {
+               mol_id=rm_p->mol[i];
+               at=mtop->mols.index[mol_id];
+               block =rm_p->block[i];
+               mtop->molblock[block].nmol--;
+               for(j=0;j<mtop->molblock[block].natoms_mol;j++)
+               {
+                       list[n]=at+j;
+                       n++;
+               }
+
+               mtop->mols.index[mol_id]=-1;
+       }
+
+       mtop->mols.nr-=rm_p->nr;
+       mtop->mols.nalloc_index-=rm_p->nr;
+       snew(new_mols,mtop->mols.nr);
+       for(i=0;i<mtop->mols.nr+rm_p->nr;i++)
+       {
+               j=0;
+               if(mtop->mols.index[i]!=-1)
+               {
+                       new_mols[j]=mtop->mols.index[i];
+                       j++;
+               }
+       }
+       sfree(mtop->mols.index);
+       mtop->mols.index=new_mols;
+
+
+       mtop->natoms-=n;
+       state->natoms-=n;
+       state->nalloc=state->natoms;
+       snew(x_tmp,state->nalloc);
+       snew(v_tmp,state->nalloc);
+
+       for(i=0;i<egcNR;i++)
+       {
+               if(groups->grpnr[i]!=NULL)
+               {
+                       groups->ngrpnr[i]=state->natoms;
+                       snew(new_egrp[i],state->natoms);
+               }
+       }
+
+       rm=0;
+       for (i=0;i<state->natoms+n;i++)
+       {
+               bRM=FALSE;
+               for(j=0;j<n;j++)
+               {
+                       if(i==list[j])
+                       {
+                               bRM=TRUE;
+                               rm++;
+                       }
+               }
+
+               if(!bRM)
+               {
+                       for(j=0;j<egcNR;j++)
+                       {
+                               if(groups->grpnr[j]!=NULL)
+                               {
+                                       new_egrp[j][i-rm]=groups->grpnr[j][i];
+                               }
+                       }
+                       copy_rvec(state->x[i],x_tmp[i-rm]);
+                       copy_rvec(state->v[i],v_tmp[i-rm]);
+                       for(j=0;j<ins_at->nr;j++)
+                       {
+                               if (i==ins_at->index[j])
+                                       ins_at->index[j]=i-rm;
+                       }
+                       for(j=0;j<pos_ins->pieces;j++)
+                       {
+                               for(k=0;k<pos_ins->nidx[j];k++)
+                               {
+                                       if (i==pos_ins->subindex[j][k])
+                                               pos_ins->subindex[j][k]=i-rm;
+                               }
+                       }
+               }
+       }
+       sfree(state->x);
+       state->x=x_tmp;
+       sfree(state->v);
+       state->v=v_tmp;
+
+       for(i=0;i<egcNR;i++)
+       {
+               if(groups->grpnr[i]!=NULL)
+               {
+                       sfree(groups->grpnr[i]);
+                       groups->grpnr[i]=new_egrp[i];
+               }
+       }
+
+        /* remove empty molblocks */
+        int RMmolblock=0;
+        for (i=0;i<mtop->nmolblock;i++)
+        {
+           if(mtop->molblock[i].nmol==0)
+           {
+             RMmolblock++;
+           } else {
+             mtop->molblock[i-RMmolblock]=mtop->molblock[i];
+           }
+        }
+        mtop->nmolblock-=RMmolblock;
+}
+
+int rm_bonded(t_block *ins_at, gmx_mtop_t *mtop)
+{
+       int i,j,m;
+       int type,natom,nmol,at,atom1=0,rm_at=0;
+       gmx_bool *bRM,bINS;
+       /*this routine lives dangerously by assuming that all molecules of a given type are in order in the structure*/
+       /*this routine does not live as dangerously as it seems. There is namely a check in mdrunner_membed to make
+         *sure that g_membed exits with a warning when there are molecules of the same type not in the 
+        *ins_at index group. MGWolf 050710 */
+
+
+       snew(bRM,mtop->nmoltype);
+       for (i=0;i<mtop->nmoltype;i++)
+       {
+               bRM[i]=TRUE;
+       }
+
+       for (i=0;i<mtop->nmolblock;i++) 
+       {
+           /*loop over molecule blocks*/
+               type        =mtop->molblock[i].type;
+               natom       =mtop->molblock[i].natoms_mol;
+               nmol            =mtop->molblock[i].nmol;
+
+               for(j=0;j<natom*nmol && bRM[type]==TRUE;j++) 
+               {
+                   /*loop over atoms in the block*/
+                       at=j+atom1; /*atom index = block index + offset*/
+                       bINS=FALSE;
+
+                       for (m=0;(m<ins_at->nr) && (bINS==FALSE);m++)
+                       {
+                           /*loop over atoms in insertion index group to determine if we're inserting one*/
+                               if(at==ins_at->index[m])
+                               {
+                                       bINS=TRUE;
+                               }
+                       }
+                       bRM[type]=bINS;
+               }
+               atom1+=natom*nmol; /*update offset*/
+               if(bRM[type])
+               {
+                       rm_at+=natom*nmol; /*increment bonded removal counter by # atoms in block*/
+               }
+       }
+
+       for(i=0;i<mtop->nmoltype;i++)
+       {
+               if(bRM[i])
+               {
+                       for(j=0;j<F_LJ;j++)
+                       {
+                               mtop->moltype[i].ilist[j].nr=0;
+                       }
+                       for(j=F_POSRES;j<=F_VSITEN;j++)
+                       {
+                               mtop->moltype[i].ilist[j].nr=0;
+                       }
+               }
+       }
+       sfree(bRM);
+
+       return rm_at;
+}
+
+void top_update(const char *topfile, char *ins, rm_t *rm_p, gmx_mtop_t *mtop)
+{
+#define TEMP_FILENM "temp.top"
+       int     bMolecules=0;
+       FILE    *fpin,*fpout;
+       char    buf[STRLEN],buf2[STRLEN],*temp;
+       int             i,*nmol_rm,nmol,line;
+
+       fpin  = ffopen(topfile,"r");
+       fpout = ffopen(TEMP_FILENM,"w");
+
+       snew(nmol_rm,mtop->nmoltype);
+       for(i=0;i<rm_p->nr;i++)
+               nmol_rm[rm_p->block[i]]++;
+
+       line=0;
+       while(fgets(buf,STRLEN,fpin))
+       {
+               line++;
+               if(buf[0]!=';')
+               {
+                       strcpy(buf2,buf);
+                       if ((temp=strchr(buf2,'\n')) != NULL)
+                               temp[0]='\0';
+                       ltrim(buf2);
+
+                       if (buf2[0]=='[')
+                       {
+                               buf2[0]=' ';
+                               if ((temp=strchr(buf2,'\n')) != NULL)
+                                       temp[0]='\0';
+                               rtrim(buf2);
+                               if (buf2[strlen(buf2)-1]==']')
+                               {
+                                       buf2[strlen(buf2)-1]='\0';
+                                       ltrim(buf2);
+                                       rtrim(buf2);
+                                       if (gmx_strcasecmp(buf2,"molecules")==0)
+                                               bMolecules=1;
+                               }
+                               fprintf(fpout,"%s",buf);
+                       } else if (bMolecules==1)
+                       {
+                               for(i=0;i<mtop->nmolblock;i++)
+                               {
+                                       nmol=mtop->molblock[i].nmol;
+                                       sprintf(buf,"%-15s %5d\n",*(mtop->moltype[mtop->molblock[i].type].name),nmol);
+                                       fprintf(fpout,"%s",buf);
+                               }
+                               bMolecules=2;
+                       } else if (bMolecules==2)
+                       {
+                               /* print nothing */
+                       } else 
+                       {
+                               fprintf(fpout,"%s",buf);
+                       }
+               } else 
+               {
+                       fprintf(fpout,"%s",buf);
+               }
+       }
+
+       fclose(fpout);
+       /* use ffopen to generate backup of topinout */
+       fpout=ffopen(topfile,"w");
+       fclose(fpout);
+       rename(TEMP_FILENM,topfile);
+#undef TEMP_FILENM
+}
+
+void rescale_membed(int step_rel, gmx_membed_t *membed, rvec *x)
+{
+       /* Set new positions for the group to embed */
+       if(step_rel<=membed->it_xy)
+       {
+               membed->fac[0]+=membed->xy_step;
+               membed->fac[1]+=membed->xy_step;
+       } else if (step_rel<=(membed->it_xy+membed->it_z))
+       {
+               membed->fac[2]+=membed->z_step;
+       }
+       resize(membed->r_ins,x,membed->pos_ins,membed->fac);
+}
+
+void init_membed(FILE *fplog, gmx_membed_t *membed, int nfile, const t_filenm fnm[], gmx_mtop_t *mtop, t_inputrec *inputrec, t_state *state, t_commrec *cr,real *cpt)
+{
+        char                    *ins;
+        int                     i,rm_bonded_at,fr_id,fr_i=0,tmp_id,warn=0;
+        int                     ng,j,max_lip_rm,ins_grp_id,ins_nat,mem_nat,ntype,lip_rm,tpr_version;
+        real                    prot_area;
+        rvec                    *r_ins=NULL;
+        t_block                 *ins_at,*rest_at;
+        pos_ins_t               *pos_ins;
+        mem_t                   *mem_p;
+        rm_t                    *rm_p;
+        gmx_groups_t            *groups;
+        gmx_bool                    bExcl=FALSE;
+        t_atoms                 atoms;
+        t_pbc                   *pbc;
+        char                    **piecename=NULL;
+    
+        /* input variables */
+       const char *membed_input;
+        real xy_fac = 0.5;
+        real xy_max = 1.0;
+        real z_fac = 1.0;
+        real z_max = 1.0;
+        int it_xy = 1000;
+        int it_z = 0;
+        real probe_rad = 0.22;
+        int low_up_rm = 0;
+        int maxwarn=0;
+        int pieces=1;
+        gmx_bool bALLOW_ASYMMETRY=FALSE;
+
+       snew(ins_at,1);
+       snew(pos_ins,1);
+
+       if(MASTER(cr))
+       {
+                /* get input data out membed file */
+               membed_input = opt2fn("-membed",nfile,fnm);
+               get_input(membed_input,&xy_fac,&xy_max,&z_fac,&z_max,&it_xy,&it_z,&probe_rad,&low_up_rm,&maxwarn,&pieces,&bALLOW_ASYMMETRY);
+
+               tpr_version = get_tpr_version(ftp2fn(efTPX,nfile,fnm));
+               if (tpr_version<58)
+                       gmx_fatal(FARGS,"Version of *.tpr file to old (%d). Rerun grompp with gromacs VERSION 4.0.3 or newer.\n",tpr_version);
+
+               if( !EI_DYNAMICS(inputrec->eI) )
+                       gmx_input("Change integrator to a dynamics integrator in mdp file (e.g. md or sd).");
+
+               if(PAR(cr))
+                       gmx_input("Sorry, parallel g_membed is not yet fully functional.");
+     
+#ifdef GMX_OPENMM
+                       gmx_input("Sorry, g_membed does not work with openmm.");
+#endif
+
+               if(*cpt>=0)
+               {
+                       fprintf(stderr,"\nSetting -cpt to -1, because embedding cannot be restarted from cpt-files.\n");
+                       *cpt=-1;
+               }
+               groups=&(mtop->groups);
+
+               atoms=gmx_mtop_global_atoms(mtop);
+               snew(mem_p,1);
+               fprintf(stderr,"\nSelect a group to embed in the membrane:\n");
+               get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(ins_at->nr),&(ins_at->index),&ins);
+               ins_grp_id = search_string(ins,groups->ngrpname,(groups->grpname));
+               fprintf(stderr,"\nSelect a group to embed %s into (e.g. the membrane):\n",ins);
+               get_index(&atoms,opt2fn_null("-mn",nfile,fnm),1,&(mem_p->mem_at.nr),&(mem_p->mem_at.index),&(mem_p->name));
+
+               pos_ins->pieces=pieces;
+               snew(pos_ins->nidx,pieces);
+               snew(pos_ins->subindex,pieces);
+               snew(piecename,pieces); 
+               if (pieces>1)
+               {
+                       fprintf(stderr,"\nSelect pieces to embed:\n");
+                       get_index(&atoms,opt2fn_null("-mn",nfile,fnm),pieces,pos_ins->nidx,pos_ins->subindex,piecename);
+               }
+               else
+               {       
+                       /*use whole embedded group*/
+                       snew(pos_ins->nidx,1);
+                       snew(pos_ins->subindex,1);
+                       pos_ins->nidx[0]=ins_at->nr;
+                       pos_ins->subindex[0]=ins_at->index;
+               }
+
+               if(probe_rad<0.2199999)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nA probe radius (-rad) smaller than 0.2 can result in overlap between waters "
+                                       "and the group to embed, which will result in Lincs errors etc.\nIf you are sure, you can increase maxwarn.\n\n",warn);
+               }
+
+               if(xy_fac<0.09999999)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe initial size of %s is probably too smal.\n"
+                                       "If you are sure, you can increase maxwarn.\n\n",warn,ins);
+               }
+
+               if(it_xy<1000)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d) is probably too small.\n"
+                                       "Increase -nxy or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_xy);
+               }
+
+               if( (it_z<100) && ( z_fac<0.99999999 || z_fac>1.0000001) )
+                {
+                        warn++;
+                        fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d) is probably too small.\n"
+                                       "Increase -nz or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_z);
+                }
+
+               if(it_xy+it_z>inputrec->nsteps)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the number of steps in the tpr.\n"
+                                       "If you are sure, you can increase maxwarn.\n\n",warn);
+               }
+
+               fr_id=-1;
+               if( inputrec->opts.ngfrz==1)
+                       gmx_fatal(FARGS,"You did not specify \"%s\" as a freezegroup.",ins);
+               for(i=0;i<inputrec->opts.ngfrz;i++)
+               {
+                       tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i];
+                       if(ins_grp_id==tmp_id)
+                       {
+                               fr_id=tmp_id;
+                               fr_i=i;
+                       }
+               }
+               if (fr_id == -1 )
+                       gmx_fatal(FARGS,"\"%s\" not as freezegroup defined in the mdp-file.",ins);
+
+               for(i=0;i<DIM;i++)
+                       if( inputrec->opts.nFreeze[fr_i][i] != 1)
+                               gmx_fatal(FARGS,"freeze dimensions for %s are not Y Y Y\n",ins);
+
+               ng = groups->grps[egcENER].nr;
+               if (ng == 1)
+                       gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group");
+
+               for(i=0;i<ng;i++)
+               {
+                       for(j=0;j<ng;j++)
+                       {
+                               if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL)
+                               {
+                                       bExcl = TRUE;
+                                       if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) || (groups->grps[egcENER].nm_ind[j] != ins_grp_id) )
+                                               gmx_fatal(FARGS,"Energy exclusions \"%s\" and  \"%s\" do not match the group to embed \"%s\"",
+                                                               *groups->grpname[groups->grps[egcENER].nm_ind[i]],
+                                                               *groups->grpname[groups->grps[egcENER].nm_ind[j]],ins);
+                               }
+                       }
+               }
+               if (!bExcl)
+                       gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in the freeze group");
+
+               /* Guess the area the protein will occupy in the membrane plane  Calculate area per lipid*/
+               snew(rest_at,1);
+               ins_nat = init_ins_at(ins_at,rest_at,state,pos_ins,groups,ins_grp_id,xy_max);
+               /* Check moleculetypes in insertion group */
+               check_types(ins_at,rest_at,mtop);
+
+               mem_nat = init_mem_at(mem_p,mtop,state->x,state->box,pos_ins);
+
+               prot_area = est_prot_area(pos_ins,state->x,ins_at,mem_p);
+               if ( (prot_area>7.5) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX])<50) )
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n"
+                                       "This might cause pressure problems during the growth phase. Just try with\n"
+                                       "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n"
+                                       "compressibility in the mdp-file or use no pressure coupling at all.\n\n",warn);
+               }
+               if(warn>maxwarn)
+                                       gmx_fatal(FARGS,"Too many warnings.\n");
+
+               printf("The estimated area of the protein in the membrane is %.3f nm^2\n",prot_area);
+               printf("\nThere are %d lipids in the membrane part that overlaps the protein.\nThe area per lipid is %.4f nm^2.\n",mem_p->nmol,mem_p->lip_area);
+
+               /* Maximum number of lipids to be removed*/
+               max_lip_rm=(int)(2*prot_area/mem_p->lip_area);
+               printf("Maximum number of lipids that will be removed is %d.\n",max_lip_rm);
+
+               printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n"
+                               "This resizing will be done with respect to the geometrical center of all protein atoms\n"
+                               "that span the membrane region, i.e. z between %.3f and %.3f\n\n",xy_fac,z_fac,mem_p->zmin,mem_p->zmax);
+
+               /* resize the protein by xy and by z if necessary*/
+               snew(r_ins,ins_at->nr);
+               init_resize(ins_at,r_ins,pos_ins,mem_p,state->x,bALLOW_ASYMMETRY);
+               membed->fac[0]=membed->fac[1]=xy_fac;
+               membed->fac[2]=z_fac;
+
+               membed->xy_step =(xy_max-xy_fac)/(double)(it_xy);
+               membed->z_step  =(z_max-z_fac)/(double)(it_z-1);
+
+               resize(r_ins,state->x,pos_ins,membed->fac);
+
+               /* remove overlapping lipids and water from the membrane box*/
+               /*mark molecules to be removed*/
+               snew(pbc,1);
+               set_pbc(pbc,inputrec->ePBC,state->box);
+
+               snew(rm_p,1);
+               lip_rm = gen_rm_list(rm_p,ins_at,rest_at,pbc,mtop,state->x, r_ins, mem_p,pos_ins,probe_rad,low_up_rm,bALLOW_ASYMMETRY);
+               lip_rm -= low_up_rm;
+
+               if(fplog)
+                       for(i=0;i<rm_p->nr;i++)
+                               fprintf(fplog,"rm mol %d\n",rm_p->mol[i]);
+
+               for(i=0;i<mtop->nmolblock;i++)
+               {
+                       ntype=0;
+                       for(j=0;j<rm_p->nr;j++)
+                               if(rm_p->block[j]==i)
+                                       ntype++;
+                       printf("Will remove %d %s molecules\n",ntype,*(mtop->moltype[mtop->molblock[i].type].name));
+               }
+
+               if(lip_rm>max_lip_rm)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nTrying to remove a larger lipid area than the estimated protein area\n"
+                                       "Try making the -xyinit resize factor smaller.\n\n",warn);
+               }
+
+               /*remove all lipids and waters overlapping and update all important structures*/
+               rm_group(inputrec,groups,mtop,rm_p,state,ins_at,pos_ins);
+
+               rm_bonded_at = rm_bonded(ins_at,mtop);
+               if (rm_bonded_at != ins_at->nr)
+               {
+                       fprintf(stderr,"Warning: The number of atoms for which the bonded interactions are removed is %d, "
+                                       "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same"
+                                       "molecule type as atoms that are not to be embedded.\n",rm_bonded_at,ins_at->nr);
+               }
+
+               if(warn>maxwarn)
+                       gmx_fatal(FARGS,"Too many warnings.\nIf you are sure these warnings are harmless, you can increase -maxwarn");
+
+               if (ftp2bSet(efTOP,nfile,fnm))
+                       top_update(opt2fn("-mp",nfile,fnm),ins,rm_p,mtop);
+
+               sfree(pbc);
+               sfree(rest_at);
+               if (pieces>1) {         sfree(piecename); }
+
+                membed->it_xy=it_xy;
+                membed->it_z=it_z;
+                membed->pos_ins=pos_ins;
+                membed->r_ins=r_ins;
+       }
+}
diff --git a/src/programs/mdrun/runner.c b/src/programs/mdrun/runner.c
new file mode 100644 (file)
index 0000000..1e3030f
--- /dev/null
@@ -0,0 +1,913 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+
+#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
+/* _isnan() */
+#include <float.h>
+#endif
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "statutil.h"
+#include "mdrun.h"
+#include "network.h"
+#include "pull.h"
+#include "pull_rotation.h"
+#include "names.h"
+#include "disre.h"
+#include "orires.h"
+#include "dihre.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdatoms.h"
+#include "repl_ex.h"
+#include "qmmm.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "coulomb.h"
+#include "constr.h"
+#include "mvdata.h"
+#include "checkpoint.h"
+#include "mtop_util.h"
+#include "sighandler.h"
+#include "tpxio.h"
+#include "txtdump.h"
+#include "membed.h"
+
+#include "md_openmm.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#ifdef GMX_FAHCORE
+#include "corewrap.h"
+#endif
+
+#ifdef GMX_OPENMM
+#include "md_openmm.h"
+#endif
+
+
+typedef struct { 
+    gmx_integrator_t *func;
+} gmx_intp_t;
+
+/* The array should match the eI array in include/types/enums.h */
+#ifdef GMX_OPENMM  /* FIXME do_md_openmm needs fixing */
+const gmx_intp_t integrator[eiNR] = { {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm}, {do_md_openmm},{do_md_openmm}};
+#else
+const gmx_intp_t integrator[eiNR] = { {do_md}, {do_steep}, {do_cg}, {do_md}, {do_md}, {do_nm}, {do_lbfgs}, {do_tpi}, {do_tpi}, {do_md}, {do_md},{do_md}};
+#endif
+
+gmx_large_int_t     deform_init_init_step_tpx;
+matrix              deform_init_box_tpx;
+#ifdef GMX_THREADS
+tMPI_Thread_mutex_t deform_init_box_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+#endif
+
+
+#ifdef GMX_THREADS
+struct mdrunner_arglist
+{
+    FILE *fplog;
+    t_commrec *cr;
+    int nfile;
+    const t_filenm *fnm;
+    output_env_t oenv;
+    gmx_bool bVerbose;
+    gmx_bool bCompact;
+    int nstglobalcomm;
+    ivec ddxyz;
+    int dd_node_order;
+    real rdd;
+    real rconstr;
+    const char *dddlb_opt;
+    real dlb_scale;
+    const char *ddcsx;
+    const char *ddcsy;
+    const char *ddcsz;
+    int nstepout;
+    int resetstep;
+    int nmultisim;
+    int repl_ex_nst;
+    int repl_ex_seed;
+    real pforce;
+    real cpt_period;
+    real max_hours;
+    const char *deviceOptions;
+    unsigned long Flags;
+    int ret; /* return value */
+};
+
+
+/* The function used for spawning threads. Extracts the mdrunner() 
+   arguments from its one argument and calls mdrunner(), after making
+   a commrec. */
+static void mdrunner_start_fn(void *arg)
+{
+    struct mdrunner_arglist *mda=(struct mdrunner_arglist*)arg;
+    struct mdrunner_arglist mc=*mda; /* copy the arg list to make sure 
+                                        that it's thread-local. This doesn't
+                                        copy pointed-to items, of course,
+                                        but those are all const. */
+    t_commrec *cr;  /* we need a local version of this */
+    FILE *fplog=NULL;
+    t_filenm *fnm;
+
+    fnm = dup_tfn(mc.nfile, mc.fnm);
+
+    cr = init_par_threads(mc.cr);
+
+    if (MASTER(cr))
+    {
+        fplog=mc.fplog;
+    }
+
+    mda->ret=mdrunner(cr->nnodes, fplog, cr, mc.nfile, fnm, mc.oenv, 
+                      mc.bVerbose, mc.bCompact, mc.nstglobalcomm, 
+                      mc.ddxyz, mc.dd_node_order, mc.rdd,
+                      mc.rconstr, mc.dddlb_opt, mc.dlb_scale, 
+                      mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, 
+                      mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce, 
+                      mc.cpt_period, mc.max_hours, mc.deviceOptions, mc.Flags);
+}
+
+/* called by mdrunner() to start a specific number of threads (including 
+   the main thread) for thread-parallel runs. This in turn calls mdrunner()
+   for each thread. 
+   All options besides nthreads are the same as for mdrunner(). */
+static t_commrec *mdrunner_start_threads(int nthreads, 
+              FILE *fplog,t_commrec *cr,int nfile, 
+              const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
+              gmx_bool bCompact, int nstglobalcomm,
+              ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+              const char *dddlb_opt,real dlb_scale,
+              const char *ddcsx,const char *ddcsy,const char *ddcsz,
+              int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+              int repl_ex_seed, real pforce,real cpt_period, real max_hours, 
+              const char *deviceOptions, unsigned long Flags)
+{
+    int ret;
+    struct mdrunner_arglist *mda;
+    t_commrec *crn; /* the new commrec */
+    t_filenm *fnmn;
+
+    /* first check whether we even need to start tMPI */
+    if (nthreads<2)
+        return cr;
+
+    /* a few small, one-time, almost unavoidable memory leaks: */
+    snew(mda,1);
+    fnmn=dup_tfn(nfile, fnm);
+
+    /* fill the data structure to pass as void pointer to thread start fn */
+    mda->fplog=fplog;
+    mda->cr=cr;
+    mda->nfile=nfile;
+    mda->fnm=fnmn;
+    mda->oenv=oenv;
+    mda->bVerbose=bVerbose;
+    mda->bCompact=bCompact;
+    mda->nstglobalcomm=nstglobalcomm;
+    mda->ddxyz[XX]=ddxyz[XX];
+    mda->ddxyz[YY]=ddxyz[YY];
+    mda->ddxyz[ZZ]=ddxyz[ZZ];
+    mda->dd_node_order=dd_node_order;
+    mda->rdd=rdd;
+    mda->rconstr=rconstr;
+    mda->dddlb_opt=dddlb_opt;
+    mda->dlb_scale=dlb_scale;
+    mda->ddcsx=ddcsx;
+    mda->ddcsy=ddcsy;
+    mda->ddcsz=ddcsz;
+    mda->nstepout=nstepout;
+    mda->resetstep=resetstep;
+    mda->nmultisim=nmultisim;
+    mda->repl_ex_nst=repl_ex_nst;
+    mda->repl_ex_seed=repl_ex_seed;
+    mda->pforce=pforce;
+    mda->cpt_period=cpt_period;
+    mda->max_hours=max_hours;
+    mda->deviceOptions=deviceOptions;
+    mda->Flags=Flags;
+
+    fprintf(stderr, "Starting %d threads\n",nthreads);
+    fflush(stderr);
+    /* now spawn new threads that start mdrunner_start_fn(), while 
+       the main thread returns */
+    ret=tMPI_Init_fn(TRUE, nthreads, mdrunner_start_fn, (void*)(mda) );
+    if (ret!=TMPI_SUCCESS)
+        return NULL;
+
+    /* make a new comm_rec to reflect the new situation */
+    crn=init_par_threads(cr);
+    return crn;
+}
+
+
+/* get the number of threads based on how many there were requested, 
+   which algorithms we're using, and how many particles there are. */
+static int get_nthreads(int nthreads_requested, t_inputrec *inputrec,
+                        gmx_mtop_t *mtop)
+{
+    int nthreads,nthreads_new;
+    int min_atoms_per_thread;
+    char *env;
+
+    nthreads = nthreads_requested;
+
+    /* determine # of hardware threads. */
+    if (nthreads_requested < 1)
+    {
+        if ((env = getenv("GMX_MAX_THREADS")) != NULL)
+        {
+            nthreads = 0;
+            sscanf(env,"%d",&nthreads);
+            if (nthreads < 1)
+            {
+                gmx_fatal(FARGS,"GMX_MAX_THREADS (%d) should be larger than 0",
+                          nthreads);
+            }
+        }
+        else
+        {
+            nthreads = tMPI_Thread_get_hw_number();
+        }
+    }
+
+    if (inputrec->eI == eiNM || EI_TPI(inputrec->eI))
+    {
+        /* Steps are divided over the nodes iso splitting the atoms */
+        min_atoms_per_thread = 0;
+    }
+    else
+    {
+        min_atoms_per_thread = MIN_ATOMS_PER_THREAD;
+    }
+
+    /* Check if an algorithm does not support parallel simulation.  */
+    if (nthreads != 1 && 
+        ( inputrec->eI == eiLBFGS ||
+          inputrec->coulombtype == eelEWALD ) )
+    {
+        fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs. Not starting any threads.\n");
+        nthreads = 1;
+    }
+    else if (nthreads_requested < 1 &&
+             mtop->natoms/nthreads < min_atoms_per_thread)
+    {
+        /* the thread number was chosen automatically, but there are too many
+           threads (too few atoms per thread) */
+        nthreads_new = max(1,mtop->natoms/min_atoms_per_thread);
+
+        if (nthreads_new > 8 || (nthreads == 8 && nthreads_new > 4))
+        {
+            /* Use only multiples of 4 above 8 threads
+             * or with an 8-core processor
+             * (to avoid 6 threads on 8 core processors with 4 real cores).
+             */
+            nthreads_new = (nthreads_new/4)*4;
+        }
+        else if (nthreads_new > 4)
+        {
+            /* Avoid 5 or 7 threads */
+            nthreads_new = (nthreads_new/2)*2;
+        }
+
+        nthreads = nthreads_new;
+
+        fprintf(stderr,"\n");
+        fprintf(stderr,"NOTE: Parallelization is limited by the small number of atoms,\n");
+        fprintf(stderr,"      only starting %d threads.\n",nthreads);
+        fprintf(stderr,"      You can use the -nt option to optimize the number of threads.\n\n");
+    }
+    return nthreads;
+}
+#endif
+
+
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+             const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,
+             gmx_bool bCompact, int nstglobalcomm,
+             ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+             const char *dddlb_opt,real dlb_scale,
+             const char *ddcsx,const char *ddcsy,const char *ddcsz,
+             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
+             const char *deviceOptions, unsigned long Flags)
+{
+    double     nodetime=0,realtime;
+    t_inputrec *inputrec;
+    t_state    *state=NULL;
+    matrix     box;
+    gmx_ddbox_t ddbox={0};
+    int        npme_major,npme_minor;
+    real       tmpr1,tmpr2;
+    t_nrnb     *nrnb;
+    gmx_mtop_t *mtop=NULL;
+    t_mdatoms  *mdatoms=NULL;
+    t_forcerec *fr=NULL;
+    t_fcdata   *fcd=NULL;
+    real       ewaldcoeff=0;
+    gmx_pme_t  *pmedata=NULL;
+    gmx_vsite_t *vsite=NULL;
+    gmx_constr_t constr;
+    int        i,m,nChargePerturbed=-1,status,nalloc;
+    char       *gro;
+    gmx_wallcycle_t wcycle;
+    gmx_bool       bReadRNG,bReadEkin;
+    int        list;
+    gmx_runtime_t runtime;
+    int        rc;
+    gmx_large_int_t reset_counters;
+    gmx_edsam_t ed=NULL;
+    t_commrec   *cr_old=cr; 
+    int         nthreads=1;
+    gmx_membed_t *membed=NULL;
+
+    /* CAUTION: threads may be started later on in this function, so
+       cr doesn't reflect the final parallel state right now */
+    snew(inputrec,1);
+    snew(mtop,1);
+
+    if (bVerbose && SIMMASTER(cr))
+    {
+        fprintf(stderr,"Getting Loaded...\n");
+    }
+    
+    if (Flags & MD_APPENDFILES) 
+    {
+        fplog = NULL;
+    }
+
+    snew(state,1);
+    if (MASTER(cr)) 
+    {
+        /* Read (nearly) all data required for the simulation */
+        read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
+
+        /* NOW the threads will be started: */
+#ifdef GMX_THREADS
+        nthreads = get_nthreads(nthreads_requested, inputrec, mtop);
+
+        if (nthreads > 1)
+        {
+            /* now start the threads. */
+            cr=mdrunner_start_threads(nthreads, fplog, cr_old, nfile, fnm, 
+                                      oenv, bVerbose, bCompact, nstglobalcomm, 
+                                      ddxyz, dd_node_order, rdd, rconstr, 
+                                      dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz,
+                                      nstepout, resetstep, nmultisim, 
+                                      repl_ex_nst, repl_ex_seed, pforce, 
+                                      cpt_period, max_hours, deviceOptions, 
+                                      Flags);
+            /* the main thread continues here with a new cr. We don't deallocate
+               the old cr because other threads may still be reading it. */
+            if (cr == NULL)
+            {
+                gmx_comm("Failed to spawn threads");
+            }
+        }
+#endif
+    }
+    /* END OF CAUTION: cr is now reliable */
+
+    /* g_membed initialisation *
+     * Because we change the mtop, init_membed is called before the init_parallel *
+     * (in case we ever want to make it run in parallel) */
+    if (opt2bSet("-membed",nfile,fnm))
+    {
+       fprintf(stderr,"Entering membed code");
+        snew(membed,1);
+        init_membed(fplog,membed,nfile,fnm,mtop,inputrec,state,cr,&cpt_period);
+    }
+
+    if (PAR(cr))
+    {
+        /* now broadcast everything to the non-master nodes/threads: */
+        init_parallel(fplog, cr, inputrec, mtop);
+    }
+    if (fplog != NULL)
+    {
+        pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
+    }
+
+    /* now make sure the state is initialized and propagated */
+    set_state_entries(state,inputrec,cr->nnodes);
+
+    /* A parallel command line option consistency check that we can
+       only do after any threads have started. */
+    if (!PAR(cr) &&
+        (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
+    {
+        gmx_fatal(FARGS,
+                  "The -dd or -npme option request a parallel simulation, "
+#ifndef GMX_MPI
+                  "but mdrun was compiled without threads or MPI enabled"
+#else
+#ifdef GMX_THREADS
+                  "but the number of threads (option -nt) is 1"
+#else
+                  "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec" 
+#endif
+#endif
+            );
+    }
+
+    if ((Flags & MD_RERUN) &&
+        (EI_ENERGY_MINIMIZATION(inputrec->eI) || eiNM == inputrec->eI))
+    {
+        gmx_fatal(FARGS, "The .mdp file specified an energy mininization or normal mode algorithm, and these are not compatible with mdrun -rerun");
+    }
+
+    if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
+    {
+        /* All-vs-all loops do not work with domain decomposition */
+        Flags |= MD_PARTDEC;
+    }
+
+    if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
+    {
+        cr->npmenodes = 0;
+    }
+
+#ifdef GMX_FAHCORE
+    fcRegisterSteps(inputrec->nsteps,inputrec->init_step);
+#endif
+
+    /* NMR restraints must be initialized before load_checkpoint,
+     * since with time averaging the history is added to t_state.
+     * For proper consistency check we therefore need to extend
+     * t_state here.
+     * So the PME-only nodes (if present) will also initialize
+     * the distance restraints.
+     */
+    snew(fcd,1);
+
+    /* This needs to be called before read_checkpoint to extend the state */
+    init_disres(fplog,mtop,inputrec,cr,Flags & MD_PARTDEC,fcd,state);
+
+    if (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0)
+    {
+        if (PAR(cr) && !(Flags & MD_PARTDEC))
+        {
+            gmx_fatal(FARGS,"Orientation restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)");
+        }
+        /* Orientation restraints */
+        if (MASTER(cr))
+        {
+            init_orires(fplog,mtop,state->x,inputrec,cr->ms,&(fcd->orires),
+                        state);
+        }
+    }
+
+    if (DEFORM(*inputrec))
+    {
+        /* Store the deform reference box before reading the checkpoint */
+        if (SIMMASTER(cr))
+        {
+            copy_mat(state->box,box);
+        }
+        if (PAR(cr))
+        {
+            gmx_bcast(sizeof(box),box,cr);
+        }
+        /* Because we do not have the update struct available yet
+         * in which the reference values should be stored,
+         * we store them temporarily in static variables.
+         * This should be thread safe, since they are only written once
+         * and with identical values.
+         */
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
+#endif
+        deform_init_init_step_tpx = inputrec->init_step;
+        copy_mat(box,deform_init_box_tpx);
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
+#endif
+    }
+
+    if (opt2bSet("-cpi",nfile,fnm)) 
+    {
+        /* Check if checkpoint file exists before doing continuation.
+         * This way we can use identical input options for the first and subsequent runs...
+         */
+        if( gmx_fexist_master(opt2fn_master("-cpi",nfile,fnm,cr),cr) )
+        {
+            load_checkpoint(opt2fn_master("-cpi",nfile,fnm,cr),&fplog,
+                            cr,Flags & MD_PARTDEC,ddxyz,
+                            inputrec,state,&bReadRNG,&bReadEkin,
+                            (Flags & MD_APPENDFILES));
+            
+            if (bReadRNG)
+            {
+                Flags |= MD_READ_RNG;
+            }
+            if (bReadEkin)
+            {
+                Flags |= MD_READ_EKIN;
+            }
+        }
+    }
+
+    if (((MASTER(cr) || (Flags & MD_SEPPOT)) && (Flags & MD_APPENDFILES))
+#ifdef GMX_THREADS
+        /* With thread MPI only the master node/thread exists in mdrun.c,
+         * therefore non-master nodes need to open the "seppot" log file here.
+         */
+        || (!MASTER(cr) && (Flags & MD_SEPPOT))
+#endif
+        )
+    {
+        gmx_log_open(ftp2fn(efLOG,nfile,fnm),cr,!(Flags & MD_SEPPOT),
+                             Flags,&fplog);
+    }
+
+    if (SIMMASTER(cr)) 
+    {
+        copy_mat(state->box,box);
+    }
+
+    if (PAR(cr)) 
+    {
+        gmx_bcast(sizeof(box),box,cr);
+    }
+
+    /* Essential dynamics */
+    if (opt2bSet("-ei",nfile,fnm))
+    {
+        /* Open input and output files, allocate space for ED data structure */
+        ed = ed_open(nfile,fnm,Flags,cr);
+    }
+
+    if (bVerbose && SIMMASTER(cr))
+    {
+        fprintf(stderr,"Loaded with Money\n\n");
+    }
+
+    if (PAR(cr) && !((Flags & MD_PARTDEC) ||
+                     EI_TPI(inputrec->eI) ||
+                     inputrec->eI == eiNM))
+    {
+        cr->dd = init_domain_decomposition(fplog,cr,Flags,ddxyz,rdd,rconstr,
+                                           dddlb_opt,dlb_scale,
+                                           ddcsx,ddcsy,ddcsz,
+                                           mtop,inputrec,
+                                           box,state->x,
+                                           &ddbox,&npme_major,&npme_minor);
+
+        make_dd_communicators(fplog,cr,dd_node_order);
+
+        /* Set overallocation to avoid frequent reallocation of arrays */
+        set_over_alloc_dd(TRUE);
+    }
+    else
+    {
+        /* PME, if used, is done on all nodes with 1D decomposition */
+        cr->npmenodes = 0;
+        cr->duty = (DUTY_PP | DUTY_PME);
+        npme_major = 1;
+        npme_minor = 1;
+        if (!EI_TPI(inputrec->eI))
+        {
+            npme_major = cr->nnodes;
+        }
+        
+        if (inputrec->ePBC == epbcSCREW)
+        {
+            gmx_fatal(FARGS,
+                      "pbc=%s is only implemented with domain decomposition",
+                      epbc_names[inputrec->ePBC]);
+        }
+    }
+
+    if (PAR(cr))
+    {
+        /* After possible communicator splitting in make_dd_communicators.
+         * we can set up the intra/inter node communication.
+         */
+        gmx_setup_nodecomm(fplog,cr);
+    }
+
+    wcycle = wallcycle_init(fplog,resetstep,cr);
+    if (PAR(cr))
+    {
+        /* Master synchronizes its value of reset_counters with all nodes 
+         * including PME only nodes */
+        reset_counters = wcycle_get_reset_counters(wcycle);
+        gmx_bcast_sim(sizeof(reset_counters),&reset_counters,cr);
+        wcycle_set_reset_counters(wcycle, reset_counters);
+    }
+
+
+    snew(nrnb,1);
+    if (cr->duty & DUTY_PP)
+    {
+        /* For domain decomposition we allocate dynamically
+         * in dd_partition_system.
+         */
+        if (DOMAINDECOMP(cr))
+        {
+            bcast_state_setup(cr,state);
+        }
+        else
+        {
+            if (PAR(cr))
+            {
+                bcast_state(cr,state,TRUE);
+            }
+        }
+
+        /* Dihedral Restraints */
+        if (gmx_mtop_ftype_count(mtop,F_DIHRES) > 0)
+        {
+            init_dihres(fplog,mtop,inputrec,fcd);
+        }
+
+        /* Initiate forcerecord */
+        fr = mk_forcerec();
+        init_forcerec(fplog,oenv,fr,fcd,inputrec,mtop,cr,box,FALSE,
+                      opt2fn("-table",nfile,fnm),
+                      opt2fn("-tablep",nfile,fnm),
+                      opt2fn("-tableb",nfile,fnm),FALSE,pforce);
+
+        /* version for PCA_NOT_READ_NODE (see md.c) */
+        /*init_forcerec(fplog,fr,fcd,inputrec,mtop,cr,box,FALSE,
+          "nofile","nofile","nofile",FALSE,pforce);
+          */        
+        fr->bSepDVDL = ((Flags & MD_SEPPOT) == MD_SEPPOT);
+
+        /* Initialize QM-MM */
+        if(fr->bQMMM)
+        {
+            init_QMMMrec(cr,box,mtop,inputrec,fr);
+        }
+
+        /* Initialize the mdatoms structure.
+         * mdatoms is not filled with atom data,
+         * as this can not be done now with domain decomposition.
+         */
+        mdatoms = init_mdatoms(fplog,mtop,inputrec->efep!=efepNO);
+
+        /* Initialize the virtual site communication */
+        vsite = init_vsite(mtop,cr);
+
+        calc_shifts(box,fr->shift_vec);
+
+        /* With periodic molecules the charge groups should be whole at start up
+         * and the virtual sites should not be far from their proper positions.
+         */
+        if (!inputrec->bContinuation && MASTER(cr) &&
+            !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols))
+        {
+            /* Make molecules whole at start of run */
+            if (fr->ePBC != epbcNONE)
+            {
+                do_pbc_first_mtop(fplog,inputrec->ePBC,box,mtop,state->x);
+            }
+            if (vsite)
+            {
+                /* Correct initial vsite positions are required
+                 * for the initial distribution in the domain decomposition
+                 * and for the initial shell prediction.
+                 */
+                construct_vsites_mtop(fplog,vsite,mtop,state->x);
+            }
+        }
+
+        /* Initiate PPPM if necessary */
+        if (fr->eeltype == eelPPPM)
+        {
+            if (mdatoms->nChargePerturbed)
+            {
+                gmx_fatal(FARGS,"Free energy with %s is not implemented",
+                          eel_names[fr->eeltype]);
+            }
+            status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
+                                   getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
+            if (status != 0)
+            {
+                gmx_fatal(FARGS,"Error %d initializing PPPM",status);
+            }
+        }
+
+        if (EEL_PME(fr->eeltype))
+        {
+            ewaldcoeff = fr->ewaldcoeff;
+            pmedata = &fr->pmedata;
+        }
+        else
+        {
+            pmedata = NULL;
+        }
+    }
+    else
+    {
+        /* This is a PME only node */
+
+        /* We don't need the state */
+        done_state(state);
+
+        ewaldcoeff = calc_ewaldcoeff(inputrec->rcoulomb, inputrec->ewald_rtol);
+        snew(pmedata,1);
+    }
+
+    /* Initiate PME if necessary,
+     * either on all nodes or on dedicated PME nodes only. */
+    if (EEL_PME(inputrec->coulombtype))
+    {
+        if (mdatoms)
+        {
+            nChargePerturbed = mdatoms->nChargePerturbed;
+        }
+        if (cr->npmenodes > 0)
+        {
+            /* The PME only nodes need to know nChargePerturbed */
+            gmx_bcast_sim(sizeof(nChargePerturbed),&nChargePerturbed,cr);
+        }
+        if (cr->duty & DUTY_PME)
+        {
+            status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
+                                  mtop ? mtop->natoms : 0,nChargePerturbed,
+                                  (Flags & MD_REPRODUCIBLE));
+            if (status != 0) 
+            {
+                gmx_fatal(FARGS,"Error %d initializing PME",status);
+            }
+        }
+    }
+
+
+    if (integrator[inputrec->eI].func == do_md
+#ifdef GMX_OPENMM
+        ||
+        integrator[inputrec->eI].func == do_md_openmm
+#endif
+        )
+    {
+        /* Turn on signal handling on all nodes */
+        /*
+         * (A user signal from the PME nodes (if any)
+         * is communicated to the PP nodes.
+         */
+        signal_handler_install();
+    }
+
+    if (cr->duty & DUTY_PP)
+    {
+        if (inputrec->ePull != epullNO)
+        {
+            /* Initialize pull code */
+            init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv,
+                      EI_DYNAMICS(inputrec->eI) && MASTER(cr),Flags);
+        }
+        
+        if (inputrec->bRot)
+        {
+           /* Initialize enforced rotation code */
+           init_rot(fplog,inputrec,nfile,fnm,cr,state->x,state->box,mtop,oenv,
+                    bVerbose,Flags);
+        }
+
+        constr = init_constraints(fplog,mtop,inputrec,ed,state,cr);
+
+        if (DOMAINDECOMP(cr))
+        {
+            dd_init_bondeds(fplog,cr->dd,mtop,vsite,constr,inputrec,
+                            Flags & MD_DDBONDCHECK,fr->cginfo_mb);
+
+            set_dd_parameters(fplog,cr->dd,dlb_scale,inputrec,fr,&ddbox);
+
+            setup_dd_grid(fplog,cr->dd);
+        }
+
+        /* Now do whatever the user wants us to do (how flexible...) */
+        integrator[inputrec->eI].func(fplog,cr,nfile,fnm,
+                                      oenv,bVerbose,bCompact,
+                                      nstglobalcomm,
+                                      vsite,constr,
+                                      nstepout,inputrec,mtop,
+                                      fcd,state,
+                                      mdatoms,nrnb,wcycle,ed,fr,
+                                      repl_ex_nst,repl_ex_seed,
+                                      membed,
+                                      cpt_period,max_hours,
+                                      deviceOptions,
+                                      Flags,
+                                      &runtime);
+
+        if (inputrec->ePull != epullNO)
+        {
+            finish_pull(fplog,inputrec->pull);
+        }
+        
+        if (inputrec->bRot)
+        {
+            finish_rot(fplog,inputrec->rot);
+        }
+
+    } 
+    else 
+    {
+        /* do PME only */
+        gmx_pmeonly(*pmedata,cr,nrnb,wcycle,ewaldcoeff,FALSE,inputrec);
+    }
+
+    if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
+    {
+        /* Some timing stats */  
+        if (SIMMASTER(cr))
+        {
+            if (runtime.proc == 0)
+            {
+                runtime.proc = runtime.real;
+            }
+        }
+        else
+        {
+            runtime.real = 0;
+        }
+    }
+
+    wallcycle_stop(wcycle,ewcRUN);
+
+    /* Finish up, write some stuff
+     * if rerunMD, don't write last frame again 
+     */
+    finish_run(fplog,cr,ftp2fn(efSTO,nfile,fnm),
+               inputrec,nrnb,wcycle,&runtime,
+               EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr));
+    
+    if (opt2bSet("-membed",nfile,fnm))
+    {
+        sfree(membed);
+    }
+
+    /* Does what it says */  
+    print_date_and_time(fplog,cr->nodeid,"Finished mdrun",&runtime);
+
+    /* Close logfile already here if we were appending to it */
+    if (MASTER(cr) && (Flags & MD_APPENDFILES))
+    {
+        gmx_log_close(fplog);
+    }  
+
+    rc=(int)gmx_get_stop_condition();
+
+#ifdef GMX_THREADS
+    /* we need to join all threads. The sub-threads join when they
+       exit this function, but the master thread needs to be told to 
+       wait for that. */
+    if (PAR(cr) && MASTER(cr))
+    {
+        tMPI_Finalize();
+    }
+#endif
+
+    return rc;
+}
diff --git a/src/programs/pdb2gmx/CMakeLists.txt b/src/programs/pdb2gmx/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a90ce45
--- /dev/null
@@ -0,0 +1,8 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+file(GLOB PDB2GMX_SOURCES *.c)
+
+add_executable(pdb2gmx ${PDB2GMX_SOURCES})
+target_link_libraries(pdb2gmx ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(pdb2gmx PROPERTIES OUTPUT_NAME "pdb2gmx${GMX_BINARY_SUFFIX}")
+install(TARGETS pdb2gmx DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/programs/tpbconv/CMakeLists.txt b/src/programs/tpbconv/CMakeLists.txt
new file mode 100644 (file)
index 0000000..323225f
--- /dev/null
@@ -0,0 +1,8 @@
+include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/gmxpreprocess)
+
+file(GLOB TPBCONV_SOURCES tpbconv.c)
+
+add_executable(tpbconv ${TPBCONV_SOURCES})
+target_link_libraries(tpbconv ${GMX_EXTRA_LIBRARIES} libgromacs)
+set_target_properties(tpbconv PROPERTIES OUTPUT_NAME "tpbconv${GMX_BINARY_SUFFIX}")
+install(TARGETS tpbconv DESTINATION ${BIN_INSTALL_DIR} COMPONENT runtime)
diff --git a/src/testutils/CMakeLists.txt b/src/testutils/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f175fc2
--- /dev/null
@@ -0,0 +1,22 @@
+set(TESTUTILS_HAVE_REFDATA FALSE)
+set(COMMON_SOURCES datapath.cpp refdata-common.cpp)
+if (GMX_USE_GTEST AND LIBXML2_FOUND)
+    include_directories(${GTEST_INCLUDE_DIRS})
+    list(APPEND COMMON_SOURCES refdata.cpp)
+    set(TESTUTILS_HAVE_REFDATA TRUE)
+endif ()
+
+add_library(testutils STATIC ${COMMON_SOURCES})
+set(TESTUTILS_LIBS testutils)
+target_link_libraries(testutils libgromacs)
+if (GMX_USE_GTEST AND LIBXML2_FOUND)
+    list(APPEND TESTUTILS_LIBS ${GTEST_LIBRARIES} ${LIBXML2_LIBRARIES})
+    target_link_libraries(testutils ${GTEST_LIBRARIES} ${LIBXML2_LIBRARIES})
+endif ()
+
+set(TESTUTILS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(TESTUTILS_DIR ${TESTUTILS_DIR} PARENT_SCOPE)
+set(TESTUTILS_LIBS ${TESTUTILS_LIBS} PARENT_SCOPE)
+set(TESTUTILS_HAVE_REFDATA ${TESTUTILS_HAVE_REFDATA} PARENT_SCOPE)
+
+add_subdirectory(tests)
diff --git a/src/testutils/TestMacros.cmake b/src/testutils/TestMacros.cmake
new file mode 100644 (file)
index 0000000..9e1f8f7
--- /dev/null
@@ -0,0 +1,50 @@
+function (add_gtest_test NAME EXENAME)
+    if (GMX_USE_GTEST AND BUILD_TESTING)
+        include_directories(${GTEST_INCLUDE_DIRS})
+        add_executable(${EXENAME} ${ARGN} ${TESTUTILS_DIR}/test_main_gtest.cpp)
+        target_link_libraries(${EXENAME} libgromacs ${TESTUTILS_LIBS} ${GTEST_LIBRARIES})
+        get_target_property(DEFS ${EXENAME} COMPILE_DEFINITIONS)
+        if (NOT DEFS)
+            set(DEFS)
+        endif ()
+        list(APPEND DEFS TEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}")
+        set_target_properties(${EXENAME} PROPERTIES COMPILE_DEFINITIONS ${DEFS})
+        add_test(NAME ${NAME}
+                 COMMAND ${EXENAME})
+    endif ()
+endfunction ()
+
+function (add_gmock_test NAME EXENAME)
+    if (GMX_USE_GMOCK AND BUILD_TESTING)
+        include_directories(${GMOCK_INCLUDE_DIRS})
+        add_executable(${EXENAME} ${ARGN} ${TESTUTILS_DIR}/test_main_gmock.cpp)
+        target_link_libraries(${EXENAME} libgromacs ${TESTUTILS_LIBS} ${GMOCK_LIBRARIES})
+        get_target_property(DEFS ${EXENAME} COMPILE_DEFINITIONS)
+        if (NOT DEFS)
+            set(DEFS)
+        endif ()
+        list(APPEND DEFS TEST_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}")
+        set_target_properties(${EXENAME} PROPERTIES COMPILE_DEFINITIONS ${DEFS})
+        add_test(NAME ${NAME}
+                 COMMAND ${EXENAME})
+    endif ()
+endfunction ()
+
+function (add_gtest_or_gmock_test NAME EXENAME)
+    if (GMX_USE_GTEST AND BUILD_TESTING)
+        set(_outvar GTEST_SOURCES)
+        foreach(_source IN ITEMS ${ARGN})
+            if (_source STREQUAL GMOCK_ONLY)
+                set(_outvar GMOCK_SOURCES)
+            else ()
+                list(APPEND ${_outvar} ${_source})
+            endif ()
+        endforeach()
+        if (GMX_USE_GMOCK)
+            set(SOURCES ${GTEST_SOURCES} ${GMOCK_SOURCES})
+            add_gmock_test(${NAME} ${EXENAME} ${SOURCES})
+        else ()
+            add_gtest_test(${NAME} ${EXENAME} ${GTEST_SOURCES})
+        endif ()
+    endif ()
+endfunction ()
diff --git a/src/testutils/datapath.cpp b/src/testutils/datapath.cpp
new file mode 100644 (file)
index 0000000..8e4cd31
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in datapath.h.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_testutils
+ */
+#include "datapath.h"
+
+#include <cassert>
+
+#include "gromacs/utility/path.h"
+
+static const char *g_testDataPath = NULL;
+
+namespace gmx
+{
+namespace test
+{
+
+std::string getTestFilePath(const char *filename)
+{
+    return Path::join(getTestDataPath(), filename);
+}
+
+const char *getTestDataPath()
+{
+    assert(g_testDataPath != NULL || !"Test data path not set");
+    return g_testDataPath;
+}
+
+void setTestDataPath(const char *path)
+{
+    assert(Directory::exists(path));
+    g_testDataPath = path;
+}
+
+} // namespace test
+} // namespace gmx
diff --git a/src/testutils/datapath.h b/src/testutils/datapath.h
new file mode 100644 (file)
index 0000000..4e54698
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Functions for accessing test input files.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+#ifndef GMX_TESTUTILS_DATAPATH_H
+#define GMX_TESTUTILS_DATAPATH_H
+
+#include <string>
+
+namespace gmx
+{
+/*! \libinternal \brief
+ * Namespace for unit testing utilities.
+ *
+ * \ingroup module_testutils
+ */
+namespace test
+{
+
+/*! \libinternal \brief
+ * Returns the path to a test input file.
+ *
+ * \inlibraryapi
+ */
+std::string getTestFilePath(const char *filename);
+/*! \libinternal \brief
+ * Returns the path to the test input directory.
+ *
+ * \inlibraryapi
+ */
+const char *getTestDataPath();
+/*! \libinternal \brief
+ * Sets the test input directory.
+ *
+ * \inlibraryapi
+ */
+void setTestDataPath(const char *path);
+
+/*!\}*/
+
+} // namespace test
+} // namespace gmx
+
+#endif
diff --git a/src/testutils/refdata-common.cpp b/src/testutils/refdata-common.cpp
new file mode 100644 (file)
index 0000000..37b27d9
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements functions in refdata.h that don't have external dependencies.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_testutils
+ */
+#include "refdata.h"
+
+#include <cstring>
+
+#include "testutils/datapath.h"
+
+namespace gmx
+{
+namespace test
+{
+
+static ReferenceDataMode g_referenceDataMode = erefdataCompare;
+
+
+ReferenceDataMode getReferenceDataMode()
+{
+    return g_referenceDataMode;
+}
+
+
+void setReferenceDataMode(ReferenceDataMode mode)
+{
+    g_referenceDataMode = mode;
+}
+
+
+std::string getReferenceDataPath()
+{
+    return getTestFilePath("refdata");
+}
+
+
+int initReferenceData(int *argc, char **argv)
+{
+    int i, newi;
+
+    for (i = newi = 1; i < *argc; ++i, ++newi)
+    {
+        argv[newi] = argv[i];
+        if (!std::strcmp(argv[i], "--create-ref-data"))
+        {
+            setReferenceDataMode(erefdataCreateMissing);
+            --newi;
+        }
+        else if (!std::strcmp(argv[i], "--update-ref-data"))
+        {
+            setReferenceDataMode(erefdataUpdateAll);
+            --newi;
+        }
+    }
+    *argc = newi;
+
+    return 0;
+}
+
+} // namespace test
+} // namespace gmx
diff --git a/src/testutils/refdata-impl.h b/src/testutils/refdata-impl.h
new file mode 100644 (file)
index 0000000..15629ec
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Declares private implementation class for gmx::test::TestReferenceData.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_testutils
+ */
+#ifndef GMX_TESTUTILS_REFDATA_IMPL_H
+#define GMX_TESTUTILS_REFDATA_IMPL_H
+
+#include <string>
+
+#include <libxml/parser.h>
+
+#include "testutils/refdata.h"
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \internal \brief
+ * Private implementation class for TestReferenceData.
+ *
+ * \ingroup module_testutils
+ */
+class TestReferenceData::Impl
+{
+    public:
+        static const xmlChar * const cXmlVersion;
+        static const xmlChar * const cRootNodeName;
+
+        explicit Impl(ReferenceDataMode mode);
+        ~Impl();
+
+        //! Full path of the reference data file.
+        std::string             _fullFilename;
+        /*! \brief
+         * XML document for the reference data.
+         *
+         * May be NULL if there was an I/O error in initialization.
+         */
+        xmlDocPtr               _refDoc;
+        /*! \brief
+         * Whether the reference data is being written (true) or compared
+         * (false).
+         */
+        bool                    _bWrite;
+        /*! \brief
+         * Whether any reference checkers have been created for this data.
+         */
+        bool                    _bInUse;
+};
+
+
+/*! \internal \brief
+ * Private implementation class for TestReferenceChecker.
+ *
+ * \ingroup module_testutils
+ */
+class TestReferenceChecker::Impl
+{
+    public:
+        static const xmlChar * const cCompoundNodeName;
+        static const xmlChar * const cBooleanNodeName;
+        static const xmlChar * const cStringNodeName;
+        static const xmlChar * const cIntegerNodeName;
+        static const xmlChar * const cRealNodeName;
+        static const xmlChar * const cVectorIntegerNodeName;
+        static const xmlChar * const cVectorRealNodeName;
+        static const xmlChar * const cIdAttrName;
+        static const xmlChar * const cCompoundTypeAttrName;
+        static const char * const cSequenceIntegerType;
+        static const char * const cSequenceRealType;
+        static const char * const cSequenceVectorType;
+        static const char * const cSequenceLengthName;
+
+        Impl(xmlNodePtr rootNode, bool bWrite);
+
+        xmlNodePtr findOrCreateNode(const xmlChar *name, const char *id);
+        std::string processItem(const xmlChar *name, const char *id,
+                                const char *value, bool *bFound);
+        std::string processItem(const xmlChar *name, const char *id,
+                                const std::string &value, bool *bFound);
+        bool shouldIgnore() const;
+
+        /*! \brief
+         * Current node under which reference data is searched.
+         *
+         * Points to either the root of TestReferenceData::Impl::_refDoc, or to
+         * a compound node.
+         *
+         * Can be NULL, in which case this checker does nothing (doesn't even
+         * report errors).
+         */
+        xmlNodePtr              _currNode;
+        /*! \brief
+         * Points to a child of \a _currNode where the next search should start.
+         *
+         * On initialization, points to the first child of \a _currNode.  After
+         * every check, is updated to point to the node following the one
+         * found, with possible wrapping.
+         *
+         * Is NULL if and only if \a _currNode contains no children.
+         * Otherwise, always points to a direct child of \a _currNode.
+         */
+        xmlNodePtr              _nextSearchNode;
+        /*! \brief
+         * Whether the reference data is being written (true) or compared
+         * (false).
+         */
+        bool                    _bWrite;
+};
+
+} // namespace test
+} // namespace gmx
+
+#endif
diff --git a/src/testutils/refdata.cpp b/src/testutils/refdata.cpp
new file mode 100644 (file)
index 0000000..240354c
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::test::TestReferenceData.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_testutils
+ */
+#include "refdata.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <string>
+
+#include <gtest/gtest.h>
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+
+#include "gromacs/fatalerror/exceptions.h"
+#include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/utility/path.h"
+#include "testutils/testexceptions.h"
+
+#include "refdata-impl.h"
+
+namespace gmx
+{
+namespace test
+{
+
+/********************************************************************
+ * TestReferenceData::Impl
+ */
+
+const xmlChar * const TestReferenceData::Impl::cXmlVersion =
+    (const xmlChar *)"1.0";
+const xmlChar * const TestReferenceData::Impl::cRootNodeName =
+    (const xmlChar *)"ReferenceData";
+const xmlChar * const TestReferenceChecker::Impl::cCompoundNodeName =
+    (const xmlChar *)"Compound";
+const xmlChar * const TestReferenceChecker::Impl::cBooleanNodeName =
+    (const xmlChar *)"Bool";
+const xmlChar * const TestReferenceChecker::Impl::cStringNodeName =
+    (const xmlChar *)"String";
+const xmlChar * const TestReferenceChecker::Impl::cIntegerNodeName  =
+    (const xmlChar *)"Int";
+const xmlChar * const TestReferenceChecker::Impl::cRealNodeName =
+    (const xmlChar *)"Real";
+const xmlChar * const TestReferenceChecker::Impl::cVectorIntegerNodeName =
+    (const xmlChar *)"Vector";
+const xmlChar * const TestReferenceChecker::Impl::cVectorRealNodeName =
+    (const xmlChar *)"Vector";
+const xmlChar * const TestReferenceChecker::Impl::cIdAttrName =
+    (const xmlChar *)"Name";
+const xmlChar * const TestReferenceChecker::Impl::cCompoundTypeAttrName =
+    (const xmlChar *)"Subtype";
+const char * const TestReferenceChecker::Impl::cSequenceIntegerType =
+    "SequenceInteger";
+const char * const TestReferenceChecker::Impl::cSequenceRealType =
+    "SequenceReal";
+const char * const TestReferenceChecker::Impl::cSequenceVectorType =
+    "SequenceVector";
+const char * const TestReferenceChecker::Impl::cSequenceLengthName =
+    "Length";
+
+
+TestReferenceData::Impl::Impl(ReferenceDataMode mode)
+    : _refDoc(NULL), _bWrite(false), _bInUse(false)
+{
+    const ::testing::TestInfo *test_info =
+        ::testing::UnitTest::GetInstance()->current_test_info();
+    std::string dirname = getReferenceDataPath();
+    std::string filename = std::string(test_info->test_case_name())
+        + "_" + test_info->name() + ".xml";
+    _fullFilename = Path::join(dirname, filename);
+
+    _bWrite = true;
+    if (mode != erefdataUpdateAll)
+    {
+        FILE *fp = std::fopen(_fullFilename.c_str(), "r");
+        if (fp != NULL)
+        {
+            _bWrite = false;
+            fclose(fp);
+        }
+        else if (mode == erefdataCompare)
+        {
+            _bWrite = false;
+            return;
+        }
+    }
+    if (_bWrite)
+    {
+        // TODO: Error checking
+        _refDoc = xmlNewDoc(cXmlVersion);
+        xmlNodePtr rootNode = xmlNewDocNode(_refDoc, NULL, cRootNodeName, NULL);
+        xmlDocSetRootElement(_refDoc, rootNode);
+    }
+    else
+    {
+        _refDoc = xmlParseFile(_fullFilename.c_str());
+        if (_refDoc == NULL)
+        {
+            GMX_THROW(TestException("Reference data not parsed successfully: " + _fullFilename));
+        }
+        xmlNodePtr rootNode = xmlDocGetRootElement(_refDoc);
+        if (rootNode == NULL)
+        {
+            xmlFreeDoc(_refDoc);
+            GMX_THROW(TestException("Reference data is empty: " + _fullFilename));
+        }
+        if (xmlStrcmp(rootNode->name, cRootNodeName) != 0)
+        {
+            xmlFreeDoc(_refDoc);
+            GMX_THROW(TestException("Invalid root node type in " + _fullFilename));
+        }
+    }
+}
+
+
+TestReferenceData::Impl::~Impl()
+{
+    if (_bWrite && _bInUse && _refDoc != NULL)
+    {
+        std::string dirname = getReferenceDataPath();
+        if (!Directory::exists(dirname))
+        {
+            if (Directory::create(dirname) != 0)
+            {
+                ADD_FAILURE() << "Creation of reference data directory failed for " << dirname;
+            }
+        }
+        if (xmlSaveFormatFile(_fullFilename.c_str(), _refDoc, 1) == -1)
+        {
+            ADD_FAILURE() << "Saving reference data failed for " + _fullFilename;
+        }
+    }
+    if (_refDoc != NULL)
+    {
+        xmlFreeDoc(_refDoc);
+    }
+}
+
+
+/********************************************************************
+ * TestReferenceChecker::Impl
+ */
+
+TestReferenceChecker::Impl::Impl(xmlNodePtr rootNode, bool bWrite)
+    : _currNode(rootNode),
+      _nextSearchNode(rootNode != NULL ? rootNode->xmlChildrenNode : NULL),
+      _bWrite(bWrite)
+{
+}
+
+
+xmlNodePtr
+TestReferenceChecker::Impl::findOrCreateNode(const xmlChar *name, const char *id)
+{
+    const xmlChar *xmlId = reinterpret_cast<const xmlChar *>(id);
+    xmlNodePtr node = _nextSearchNode;
+    while (node != NULL && node->next != _nextSearchNode)
+    {
+        if (xmlStrcmp(node->name, name) == 0)
+        {
+            xmlChar *refId = xmlGetProp(node, cIdAttrName);
+            if (xmlId == NULL && refId == NULL)
+            {
+                break;
+            }
+            if (refId != NULL)
+            {
+                if (xmlId != NULL && xmlStrcmp(refId, xmlId) == 0)
+                {
+                    xmlFree(refId);
+                    break;
+                }
+                xmlFree(refId);
+            }
+        }
+        node = node->next;
+        if (node == NULL && _nextSearchNode != _currNode->xmlChildrenNode)
+        {
+            node = _currNode->xmlChildrenNode;
+        }
+    }
+    if (node == NULL || node->next == _nextSearchNode)
+    {
+        if (_bWrite)
+        {
+            node = xmlNewTextChild(_currNode, NULL, name, NULL);
+            if (node != NULL && xmlId != NULL)
+            {
+                xmlAttrPtr prop = xmlNewProp(node, cIdAttrName, xmlId);
+                if (prop == NULL)
+                {
+                    xmlFreeNode(node);
+                    node = NULL;
+                }
+            }
+            if (node == NULL)
+            {
+                GMX_THROW(TestException("XML node creation failed"));
+            }
+        }
+        else
+        {
+            node = NULL;
+        }
+    }
+    else
+    {
+        _nextSearchNode = node->next;
+        if (_nextSearchNode == NULL)
+        {
+            _nextSearchNode = _currNode->xmlChildrenNode;
+        }
+    }
+    return node;
+}
+
+
+std::string
+TestReferenceChecker::Impl::processItem(const xmlChar *name, const char *id,
+                                        const char *value, bool *bFound)
+{
+    *bFound = false;
+    xmlNodePtr node = findOrCreateNode(name, id);
+    if (node == NULL)
+    {
+        GMX_RELEASE_ASSERT(!_bWrite, "Node creation failed without exception");
+        ADD_FAILURE() << "Reference data item not found";
+        return std::string();
+    }
+    *bFound = true;
+    if (_bWrite)
+    {
+        xmlNodeAddContent(node, reinterpret_cast<const xmlChar *>(value));
+        return std::string(value);
+    }
+    else
+    {
+        xmlChar *refXmlValue = xmlNodeGetContent(node);
+        std::string refValue(reinterpret_cast<const char *>(refXmlValue));
+        xmlFree(refXmlValue);
+        return refValue;
+    }
+}
+
+
+std::string
+TestReferenceChecker::Impl::processItem(const xmlChar *name, const char *id,
+                                        const std::string &value, bool *bFound)
+{
+    return processItem(name, id, value.c_str(), bFound);
+}
+
+
+bool
+TestReferenceChecker::Impl::shouldIgnore() const
+{
+    return _currNode == NULL;
+}
+
+
+/********************************************************************
+ * TestReferenceData
+ */
+
+TestReferenceData::TestReferenceData()
+    : _impl(new Impl(getReferenceDataMode()))
+{
+}
+
+
+TestReferenceData::TestReferenceData(ReferenceDataMode mode)
+    : _impl(new Impl(mode))
+{
+}
+
+
+TestReferenceData::~TestReferenceData()
+{
+    delete _impl;
+}
+
+
+bool TestReferenceData::isWriteMode() const
+{
+    return _impl->_bWrite;
+}
+
+
+TestReferenceChecker TestReferenceData::rootChecker()
+{
+    if (!isWriteMode() && !_impl->_bInUse && _impl->_refDoc == NULL)
+    {
+        ADD_FAILURE() << "Reference data file not found: "
+                      << _impl->_fullFilename;
+    }
+    _impl->_bInUse = true;
+    xmlNodePtr rootNode =
+        _impl->_refDoc != NULL ? xmlDocGetRootElement(_impl->_refDoc) : NULL;
+    return TestReferenceChecker(new TestReferenceChecker::Impl(rootNode, isWriteMode()));
+}
+
+
+/********************************************************************
+ * TestReferenceChecker
+ */
+
+TestReferenceChecker::TestReferenceChecker(Impl *impl)
+    : _impl(impl)
+{
+}
+
+
+TestReferenceChecker::TestReferenceChecker(const TestReferenceChecker &other)
+    : _impl(new Impl(*other._impl))
+{
+}
+
+
+TestReferenceChecker &
+TestReferenceChecker::operator =(const TestReferenceChecker &other)
+{
+    Impl *newImpl = new Impl(*other._impl);
+    std::swap(_impl, newImpl);
+    delete newImpl;
+    return *this;
+}
+
+
+TestReferenceChecker::~TestReferenceChecker()
+{
+    delete _impl;
+}
+
+
+bool TestReferenceChecker::isWriteMode() const
+{
+    return _impl->_bWrite;
+}
+
+
+TestReferenceChecker TestReferenceChecker::checkCompound(const char *type, const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return TestReferenceChecker(new Impl(NULL, isWriteMode()));
+    }
+    xmlNodePtr newNode = _impl->findOrCreateNode(Impl::cCompoundNodeName, id);
+    if (newNode == NULL)
+    {
+        GMX_RELEASE_ASSERT(!isWriteMode(), "Node creation failed without exception");
+        ADD_FAILURE() << "Reference data item not found";
+        return TestReferenceChecker(new Impl(NULL, isWriteMode()));
+    }
+    if (isWriteMode())
+    {
+        if (xmlNewProp(newNode, Impl::cCompoundTypeAttrName,
+                       reinterpret_cast<const xmlChar *>(type)) == NULL)
+        {
+            GMX_THROW(TestException("XML property creation failed"));
+        }
+    }
+    return TestReferenceChecker(new Impl(newNode, isWriteMode()));
+}
+
+
+void TestReferenceChecker::checkBoolean(bool value, const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    const char *strValue = value ? "true" : "false";
+    std::string refStrValue =
+        _impl->processItem(Impl::cBooleanNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        EXPECT_EQ(refStrValue, strValue);
+    }
+}
+
+
+void TestReferenceChecker::checkString(const char *value, const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    std::string refStrValue =
+        _impl->processItem(Impl::cStringNodeName, id, value, &bFound);
+    if (bFound)
+    {
+        EXPECT_EQ(refStrValue, value);
+    }
+}
+
+
+void TestReferenceChecker::checkString(const std::string &value, const char *id)
+{
+    checkString(value.c_str(), id);
+}
+
+
+void TestReferenceChecker::checkInteger(int value, const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    char strValue[20];
+    snprintf(strValue, 20, "%d", value);
+    std::string refStrValue =
+        _impl->processItem(Impl::cIntegerNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        EXPECT_EQ(refStrValue, strValue);
+    }
+}
+
+
+void TestReferenceChecker::checkDouble(double value, const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    char strValue[20];
+    snprintf(strValue, 20, "%f", value);
+    std::string refStrValue =
+        _impl->processItem(Impl::cRealNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        char *endptr = NULL;
+        double refValue = std::strtof(refStrValue.c_str(), &endptr);
+        EXPECT_EQ('\0', *endptr);
+        EXPECT_NEAR(refValue, value, 0.0001);
+    }
+}
+
+
+void TestReferenceChecker::checkFloat(float value, const char *id)
+{
+    checkDouble(value, id);
+}
+
+
+void TestReferenceChecker::checkReal(float value, const char *id)
+{
+    checkDouble(value, id);
+}
+
+
+void TestReferenceChecker::checkReal(double value, const char *id)
+{
+    checkDouble(value, id);
+}
+
+
+void TestReferenceChecker::checkVector(const int value[3], const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    char strValue[50];
+    snprintf(strValue, 50, "%d %d %d", value[0], value[1], value[2]);
+    std::string refStrValue =
+        _impl->processItem(Impl::cVectorIntegerNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        EXPECT_EQ(refStrValue, strValue);
+    }
+}
+
+
+void TestReferenceChecker::checkVector(const float value[3], const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    char strValue[50];
+    snprintf(strValue, 50, "%f %f %f", value[0], value[1], value[2]);
+    std::string refStrValue =
+        _impl->processItem(Impl::cVectorRealNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        float refX, refY, refZ;
+        int count = std::sscanf(refStrValue.c_str(), " %g %g %g", &refX, &refY, &refZ);
+        if (count != 3)
+        {
+            GMX_THROW(TestException("Corrupt reference vector data"));
+        }
+        EXPECT_NEAR(refX, value[0], 0.0001);
+        EXPECT_NEAR(refY, value[1], 0.0001);
+        EXPECT_NEAR(refZ, value[2], 0.0001);
+    }
+}
+
+
+void TestReferenceChecker::checkVector(const double value[3], const char *id)
+{
+    if (_impl->shouldIgnore())
+    {
+        return;
+    }
+    bool bFound = false;
+    char strValue[50];
+    snprintf(strValue, 50, "%f %f %f", value[0], value[1], value[2]);
+    std::string refStrValue =
+        _impl->processItem(Impl::cVectorRealNodeName, id, strValue, &bFound);
+    if (bFound)
+    {
+        double refX, refY, refZ;
+        int count = std::sscanf(refStrValue.c_str(), " %lg %lg %lg", &refX, &refY, &refZ);
+        if (count != 3)
+        {
+            GMX_THROW(TestException("Corrupt reference vector data"));
+        }
+        EXPECT_NEAR(refX, value[0], 0.0001);
+        EXPECT_NEAR(refY, value[1], 0.0001);
+        EXPECT_NEAR(refZ, value[2], 0.0001);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const int *values,
+                                              const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceIntegerType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkInteger(values[i], NULL);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const float *values,
+                                              const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceRealType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkFloat(values[i], NULL);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const double *values,
+                                              const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceRealType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkDouble(values[i], NULL);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const int values[][3],
+                                              const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceVectorType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkVector(values[i], NULL);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const float values[][3],
+                                              const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceVectorType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkVector(values[i], NULL);
+    }
+}
+
+
+void TestReferenceChecker::checkSequenceArray(size_t length, const double values[][3],
+                                             const char *id)
+{
+    TestReferenceChecker compound(checkCompound(Impl::cSequenceVectorType, id));
+    compound.checkInteger(static_cast<int>(length), Impl::cSequenceLengthName);
+    for (size_t i = 0; i < length; ++i)
+    {
+        compound.checkVector(values[i], NULL);
+    }
+}
+
+} // namespace test
+} // namespace gmx
diff --git a/src/testutils/refdata.h b/src/testutils/refdata.h
new file mode 100644 (file)
index 0000000..37ba8a8
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Functionality for writing tests that can produce their own reference data.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+#ifndef GMX_TESTUTILS_REFDATA_H
+#define GMX_TESTUTILS_REFDATA_H
+
+#include <string>
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \libinternal \brief
+ * Mode of operation for reference data handling.
+ *
+ * There should be no need to use this type outside the test utility module.
+ */
+enum ReferenceDataMode
+{
+    /*! \brief
+     * Compare to existing reference data.
+     *
+     * If reference data does not exist, or if the test results differ from
+     * those in the reference data, the test fails.
+     */
+    erefdataCompare,
+    /*! \brief
+     * Create missing reference data.
+     *
+     * If reference data does not exist for a test, that test behaves as if
+     * ::erefdataUpdateAll had been specified.  Tests for which reference data
+     * exists, behave like with ::erefdataCompare.
+     */
+    erefdataCreateMissing,
+    /*! \brief
+     * Update reference data, overwriting old data.
+     *
+     * Tests utilizing reference data should always pass in this mode unless
+     * there is an I/O error.
+     */
+    erefdataUpdateAll
+};
+
+/*! \libinternal \brief
+ * Returns the global reference data mode.
+ *
+ * There should be no need to use this function outside the test utility module.
+ */
+ReferenceDataMode getReferenceDataMode();
+/*! \libinternal \brief
+ * Sets the global reference data mode.
+ *
+ * There should be no need to use this function outside the test utility module.
+ */
+void setReferenceDataMode(ReferenceDataMode mode);
+/*! \libinternal \brief
+ * Returns the directory where reference data files are stored.
+ *
+ * There should be no need to use this function outside the test utility module.
+ */
+std::string getReferenceDataPath();
+/*! \libinternal \brief
+ * Initializes reference data handling.
+ *
+ * Sets the reference data mode based on command-line arguments.  By default,
+ * ::erefdataCompare is used, but \c --create-ref-data or \c --update-ref-data
+ * can be used to change it.
+ * Recognized command-line arguments are removed from the list.
+ *
+ * Also creates the directory for storing the reference data.
+ *
+ * This function is automatically called by test_main_gtest.cpp and
+ * test_main_gmock.cpp.
+ */
+int initReferenceData(int *argc, char **argv);
+
+class TestReferenceChecker;
+
+/*! \libinternal \brief
+ * Handles creation of and comparison to test reference data.
+ *
+ * This class provides functionality to use the same code to generate reference
+ * data and then on later runs compare the results of the code against that
+ * reference.  The mode in which the class operates (writing reference data or
+ * comparing against existing data) is set with parseReferenceDataArgs(), which
+ * is automatically called when using the testutils module to implement tests.
+ * Tests only need to create an instance of TestReferenceData, obtain a
+ * TestReferenceChecker using the rootChecker() method and use the various
+ * check*() methods in TestReferenceChecker to indicate values to check.  If
+ * the test is running in reference data creation mode, it will produce an XML
+ * file with the values recorder.  In comparison mode, it will read that same
+ * XML file and produce a Google Test non-fatal assertion for every discrepancy
+ * it detects with the reference data (including missing reference data file or
+ * individual item).  Exceptions derived from TestException are thrown for I/O
+ * errors and syntax errors in the reference data.
+ *
+ * Simple example (using Google Test):
+ * \code
+int functionToTest(int param);
+
+TEST(MyTest, SimpleTest)
+{
+    gmx::test::TestReferenceData data;
+
+    gmx::test::TestReferenceChecker checker(data.rootChecker());
+    checker.checkInteger(functionToTest(3), "ValueWith3");
+    checker.checkInteger(functionToTest(5), "ValueWith5");
+    gmx::test::TestReferenceChecker compound(checker.startCompound("CustomCompound", "Item"));
+    compound.checkInteger(function2ToTest(3), "ValueWith3");
+    compound.checkInteger(function2ToTest(5), "ValueWith5");
+    checker.checkInteger(functionToTest(4), "ValueWith4");
+}
+ * \endcode
+ *
+ * If rootChecker() is never called, no comparison is done (i.e., missing
+ * reference data file is not reported as an error, nor is empty reference data
+ * file created in write mode).
+ *
+ * This class is only available if both Google Test and libxml2 are enabled.
+ * If either one is missing, trying to use this class will result in unresolved
+ * symbols in linking.
+ *
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+class TestReferenceData
+{
+    public:
+        /*! \brief
+         * Initializes the reference data in the global mode.
+         */
+        TestReferenceData();
+        /*! \brief
+         * Initializes the reference data in a specific mode.
+         *
+         * This function is mainly useful for self-testing the reference data
+         * framework.
+         * The default constructor should be used in tests utilizing this class.
+         */
+        explicit TestReferenceData(ReferenceDataMode mode);
+        /*! \brief
+         * Frees reference data structures.
+         *
+         * In the current implementation, this function writes the reference
+         * data out if necessary.
+         */
+        ~TestReferenceData();
+
+        //! Returns true if reference data is currently being written.
+        bool isWriteMode() const;
+
+        /*! \brief
+         * Returns a root-level checker object for comparisons.
+         *
+         * Each call returns an independent instance.
+         */
+        TestReferenceChecker rootChecker();
+
+    private:
+        class Impl;
+
+        Impl                   *_impl;
+
+        // Disallow copy and assign.
+        TestReferenceData(const TestReferenceData &);
+        void operator =(const TestReferenceData &);
+};
+
+/*! \libinternal \brief
+ * Handles comparison to test reference data.
+ *
+ * Every check*() method takes an id string as the last parameter.  This id is
+ * used to uniquely identify the value in the reference data, and it makes the
+ * output XML more human-friendly and more robust to errors.  The id can be
+ * NULL; in this case, multiple elements with no id are created, and they will
+ * be matched in the same order as in which they are created.  The
+ * checkCompound() method can be used to create a set of reference values
+ * grouped together.  In this case, all check*() calls using the returned child
+ * TestReferenceChecker object will create the reference data within this
+ * group, and the ids only need to be unique within the compound.  Compounds
+ * can be nested.
+ *
+ * For usage example, see TestReferenceData.
+ *
+ * Copies of this class behave have independent internal state.
+ *
+ * This class is only available if both Google Test and libxml2 are enabled.
+ * If either one is missing, trying to use this class will result in unresolved
+ * symbols in linking.
+ *
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+class TestReferenceChecker
+{
+    public:
+        /*! \brief
+         * Creates a deep copy of the other checker.
+         */
+        TestReferenceChecker(const TestReferenceChecker &other);
+        ~TestReferenceChecker();
+
+        TestReferenceChecker &operator =(const TestReferenceChecker &other);
+
+        //! Returns true if reference data is currently being written.
+        bool isWriteMode() const;
+
+        /*! \brief
+         * Initializes comparison of a group of related data items.
+         *
+         * \param[in] type Informational type for the compound.
+         * \param[in] id   Unique identifier for the compound among its
+         *                 siblings.
+         * \returns   Checker to use for comparison within the compound.
+         *
+         * All checks performed with the returned checker only
+         * need to have unique ids within the compound, not globally.
+         *
+         * Compound structures can be nested.
+         */
+        TestReferenceChecker checkCompound(const char *type, const char *id);
+
+        //! Check a single boolean value.
+        void checkBoolean(bool value, const char *id);
+        //! Check a single string value.
+        void checkString(const char *value, const char *id);
+        //! Check a single string value.
+        void checkString(const std::string &value, const char *id);
+        //! Check a single integer value.
+        void checkInteger(int value, const char *id);
+        //! Check a single single-precision floating point value.
+        void checkFloat(float value, const char *id);
+        //! Check a single double-precision floating point value.
+        void checkDouble(double value, const char *id);
+        //! Check a single floating point value.
+        void checkReal(float value, const char *id);
+        //! Check a single floating point value.
+        void checkReal(double value, const char *id);
+        //! Check a vector of three integer values.
+        void checkVector(const int value[3], const char *id);
+        //! Check a vector of three single-precision floating point values.
+        void checkVector(const float value[3], const char *id);
+        //! Check a vector of three double-precision floating point values.
+        void checkVector(const double value[3], const char *id);
+        //! Check an arbitrary-length sequence of integer values.
+        void checkSequenceArray(size_t length, const int *values,
+                                const char *id);
+        //! Check an arbitrary-length sequence of floating-point values.
+        void checkSequenceArray(size_t length, const float *values,
+                                const char *id);
+        //! Check an arbitrary-length sequence of floating-point values.
+        void checkSequenceArray(size_t length, const double *values,
+                                const char *id);
+        //! Check an arbitrary-length sequence of integer vector values.
+        void checkSequenceArray(size_t length, const int values[][3],
+                                const char *id);
+        //! Check an arbitrary-length sequence of floating-point vector values.
+        void checkSequenceArray(size_t length, const float values[][3],
+                                const char *id);
+        //! Check an arbitrary-length sequence of floating-point vector values.
+        void checkSequenceArray(size_t length, const double values[][3],
+                                const char *id);
+
+    private:
+        class Impl;
+
+        /*! \brief
+         * Constructs a checker with a specific internal state.
+         *
+         * Is private to only allow users of this class to create instances
+         * using TestReferenceData::rootChecker() or checkCompound()
+         * (or by copying).
+         */
+        explicit TestReferenceChecker(Impl *impl);
+
+        Impl                   *_impl;
+
+        /*! \brief
+         * Needed to expose the constructor only to TestReferenceData.
+         */
+        friend class TestReferenceData;
+};
+
+} // namespace test
+} // namespace gmx
+
+#endif
diff --git a/src/testutils/test_main_gmock.cpp b/src/testutils/test_main_gmock.cpp
new file mode 100644 (file)
index 0000000..8b2ac90
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * main() for unit tests that use Google C++ Mocking Framework.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#include <gmock/gmock.h>
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "testutils/datapath.h"
+#include "testutils/refdata.h"
+
+/*! \brief
+ * Initializes unit testing with Google C++ Mocking Framework.
+ */
+int main(int argc, char *argv[])
+{
+    ::testing::InitGoogleMock(&argc, argv);
+#ifdef TEST_DATA_PATH
+    ::gmx::test::setTestDataPath(TEST_DATA_PATH);
+    if (::gmx::test::initReferenceData(&argc, argv) != 0)
+    {
+        return 1;
+    }
+#endif
+    ::gmx::setFatalErrorHandler(NULL);
+    return RUN_ALL_TESTS();
+}
diff --git a/src/testutils/test_main_gtest.cpp b/src/testutils/test_main_gtest.cpp
new file mode 100644 (file)
index 0000000..b275a1b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * main() for unit tests that use Google C++ Testing Framework.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ */
+#include <gtest/gtest.h>
+
+#include "gromacs/fatalerror/errorcodes.h"
+#include "testutils/datapath.h"
+#include "testutils/refdata.h"
+
+/*! \brief
+ * Initializes unit testing with Google C++ Testing Framework.
+ */
+int main(int argc, char *argv[])
+{
+    ::testing::InitGoogleTest(&argc, argv);
+#ifdef TEST_DATA_PATH
+    ::gmx::test::setTestDataPath(TEST_DATA_PATH);
+    if (::gmx::test::initReferenceData(&argc, argv) != 0)
+    {
+        return 1;
+    }
+#endif
+    ::gmx::setFatalErrorHandler(NULL);
+    return RUN_ALL_TESTS();
+}
diff --git a/src/testutils/testexceptions.h b/src/testutils/testexceptions.h
new file mode 100644 (file)
index 0000000..8192ad9
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \libinternal \file
+ * \brief
+ * Exception classes for errors in tests.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+#ifndef GMX_TESTUTILS_TESTEXCEPTIONS_H
+#define GMX_TESTUTILS_TESTEXCEPTIONS_H
+
+#include <string>
+
+#include "gromacs/fatalerror/exceptions.h"
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \libinternal \brief
+ * Exception class for reporting errors in tests.
+ *
+ * \ingroup module_testutils
+ */
+class TestException : public GromacsException
+{
+    public:
+        explicit TestException(const std::string &reason)
+            : GromacsException(reason) {}
+
+        virtual int errorCode() const { return -1; }
+};
+
+} // namespace test
+} // namespace gmx
+
+#endif
+
diff --git a/src/testutils/tests/.gitignore b/src/testutils/tests/.gitignore
new file mode 100644 (file)
index 0000000..8d1061e
--- /dev/null
@@ -0,0 +1,2 @@
+testutils-test
+refdata
diff --git a/src/testutils/tests/CMakeLists.txt b/src/testutils/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..52d1f2a
--- /dev/null
@@ -0,0 +1,4 @@
+if (TESTUTILS_HAVE_REFDATA)
+    add_gtest_test(TestUtilsUnitTests testutils-test
+                   refdata.cpp)
+endif (TESTUTILS_HAVE_REFDATA)
diff --git a/src/testutils/tests/refdata.cpp b/src/testutils/tests/refdata.cpp
new file mode 100644 (file)
index 0000000..3aafd4c
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * 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.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief
+ * Tests utilities for test reference data.
+ *
+ * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \ingroup module_testutils
+ */
+#include <vector>
+
+#include <gtest/gtest.h>
+#include <gtest/gtest-spi.h>
+
+#include "testutils/refdata.h"
+
+namespace
+{
+
+TEST(ReferenceDataTest, HandlesSimpleData)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkBoolean(true, "int");
+        checker.checkInteger(1, "int");
+        checker.checkDouble(0.5, "real");
+        checker.checkString("Test", "string");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkBoolean(true, "int");
+        checker.checkInteger(1, "int");
+        checker.checkDouble(0.5, "real");
+        checker.checkString("Test", "string");
+    }
+}
+
+
+TEST(ReferenceDataTest, HandlesVectorData)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+    int veci[3] = { -1, 3, 5 };
+    float vecf[3] = { -2.3, 1.43, 2.5 };
+    double vecd[3] = { -2.3, 1.43, 2.5 };
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkVector(veci, "ivec");
+        checker.checkVector(vecf, "fvec");
+        checker.checkVector(vecd, "dvec");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkVector(veci, "ivec");
+        checker.checkVector(vecf, "fvec");
+        checker.checkVector(vecd, "dvec");
+    }
+}
+
+
+TEST(ReferenceDataTest, HandlesSequenceData)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+    const int seq[5] = { -1, 3, 5, 2, 4 };
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkSequenceArray(5, seq, "seq");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkSequenceArray(5, seq, "seq");
+    }
+}
+
+
+TEST(ReferenceDataTest, HandlesIncorrectData)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+    int seq[5] = { -1, 3, 5, 2, 4 };
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkInteger(1, "int");
+        checker.checkDouble(0.5, "real");
+        checker.checkString("Test", "string");
+        checker.checkSequenceArray(5, seq, "seq");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        EXPECT_NONFATAL_FAILURE(checker.checkInteger(2, "int"), "");
+        EXPECT_NONFATAL_FAILURE(checker.checkDouble(0.3, "real"), "");
+        EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
+        EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(4, seq, "seq"), "");
+        seq[0] = 2;
+        EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "");
+    }
+}
+
+
+TEST(ReferenceDataTest, HandlesMissingData)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+    const int seq[5] = { -1, 3, 5, 2, 4 };
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkInteger(1, "int");
+        checker.checkSequenceArray(5, seq, "seq");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        EXPECT_NONFATAL_FAILURE(checker.checkInteger(1, "missing"), "");
+        EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "missing"), "");
+    }
+}
+
+
+TEST(ReferenceDataTest, HandlesMissingReferenceDataFile)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+    const int seq[5] = { -1, 3, 5, 2, 4 };
+
+    EXPECT_NONFATAL_FAILURE({
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkInteger(1, "int");
+        checker.checkDouble(0.5, "real");
+        checker.checkString("Test", "string");
+        checker.checkSequenceArray(5, seq, "seq");
+    }, "");
+}
+
+
+TEST(ReferenceDataTest, HandlesSpecialCharactersInStrings)
+{
+    using gmx::test::TestReferenceData;
+    using gmx::test::TestReferenceChecker;
+
+    {
+        TestReferenceData data(gmx::test::erefdataUpdateAll);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkString("\"<'>\n \r &\\/;", "string");
+    }
+    {
+        TestReferenceData data(gmx::test::erefdataCompare);
+        TestReferenceChecker checker(data.rootChecker());
+        checker.checkString("\"<'>\n \r &\\/;", "string");
+    }
+}
+
+} // namespace
diff --git a/src/tools/.cvsignore b/src/tools/.cvsignore
deleted file mode 100644 (file)
index eccc86b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
\ No newline at end of file
diff --git a/src/tools/.gitignore b/src/tools/.gitignore
new file mode 100644 (file)
index 0000000..87fe1df
--- /dev/null
@@ -0,0 +1,81 @@
+do_dssp
+editconf
+eneconv
+g_anadock
+g_anaeig
+g_analyze
+g_angle
+g_bar
+g_bond
+g_bundle
+g_chi
+g_cluster
+g_clustsize
+g_confrms
+g_covar
+g_current
+g_density
+g_densmap
+g_dielectric
+g_dih
+g_dipoles
+g_disre
+g_dist
+g_dyndom
+g_enemat
+g_energy
+g_filter
+g_gyrate
+g_h2order
+g_hbond
+g_helix
+g_helixorient
+g_kinetics
+g_lie
+g_mdmat
+g_membed
+g_mindist
+g_morph
+g_msd
+g_nmeig
+g_nmens
+g_nmtraj
+g_order
+g_polystat
+g_potential
+g_principal
+g_rama
+g_rdf
+g_rms
+g_rmsdist
+g_rmsf
+g_rotacf
+g_rotmat
+g_saltbr
+g_sas
+g_sdf
+g_select
+g_sgangle
+g_sham
+g_sigeps
+g_sorient
+g_spatial
+g_spol
+g_tcaf
+g_traj
+g_tune_pme
+g_vanhove
+g_velacc
+g_wham
+g_wheel
+genbox
+genconf
+genion
+genrestr
+make_edi
+make_ndx
+mk_angndx
+trjcat
+trjconv
+trjorder
+xpm2ps
index 81d4f634497adbffa3c834125398b9bf38275d04..99a46d5a9b49dfcec42cf572448bd9c76d58afea 100644 (file)
@@ -1,4 +1,3 @@
-
 add_library(gmxana 
             autocorr.c      expfit.c        polynomials.c   levenmar.c      
             anadih.c        pp2shift.c      dlist.c         
@@ -20,7 +19,7 @@ add_library(gmxana
             gmx_polystat.c  gmx_potential.c gmx_rama.c      
             gmx_rdf.c       gmx_rms.c       gmx_rmsf.c      
             gmx_rotacf.c    gmx_saltbr.c    gmx_sas.c              
-            gmx_select.c    gmx_rmsdist.c   gmx_rotmat.c
+            gmx_rmsdist.c   gmx_rotmat.c
             gmx_sgangle.c   gmx_sorient.c   gmx_spol.c      gmx_tcaf.c      
             gmx_traj.c      gmx_velacc.c    gmx_helixorient.c 
             gmx_clustsize.c gmx_mdmat.c     gmx_wham.c      
@@ -29,13 +28,13 @@ add_library(gmxana
             gmx_editconf.c  gmx_genbox.c    gmx_genion.c    gmx_genconf.c   
             gmx_genpr.c     gmx_eneconv.c   gmx_vanhove.c   gmx_wheel.c     
             addconf.c       calcpot.c       edittop.c       gmx_bar.c
-            gmx_membed.c    gmx_pme_error.c gmx_options.c   gmx_dos.c
+            gmx_pme_error.c gmx_options.c   gmx_dos.c
             gmx_hydorder.c  gmx_densorder.c powerspect.c    dens_filter.c
             binsearch.c
             )
 
 
-target_link_libraries(gmxana md gmx ${GSL_LIBRARIES})
+target_link_libraries(gmxana libgromacs ${GSL_LIBRARIES})
 set_target_properties(gmxana PROPERTIES OUTPUT_NAME "gmxana${GMX_LIBS_SUFFIX}" SOVERSION ${SOVERSION} INSTALL_NAME_DIR "${LIB_INSTALL_DIR}")
 
 # List of programs with single corresponding .c source file,
@@ -51,10 +50,10 @@ set(GMX_TOOLS_PROGRAMS
     g_dyndom g_enemat g_energy g_lie g_filter g_gyrate
     g_h2order g_hbond g_helix g_mindist g_msd g_morph g_nmeig
     g_nmens g_order g_kinetics g_polystat g_potential g_rama g_rdf g_rms
-    g_rmsf g_rotacf g_saltbr g_sas g_select g_sgangle g_sham g_sorient
+    g_rmsf g_rotacf g_saltbr g_sas g_sgangle g_sham g_sorient
     g_spol g_spatial g_tcaf g_traj g_tune_pme g_vanhove
     g_velacc g_clustsize g_mdmat g_wham g_sigeps g_bar
-    g_membed g_pme_error g_rmsdist g_rotmat g_options
+    g_pme_error g_rmsdist g_rotmat g_options
     g_dos    g_hydorder  g_densorder
     )
 
diff --git a/src/tools/g_select.c b/src/tools/g_select.c
deleted file mode 100644 (file)
index 39a8805..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \file
- * \brief Utility program for writing out basic data for selections.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gmx_ana.h>
-
-/* This is just a wrapper binary. */
-int
-main(int argc, char *argv[])
-{
-    gmx_select(argc, argv);
-    return 0;
-}
index 9d64e7b839fe3311efc9d353be2048715d9e125f..466eeff7cabf5360eab2418efdd79ef1f8ca2ce2 100644 (file)
@@ -323,7 +323,7 @@ void calc_density(const char *fn, atom_id **index, int gnx[],
   sfree(x0);  /* free memory used by coordinate array */
 }
 
-void plot_density(real *slDensity[], const char *afile, int nslices,
+void plot_density(double *slDensity[], const char *afile, int nslices,
                  int nr_grps, char *grpname[], real slWidth, 
                  const char **dens_opt,
                  gmx_bool bSymmetrize, const output_env_t oenv)
index a290ec057b7cfd1b38b6dd16872a86549323fe08..cb5516174fe19633be0692f06aa67605c106ac40 100644 (file)
 #include <signal.h>
 #include <stdlib.h>
 #include "typedefs.h"
-#include "smalloc.h"
 #include "sysstuff.h"
-#include "vec.h"
 #include "statutil.h"
 #include "macros.h"
 #include "copyrite.h"
 #include "main.h"
-#include "futil.h"
-#include "edsam.h"
-#include "checkpoint.h"
-#include "vcm.h"
-#include "mdebin.h"
-#include "nrnb.h"
-#include "calcmu.h"
-#include "index.h"
-#include "vsite.h"
-#include "update.h"
-#include "ns.h"
-#include "trnio.h"
-#include "xtcio.h"
-#include "mdrun.h"
-#include "confio.h"
-#include "network.h"
-#include "pull.h"
-#include "xvgr.h"
-#include "physics.h"
-#include "names.h"
-#include "disre.h"
-#include "orires.h"
-#include "dihre.h"
-#include "pppm.h"
-#include "pme.h"
-#include "mdatoms.h"
-#include "qmmm.h"
-#include "mpelogging.h"
-#include "domdec.h"
-#include "partdec.h"
-#include "topsort.h"
-#include "coulomb.h"
-#include "constr.h"
-#include "shellfc.h"
-#include "mvdata.h"
-#include "checkpoint.h"
-#include "mtop_util.h"
-#include "tpxio.h"
-#include "string2.h"
-#include "sighandler.h"
 #include "gmx_ana.h"
 
 #ifdef GMX_LIB_MPI
@@ -1489,8 +1447,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
 
         wallcycle_start(wcycle,ewcSTEP);
 
-        GMX_MPE_LOG(ev_timestep1);
-
         if (bRerunMD) {
             if (rerun_fr.bStep) {
                 step = rerun_fr.step;
@@ -1722,8 +1678,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
         }*/
 
-        GMX_MPE_LOG(ev_timestep2);
-
         /* We write a checkpoint at this MD step when:
          * either at an NS step when we signalled through gs,
          * or at the last step (but not when we do not want confout),
@@ -1805,9 +1759,7 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                      (bNS ? GMX_FORCE_NS : 0) | force_flags);
         }
 
-        GMX_BARRIER(cr->mpi_comm_mygroup);
-
- /*       if (bTCR)
+/*       if (bTCR)
         {
             mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
                                    mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
@@ -1973,9 +1925,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
             }
             enerd->term[F_DHDL_CON] += dvdl;
-
-            GMX_MPE_LOG(ev_timestep1);
-
         }
 
         /* MRS -- now done iterating -- compute the conserved quantity */
@@ -2005,8 +1954,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
          * the update.
          * for RerunMD t is read from input trajectory
          */
-        GMX_MPE_LOG(ev_output_start);
-
         mdof_flags = 0;
         if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
         if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
@@ -2082,7 +2029,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
             wallcycle_stop(wcycle,ewcTRAJ);
         }
-        GMX_MPE_LOG(ev_output_finish);
 
         /* kludge -- virial is lost with restart for NPT control. Must restart */
         if (bStartingFromCpt && bVV)
@@ -2226,7 +2172,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                so scroll down for that logic */
 
             /* #########   START SECOND UPDATE STEP ################# */
-            GMX_MPE_LOG(ev_update_start);
             bOK = TRUE;
             if (!bRerunMD || rerun_fr.bV || bForceUpdate)
             {
@@ -2343,9 +2288,6 @@ double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 unshift_self(graph,state->box,state->x);
             }
 
-            GMX_BARRIER(cr->mpi_comm_mygroup);
-            GMX_MPE_LOG(ev_update_finish);
-
             if (vsite != NULL)
             {
                 wallcycle_start(wcycle,ewcVSITECONSTR);
@@ -3458,20 +3400,22 @@ int gmx_membed(int argc,char *argv[])
                        "NOTE[BR]----[BR]",
                        " - Protein can be any molecule you want to insert in the membrane.[BR]",
                        " - It is recommended to perform a short equilibration run after the embedding",
-                       "(see Wolf et al, J Comp Chem 31 (2010) 2169-2174), to re-equilibrate the membrane. Clearly",
-                       "protein equilibration might require longer.[PAR]"
+                       "(see Wolf et al, J Comp Chem 31 (2010) 2169-2174, to re-equilibrate the membrane. Clearly",
+                       "protein equilibration might require longer.\n",
+                       " - It is now also possible to use the g_membed functionality with mdrun. You should than pass",
+                       "a data file containing the command line options of g_membed following the -membed option, for",
+                       "example mdrun -s into_mem.tpr -membed membed.dat.",
+                       "\n"
        };
-       t_commrec    *cr;
        t_filenm fnm[] = {
                        { efTPX, "-f",      "into_mem", ffREAD },
                        { efNDX, "-n",      "index",    ffOPTRD },
                        { efTOP, "-p",      "topol",    ffOPTRW },
                        { efTRN, "-o",      NULL,       ffWRITE },
                        { efXTC, "-x",      NULL,       ffOPTWR },
-                       { efCPT, "-cpi",    NULL,       ffOPTRD },
-                       { efCPT, "-cpo",    NULL,       ffOPTWR },
                        { efSTO, "-c",      "membedded",  ffWRITE },
                        { efEDR, "-e",      "ener",     ffWRITE },
+                        { efDAT, "-dat",    "membed",   ffWRITE }
                        { efLOG, "-g",      "md",       ffWRITE },
                        { efEDI, "-ei",     "sam",      ffOPTRD },
                        { efTRX, "-rerun",  "rerun",    ffOPTRD },
@@ -3502,41 +3446,6 @@ int gmx_membed(int argc,char *argv[])
 #define NFILE asize(fnm)
 
        /* Command line options ! */
-       gmx_bool bCart        = FALSE;
-       gmx_bool bPPPME       = FALSE;
-       gmx_bool bPartDec     = FALSE;
-       gmx_bool bDDBondCheck = TRUE;
-       gmx_bool bDDBondComm  = TRUE;
-       gmx_bool bVerbose     = FALSE;
-       gmx_bool bCompact     = TRUE;
-       gmx_bool bSepPot      = FALSE;
-       gmx_bool bRerunVSite  = FALSE;
-       gmx_bool bIonize      = FALSE;
-       gmx_bool bConfout     = TRUE;
-       gmx_bool bReproducible = FALSE;
-
-       int  npme=-1;
-       int  nmultisim=0;
-       int  nstglobalcomm=-1;
-       int  repl_ex_nst=0;
-       int  repl_ex_seed=-1;
-       int  nstepout=100;
-       int  nthreads=0; /* set to determine # of threads automatically */
-       int  resetstep=-1;
-
-       rvec realddxyz={0,0,0};
-       const char *ddno_opt[ddnoNR+1] =
-       { NULL, "interleave", "pp_pme", "cartesian", NULL };
-       const char *dddlb_opt[] =
-       { NULL, "auto", "no", "yes", NULL };
-       real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
-       char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
-       real cpt_period=15.0,max_hours=-1;
-       gmx_bool bAppendFiles=TRUE,bAddPart=TRUE;
-       gmx_bool bResetCountersHalfWay=FALSE;
-       output_env_t oenv=NULL;
-       const char *deviceOptions = "";
-
        real xy_fac = 0.5;
        real xy_max = 1.0;
        real z_fac = 1.0;
@@ -3547,8 +3456,11 @@ int gmx_membed(int argc,char *argv[])
        int low_up_rm = 0;
        int maxwarn=0;
        int pieces=1;
-    gmx_bool bALLOW_ASYMMETRY=FALSE;
-
+        gmx_bool bALLOW_ASYMMETRY=FALSE;
+        gmx_bool bStart=FALSE;
+        int nstepout=100;
+        gmx_bool bVerbose=FALSE;
+        char *mdrun_path=NULL;
 
 /* arguments relevant to OPENMM only*/
 #ifdef GMX_OPENMM
@@ -3556,84 +3468,41 @@ int gmx_membed(int argc,char *argv[])
 #endif
 
        t_pargs pa[] = {
-                       { "-xyinit",   FALSE, etREAL,  {&xy_fac},       "Resize factor for the protein in the xy dimension before starting embedding" },
-                       { "-xyend",   FALSE, etREAL,  {&xy_max},                "Final resize factor in the xy dimension" },
-                       { "-zinit",    FALSE, etREAL,  {&z_fac},                "Resize factor for the protein in the z dimension before starting embedding" },
-                       { "-zend",    FALSE, etREAL,  {&z_max},                 "Final resize faction in the z dimension" },
-                       { "-nxy",     FALSE,  etINT,  {&it_xy},         "Number of iteration for the xy dimension" },
-                       { "-nz",      FALSE,  etINT,  {&it_z},          "Number of iterations for the z dimension" },
-                       { "-rad",     FALSE, etREAL,  {&probe_rad},     "Probe radius to check for overlap between the group to embed and the membrane"},
-                       { "-pieces",  FALSE,  etINT,  {&pieces},        "Perform piecewise resize. Select parts of the group to insert and resize these with respect to their own geometrical center." },
-            { "-asymmetry",FALSE, etBOOL,{&bALLOW_ASYMMETRY}, "Allow asymmetric insertion, i.e. the number of lipids removed from the upper and lower leaflet will not be checked." },
-            { "-ndiff" ,  FALSE, etINT, {&low_up_rm},       "Number of lipids that will additionally be removed from the lower (negative number) or upper (positive number) membrane leaflet." },
-                       { "-maxwarn", FALSE, etINT, {&maxwarn},                 "Maximum number of warning allowed" },
-  { "-pd",      FALSE, etBOOL,{&bPartDec},
-    "HIDDENUse particle decompostion" },
-  { "-dd",      FALSE, etRVEC,{&realddxyz},
-    "HIDDENDomain decomposition grid, 0 is optimize" },
-  { "-nt",      FALSE, etINT, {&nthreads},
-    "HIDDENNumber of threads to start (0 is guess)" },
-  { "-npme",    FALSE, etINT, {&npme},
-    "HIDDENNumber of separate nodes to be used for PME, -1 is guess" },
-  { "-ddorder", FALSE, etENUM, {ddno_opt},
-    "HIDDENDD node order" },
-  { "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
-    "HIDDENCheck for all bonded interactions with DD" },
-  { "-ddbondcomm", FALSE, etBOOL, {&bDDBondComm},
-    "HIDDENUse special bonded atom communication when [TT]-rdd[tt] > cut-off" },
-  { "-rdd",     FALSE, etREAL, {&rdd},
-    "HIDDENThe maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
-  { "-rcon",    FALSE, etREAL, {&rconstr},
-    "HIDDENMaximum distance for P-LINCS (nm), 0 is estimate" },
-  { "-dlb",     FALSE, etENUM, {dddlb_opt},
-    "HIDDENDynamic load balancing (with DD)" },
-  { "-dds",     FALSE, etREAL, {&dlb_scale},
-    "HIDDENMinimum allowed dlb scaling of the DD cell size" },
-  { "-ddcsx",   FALSE, etSTR, {&ddcsx},
-    "HIDDENThe DD cell sizes in x" },
-  { "-ddcsy",   FALSE, etSTR, {&ddcsy},
-    "HIDDENThe DD cell sizes in y" },
-  { "-ddcsz",   FALSE, etSTR, {&ddcsz},
-    "HIDDENThe DD cell sizes in z" },
-  { "-gcom",    FALSE, etINT,{&nstglobalcomm},
-    "HIDDENGlobal communication frequency" },
-  { "-compact", FALSE, etBOOL,{&bCompact},
-    "Write a compact log file" },
-  { "-seppot",  FALSE, etBOOL, {&bSepPot},
-    "HIDDENWrite separate V and dVdl terms for each interaction type and node to the log file(s)" },
-  { "-pforce",  FALSE, etREAL, {&pforce},
-    "HIDDENPrint all forces larger than this (kJ/mol nm)" },
-  { "-reprod",  FALSE, etBOOL,{&bReproducible},
-    "HIDDENTry to avoid optimizations that affect binary reproducibility" },
-  { "-multi",   FALSE, etINT,{&nmultisim},
-    "HIDDENDo multiple simulations in parallel" },
-  { "-replex",  FALSE, etINT, {&repl_ex_nst},
-    "HIDDENAttempt replica exchange every # steps" },
-  { "-reseed",  FALSE, etINT, {&repl_ex_seed},
-    "HIDDENSeed for replica exchange, -1 is generate a seed" },
-  { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
-    "HIDDENRecalculate virtual site coordinates with [TT]-rerun[tt]" },
-  { "-ionize",  FALSE, etBOOL,{&bIonize},
-    "HIDDENDo a simulation including the effect of an X-Ray bombardment on your system" },
-  { "-confout", TRUE, etBOOL, {&bConfout},
-    "HIDDENWrite the last configuration with [TT]-c[tt] and force checkpointing at the last step" },
-  { "-stepout", FALSE, etINT, {&nstepout},
-    "HIDDENFrequency of writing the remaining runtime" },
-  { "-resetstep", FALSE, etINT, {&resetstep},
-    "HIDDENReset cycle counters after these many time steps" },
-  { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
-    "HIDDENReset the cycle counters after half the number of steps or halfway [TT]-maxh[tt]" },
-  { "-v",       FALSE, etBOOL,{&bVerbose},
-    "Be loud and noisy" },
-  { "-maxh",   FALSE, etREAL, {&max_hours},
-    "HIDDENTerminate after 0.99 times this time (hours)" },
-  { "-cpt",     FALSE, etREAL, {&cpt_period},
-    "HIDDENCheckpoint interval (minutes)" },
-  { "-append",  FALSE, etBOOL, {&bAppendFiles},
-    "HIDDENAppend to previous output files when continuing from checkpoint" },
-  { "-addpart",  FALSE, etBOOL, {&bAddPart},
-    "HIDDENAdd the simulation part number to all output files when continuing from checkpoint" },
+                       { "-xyinit",   FALSE, etREAL,  {&xy_fac},       
+                               "Resize factor for the protein in the xy dimension before starting embedding" },
+                       { "-xyend",   FALSE, etREAL,  {&xy_max},
+                               "Final resize factor in the xy dimension" },
+                       { "-zinit",    FALSE, etREAL,  {&z_fac},
+                               "Resize factor for the protein in the z dimension before starting embedding" },
+                       { "-zend",    FALSE, etREAL,  {&z_max},
+                               "Final resize faction in the z dimension" },
+                       { "-nxy",     FALSE,  etINT,  {&it_xy},
+                               "Number of iteration for the xy dimension" },
+                       { "-nz",      FALSE,  etINT,  {&it_z},
+                               "Number of iterations for the z dimension" },
+                       { "-rad",     FALSE, etREAL,  {&probe_rad},
+                               "Probe radius to check for overlap between the group to embed and the membrane"},
+                       { "-pieces",  FALSE,  etINT,  {&pieces},
+                               "Perform piecewise resize. Select parts of the group to insert and resize these with respect to their own geometrical center." },
+                       { "-asymmetry",FALSE, etBOOL,{&bALLOW_ASYMMETRY}, 
+                               "Allow asymmetric insertion, i.e. the number of lipids removed from the upper and lower leaflet will not be checked." },
+                       { "-ndiff" ,  FALSE, etINT, {&low_up_rm},
+                               "Number of lipids that will additionally be removed from the lower (negative number) or upper (positive number) membrane leaflet." },
+                       { "-maxwarn", FALSE, etINT, {&maxwarn},         
+                               "Maximum number of warning allowed" },
+                        { "-start",   FALSE, etBOOL, {&bStart},
+                                "Call mdrun with membed options" },
+                       { "-stepout", FALSE, etINT, {&nstepout},
+                               "HIDDENFrequency of writing the remaining runtime" },
+                       { "-v",       FALSE, etBOOL,{&bVerbose},
+                               "Be loud and noisy" },
+                       { "-mdrun_path", FALSE, etSTR, {&mdrun_path},
+                               "Path to the mdrun executable compiled with this g_membed version" }
        };
+
+        FILE *data_out;
+        output_env_t oenv;
+        char buf[256],buf2[64];
        gmx_edsam_t  ed;
        unsigned long Flags, PCA_Flags;
        ivec     ddxyz;
@@ -3697,9 +3566,9 @@ int gmx_membed(int argc,char *argv[])
         }
 
 
-       if (repl_ex_nst != 0 && nmultisim < 2)
-               gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
 
+        parse_common_args(&argc,argv,0, NFILE,fnm,asize(pa),pa,
+                    asize(desc),desc,0,NULL, &oenv);
        if (nmultisim > 1) {
 #ifndef GMX_THREADS
                 gmx_bool bParFn = (multidir == NULL);
@@ -3733,83 +3602,47 @@ int gmx_membed(int argc,char *argv[])
                bAppendFiles = FALSE;
        }
 
-       if (!bAppendFiles)
-       {
-               sim_part_fn = sim_part;
-       }
-
-       if (bAddPart && sim_part_fn > 1)
+        data_out = ffopen(opt2fn("-dat",NFILE,fnm),"w");
+        fprintf(data_out,"nxy = %d\nnz = %d\nxyinit = %f\nxyend = %f\nzinit = %f\nzend = %f\n"
+                       "rad = %f\npieces = %d\nasymmetry = %s\nndiff = %d\nmaxwarn = %d\n",
+                       it_xy,it_z,xy_fac,xy_max,z_fac,z_max,probe_rad,pieces,
+                       bALLOW_ASYMMETRY ? "yes" : "no",low_up_rm,maxwarn);
+        fclose(data_out);
+
+        sprintf(buf,"%s -s %s -membed %s -o %s -c %s -e %s -nt 1 -cpt -1",
+                   (mdrun_path==NULL) ? "mdrun" : mdrun_path,
+                   opt2fn("-f",NFILE,fnm),opt2fn("-dat",NFILE,fnm),opt2fn("-o",NFILE,fnm),
+                   opt2fn("-c",NFILE,fnm),opt2fn("-e",NFILE,fnm));
+        if (opt2bSet("-n",NFILE,fnm))
        {
-               /* This is a continuation run, rename trajectory output files
-       (except checkpoint files) */
-               /* create new part name first (zero-filled) */
-               sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
-
-               add_suffix_to_output_names(fnm,NFILE,suffix);
-               fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
-       }
-
-       Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
-       Flags = Flags | (bSepPot       ? MD_SEPPOT       : 0);
-       Flags = Flags | (bIonize       ? MD_IONIZE       : 0);
-       Flags = Flags | (bPartDec      ? MD_PARTDEC      : 0);
-       Flags = Flags | (bDDBondCheck  ? MD_DDBONDCHECK  : 0);
-       Flags = Flags | (bDDBondComm   ? MD_DDBONDCOMM   : 0);
-       Flags = Flags | (bConfout      ? MD_CONFOUT      : 0);
-       Flags = Flags | (bRerunVSite   ? MD_RERUN_VSITE  : 0);
-       Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
-       Flags = Flags | (bAppendFiles  ? MD_APPENDFILES  : 0);
-       Flags = Flags | (sim_part>1    ? MD_STARTFROMCPT : 0);
-       Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
-
-
-       /* We postpone opening the log file if we are appending, so we can
-   first truncate the old log file and append to the correct position
-   there instead.  */
-       if ((MASTER(cr) || bSepPot) && !bAppendFiles)
+               sprintf(buf2," -mn %s",opt2fn("-n",NFILE,fnm));
+               strcat(buf,buf2);
+        }
+       if (opt2bSet("-x",NFILE,fnm))
        {
-               gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
-               CopyRight(fplog,argv[0]);
-               please_cite(fplog,"Hess2008b");
-               please_cite(fplog,"Spoel2005a");
-               please_cite(fplog,"Lindahl2001a");
-               please_cite(fplog,"Berendsen95a");
+               sprintf(buf2," -x %s",opt2fn("-x",NFILE,fnm));
+                strcat(buf,buf2);
        }
-       else
+        if (opt2bSet("-p",NFILE,fnm))
+        {
+                sprintf(buf2," -mp %s",opt2fn("-p",NFILE,fnm));
+                strcat(buf,buf2);
+        }
+       if (bVerbose)
        {
-               fplog = NULL;
-       }
-
-       ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
-       ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
-       ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
-
-       /* even if nthreads = 1, we still call this one */
-
-       rc = mdrunner_membed(fplog, cr, NFILE, fnm, oenv, bVerbose, bCompact,
-                       nstglobalcomm,
-                       ddxyz, dd_node_order, rdd, rconstr, dddlb_opt[0], dlb_scale,
-                       ddcsx, ddcsy, ddcsz, nstepout, resetstep, nmultisim, repl_ex_nst,
-                       repl_ex_seed, pforce, cpt_period, max_hours, deviceOptions, Flags,
-                       xy_fac,xy_max,z_fac,z_max,
-                       it_xy,it_z,probe_rad,low_up_rm,
-                       pieces,bALLOW_ASYMMETRY,maxwarn);
-
-       if (gmx_parallel_env_initialized())
-               gmx_finalize();
-
-       if (MULTIMASTER(cr)) {
-               thanx(stderr);
+               sprintf(buf2," -v -stepout %d",nstepout);
+               strcat(buf,buf2);
        }
 
-       /* Log file has to be closed in mdrunner if we are appending to it
-   (fplog not set here) */
-       fprintf(stderr,"Please cite:\nWolf et al, J Comp Chem 31 (2010) 2169-2174.\n");
+        printf("%s\n",buf);
+        if (bStart)
+        {
+                system(buf);
+        } else {
+                printf("You can membed your protein now by:\n%s\n",buf);
+        }
 
-       if (MASTER(cr) && !bAppendFiles)
-       {
-               gmx_log_close(fplog);
-       }
+        fprintf(stderr,"Please cite:\nWolf et al, J Comp Chem 31 (2010) 2169-2174.\n");
 
-       return rc;
+       return 0;
 }
index a6343f445e648ff226f72b310e1ba9f5f1f1853b..c381f89e79da7e87bf612e40da9c35d975099328 100644 (file)
@@ -508,7 +508,7 @@ void printmol(t_corr *curr,const char *fn,
     for(j=0; (j<curr->nrestart); j++) {
       real xx,yy,dx,dy;
       
-      while(gmx_stats_get_point(curr->lsq[j][i],&xx,&yy,&dx,&dy) == estatsOK)
+      while(gmx_stats_get_point(curr->lsq[j][i],&xx,&yy,&dx,&dy,0) == estatsOK)
           gmx_stats_add_point(lsq1,xx,yy,dx,dy);
     }
     gmx_stats_get_ab(lsq1,elsqWEIGHT_NONE,&a,&b,NULL,NULL,NULL,NULL);
diff --git a/src/tools/gmx_select.c b/src/tools/gmx_select.c
deleted file mode 100644 (file)
index 33e3f05..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- *
- *                This source code is part of
- *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
- *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * 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.
- *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
- */
-/*! \example gmx_select.c
- * \brief Utility/example program for writing out basic data for selections.
- */
-/*! \file
- * \brief Utility program for writing out basic data for selections.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <copyrite.h>
-#include <index.h>
-#include <macros.h>
-#include <smalloc.h>
-#include <statutil.h>
-#include <xvgr.h>
-#include <string2.h>
-#include <trajana.h>
-#include "gmx_ana.h"
-#include "gmx_fatal.h"
-
-
-typedef struct
-{
-    gmx_bool                bDump;
-    gmx_bool                bFracNorm;
-    const char         *routt;
-    int                *size;
-    FILE               *sfp;
-    FILE               *cfp;
-    FILE               *ifp;
-    t_blocka           *block;
-    char              **gnames;
-    FILE               *mfp;
-    gmx_ana_indexmap_t *mmap;
-} t_dsdata;
-
-static int
-print_data(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           int nr, gmx_ana_selection_t *sel[], void *data)
-{
-    t_dsdata           *d = (t_dsdata *)data;
-    int                 g, i, b, mask;
-    real                normfac;
-    char                buf2[100],*buf,*nl;
-    static int          bFirstFrame=1;
-
-    /* Write the sizes of the groups, possibly normalized */
-    if (d->sfp)
-    {
-        fprintf(d->sfp, "%11.3f", fr->time);
-        for (g = 0; g < nr; ++g)
-        {
-            normfac = d->bFracNorm ? 1.0 / sel[g]->cfrac : 1.0;
-            fprintf(d->sfp, " %8.3f", sel[g]->p.nr * normfac / d->size[g]);
-        }
-        fprintf(d->sfp, "\n");
-    }
-
-    /* Write the covered fraction */
-    if (d->cfp)
-    {
-        fprintf(d->cfp, "%11.3f", fr->time);
-        for (g = 0; g < nr; ++g)
-        {
-            fprintf(d->cfp, " %6.4f", sel[g]->cfrac);
-        }
-        fprintf(d->cfp, "\n");
-    }
-
-    /* Write the actual indices */
-    if (d->ifp)
-    {
-        if (!d->bDump)
-        {
-            fprintf(d->ifp, "%11.3f", fr->time);
-        }
-        for (g = 0; g < nr; ++g)
-        {
-            if (!d->bDump)
-            {
-                fprintf(d->ifp, " %d", sel[g]->p.nr);
-            }
-            for (i = 0; i < sel[g]->p.nr; ++i)
-            {
-                if (sel[g]->p.m.type == INDEX_RES && d->routt[0] == 'n')
-                {
-                    fprintf(d->ifp, " %d", top->atoms.resinfo[sel[g]->p.m.mapid[i]].nr);
-                }
-                else
-                {
-                    fprintf(d->ifp, " %d", sel[g]->p.m.mapid[i]+1);
-                }
-            }
-        }
-        fprintf(d->ifp, "\n");
-    }
-    
-    if (d->block) 
-    {
-        for (g = 0; g < nr; ++g) 
-        {        
-            if (sel[g]->bDynamic || bFirstFrame) 
-            {
-                buf = strdup(sel[g]->name);
-                while ((nl = strchr(buf, ' ')) != NULL)
-                {
-                    *nl = '_';
-                }
-                if (sel[g]->bDynamic)
-                {
-                    sprintf(buf2, "_%.3f", fr->time);
-                    srenew(buf, strlen(buf) + strlen(buf2) + 1);
-                    strcat(buf, buf2);
-                }
-                add_grp(d->block, &d->gnames, sel[g]->p.nr, sel[g]->p.m.mapid, buf);
-                sfree(buf);
-            }
-        }
-    }
-
-    /* Write masks */
-    if (d->mfp)
-    {
-        gmx_ana_indexmap_update(d->mmap, sel[0]->g, TRUE);
-        if (!d->bDump)
-        {
-            fprintf(d->mfp, "%11.3f", fr->time);
-        }
-        for (b = 0; b < d->mmap->nr; ++b)
-        {
-            mask = (d->mmap->refid[b] == -1 ? 0 : 1);
-            fprintf(d->mfp, d->bDump ? "%d\n" : " %d", mask);
-        }
-        if (!d->bDump)
-        {
-            fprintf(d->mfp, "\n");
-        }
-    }
-    bFirstFrame = 0;
-    return 0;
-}
-
-int
-gmx_select(int argc, char *argv[])
-{
-    const char *desc[] = {
-        "[TT]g_select[tt] writes out basic data about dynamic selections.",
-        "It can be used for some simple analyses, or the output can",
-        "be combined with output from other programs and/or external",
-        "analysis programs to calculate more complex things.",
-        "Any combination of the output options is possible, but note",
-        "that [TT]-om[tt] only operates on the first selection.[PAR]",
-        "With [TT]-os[tt], calculates the number of positions in each",
-        "selection for each frame. With [TT]-norm[tt], the output is",
-        "between 0 and 1 and describes the fraction from the maximum",
-        "number of positions (e.g., for selection 'resname RA and x < 5'",
-        "the maximum number of positions is the number of atoms in",
-        "RA residues). With [TT]-cfnorm[tt], the output is divided",
-        "by the fraction covered by the selection.",
-        "[TT]-norm[tt] and [TT]-cfnorm[tt] can be specified independently",
-        "of one another.[PAR]",
-        "With [TT]-oc[tt], the fraction covered by each selection is",
-        "written out as a function of time.[PAR]",
-        "With [TT]-oi[tt], the selected atoms/residues/molecules are",
-        "written out as a function of time. In the output, the first",
-        "column contains the frame time, the second contains the number",
-        "of positions, followed by the atom/residue/molecule numbers.",
-        "If more than one selection is specified, the size of the second",
-        "group immediately follows the last number of the first group",
-        "and so on. With [TT]-dump[tt], the frame time and the number",
-        "of positions is omitted from the output. In this case, only one",
-        "selection can be given.[PAR]",
-        "With [TT]-on[tt], the selected atoms are written as a index file",
-        "compatible with [TT]make_ndx[tt] and the analyzing tools. Each selection",
-        "is written as a selection group and for dynamic selections a",
-        "group is written for each frame.[PAR]",
-        "For residue numbers, the output of [TT]-oi[tt] can be controlled",
-        "with [TT]-resnr[tt]: [TT]number[tt] (default) prints the residue",
-        "numbers as they appear in the input file, while [TT]index[tt] prints",
-        "unique numbers assigned to the residues in the order they appear",
-        "in the input file, starting with 1. The former is more intuitive,",
-        "but if the input contains multiple residues with the same number,",
-        "the output can be less useful.[PAR]",
-        "With [TT]-om[tt], a mask is printed for the first selection",
-        "as a function of time. Each line in the output corresponds to",
-        "one frame, and contains either 0/1 for each atom/residue/molecule",
-        "possibly selected. 1 stands for the atom/residue/molecule being",
-        "selected for the current frame, 0 for not selected.",
-        "With [TT]-dump[tt], the frame time is omitted from the output.",
-    };
-
-    gmx_bool                bDump     = FALSE;
-    gmx_bool                bFracNorm = FALSE;
-    gmx_bool                bTotNorm  = FALSE;
-    const char         *routt[] = {NULL, "number", "index", NULL};
-    t_pargs             pa[] = {
-        {"-dump",   FALSE, etBOOL, {&bDump},
-         "Do not print the frame time (-om, -oi) or the index size (-oi)"},
-        {"-norm",   FALSE, etBOOL, {&bTotNorm},
-         "Normalize by total number of positions with -os"},
-        {"-cfnorm", FALSE, etBOOL, {&bFracNorm},
-         "Normalize by covered fraction with -os"},
-        {"-resnr",  FALSE, etENUM, {routt},
-         "Residue number output type"},
-    };
-
-    t_filenm            fnm[] = {
-        {efXVG, "-os", "size.xvg",  ffOPTWR},
-        {efXVG, "-oc", "cfrac.xvg", ffOPTWR},
-        {efDAT, "-oi", "index.dat", ffOPTWR},
-        {efDAT, "-om", "mask.dat",  ffOPTWR},
-        {efNDX, "-on", "index.ndx", ffOPTWR},
-    };
-#define NFILE asize(fnm)
-
-    gmx_ana_traj_t       *trj;
-    t_topology           *top;
-    int                   ngrps;
-    gmx_ana_selection_t **sel;
-    char                **grpnames;
-    t_dsdata              d;
-    const char            *fnSize, *fnFrac, *fnIndex, *fnNdx, *fnMask;
-    int                   g;
-    int                   rc;
-    output_env_t          oenv;
-
-    CopyRight(stderr, argv[0]);
-    gmx_ana_traj_create(&trj, 0);
-    gmx_ana_set_nanagrps(trj, -1);
-    parse_trjana_args(trj, &argc, argv, 0,
-                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL,
-                      &oenv);
-    gmx_ana_get_nanagrps(trj, &ngrps);
-    gmx_ana_get_anagrps(trj, &sel);
-    gmx_ana_init_coverfrac(trj, CFRAC_SOLIDANGLE);
-
-    /* Get output file names */
-    fnSize  = opt2fn_null("-os", NFILE, fnm);
-    fnFrac  = opt2fn_null("-oc", NFILE, fnm);
-    fnIndex = opt2fn_null("-oi", NFILE, fnm);
-    fnNdx   = opt2fn_null("-on", NFILE, fnm);
-    fnMask  = opt2fn_null("-om", NFILE, fnm);
-    /* Write out sizes if nothing specified */
-    if (!fnFrac && !fnIndex && !fnMask && !fnNdx)
-    {
-        fnSize = opt2fn("-os", NFILE, fnm);
-    }
-
-    if ( bDump && ngrps > 1)
-    {
-        gmx_fatal(FARGS, "Only one index group allowed with -dump");
-    }
-    if (fnNdx && sel[0]->p.m.type != INDEX_ATOM)
-    {
-        gmx_fatal(FARGS, "Only atom selection allowed with -on");
-    }
-    if (fnMask && ngrps > 1)
-    {
-        fprintf(stderr, "warning: the mask (-om) will only be written for the first group\n");
-    }
-    if (fnMask && !sel[0]->bDynamic)
-    {
-        fprintf(stderr, "warning: will not write the mask (-om) for a static selection\n");
-        fnMask = NULL;
-    }
-
-    /* Initialize reference calculation for masks */
-    if (fnMask)
-    {
-        gmx_ana_get_topology(trj, FALSE, &top, NULL);
-        snew(d.mmap, 1);
-        gmx_ana_indexmap_init(d.mmap, sel[0]->g, top, sel[0]->p.m.type);
-    }
-
-    /* Initialize calculation data */
-    d.bDump     = bDump;
-    d.bFracNorm = bFracNorm;
-    d.routt     = routt[0];
-    snew(d.size,  ngrps);
-    for (g = 0; g < ngrps; ++g)
-    {
-        d.size[g] = bTotNorm ? sel[g]->p.nr : 1;
-    }
-
-    /* Open output files */
-    d.sfp = d.cfp = d.ifp = d.mfp = NULL;
-    d.block = NULL;
-    gmx_ana_get_grpnames(trj, &grpnames);
-    if (fnSize)
-    {
-        d.sfp = xvgropen(fnSize, "Selection size", "Time (ps)", "Number",oenv);
-        xvgr_selections(d.sfp, trj);
-        xvgr_legend(d.sfp, ngrps, (const char**)grpnames, oenv);
-    }
-    if (fnFrac)
-    {
-        d.cfp = xvgropen(fnFrac, "Covered fraction", "Time (ps)", "Fraction",
-                         oenv);
-        xvgr_selections(d.cfp, trj);
-        xvgr_legend(d.cfp, ngrps, (const char**)grpnames, oenv);
-    }
-    if (fnIndex)
-    {
-        d.ifp = ffopen(fnIndex, "w");
-        xvgr_selections(d.ifp, trj);
-    }
-    if (fnNdx)
-    {
-        d.block = new_blocka();
-        d.gnames = NULL;
-    }
-    if (fnMask)
-    {
-        d.mfp = ffopen(fnMask, "w");
-        xvgr_selections(d.mfp, trj);
-    }
-
-    /* Do the analysis and write out results */
-    gmx_ana_do(trj, 0, &print_data, &d);
-
-    /* Close the files */
-    if (d.sfp)
-    {
-        ffclose(d.sfp);
-    }
-    if (d.cfp)
-    {
-        ffclose(d.cfp);
-    }
-    if (d.ifp)
-    {
-        ffclose(d.ifp);
-    }
-    if (d.block)
-    {
-        write_index(fnNdx, d.block, d.gnames);
-    }
-    if (d.mfp)
-    {
-        ffclose(d.mfp);
-    }
-
-    thanx(stderr);
-
-    return 0;
-}
index 5e00f8351da548a9d643f934c131d0540f3970cd..fe7528170b05221176a0725c3416600bfb62c9d6 100644 (file)
@@ -1153,7 +1153,11 @@ static void make_benchmark_tprs(
  * not on mdrun command line options! */
 static gmx_bool tpr_triggers_file(const char *opt)
 {
-    if ( (0 == strcmp(opt, "-pf"))
+    if ( (0 == strcmp(opt, "-ro"))
+      || (0 == strcmp(opt, "-ra"))
+      || (0 == strcmp(opt, "-rt"))
+      || (0 == strcmp(opt, "-rs"))
+      || (0 == strcmp(opt, "-pf"))
       || (0 == strcmp(opt, "-px")) )
         return TRUE;
     else
@@ -2108,6 +2112,10 @@ int gmx_tune_pme(int argc,char *argv[])
       { efXVG, "-runav",  "runaver",  ffOPTWR },
       { efXVG, "-px",     "pullx",    ffOPTWR },
       { efXVG, "-pf",     "pullf",    ffOPTWR },
+      { efXVG, "-ro",     "rotation", ffOPTWR },
+      { efLOG, "-ra",     "rotangles",ffOPTWR },
+      { efLOG, "-rs",     "rotslabs", ffOPTWR },
+      { efLOG, "-rt",     "rottorque",ffOPTWR },
       { efMTX, "-mtx",    "nm",       ffOPTWR },
       { efNDX, "-dn",     "dipole",   ffOPTWR },
       /* Output files that are deleted after each benchmark run */
@@ -2128,6 +2136,10 @@ int gmx_tune_pme(int argc,char *argv[])
       { efXVG, "-brunav", "benchrnav",ffOPTWR },
       { efXVG, "-bpx",    "benchpx",  ffOPTWR },
       { efXVG, "-bpf",    "benchpf",  ffOPTWR },
+      { efXVG, "-bro",    "benchrot", ffOPTWR },
+      { efLOG, "-bra",    "benchrota",ffOPTWR },
+      { efLOG, "-brs",    "benchrots",ffOPTWR },
+      { efLOG, "-brt",    "benchrott",ffOPTWR },
       { efMTX, "-bmtx",   "benchn",   ffOPTWR },
       { efNDX, "-bdn",    "bench",    ffOPTWR }
     };
index 329e4e6ff35ffb3777a90a6c8a934acd7636b1d4..16b88500198c8cb46987b793715645ad375940e7 100644 (file)
@@ -5,7 +5,7 @@ Name: libgmxana
 Description: Gromacs analysis lib
 URL: http://www.gromacs.org
 Version: @PROJECT_VERSION@
-Requires: @PKG_GSL@ libgmx@GMX_LIBS_SUFFIX@ libmd@GMX_LIBS_SUFFIX@
+Requires: @PKG_GSL@ libgromacs@GMX_LIBS_SUFFIX@
 Libs.private: -lm @CMAKE_THREAD_LIBS_INIT@
 Libs: -L${libdir} -lgmxana@GMX_LIBS_SUFFIX@
 Cflags: -I${includedir} @PKG_CFLAGS@
index e7a39ae99c6eec9413ab78d58dfb6a95c9437334..d1c2d7061068a275f82e7039c74a8f2015c1209b 100644 (file)
@@ -1,2 +1,2 @@
-enable_testing()
-add_test(TestExec_mdrun-h ../src/kernel/mdrun -h)
+add_test(NAME TestExec_mdrun-h
+         COMMAND mdrun -h)